diff --git a/notebooks/22_sky130nm_inverter_schematic_to_layout.ipynb b/notebooks/22_sky130nm_inverter_schematic_to_layout.ipynb
index 9cb5c021..145cd6dc 100644
--- a/notebooks/22_sky130nm_inverter_schematic_to_layout.ipynb
+++ b/notebooks/22_sky130nm_inverter_schematic_to_layout.ipynb
@@ -42,361 +42,10 @@
},
{
"cell_type": "code",
- "execution_count": 1,
+ "execution_count": null,
"id": "4",
"metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\u001b[32m2024-06-02 17:54:34.141\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mgdsfactory.pdk\u001b[0m:\u001b[36mregister_cells_yaml\u001b[0m:\u001b[36m376\u001b[0m - \u001b[1mRegistered cell 'sample'\u001b[0m\n",
- "\u001b[32m2024-06-02 17:54:34.464\u001b[0m | \u001b[33m\u001b[1mWARNING \u001b[0m | \u001b[36mpydantic._internal._fields\u001b[0m:\u001b[36mcollect_model_fields\u001b[0m:\u001b[36m186\u001b[0m - \u001b[33m\u001b[1mUserWarning: Field name \"schema\" shadows an attribute in parent \"BaseModel\"; \u001b[0m\n",
- "env: BOKEH_ALLOW_WS_ORIGIN=*\n"
- ]
- },
- {
- "data": {
- "text/html": [
- " \n",
- "
\n",
- "
\n",
- "
Loading BokehJS ...\n",
- "
\n"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "application/javascript": [
- "'use strict';\n",
- "(function(root) {\n",
- " function now() {\n",
- " return new Date();\n",
- " }\n",
- "\n",
- " const force = true;\n",
- "\n",
- " if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n",
- " root._bokeh_onload_callbacks = [];\n",
- " root._bokeh_is_loading = undefined;\n",
- " }\n",
- "\n",
- "const JS_MIME_TYPE = 'application/javascript';\n",
- " const HTML_MIME_TYPE = 'text/html';\n",
- " const EXEC_MIME_TYPE = 'application/vnd.bokehjs_exec.v0+json';\n",
- " const CLASS_NAME = 'output_bokeh rendered_html';\n",
- "\n",
- " /**\n",
- " * Render data to the DOM node\n",
- " */\n",
- " function render(props, node) {\n",
- " const script = document.createElement(\"script\");\n",
- " node.appendChild(script);\n",
- " }\n",
- "\n",
- " /**\n",
- " * Handle when an output is cleared or removed\n",
- " */\n",
- " function handleClearOutput(event, handle) {\n",
- " function drop(id) {\n",
- " const view = Bokeh.index.get_by_id(id)\n",
- " if (view != null) {\n",
- " view.model.document.clear()\n",
- " Bokeh.index.delete(view)\n",
- " }\n",
- " }\n",
- "\n",
- " const cell = handle.cell;\n",
- "\n",
- " const id = cell.output_area._bokeh_element_id;\n",
- " const server_id = cell.output_area._bokeh_server_id;\n",
- "\n",
- " // Clean up Bokeh references\n",
- " if (id != null) {\n",
- " drop(id)\n",
- " }\n",
- "\n",
- " if (server_id !== undefined) {\n",
- " // Clean up Bokeh references\n",
- " const cmd_clean = \"from bokeh.io.state import curstate; print(curstate().uuid_to_server['\" + server_id + \"'].get_sessions()[0].document.roots[0]._id)\";\n",
- " cell.notebook.kernel.execute(cmd_clean, {\n",
- " iopub: {\n",
- " output: function(msg) {\n",
- " const id = msg.content.text.trim()\n",
- " drop(id)\n",
- " }\n",
- " }\n",
- " });\n",
- " // Destroy server and session\n",
- " const cmd_destroy = \"import bokeh.io.notebook as ion; ion.destroy_server('\" + server_id + \"')\";\n",
- " cell.notebook.kernel.execute(cmd_destroy);\n",
- " }\n",
- " }\n",
- "\n",
- " /**\n",
- " * Handle when a new output is added\n",
- " */\n",
- " function handleAddOutput(event, handle) {\n",
- " const output_area = handle.output_area;\n",
- " const output = handle.output;\n",
- "\n",
- " // limit handleAddOutput to display_data with EXEC_MIME_TYPE content only\n",
- " if ((output.output_type != \"display_data\") || (!Object.prototype.hasOwnProperty.call(output.data, EXEC_MIME_TYPE))) {\n",
- " return\n",
- " }\n",
- "\n",
- " const toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n",
- "\n",
- " if (output.metadata[EXEC_MIME_TYPE][\"id\"] !== undefined) {\n",
- " toinsert[toinsert.length - 1].firstChild.textContent = output.data[JS_MIME_TYPE];\n",
- " // store reference to embed id on output_area\n",
- " output_area._bokeh_element_id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n",
- " }\n",
- " if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n",
- " const bk_div = document.createElement(\"div\");\n",
- " bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n",
- " const script_attrs = bk_div.children[0].attributes;\n",
- " for (let i = 0; i < script_attrs.length; i++) {\n",
- " toinsert[toinsert.length - 1].firstChild.setAttribute(script_attrs[i].name, script_attrs[i].value);\n",
- " toinsert[toinsert.length - 1].firstChild.textContent = bk_div.children[0].textContent\n",
- " }\n",
- " // store reference to server id on output_area\n",
- " output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n",
- " }\n",
- " }\n",
- "\n",
- " function register_renderer(events, OutputArea) {\n",
- "\n",
- " function append_mime(data, metadata, element) {\n",
- " // create a DOM node to render to\n",
- " const toinsert = this.create_output_subarea(\n",
- " metadata,\n",
- " CLASS_NAME,\n",
- " EXEC_MIME_TYPE\n",
- " );\n",
- " this.keyboard_manager.register_events(toinsert);\n",
- " // Render to node\n",
- " const props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n",
- " render(props, toinsert[toinsert.length - 1]);\n",
- " element.append(toinsert);\n",
- " return toinsert\n",
- " }\n",
- "\n",
- " /* Handle when an output is cleared or removed */\n",
- " events.on('clear_output.CodeCell', handleClearOutput);\n",
- " events.on('delete.Cell', handleClearOutput);\n",
- "\n",
- " /* Handle when a new output is added */\n",
- " events.on('output_added.OutputArea', handleAddOutput);\n",
- "\n",
- " /**\n",
- " * Register the mime type and append_mime function with output_area\n",
- " */\n",
- " OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n",
- " /* Is output safe? */\n",
- " safe: true,\n",
- " /* Index of renderer in `output_area.display_order` */\n",
- " index: 0\n",
- " });\n",
- " }\n",
- "\n",
- " // register the mime type if in Jupyter Notebook environment and previously unregistered\n",
- " if (root.Jupyter !== undefined) {\n",
- " const events = require('base/js/events');\n",
- " const OutputArea = require('notebook/js/outputarea').OutputArea;\n",
- "\n",
- " if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n",
- " register_renderer(events, OutputArea);\n",
- " }\n",
- " }\n",
- " if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n",
- " root._bokeh_timeout = Date.now() + 5000;\n",
- " root._bokeh_failed_load = false;\n",
- " }\n",
- "\n",
- " const NB_LOAD_WARNING = {'data': {'text/html':\n",
- " \"\\n\"+\n",
- " \"
\\n\"+\n",
- " \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n",
- " \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n",
- " \"
\\n\"+\n",
- " \"
\\n\"+\n",
- " \"- re-rerun `output_notebook()` to attempt to load from CDN again, or
\\n\"+\n",
- " \"- use INLINE resources instead, as so:
\\n\"+\n",
- " \"
\\n\"+\n",
- " \"
\\n\"+\n",
- " \"from bokeh.resources import INLINE\\n\"+\n",
- " \"output_notebook(resources=INLINE)\\n\"+\n",
- " \"
\\n\"+\n",
- " \"
\"}};\n",
- "\n",
- " function display_loaded(error = null) {\n",
- " const el = document.getElementById(\"bbf1a771-e47d-48dd-91f1-72c4a20308f1\");\n",
- " if (el != null) {\n",
- " const html = (() => {\n",
- " if (typeof root.Bokeh === \"undefined\") {\n",
- " if (error == null) {\n",
- " return \"BokehJS is loading ...\";\n",
- " } else {\n",
- " return \"BokehJS failed to load.\";\n",
- " }\n",
- " } else {\n",
- " const prefix = `BokehJS ${root.Bokeh.version}`;\n",
- " if (error == null) {\n",
- " return `${prefix} successfully loaded.`;\n",
- " } else {\n",
- " return `${prefix} encountered errors while loading and may not function as expected.`;\n",
- " }\n",
- " }\n",
- " })();\n",
- " el.innerHTML = html;\n",
- "\n",
- " if (error != null) {\n",
- " const wrapper = document.createElement(\"div\");\n",
- " wrapper.style.overflow = \"auto\";\n",
- " wrapper.style.height = \"5em\";\n",
- " wrapper.style.resize = \"vertical\";\n",
- " const content = document.createElement(\"div\");\n",
- " content.style.fontFamily = \"monospace\";\n",
- " content.style.whiteSpace = \"pre-wrap\";\n",
- " content.style.backgroundColor = \"rgb(255, 221, 221)\";\n",
- " content.textContent = error.stack ?? error.toString();\n",
- " wrapper.append(content);\n",
- " el.append(wrapper);\n",
- " }\n",
- " } else if (Date.now() < root._bokeh_timeout) {\n",
- " setTimeout(() => display_loaded(error), 100);\n",
- " }\n",
- " }\n",
- "\n",
- " function run_callbacks() {\n",
- " try {\n",
- " root._bokeh_onload_callbacks.forEach(function(callback) {\n",
- " if (callback != null)\n",
- " callback();\n",
- " });\n",
- " } finally {\n",
- " delete root._bokeh_onload_callbacks\n",
- " }\n",
- " console.debug(\"Bokeh: all callbacks have finished\");\n",
- " }\n",
- "\n",
- " function load_libs(css_urls, js_urls, callback) {\n",
- " if (css_urls == null) css_urls = [];\n",
- " if (js_urls == null) js_urls = [];\n",
- "\n",
- " root._bokeh_onload_callbacks.push(callback);\n",
- " if (root._bokeh_is_loading > 0) {\n",
- " console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n",
- " return null;\n",
- " }\n",
- " if (js_urls == null || js_urls.length === 0) {\n",
- " run_callbacks();\n",
- " return null;\n",
- " }\n",
- " console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n",
- " root._bokeh_is_loading = css_urls.length + js_urls.length;\n",
- "\n",
- " function on_load() {\n",
- " root._bokeh_is_loading--;\n",
- " if (root._bokeh_is_loading === 0) {\n",
- " console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n",
- " run_callbacks()\n",
- " }\n",
- " }\n",
- "\n",
- " function on_error(url) {\n",
- " console.error(\"failed to load \" + url);\n",
- " }\n",
- "\n",
- " for (let i = 0; i < css_urls.length; i++) {\n",
- " const url = css_urls[i];\n",
- " const element = document.createElement(\"link\");\n",
- " element.onload = on_load;\n",
- " element.onerror = on_error.bind(null, url);\n",
- " element.rel = \"stylesheet\";\n",
- " element.type = \"text/css\";\n",
- " element.href = url;\n",
- " console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n",
- " document.body.appendChild(element);\n",
- " }\n",
- "\n",
- " for (let i = 0; i < js_urls.length; i++) {\n",
- " const url = js_urls[i];\n",
- " const element = document.createElement('script');\n",
- " element.onload = on_load;\n",
- " element.onerror = on_error.bind(null, url);\n",
- " element.async = false;\n",
- " element.src = url;\n",
- " console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n",
- " document.head.appendChild(element);\n",
- " }\n",
- " };\n",
- "\n",
- " function inject_raw_css(css) {\n",
- " const element = document.createElement(\"style\");\n",
- " element.appendChild(document.createTextNode(css));\n",
- " document.body.appendChild(element);\n",
- " }\n",
- "\n",
- " const js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-3.4.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-3.4.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.4.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.4.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-3.4.1.min.js\"];\n",
- " const css_urls = [];\n",
- "\n",
- " const inline_js = [ function(Bokeh) {\n",
- " Bokeh.set_log_level(\"info\");\n",
- " },\n",
- "function(Bokeh) {\n",
- " }\n",
- " ];\n",
- "\n",
- " function run_inline_js() {\n",
- " if (root.Bokeh !== undefined || force === true) {\n",
- " try {\n",
- " for (let i = 0; i < inline_js.length; i++) {\n",
- " inline_js[i].call(root, root.Bokeh);\n",
- " }\n",
- "\n",
- " } catch (error) {display_loaded(error);throw error;\n",
- " }if (force === true) {\n",
- " display_loaded();\n",
- " }} else if (Date.now() < root._bokeh_timeout) {\n",
- " setTimeout(run_inline_js, 100);\n",
- " } else if (!root._bokeh_failed_load) {\n",
- " console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n",
- " root._bokeh_failed_load = true;\n",
- " } else if (force !== true) {\n",
- " const cell = $(document.getElementById(\"bbf1a771-e47d-48dd-91f1-72c4a20308f1\")).parents('.cell').data().cell;\n",
- " cell.output_area.append_execute_result(NB_LOAD_WARNING)\n",
- " }\n",
- " }\n",
- "\n",
- " if (root._bokeh_is_loading === 0) {\n",
- " console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n",
- " run_inline_js();\n",
- " } else {\n",
- " load_libs(css_urls, js_urls, function() {\n",
- " console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n",
- " run_inline_js();\n",
- " });\n",
- " }\n",
- "}(window));"
- ],
- "application/vnd.bokehjs_load.v0+json": "'use strict';\n(function(root) {\n function now() {\n return new Date();\n }\n\n const force = true;\n\n if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n root._bokeh_onload_callbacks = [];\n root._bokeh_is_loading = undefined;\n }\n\n\n if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n root._bokeh_timeout = Date.now() + 5000;\n root._bokeh_failed_load = false;\n }\n\n const NB_LOAD_WARNING = {'data': {'text/html':\n \"\\n\"+\n \"
\\n\"+\n \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n \"
\\n\"+\n \"
\\n\"+\n \"- re-rerun `output_notebook()` to attempt to load from CDN again, or
\\n\"+\n \"- use INLINE resources instead, as so:
\\n\"+\n \"
\\n\"+\n \"
\\n\"+\n \"from bokeh.resources import INLINE\\n\"+\n \"output_notebook(resources=INLINE)\\n\"+\n \"
\\n\"+\n \"
\"}};\n\n function display_loaded(error = null) {\n const el = document.getElementById(\"bbf1a771-e47d-48dd-91f1-72c4a20308f1\");\n if (el != null) {\n const html = (() => {\n if (typeof root.Bokeh === \"undefined\") {\n if (error == null) {\n return \"BokehJS is loading ...\";\n } else {\n return \"BokehJS failed to load.\";\n }\n } else {\n const prefix = `BokehJS ${root.Bokeh.version}`;\n if (error == null) {\n return `${prefix} successfully loaded.`;\n } else {\n return `${prefix} encountered errors while loading and may not function as expected.`;\n }\n }\n })();\n el.innerHTML = html;\n\n if (error != null) {\n const wrapper = document.createElement(\"div\");\n wrapper.style.overflow = \"auto\";\n wrapper.style.height = \"5em\";\n wrapper.style.resize = \"vertical\";\n const content = document.createElement(\"div\");\n content.style.fontFamily = \"monospace\";\n content.style.whiteSpace = \"pre-wrap\";\n content.style.backgroundColor = \"rgb(255, 221, 221)\";\n content.textContent = error.stack ?? error.toString();\n wrapper.append(content);\n el.append(wrapper);\n }\n } else if (Date.now() < root._bokeh_timeout) {\n setTimeout(() => display_loaded(error), 100);\n }\n }\n\n function run_callbacks() {\n try {\n root._bokeh_onload_callbacks.forEach(function(callback) {\n if (callback != null)\n callback();\n });\n } finally {\n delete root._bokeh_onload_callbacks\n }\n console.debug(\"Bokeh: all callbacks have finished\");\n }\n\n function load_libs(css_urls, js_urls, callback) {\n if (css_urls == null) css_urls = [];\n if (js_urls == null) js_urls = [];\n\n root._bokeh_onload_callbacks.push(callback);\n if (root._bokeh_is_loading > 0) {\n console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n return null;\n }\n if (js_urls == null || js_urls.length === 0) {\n run_callbacks();\n return null;\n }\n console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n root._bokeh_is_loading = css_urls.length + js_urls.length;\n\n function on_load() {\n root._bokeh_is_loading--;\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n run_callbacks()\n }\n }\n\n function on_error(url) {\n console.error(\"failed to load \" + url);\n }\n\n for (let i = 0; i < css_urls.length; i++) {\n const url = css_urls[i];\n const element = document.createElement(\"link\");\n element.onload = on_load;\n element.onerror = on_error.bind(null, url);\n element.rel = \"stylesheet\";\n element.type = \"text/css\";\n element.href = url;\n console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n document.body.appendChild(element);\n }\n\n for (let i = 0; i < js_urls.length; i++) {\n const url = js_urls[i];\n const element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error.bind(null, url);\n element.async = false;\n element.src = url;\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n };\n\n function inject_raw_css(css) {\n const element = document.createElement(\"style\");\n element.appendChild(document.createTextNode(css));\n document.body.appendChild(element);\n }\n\n const js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-3.4.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-3.4.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.4.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.4.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-3.4.1.min.js\"];\n const css_urls = [];\n\n const inline_js = [ function(Bokeh) {\n Bokeh.set_log_level(\"info\");\n },\nfunction(Bokeh) {\n }\n ];\n\n function run_inline_js() {\n if (root.Bokeh !== undefined || force === true) {\n try {\n for (let i = 0; i < inline_js.length; i++) {\n inline_js[i].call(root, root.Bokeh);\n }\n\n } catch (error) {display_loaded(error);throw error;\n }if (force === true) {\n display_loaded();\n }} else if (Date.now() < root._bokeh_timeout) {\n setTimeout(run_inline_js, 100);\n } else if (!root._bokeh_failed_load) {\n console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n root._bokeh_failed_load = true;\n } else if (force !== true) {\n const cell = $(document.getElementById(\"bbf1a771-e47d-48dd-91f1-72c4a20308f1\")).parents('.cell').data().cell;\n cell.output_area.append_execute_result(NB_LOAD_WARNING)\n }\n }\n\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n run_inline_js();\n } else {\n load_libs(css_urls, js_urls, function() {\n console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n run_inline_js();\n });\n }\n}(window));"
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
+ "outputs": [],
"source": [
"import hdl21 as h\n",
"import gdsfactory as gf\n",
@@ -417,7 +66,7 @@
},
{
"cell_type": "code",
- "execution_count": 2,
+ "execution_count": null,
"id": "5",
"metadata": {},
"outputs": [],
@@ -427,7 +76,7 @@
},
{
"cell_type": "code",
- "execution_count": 3,
+ "execution_count": null,
"id": "6",
"metadata": {},
"outputs": [],
@@ -458,76 +107,10 @@
},
{
"cell_type": "code",
- "execution_count": 4,
+ "execution_count": null,
"id": "8",
"metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "connections:\n",
- " ns,g: ps,g\n",
- " ns,s: ps,d\n",
- " ps,d: ns,s\n",
- " ps,g: ns,g\n",
- "instances:\n",
- " ns:\n",
- " component: sky130_fd_pr__nfet_01v8\n",
- " info: {}\n",
- " settings:\n",
- " As: int((nf+2)/2) * w/nf * 0.29\n",
- " ad: int((nf+1)/2) * w/nf * 0.29\n",
- " l: UNIT_1\n",
- " m: UNIT_1\n",
- " mult: UNIT_1\n",
- " nf: UNIT_1\n",
- " nrd: 0.29 / w\n",
- " nrs: 0.29 / w\n",
- " pd: 2*int((nf+1)/2) * (w/nf + 0.29)\n",
- " ports:\n",
- " b: VSS\n",
- " d: VSS\n",
- " g: i\n",
- " s: o\n",
- " ps: 2*int((nf+2)/2) * (w/nf + 0.29)\n",
- " sa: UNIT_0\n",
- " sb: UNIT_0\n",
- " sd: UNIT_0\n",
- " w: UNIT_1\n",
- " ps:\n",
- " component: sky130_fd_pr__pfet_01v8\n",
- " info: {}\n",
- " settings:\n",
- " As: int((nf+2)/2) * w/nf * 0.29\n",
- " ad: int((nf+1)/2) * w/nf * 0.29\n",
- " l: UNIT_1\n",
- " m: UNIT_1\n",
- " mult: UNIT_1\n",
- " nf: UNIT_1\n",
- " nrd: 0.29 / w\n",
- " nrs: 0.29 / w\n",
- " pd: 2*int((nf+1)/2) * (w/nf + 0.29)\n",
- " ports:\n",
- " b: VDD\n",
- " d: o\n",
- " g: i\n",
- " s: VDD\n",
- " ps: 2*int((nf+2)/2) * (w/nf + 0.29)\n",
- " sa: UNIT_0\n",
- " sb: UNIT_0\n",
- " sd: UNIT_0\n",
- " w: UNIT_1\n",
- "name: SkyInv\n",
- "ports:\n",
- " VDD: ps,s\n",
- " VSS: ns,d\n",
- " i: ps,g\n",
- " o: ps,d\n",
- "\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"example_inverter_manual_yaml = gph.generate_raw_yaml_from_module(\n",
" SkyInv\n",
@@ -537,7 +120,7 @@
},
{
"cell_type": "code",
- "execution_count": 5,
+ "execution_count": null,
"id": "9",
"metadata": {},
"outputs": [],
@@ -618,121 +201,10 @@
},
{
"cell_type": "code",
- "execution_count": 6,
+ "execution_count": null,
"id": "11",
- "metadata": {
- "scrolled": true
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Mapping for sky130_fd_pr__pfet_01v8: sky130_fd_pr__rf_pfet_01v8_mcM04W3p00L0p15\n",
- "\u001b[32m2024-06-02 17:54:34.684\u001b[0m | \u001b[33m\u001b[1mWARNING \u001b[0m | \u001b[36msky130.components\u001b[0m:\u001b[36msky130_fd_pr__rf_pfet_01v8_mcM04W3p00L0p15\u001b[0m:\u001b[36m1318\u001b[0m - \u001b[33m\u001b[1mUserWarning: decorator is deprecated and will be removed soon. import_gds\u001b[0m\n",
- "Mapping for sky130_fd_pr__nfet_01v8: sky130_fd_pr__rf_nfet_01v8_aM02W1p65L0p15\n",
- "\u001b[32m2024-06-02 17:54:34.691\u001b[0m | \u001b[33m\u001b[1mWARNING \u001b[0m | \u001b[36msky130.components\u001b[0m:\u001b[36msky130_fd_pr__rf_nfet_01v8_aM02W1p65L0p15\u001b[0m:\u001b[36m526\u001b[0m - \u001b[33m\u001b[1mUserWarning: decorator is deprecated and will be removed soon. import_gds\u001b[0m\n",
- "\u001b[32m2024-06-02 17:54:34.692\u001b[0m | \u001b[33m\u001b[1mWARNING \u001b[0m | \u001b[36mgdsfactory.read.import_gds\u001b[0m:\u001b[36mimport_gds\u001b[0m:\u001b[36m56\u001b[0m - \u001b[33m\u001b[1mRuntimeWarning: Unsupported record in file.\u001b[0m\n",
- "self.schematic\n",
- "schema=None instances={'ps': Instance(component='sky130_fd_pr__rf_pfet_01v8_mcM04W3p00L0p15', settings={}), 'ns': Instance(component='sky130_fd_pr__rf_nfet_01v8_aM02W1p65L0p15', settings={})} schematic_placements={'ps': Placement(x=None, y=None, port=None, rotation=0, dx=None, dy=None, mirror=None), 'ns': Placement(x=None, y=None, port=None, rotation=0, dx=None, dy=None, mirror=None)} nets=[['ps,DRAIN', 'ns,SOURCE'], ['ps,GATE', 'ns,GATE']] ports={} schema_version=1\n",
- "self.symbols\n",
- "\u001b[32m2024-06-02 17:54:34.708\u001b[0m | \u001b[33m\u001b[1mWARNING \u001b[0m | \u001b[36mgdsfactory.pdk\u001b[0m:\u001b[36mget_symbol\u001b[0m:\u001b[36m438\u001b[0m - \u001b[33m\u001b[1mUserWarning: prefix is deprecated and will be removed soon. floorplan_with_block_letters\u001b[0m\n",
- "{'ps': SYMBOL_floorplan_with_block_letters_eaac2db4: uid f95c32c9, ports ['DRAIN', 'SOURCE', 'BULK', 'GATE', 'GATE1', 'BULK1'], references ['rectangle_1', 'text_1'], 0 polygons, 'ns': SYMBOL_floorplan_with_block_letters_0c1c900e: uid b7de88b3, ports ['DRAIN', 'SOURCE', 'GATE', 'SUBSTRATE', 'GATE1', 'SUBSTRATE1'], references ['rectangle_1', 'text_1'], 0 polygons}\n",
- "self.path\n",
- "data/sky130nm/example_inverter_auto.schem.yaml\n",
- "schema=None instances={'ps': Instance(component='sky130_fd_pr__rf_pfet_01v8_mcM04W3p00L0p15', settings={}), 'ns': Instance(component='sky130_fd_pr__rf_nfet_01v8_aM02W1p65L0p15', settings={})} schematic_placements={'ps': Placement(x=None, y=None, port=None, rotation=0, dx=None, dy=None, mirror=None), 'ns': Placement(x=None, y=None, port=None, rotation=0, dx=None, dy=None, mirror=None)} nets=[['ps,DRAIN', 'ns,SOURCE'], ['ps,GATE', 'ns,GATE']] ports={} schema_version=1\n",
- "\u001b[32m2024-06-02 17:54:34.735\u001b[0m | \u001b[33m\u001b[1mWARNING \u001b[0m | \u001b[36mgdsfactory.read.from_yaml\u001b[0m:\u001b[36mfrom_yaml\u001b[0m:\u001b[36m692\u001b[0m - \u001b[33m\u001b[1mUserWarning: prefix is deprecated and will be removed soon. _from_yaml\u001b[0m\n",
- "layer (2, 0) not found\n",
- "layer (0, 0) not found\n",
- "layer (2, 0) not found\n",
- "layer (0, 0) not found\n",
- "{'ps,DRAIN': array([0.643, 5.02 ]), 'ps,SOURCE': array([0.66 , 2.523]), 'ps,BULK': array([0.245, 3.858]), 'ps,GATE': array([2.305, 1.953]), 'ps,GATE1': array([2.305, 5.658]), 'ps,BULK1': array([4.115, 3.858]), 'ns,DRAIN': array([0.15, 1.78]), 'ns,SOURCE': array([0.15, 0.89]), 'ns,BULK': array([0.245, 3.858]), 'ns,GATE': array([1.31 , 2.435]), 'ns,GATE1': array([1.31 , 0.235]), 'ns,BULK1': array([4.115, 3.858]), 'ns,SUBSTRATE': array([0.32, 0.65]), 'ns,SUBSTRATE1': array([2.29, 0.65])}\n",
- "{'ps,DRAIN': array([0.643, 5.02 ]), 'ps,SOURCE': array([0.66 , 2.523]), 'ps,BULK': array([0.245, 3.858]), 'ps,GATE': array([2.305, 1.953]), 'ps,GATE1': array([2.305, 5.658]), 'ps,BULK1': array([4.115, 3.858]), 'ns,DRAIN': array([0.15, 1.78]), 'ns,SOURCE': array([0.15, 0.89]), 'ns,BULK': array([0.245, 3.858]), 'ns,GATE': array([1.31 , 2.435]), 'ns,GATE1': array([1.31 , 0.235]), 'ns,BULK1': array([4.115, 3.858]), 'ns,SUBSTRATE': array([0.32, 0.65]), 'ns,SUBSTRATE1': array([2.29, 0.65])}\n",
- ".bkapp at 0x7c73918b3eb0>\n"
- ]
- },
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- "[GDSTK] Record type NODE (0x15) is not supported.\n",
- "[GDSTK] Record type NODETYPE (0x2A) is not supported.\n",
- "[GDSTK] Record type NODE (0x15) is not supported.\n",
- "[GDSTK] Record type NODETYPE (0x2A) is not supported.\n",
- "[GDSTK] Record type NODE (0x15) is not supported.\n",
- "[GDSTK] Record type NODETYPE (0x2A) is not supported.\n",
- "[GDSTK] Record type NODE (0x15) is not supported.\n",
- "[GDSTK] Record type NODETYPE (0x2A) is not supported.\n",
- "[GDSTK] Record type NODE (0x15) is not supported.\n",
- "[GDSTK] Record type NODETYPE (0x2A) is not supported.\n",
- "[GDSTK] Record type NODE (0x15) is not supported.\n",
- "[GDSTK] Record type NODETYPE (0x2A) is not supported.\n",
- "[GDSTK] Record type NODE (0x15) is not supported.\n",
- "[GDSTK] Record type NODETYPE (0x2A) is not supported.\n",
- "[GDSTK] Record type NODE (0x15) is not supported.\n",
- "[GDSTK] Record type NODETYPE (0x2A) is not supported.\n",
- "[GDSTK] Record type NODE (0x15) is not supported.\n",
- "[GDSTK] Record type NODETYPE (0x2A) is not supported.\n",
- "[GDSTK] Record type NODE (0x15) is not supported.\n",
- "[GDSTK] Record type NODETYPE (0x2A) is not supported.\n",
- "[GDSTK] Record type NODE (0x15) is not supported.\n",
- "[GDSTK] Record type NODETYPE (0x2A) is not supported.\n",
- "[GDSTK] Record type NODE (0x15) is not supported.\n",
- "[GDSTK] Record type NODETYPE (0x2A) is not supported.\n",
- "[GDSTK] Record type NODE (0x15) is not supported.\n",
- "[GDSTK] Record type NODETYPE (0x2A) is not supported.\n",
- "[GDSTK] Record type NODE (0x15) is not supported.\n",
- "[GDSTK] Record type NODETYPE (0x2A) is not supported.\n",
- "[GDSTK] Record type NODE (0x15) is not supported.\n",
- "[GDSTK] Record type NODETYPE (0x2A) is not supported.\n",
- "[GDSTK] Record type NODE (0x15) is not supported.\n",
- "[GDSTK] Record type NODETYPE (0x2A) is not supported.\n",
- "[GDSTK] Record type NODE (0x15) is not supported.\n",
- "[GDSTK] Record type NODETYPE (0x2A) is not supported.\n",
- "[GDSTK] Record type NODE (0x15) is not supported.\n",
- "[GDSTK] Record type NODETYPE (0x2A) is not supported.\n",
- "[GDSTK] Record type NODE (0x15) is not supported.\n",
- "[GDSTK] Record type NODETYPE (0x2A) is not supported.\n",
- "[GDSTK] Record type NODE (0x15) is not supported.\n",
- "[GDSTK] Record type NODETYPE (0x2A) is not supported.\n",
- "[GDSTK] Record type NODE (0x15) is not supported.\n",
- "[GDSTK] Record type NODETYPE (0x2A) is not supported.\n",
- "[GDSTK] Record type NODE (0x15) is not supported.\n",
- "[GDSTK] Record type NODETYPE (0x2A) is not supported.\n",
- "[GDSTK] Record type NODE (0x15) is not supported.\n",
- "[GDSTK] Record type NODETYPE (0x2A) is not supported.\n",
- "[GDSTK] Record type NODE (0x15) is not supported.\n",
- "[GDSTK] Record type NODETYPE (0x2A) is not supported.\n"
- ]
- },
- {
- "data": {
- "application/vnd.bokehjs_exec.v0+json": "",
- "text/html": [
- ""
- ]
- },
- "metadata": {
- "application/vnd.bokehjs_exec.v0+json": {
- "server_id": "37434868bba14c18bfdaf37f2cfec3ca"
- }
- },
- "output_type": "display_data"
- }
- ],
+ "metadata": {},
+ "outputs": [],
"source": [
"example_inverter_schematic_editor = gph.hdl21_module_to_schematic_editor(\n",
" module=SkyInv,\n",
@@ -743,39 +215,10 @@
},
{
"cell_type": "code",
- "execution_count": 21,
- "id": "fe487030-00cd-403f-a866-4ddc85784761",
+ "execution_count": null,
+ "id": "12",
"metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\u001b[32m2024-06-02 17:58:43.284\u001b[0m | \u001b[33m\u001b[1mWARNING \u001b[0m | \u001b[36mgdsfactory.component\u001b[0m:\u001b[36m_write_library\u001b[0m:\u001b[36m1933\u001b[0m - \u001b[33m\u001b[1mUserWarning: Component Unnamed_8f9aca90 has invalid transformations. Try component.flatten_offgrid_references() first.\u001b[0m\n",
- "\u001b[32m2024-06-02 17:58:43.285\u001b[0m | \u001b[33m\u001b[1mWARNING \u001b[0m | \u001b[36mgdsfactory.component\u001b[0m:\u001b[36mplot_klayout\u001b[0m:\u001b[36m1645\u001b[0m - \u001b[33m\u001b[1mUserWarning: Unnamed cells, 1 in 'Unnamed_8f9aca90'\u001b[0m\n"
- ]
- },
- {
- "data": {
- "text/html": [
- "\n"
- ],
- "text/plain": []
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "image/png": "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",
- "text/plain": [
- "\u001b[1m<\u001b[0m\u001b[1;95mFigure\u001b[0m\u001b[39m size 80\u001b[0m\u001b[1;36m0x600\u001b[0m\u001b[39m with \u001b[0m\u001b[1;36m1\u001b[0m\u001b[39m Axes\u001b[0m\u001b[1m>\u001b[0m"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
+ "outputs": [],
"source": [
"example_inverter_layout = \"data/sky130nm/example_inverter_auto.layout.yaml\"\n",
"example_inverter_schematic_editor.instantiate_layout(example_inverter_layout, default_router=\"get_bundle\", default_cross_section=\"xs_metal1\")\n",
@@ -785,7 +228,7 @@
},
{
"cell_type": "markdown",
- "id": "26",
+ "id": "13",
"metadata": {},
"source": [
"## Setting up the required tools: `xschem`, `volare` and the `sky130nm` PDKs\n",
@@ -804,7 +247,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "27",
+ "id": "14",
"metadata": {},
"outputs": [],
"source": [
@@ -814,7 +257,7 @@
},
{
"cell_type": "markdown",
- "id": "28",
+ "id": "15",
"metadata": {},
"source": [
"Our example files are under the directory of `gplugins/notebooks/data`, let's extract our SPICE declaration:"
@@ -823,7 +266,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "29",
+ "id": "16",
"metadata": {},
"outputs": [],
"source": [
@@ -839,7 +282,7 @@
},
{
"cell_type": "markdown",
- "id": "30",
+ "id": "17",
"metadata": {},
"source": [
"Let's list the files we're going to be reading into:"
@@ -848,7 +291,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "31",
+ "id": "18",
"metadata": {},
"outputs": [],
"source": [
@@ -857,7 +300,7 @@
},
{
"cell_type": "markdown",
- "id": "32",
+ "id": "19",
"metadata": {},
"source": [
"Let's extract our raw spice netlist. An important aspect to understand is that unfortunately, every SPICE tool developed their own file format. So in this sense, netlist parsing function is implemented according to the type of spice toolset that has generated this netlist.\n",
@@ -871,7 +314,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "33",
+ "id": "20",
"metadata": {},
"outputs": [],
"source": [
@@ -882,7 +325,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "34",
+ "id": "21",
"metadata": {},
"outputs": [],
"source": [
@@ -892,7 +335,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "35",
+ "id": "22",
"metadata": {},
"outputs": [],
"source": [
@@ -902,7 +345,7 @@
},
{
"cell_type": "markdown",
- "id": "36",
+ "id": "23",
"metadata": {},
"source": [
"So we can use our `netlist` parsing function to convert this to a compatible netlist for gdsfactory plugins into the extracted elements and the extracted connections:"
@@ -911,7 +354,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "37",
+ "id": "24",
"metadata": {},
"outputs": [],
"source": [
@@ -921,7 +364,7 @@
},
{
"cell_type": "markdown",
- "id": "38",
+ "id": "25",
"metadata": {},
"source": [
"### Automated schematic-driven-layout"
@@ -929,7 +372,7 @@
},
{
"cell_type": "markdown",
- "id": "39",
+ "id": "26",
"metadata": {},
"source": [
"We have now extracted our spice elements and our connectivity. Let's explore what we have there:"
@@ -937,7 +380,7 @@
},
{
"cell_type": "raw",
- "id": "40",
+ "id": "27",
"metadata": {},
"source": [
"# Current TODOs\n",
@@ -949,7 +392,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "41",
+ "id": "28",
"metadata": {},
"outputs": [],
"source": []
@@ -957,7 +400,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "42",
+ "id": "29",
"metadata": {},
"outputs": [],
"source": []