2023-04-10 10:16:55 +02:00
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "9quLG8jhYqwq"
},
"source": [
2023-04-11 23:22:54 +02:00
"# Fullcustom analog design demo using Magic\n",
"\n",
"The environment path must be retrieved in order to provide _Magic_ with the technology files:"
2023-04-10 10:16:55 +02:00
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "ghmpRJhL3ac3"
},
"outputs": [],
"source": [
"import os\n",
"CONDA_PREFIX = os.environ['CONDA_PREFIX']"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
2023-04-11 23:22:54 +02:00
"## Source files\n",
2023-04-10 10:16:55 +02:00
"\n",
2023-04-11 23:22:54 +02:00
"### 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:"
2023-04-10 10:16:55 +02:00
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "hhpUJrMBmlfj",
2023-04-11 23:22:54 +02:00
"outputId": "bb1109ea-5d45-4a35-e81e-5f0fca3bea9f",
"scrolled": true
2023-04-10 10:16:55 +02:00
},
"outputs": [],
"source": [
"%%script magic -dnull -noconsole -rcfile {CONDA_PREFIX}/share/pdk/sky130A/libs.tech/magic/sky130A.magicrc\n",
"\n",
2023-04-11 23:22:54 +02:00
"load cad/mag/inverter.mag\n",
2023-04-10 10:16:55 +02:00
"\n",
"extract\n",
"ext2spice lvs\n",
"ext2spice cthresh 0\n",
2023-04-11 23:22:54 +02:00
"ext2spice rthresh 0\n",
"ext2spice -o cad/spice/inverter.spice\n",
2023-04-10 10:16:55 +02:00
"\n",
"gds labels no\n",
2023-04-11 23:22:54 +02:00
"gds write cad/gds/inverter.gds"
2023-04-10 10:16:55 +02:00
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
2023-04-11 23:22:54 +02:00
"### Display the inverter layout\n",
2023-04-10 10:16:55 +02:00
"\n",
2023-04-11 23:22:54 +02:00
"The `.gds` file can be converted to vector graphics for displaying:"
2023-04-10 10:16:55 +02:00
]
},
{
"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",
2023-04-11 23:22:54 +02:00
"library = gdstk.read_gds('cad/gds/inverter.gds')\n",
2023-04-10 10:16:55 +02:00
"top_cells = library.top_level()\n",
2023-04-11 23:22:54 +02:00
"top_cells[0].write_svg('cad/svg/inverter.svg', scaling=100)\n",
"IPython.display.SVG('cad/svg/inverter.svg')"
2023-04-10 10:16:55 +02:00
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
2023-04-11 23:22:54 +02:00
"## Simulation\n",
"\n",
"### Using _SPICE_ simulation engine\n",
"\n",
"[_PySPICE_](https://pyspice.fabrice-salvaire.fr/releases/v1.4/overview.html) is a _Python_ implementation of several _SPICE_ simulation engines. The _SPICE_ engines are used to simulate analog circuits. A top-level test bench circuit must be built:"
2023-04-10 10:16:55 +02:00
]
},
{
"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",
2023-04-11 23:22:54 +02:00
"# Declare the top-level circuit\n",
"circuit = Circuit('Inverter')\n",
"# Link to technology libraries\n",
2023-04-10 10:16:55 +02:00
"circuit.lib(f'{CONDA_PREFIX}/share/pdk/sky130A/libs.tech/ngspice/sky130.lib.spice', 'tt')\n",
2023-04-11 23:22:54 +02:00
"\n",
"# Import and instantiate the CUT (Circuit Under Test)\n",
"circuit.include('cad/spice/inverter.spice')\n",
"circuit.X('Inverter', 'inverter', 'VDD','VSS','I','O');\n",
"\n",
"# Add voltage sources\n",
"circuit.V('VSS', 'VSS', 0, 0)\n",
"circuit.V('VDD', 'VDD', 'VSS', 1.8)\n",
"# Add pulse source\n",
"circuit.PulseVoltageSource(\n",
" 'I', 'I', 'VSS',\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=40@u_ps, period=160@u_ps, delay_time=10@u_ps\n",
")\n",
"\n",
"# Create the simulation and simulate\n",
2023-04-10 10:16:55 +02:00
"simulator = circuit.simulator()\n",
2023-04-11 23:22:54 +02:00
"analysis = simulator.transient(step_time=1@u_ps, end_time=160@u_ps)"
2023-04-10 10:16:55 +02:00
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
2023-04-11 23:22:54 +02:00
"### Plot the waveform\n",
"\n",
2023-04-10 10:16:55 +02:00
"The output waveform can be plotted:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": false
},
"outputs": [],
"source": [
2023-04-11 23:22:54 +02:00
"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,160e-12,9,endpoint=True));\n",
"ax.set_xticks(np.linspace(0e-12,160e-12,17,endpoint=True),minor=True);\n",
"ax.set_title('Inverter - Transient Simulation')\n",
"ax.set_xlabel('Time [s]')\n",
"ax.set_ylabel('Signal [V]')\n",
"ax.plot(analysis.time,analysis.I)\n",
"ax.plot(analysis.time,analysis.O)\n",
"ax.legend(('Input (I)', 'Output (O)'))\n",
2023-04-10 10:16:55 +02:00
"plt.tight_layout()\n",
"plt.show()"
]
},
2023-04-11 23:22:54 +02:00
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 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_PREFIX}/share/pdk/sky130A/libs.tech/magic/sky130A.magicrc"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# To have fun going further...\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 another inverter.\n",
" * Vary the devices' geometry; try to make the pull-up and the pull-down waveforms symmetrical.\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. 😉"
]
},
2023-04-10 10:16:55 +02:00
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# References\n",
2023-04-11 23:22:54 +02:00
"\n",
2023-04-10 10:16:55 +02:00
"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
}