Pierre Guillod
a1bacf9623
* Notebook names and titles were out of date * Add captions to workflow diagrms * Fix READMEs (setup flows) * Fix READMEs extracts in slides (cf. above)
348 lines
11 KiB
Text
348 lines
11 KiB
Text
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "9quLG8jhYqwq"
|
|
},
|
|
"source": [
|
|
"# Fullcustom analog design crashbook\n",
|
|
"\n",
|
|
"The environment path must be retrieved in order to provide _Magic_ with the technology files.\n",
|
|
"\n",
|
|
"**Please check them. If they are wrong, you can hardcode the correct ones. If you don't know, let it as it is and check for strange behaviours afterwards 😉**"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"id": "ghmpRJhL3ac3"
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"import os\n",
|
|
"from pathlib import Path\n",
|
|
"CONDA_DIR = os.environ['CONDA_PREFIX']\n",
|
|
"HOME_DIR = Path.home()\n",
|
|
"FULLCUSTOM_DIR = os.path.abspath(\"\")\n",
|
|
"\n",
|
|
"print(f\"Anaconda environment absolute path = '{CONDA_DIR}'\")\n",
|
|
"print(f\"Home directory absolute path = '{HOME_DIR}'\")\n",
|
|
"print(f\"Fullcustom absolute path = '{FULLCUSTOM_DIR}'\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Source files\n",
|
|
"\n",
|
|
"### Using the _Magic_ VLSI layout tool\n",
|
|
"\n",
|
|
"[_Magic_](http://opencircuitdesign.com/magic/) cells (`.mag`) are used to store and manage the layouts. They can be edited using _Magic_ commands or using _Magic_'s GUI.\n",
|
|
"\n",
|
|
"An existing _inverter_ design as well as its dependencies is imported and converted to _Graphic Design System_ (`.gds`) file for viewing and manufacturing and a _SPICE_ (`.spice`) file for simulation:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"colab": {
|
|
"base_uri": "https://localhost:8080/"
|
|
},
|
|
"id": "hhpUJrMBmlfj",
|
|
"outputId": "bb1109ea-5d45-4a35-e81e-5f0fca3bea9f",
|
|
"scrolled": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"%%script magic -dnull -noconsole -rcfile {CONDA_DIR}/share/pdk/sky130A/libs.tech/magic/sky130A.magicrc\n",
|
|
"\n",
|
|
"load cad/inv/mag/inv.mag\n",
|
|
"\n",
|
|
"extract all\n",
|
|
"ext2spice lvs\n",
|
|
"ext2spice cthresh 0\n",
|
|
"ext2spice rthresh 0\n",
|
|
"ext2spice -o cad/inv/spice/inv.spice\n",
|
|
"\n",
|
|
"gds labels no\n",
|
|
"gds write cad/inv/gds/inv.gds"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Display the inverter layout\n",
|
|
"\n",
|
|
"The `.gds` file can be converted to vector graphics for displaying:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"colab": {
|
|
"base_uri": "https://localhost:8080/",
|
|
"height": 611
|
|
},
|
|
"id": "xjz3IYz55vu2",
|
|
"outputId": "8b2b0d37-abc2-4446-a9b9-8dd4b8d7bfe7"
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"import gdstk\n",
|
|
"import IPython.display\n",
|
|
"\n",
|
|
"library = gdstk.read_gds('cad/inv/gds/inv.gds')\n",
|
|
"top_cells = library.top_level()\n",
|
|
"top_cells[0].write_svg('cad/inv/svg/inv.svg', scaling=100)\n",
|
|
"IPython.display.SVG('cad/inv/svg/inv.svg')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Simulation\n",
|
|
"\n",
|
|
"### Using _SPICE_ simulation engine\n",
|
|
"\n",
|
|
"[_PySPICE_](https://pyspice.fabrice-salvaire.fr/releases/v1.4/overview.html) is a _Python_ interface for several _SPICE_ simulation engines. The _SPICE_ engines are used to simulate analog circuits. A top-level test bench circuit must be built:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"colab": {
|
|
"base_uri": "https://localhost:8080/",
|
|
"height": 927
|
|
},
|
|
"id": "9scIFl1w7Lk6",
|
|
"outputId": "47f12782-4e69-471f-8101-6abfdc041a28"
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"from PySpice.Spice.Netlist import Circuit, SubCircuit, SubCircuitFactory\n",
|
|
"from PySpice.Unit import *\n",
|
|
"\n",
|
|
"# Declare the top-level circuit\n",
|
|
"circuit = Circuit('INV')\n",
|
|
"# Link to technology libraries\n",
|
|
"circuit.lib(f'{CONDA_DIR}/share/pdk/sky130A/libs.tech/ngspice/sky130.lib.spice', 'tt')\n",
|
|
"\n",
|
|
"# Import and instantiate the CUT (Circuit Under Test)\n",
|
|
"circuit.include('cad/inv/spice/inv.spice')\n",
|
|
"circuit.X('INV', 'inv', 'VDD','VSS','A','X');\n",
|
|
"circuit.C('','X','VSS','10f')\n",
|
|
"\n",
|
|
"# Add voltage sources\n",
|
|
"circuit.V('V_SS', 'VSS', 0, 0)\n",
|
|
"circuit.V('V_DD', 'VDD', 'VSS', 1.8)\n",
|
|
"\n",
|
|
"# Add pulse sources\n",
|
|
"circuit.PulseVoltageSource('A', 'A', 0,\n",
|
|
" initial_value=0@u_V, pulsed_value=1.8@u_V,\n",
|
|
" rise_time=10@u_ps, fall_time=10@u_ps,\n",
|
|
" pulse_width=0.35@u_ns, period=0.8@u_ns, delay_time=0.2@u_ns)\n",
|
|
"\n",
|
|
"# Create the simulation and simulate\n",
|
|
"simulator = circuit.simulator()\n",
|
|
"analysis = simulator.transient(step_time=10@u_ps, end_time=1@u_ns)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Plot the waveform\n",
|
|
"\n",
|
|
"The output waveform can be plotted:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"scrolled": false
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"import matplotlib.pyplot as plt\n",
|
|
"import numpy as np\n",
|
|
"fig, ax = plt.subplots(figsize=(8,5))\n",
|
|
"ax.grid(visible=True, which='major', axis='both');\n",
|
|
"ax.grid(visible=True, which='minor', axis='both', linestyle=\"--\");\n",
|
|
"ax.set_yticks(np.linspace(-1.0,2.5,8,endpoint=True));\n",
|
|
"ax.set_yticks(np.linspace(-1.0,2.5,36,endpoint=True),minor=True);\n",
|
|
"ax.set_xticks(np.linspace(0e-12,1e-9,11,endpoint=True));\n",
|
|
"ax.set_xticks(np.linspace(0e-12,1e-9,21,endpoint=True),minor=True);\n",
|
|
"ax.set_title('INV Gate - Transient Simulation')\n",
|
|
"ax.set_xlabel('Time [s]')\n",
|
|
"ax.set_ylabel('Signal [V]')\n",
|
|
"ax.plot(analysis.time,analysis.A)\n",
|
|
"ax.plot(analysis.time,analysis.X)\n",
|
|
"ax.legend(('Input (A)', 'Output (X)'))\n",
|
|
"plt.tight_layout()\n",
|
|
"plt.show()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# To have fun going further...\n",
|
|
"\n",
|
|
"## Graphical editor\n",
|
|
"\n",
|
|
"_Magic_ can be started specifying only one file (`.magicrc`) that sets everything up (layers, macros, DRC rules, etc.)! Both a console and a GUI are started. Some functions are only accessible using the command-line interface or using keybindings."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"!magic -rcfile {CONDA_DIR}/share/pdk/sky130A/libs.tech/magic/sky130A.magicrc"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Schematic editor\n",
|
|
"\n",
|
|
"Of course, the workflow would not be complete without a schematic editor... and an LVS tool. For instance, one can use _Xscheme_:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"!export PDK_ROOT={CONDA_DIR}/share/pdk/; \\\n",
|
|
"xschem --rcfile {CONDA_DIR}/share/pdk/sky130A/libs.tech/xschem/xschemrc"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"The inverter schematic is available under:\n",
|
|
" \n",
|
|
"```\n",
|
|
"fullcustom/cad/inv/sch/inv.sch\n",
|
|
"```\n",
|
|
"\n",
|
|
"Open it with _xschem_ and generate the netlist by:\n",
|
|
"\n",
|
|
" * Selecting _Spice netlist_ in the _Options_ toolbar menu. (This will produce a netlist in a format accepted by the _LVS_ tool.)\n",
|
|
" * Selecting _LVS netlist: Top level is a .subckt_ in the _Simulation_ toolbar menu. (This will encapsulate the circuit in a subcircuit. The _LVS_ tool fails otherwose.)\n",
|
|
" \n",
|
|
"Click on _Netlist_ (top right) to generate the netlist. It is generated by default under the user repository:\n",
|
|
"\n",
|
|
"```\n",
|
|
"~/.xschem/simulations/<circuit>.spice\n",
|
|
"```\n",
|
|
"\n",
|
|
"This location is assumed in the following cells."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Layout Versus Schematic\n",
|
|
"\n",
|
|
"The layout netlists takes into account the parasitics. They are modeled as lumped resistances and capacitances but they are reported on the schematic. They must be therefore removed from the schematic's netlist. Comment out the two following lines of the corresponding cell above:\n",
|
|
"\n",
|
|
"```diff\n",
|
|
"- ext2spice cthresh 0\n",
|
|
"- ext2spice rthresh 0\n",
|
|
"+ #ext2spice cthresh 0\n",
|
|
"+ #ext2spice rthresh 0\n",
|
|
"```\n",
|
|
"\n",
|
|
"Now that both the schematic's and the layout's netlists are written, they can be compare by _netgen_, the LVS tool:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"!netgen lvs \\\n",
|
|
"\"{FULLCUSTOM_DIR}/cad/inv/spice/inv.spice inv\" \\\n",
|
|
"\"{HOME_DIR}/.xschem/simulations/inv.spice inv\" \\\n",
|
|
"\"{CONDA_DIR}/share/pdk/sky130A/libs.tech/netgen/setup.tcl\""
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Some ideas...\n",
|
|
"\n",
|
|
"Here are a couple ideas to spend a good time exploring those beautiful pieces of software:\n",
|
|
"\n",
|
|
" * Characterize an NMOS device or a PMOS device by applying voltage pulses on the different pads.\n",
|
|
" * Start _Magic_ on another PDK and design an inverter.\n",
|
|
" * Vary the devices' geometry and compare the pull-down and pull-up curves.\n",
|
|
" * Copy this notebook to explore the NAND gate cell available in the repository.\n",
|
|
" \n",
|
|
" **Do not hesitate to open the `.mag` files to see how they are built and to adapt from them!**\n",
|
|
" \n",
|
|
" > Good luck and read the docs. 😉\n",
|
|
" \n",
|
|
"## More food for the brain\n",
|
|
"\n",
|
|
" * http://opencircuitdesign.com/\n",
|
|
" * https://skywater-pdk.readthedocs.io"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# References\n",
|
|
"\n",
|
|
"Inspired from:\n",
|
|
"“Silicon Notebooks.” CHIPS Alliance, Apr. 08, 2023. Accessed: Apr. 10, 2023. [Online]. Available: https://github.com/chipsalliance/silicon-notebooks/blob/b65134a43b01ae31423f7ee87110740b2257ac42/analog-inverter-magic.ipynb (Apache License 2.0)"
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"colab": {
|
|
"collapsed_sections": [],
|
|
"include_colab_link": true,
|
|
"name": "analog-inverter-magic.ipynb",
|
|
"provenance": []
|
|
},
|
|
"kernelspec": {
|
|
"display_name": "Python 3 (ipykernel)",
|
|
"language": "python",
|
|
"name": "python3"
|
|
},
|
|
"language_info": {
|
|
"codemirror_mode": {
|
|
"name": "ipython",
|
|
"version": 3
|
|
},
|
|
"file_extension": ".py",
|
|
"mimetype": "text/x-python",
|
|
"name": "python",
|
|
"nbconvert_exporter": "python",
|
|
"pygments_lexer": "ipython3",
|
|
"version": "3.7.12"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 1
|
|
}
|