├── .gitignore ├── README.md ├── install.sh ├── install_develop.sh ├── librecell-common ├── LICENSE ├── README.md ├── lccommon │ ├── __init__.py │ ├── net_util.py │ └── spice_parser.py └── setup.py ├── librecell-layout ├── .gitignore ├── LICENCE ├── LICENSE ├── README.md ├── examples │ ├── cells.sp │ ├── dummy_tech.py │ ├── gds3xtrude_dummytech.layerstack │ └── run_example.sh ├── lclayout │ ├── __init__.py │ ├── data_types.py │ ├── drc_cleaner │ │ ├── __init__.py │ │ ├── base.py │ │ ├── drc_cleaner.py │ │ ├── drc_theorem_proofs.py │ │ └── standalone.py │ ├── extrema.py │ ├── graphrouter │ │ ├── __init__.py │ │ ├── graphrouter.py │ │ ├── hv_router.py │ │ ├── lp_router.py │ │ ├── min_area_router.py │ │ ├── multi_via_router.py │ │ ├── pathfinder.py │ │ ├── pyo3_graphrouter.py │ │ ├── signal_router.py │ │ └── smt_router.py │ ├── layout │ │ ├── __init__.py │ │ ├── cell_template.py │ │ ├── geometry_helpers.py │ │ ├── grid.py │ │ ├── grid_helpers.py │ │ ├── layers.py │ │ ├── notch_removal.py │ │ └── transistor.py │ ├── lef │ │ ├── __init__.py │ │ └── types.py │ ├── lvs │ │ ├── __init__.py │ │ └── lvs.py │ ├── place │ │ ├── __init__.py │ │ ├── anneal_placer.py │ │ ├── euler_placer.py │ │ ├── eulertours.py │ │ ├── meta_placer.py │ │ ├── partition.py │ │ ├── place.py │ │ └── smt_placer.py │ ├── routing_graph.py │ ├── standalone.py │ ├── tech_util.py │ └── writer │ │ ├── __init__.py │ │ ├── gds_writer.py │ │ ├── lef_writer.py │ │ ├── magic_writer.py │ │ └── writer.py └── setup.py ├── librecell-lib ├── LICENSE ├── README.md ├── examples │ ├── AND2X1.pex.netlist │ ├── INVX1.pex.netlist │ ├── gpdk45nm.m │ ├── invx1_template.lib │ └── run_example.sh ├── lclib │ ├── __init__.py │ ├── characterization │ │ ├── __init__.py │ │ ├── input_capacitance.py │ │ ├── main_lctime.py │ │ ├── main_sp2bool.py │ │ ├── ngspice_simulation.py │ │ ├── ngspice_subprocess.py │ │ ├── piece_wise_linear.py │ │ ├── test_ngspice_shared.py │ │ ├── test_ngspice_subprocess.py │ │ ├── timing_combinatorial.py │ │ ├── timing_sequential.py │ │ └── util.py │ ├── liberty │ │ ├── __init__.py │ │ ├── merge.py │ │ ├── util.py │ │ └── visualize.py │ ├── logic │ │ ├── __init__.py │ │ ├── cmos_sim.py │ │ ├── cmos_synth.py │ │ ├── functional_abstraction.py │ │ ├── graph_enumeration.py │ │ ├── seq_recognition.py │ │ ├── smt_4value_logic_scratch.py │ │ └── util.py │ └── transistor_sizing │ │ ├── __init__.py │ │ └── width_opt.py ├── setup.py └── test_data │ ├── freepdk45 │ ├── gpdk45nm.m │ └── netlists_pex │ │ ├── AND2X1.pex.netlist │ │ ├── AND2X1.pex.netlist.AND2X1.pxi │ │ ├── AND2X2.pex.netlist │ │ ├── AND2X2.pex.netlist.AND2X2.pxi │ │ ├── AOI21X1.pex.netlist │ │ ├── AOI21X1.pex.netlist.AOI21X1.pxi │ │ ├── AOI22X1.pex.netlist │ │ ├── AOI22X1.pex.netlist.AOI22X1.pxi │ │ ├── BUFX2.pex.netlist │ │ ├── BUFX2.pex.netlist.BUFX2.pxi │ │ ├── BUFX4.pex.netlist │ │ ├── BUFX4.pex.netlist.BUFX4.pxi │ │ ├── CLKBUF1.pex.netlist │ │ ├── CLKBUF1.pex.netlist.CLKBUF1.pxi │ │ ├── CLKBUF2.pex.netlist │ │ ├── CLKBUF2.pex.netlist.CLKBUF2.pxi │ │ ├── CLKBUF3.pex.netlist │ │ ├── CLKBUF3.pex.netlist.CLKBUF3.pxi │ │ ├── DFFNEGX1.pex.netlist │ │ ├── DFFNEGX1.pex.netlist.DFFNEGX1.pxi │ │ ├── DFFPOSX1.pex.netlist │ │ ├── DFFPOSX1.pex.netlist.DFFPOSX1.pxi │ │ ├── DFFSR.pex.netlist │ │ ├── DFFSR.pex.netlist.DFFSR.pxi │ │ ├── FAX1.pex.netlist │ │ ├── FAX1.pex.netlist.FAX1.pxi │ │ ├── HAX1.pex.netlist │ │ ├── HAX1.pex.netlist.HAX1.pxi │ │ ├── INVX1.pex.netlist │ │ ├── INVX1.pex.netlist.INVX1.pxi │ │ ├── INVX2.pex.netlist │ │ ├── INVX2.pex.netlist.INVX2.pxi │ │ ├── INVX4.pex.netlist │ │ ├── INVX4.pex.netlist.INVX4.pxi │ │ ├── INVX8.pex.netlist │ │ ├── INVX8.pex.netlist.INVX8.pxi │ │ ├── LATCH.pex.netlist │ │ ├── LATCH.pex.netlist.LATCH.pxi │ │ ├── MUX2X1.pex.netlist │ │ ├── MUX2X1.pex.netlist.MUX2X1.pxi │ │ ├── NAND2X1.pex.netlist │ │ ├── NAND2X1.pex.netlist.NAND2X1.pxi │ │ ├── NAND3X1.pex.netlist │ │ ├── NAND3X1.pex.netlist.NAND3X1.pxi │ │ ├── NOR2X1.pex.netlist │ │ ├── NOR2X1.pex.netlist.NOR2X1.pxi │ │ ├── NOR3X1.pex.netlist │ │ ├── NOR3X1.pex.netlist.NOR3X1.pxi │ │ ├── OAI21X1.pex.netlist │ │ ├── OAI21X1.pex.netlist.OAI21X1.pxi │ │ ├── OAI22X1.pex.netlist │ │ ├── OAI22X1.pex.netlist.OAI22X1.pxi │ │ ├── OR2X1.pex.netlist │ │ ├── OR2X1.pex.netlist.OR2X1.pxi │ │ ├── OR2X2.pex.netlist │ │ ├── OR2X2.pex.netlist.OR2X2.pxi │ │ ├── TBUFX1.pex.netlist │ │ ├── TBUFX1.pex.netlist.TBUFX1.pxi │ │ ├── TBUFX2.pex.netlist │ │ ├── TBUFX2.pex.netlist.TBUFX2.pxi │ │ ├── XNOR2X1.pex.netlist │ │ ├── XNOR2X1.pex.netlist.XNOR2X1.pxi │ │ ├── XOR2X1.pex.netlist │ │ └── XOR2X1.pex.netlist.XOR2X1.pxi │ └── gscl45nm.lib └── librecell-meta ├── README.md └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *_nda.py 3 | */.idea 4 | *.scad 5 | *.gds 6 | *.so 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LibreCell 2 | LibreCell aims to be a toolbox for automated synthesis of CMOS logic cells. 3 | 4 | LibreCell is structured in multiple sub-projects: 5 | * [librecell-layout](librecell-layout): Automated layout generator for CMOS standard cells. 6 | * [librecell-lib](librecell-lib): Characterization kit for CMOS cells and tool for handling liberty files. 7 | * [librecell-common](librecell-common): Code that is used across different LibreCell projects such as a netlist parser. 8 | * [librecell-meta](librecell-meta): Convinience Python package for easier installation. 9 | 10 | The project is in a very early stage and might not yet be ready for productive use. 11 | Project structure and API might change heavily in near future. 12 | 13 | ### Getting started 14 | LibreCell can be installed using the Python package manager `pip` or directly from the git repository. 15 | 16 | #### Dependencies 17 | The following dependencies must be installed manually: 18 | * python3 19 | * ngspice http://ngspice.sourceforge.net/ : SPICE simulator used for cell characterization. 20 | * z3 https://github.com/Z3Prover/z3 : SMT solver. 21 | 22 | Optional dependencies (not required for default configuration): 23 | * GLPK https://www.gnu.org/software/glpk : ILP/MIP solver 24 | 25 | Depending on your linux distribution this packages can be installed using the package manager. 26 | 27 | Example for Arch Linux: 28 | ```sh 29 | sudo pacman -S python ngspice z3 30 | ``` 31 | 32 | #### Installing with pip 33 | 34 | It is recommended to use a Python 'virtual environment' for installing all Python dependencies: 35 | ```sh 36 | # Create a new virtual environment 37 | python3 -m venv my-librecell-env 38 | # Activate the virtual environment 39 | source ./my-librecell-env/bin/activate 40 | 41 | pip3 install librecell 42 | ``` 43 | 44 | #### Installing from git 45 | It is recommended to use a Python 'virtual environment' for installing all Python dependencies: 46 | ```sh 47 | # Create a new virtual environment 48 | python3 -m venv my-librecell-env 49 | # Activate the virtual environment 50 | source ./my-librecell-env/bin/activate 51 | ``` 52 | 53 | Install from git: 54 | ```sh 55 | git clone https://codeberg.org/tok/librecell.git 56 | cd librecell 57 | 58 | # Install librecell-common 59 | cd librecell-common 60 | python3 setup.py develop 61 | cd .. 62 | 63 | # Install lclayout 64 | cd librecell-layout 65 | python3 setup.py develop 66 | cd .. 67 | 68 | # Install lclib 69 | cd librecell-lib 70 | python3 setup.py develop 71 | cd .. 72 | ``` 73 | 74 | Now, check if the command-line scripts are in the current search path: 75 | ```sh 76 | lclayout --help 77 | ``` 78 | If this shows the documentation of the `lclayout` command, then things are fine. Otherwise, the `PATH` environment variable needs to be updated to include `$HOME/.local/bin`. 79 | 80 | ```sh 81 | # Instead of executing this line each time it can be added to ~/.bashrc 82 | export PATH=$PATH:$HOME/.local/bin 83 | ``` 84 | 85 | #### Generate a layout 86 | Generate a layout from a SPICE netlist which includes the transistor sizes. 87 | ```sh 88 | cd librecell-layout 89 | mkdir /tmp/mylibrary 90 | lclayout --output-dir /tmp/mylibrary --tech examples/dummy_tech.py --netlist examples/cells.sp --cell AND2X1 91 | # Use a GDS viewer such as KLayout to inspect the generated layout file `/tmp/mylibrary/*.gds` 92 | ``` 93 | 94 | ### Known issues 95 | 96 | #### Reproducibility 97 | You may want to generate standard cells in a fully reproducable manner. 98 | Right now there is some non-determinism in LibreCell that has not been investigated yet. 99 | The current workaround is to set the `PYTHONHASHSEED` environment variable. 100 | 101 | ```sh 102 | export PYTHONHASHSEED=42 103 | lclayout ... 104 | ``` 105 | 106 | ## Contact 107 | ```python 108 | "codextkramerych".replace("x", "@").replace("y", ".") 109 | ``` 110 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Install library code shared by multiple parts of librecell. 4 | cd librecell-common 5 | python3 setup.py install 6 | cd .. 7 | 8 | # Install lclayout 9 | cd librecell-layout 10 | python3 setup.py install 11 | cd .. 12 | 13 | # Install lclib 14 | cd librecell-lib 15 | python3 setup.py install 16 | cd .. 17 | 18 | #cd librecell-meta 19 | #python3 setup.py install 20 | #cd .. 21 | -------------------------------------------------------------------------------- /install_develop.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Install library code shared by multiple parts of librecell. 4 | cd librecell-common 5 | python3 setup.py develop 6 | cd .. 7 | 8 | # Install lclayout 9 | cd librecell-layout 10 | python3 setup.py develop 11 | cd .. 12 | 13 | # Install lclib 14 | cd librecell-lib 15 | python3 setup.py develop 16 | cd .. 17 | 18 | #cd librecell-meta 19 | #python3 setup.py develop 20 | #cd .. 21 | -------------------------------------------------------------------------------- /librecell-common/README.md: -------------------------------------------------------------------------------- 1 | # LibreCell - Common 2 | This project contains code that is used across different LibreCell projects. -------------------------------------------------------------------------------- /librecell-common/lccommon/__init__.py: -------------------------------------------------------------------------------- 1 | name = "lccommon" -------------------------------------------------------------------------------- /librecell-common/lccommon/spice_parser.py: -------------------------------------------------------------------------------- 1 | ## 2 | ## Copyright (c) 2019 Thomas Kramer. 3 | ## 4 | ## This file is part of librecell-common 5 | ## (see https://codeberg.org/tok/librecell/src/branch/master/librecell-common). 6 | ## 7 | ## This program is free software: you can redistribute it and/or modify 8 | ## it under the terms of the GNU General Public License as published by 9 | ## the Free Software Foundation, either version 3 of the License, or 10 | ## (at your option) any later version. 11 | ## 12 | ## This program is distributed in the hope that it will be useful, 13 | ## but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | ## GNU General Public License for more details. 16 | ## 17 | ## You should have received a copy of the GNU General Public License 18 | ## along with this program. If not, see . 19 | ## 20 | from pyparsing import * 21 | import re 22 | 23 | """ 24 | Simple SPICE parser used to read transistor netlists. 25 | """ 26 | 27 | 28 | class Resistor: 29 | def __init__(self, name, n1, n2, value=0, params={}): 30 | self.name = name 31 | self.n1 = n1 32 | self.n2 = n2 33 | self.value = value 34 | self.params = params 35 | 36 | def __repr__(self): 37 | return "Resistor(%s, %s, %s, %f, params=%s)" % (self.name, self.n1, self.n2, self.value, self.params) 38 | 39 | 40 | class Capacitor: 41 | def __init__(self, name, n1, n2, value=0): 42 | self.name = name 43 | self.n1 = n1 44 | self.n2 = n2 45 | self.value = value 46 | 47 | def __repr__(self): 48 | return "Capacitor(%s, %s, %s, %f)" % (self.name, self.n1, self.n2, self.value) 49 | 50 | 51 | class MOSFET: 52 | def __init__(self, name, nd, ng, ns, nb, model_name, params={}): 53 | self.name = name 54 | self.nd = nd 55 | self.ng = ng 56 | self.ns = ns 57 | self.nb = nb 58 | self.model_name = model_name 59 | self.params = params 60 | 61 | def __repr__(self): 62 | return "MOSFET(%s, %s, %s, %s, %s, %s, params=%s)" % ( 63 | self.name, self.nd, self.ng, self.ns, self.nb, self.model_name, self.params) 64 | 65 | 66 | class Subckt: 67 | def __init__(self, name, ports=[], content=[]): 68 | self.name = name 69 | self.ports = ports 70 | self.content = content 71 | 72 | def __repr__(self): 73 | return "Subckt(%s, %s, %s)" % (self.name, self.ports, self.content) 74 | 75 | 76 | class Include: 77 | def __init__(self, path): 78 | self.path = path 79 | 80 | def __repr__(self): 81 | return ".include '%s'" % self.path 82 | 83 | 84 | def parse_spice(inp): 85 | # Strip away comments but don't change number of lines. 86 | inp = re.sub(r"^\*.*$", "", inp, flags=re.MULTILINE) 87 | 88 | # Concatenate lines 89 | inp = re.sub("\n\+", " ", inp, flags=re.MULTILINE) 90 | 91 | # Don't ignore newline. 92 | ParserElement.setDefaultWhitespaceChars(' \t') 93 | 94 | # Elementary tokens 95 | beginl = (Word('\n') * (0, None)).suppress() 96 | endl = (LineEnd() * (1, None)).suppress() 97 | 98 | def parse_float(t): 99 | scale = 1 100 | if len(t) > 1: 101 | suffix = t[1] 102 | units = { 103 | 'a': 1e-18, 104 | 'f': 1e-15, 105 | 'p': 1e-12, 106 | 'n': 1e-9, 107 | 'u': 1e-6, 108 | 'U': 1e-6, 109 | 'm': 1e-3, 110 | 'k': 1e3, 111 | 'M': 1e6, 112 | 'G': 1e9, 113 | 'T': 1e12 114 | } 115 | 116 | scale = units.get(suffix, 1) 117 | 118 | return float(t[0]) * scale 119 | 120 | # number = -123.123e-123 121 | number = (Combine( 122 | Optional('-') + Word(nums) + Optional('.' + Word(nums)) + Optional(Word('eE') + Optional('-') + Word(nums))) 123 | + Optional(Word(alphas)).leaveWhitespace() 124 | ).setParseAction(lambda t: parse_float(t)).setName('float') 125 | 126 | name = Word(alphanums + '_' + '#') 127 | net = name.setName('net') 128 | path = CharsNotIn('\n') 129 | 130 | # .end 131 | end = (beginl + '.end' + Optional('s') + Optional(name)).suppress() 132 | 133 | # Parameter list 134 | param = (name + Suppress('=') + number).setParseAction(lambda t: (t[0].upper(), t[1])) 135 | parameter_list = (param * (1, None)).setParseAction(lambda t: dict(list(t))) 136 | 137 | # Components 138 | resistor = ( 139 | Combine(Word('rR') + name) + net + net + Optional(number) + Optional(parameter_list) 140 | ).setParseAction(lambda s, l, t: Resistor(*t)) 141 | 142 | capacitor = ( 143 | Combine(Word('cC') + name) + net + net + Optional(number) + Optional(parameter_list) 144 | ).setParseAction(lambda t: Capacitor(*t)) 145 | 146 | mosfet = ( 147 | Combine(Word('mM') + name) + net + net + net + net + Optional(name) + Optional(parameter_list) 148 | ).setParseAction(lambda t: MOSFET(*t)) 149 | 150 | # Component 151 | component = (resistor | capacitor | mosfet) + endl 152 | 153 | # Include 154 | include = (Suppress('.include') + path + endl).setParseAction(lambda t: Include(*t)) 155 | 156 | # subckt start 157 | subcircuit_def = ( 158 | beginl + 159 | Suppress('.subckt') + 160 | name + 161 | (net * (0, None)).setParseAction(lambda t: [t]) + 162 | endl 163 | ) 164 | 165 | # subckt body 166 | subcircuit = Forward() 167 | subcircuit << subcircuit_def + ((component | subcircuit | include) * (0, None)).setParseAction( 168 | lambda t: [t]) + end + endl 169 | subcircuit.setParseAction(lambda t: Subckt(*t)) 170 | 171 | netlist = ((subcircuit | include) * (0, None)) 172 | 173 | parsed = netlist.parseString(inp, parseAll=True) 174 | 175 | return parsed 176 | 177 | 178 | def test_spice_parser(): 179 | inp = """ 180 | * 181 | * 182 | .subckt testCircuit in1 in2 out1 183 | * 184 | R1 gnd vdd 4.7 T=270K 185 | R2 gnd vdd 6.3e3 186 | C1 gnd vdd 0.47 187 | * Comment 188 | M1 gnd in1 vdd gnd nmos T=300K 189 | .end 190 | .include blabla 191 | .subckt empty 192 | .end 193 | 194 | .subckt inv1 in out vcc gnd 195 | MN1 out in gnd gnd NMOS L=0.35U W=2.0U 196 | MP2 out in vcc vcc PMOS L=0.35U W=4.0U 197 | .end 198 | 199 | .subckt container 200 | R1 gnd vdd 4.7 201 | .subckt child a b c 202 | R1 gnd vdd 4.7 203 | .end 204 | .end 205 | 206 | .subckt testCircuit2 in1 in2 out1 207 | R1 gnd vdd 4.7 208 | R2 gnd vdd 6.3 209 | 210 | C1 gnd vdd 0.47 211 | C2 gnd vdd 0.47555 212 | .end""" 213 | 214 | parsed = parse_spice(inp) 215 | 216 | print(parsed) 217 | -------------------------------------------------------------------------------- /librecell-common/setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup, find_packages 2 | 3 | 4 | def readme(): 5 | with open("README.md", "r") as f: 6 | return f.read() 7 | 8 | 9 | setup(name='librecell-common', 10 | version='0.0.9', 11 | description='Common utility functions for LibreCell suite.', 12 | long_description=readme(), 13 | long_description_content_type="text/markdown", 14 | keywords='cmos cell vlsi asic', 15 | classifiers=[ 16 | 'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)', 17 | 'Development Status :: 3 - Alpha', 18 | 'Topic :: Scientific/Engineering', 19 | 'Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)', 20 | 'Programming Language :: Python :: 3' 21 | ], 22 | url='https://codeberg.org/tok/librecell', 23 | author='T. Kramer', 24 | author_email='code@tkramer.ch', 25 | license='GPLv3', 26 | packages=find_packages(), 27 | install_requires=[ 28 | 'networkx==2.5', # BSD 29 | ], 30 | zip_safe=False) 31 | -------------------------------------------------------------------------------- /librecell-layout/.gitignore: -------------------------------------------------------------------------------- 1 | *.egg-info 2 | *.pyc 3 | -------------------------------------------------------------------------------- /librecell-layout/LICENSE: -------------------------------------------------------------------------------- 1 | This is a placeholder for the CERN Open Hardware License (OHL-S) version 2.0 or later 2 | as it will be published by CERN. 3 | The license text will be published at . 4 | -------------------------------------------------------------------------------- /librecell-layout/README.md: -------------------------------------------------------------------------------- 1 | # LibreCell - Layout 2 | CMOS Standard Cell layout generator. 3 | 4 | ## Getting started 5 | 6 | See install instructions in top-project. 7 | 8 | ### Generate a layout 9 | Generate a layout from a SPICE netlist which includes the transistor sizes: 10 | * --output-dir: Directory which will be used to store GDS and LEF of the cell 11 | * --tech: Python script file containing design rules and technology related data 12 | * --netlist: A SPICE netlist containing the netlist of the cell as a sub circuit (`.subckt`). 13 | * --cell: Name of the cell. Must match the name of the sub circuit in the SPICE netlist. 14 | 15 | ```sh 16 | mkdir mylibrary 17 | lclayout --output-dir mylibrary --tech examples/dummy_tech.py --netlist examples/cells.sp --cell AND2X1 18 | ``` 19 | 20 | ## Adapting design rules 21 | Design rulesi and technology related data need to be encoded in a Python script file as shown in `examples/dummy_tech.py`. 22 | -------------------------------------------------------------------------------- /librecell-layout/examples/gds3xtrude_dummytech.layerstack: -------------------------------------------------------------------------------- 1 | from gds3xtrude.include import layer, Material 2 | 3 | # GDS2 layer numbers. 4 | 5 | ndiffusion = layer(1, 0) 6 | pdiffusion = layer(1, 7) 7 | nwell = layer(2, 0) 8 | nwell2 = layer(2, 1) 9 | pwell = layer(2, 7) 10 | poly = layer(3, 0) 11 | poly_contact = layer(4, 0) 12 | pdiff_contact = layer(5, 0) 13 | ndiff_contact = layer(5, 1) 14 | metal1 = layer(6, 0) 15 | metal1_label = layer(6, 1) 16 | metal1_pin = layer(6, 2) 17 | via1 = layer(7, 0) 18 | metal2 = layer(8, 0) 19 | metal2_label = layer(8, 1) 20 | metal2_pin = layer(8, 2) 21 | abutment_box = layer(200, 0) 22 | 23 | diff_contact = ndiff_contact + pdiff_contact 24 | 25 | # Define materials 26 | m_poly = Material("poly", color=(0.7, 0, 0)) 27 | m_via = Material("tungsten", color=(0.1, 0.1, 0.1)) 28 | m_metal1 = Material("copper1", color=(0.3, 0.3, 1)) 29 | m_metal2 = Material("copper2", color=(0.3, 1, 0.3)) 30 | 31 | # Set materials/colors 32 | poly.material = m_poly 33 | poly_contact.material = m_via 34 | diff_contact.material = m_via 35 | metal1.material = m_metal1 36 | via1.material = m_via 37 | metal2.material = m_metal2 38 | 39 | layerstack = [ 40 | # (1, abutment_box), 41 | (100, ndiffusion + pdiffusion), 42 | (20, diff_contact), 43 | (20, [diff_contact, poly]), 44 | (200, [poly_contact, diff_contact]), 45 | (50, metal1), 46 | (200, via1), 47 | (50, metal2), 48 | ] 49 | -------------------------------------------------------------------------------- /librecell-layout/examples/run_example.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | mkdir mylibrary 4 | # Generate the layout of an AND2X1 cell. 5 | lclayout --output-dir mylibrary --tech dummy_tech.py --netlist cells.sp --cell AND2X1 --verbose 6 | -------------------------------------------------------------------------------- /librecell-layout/lclayout/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2019-2020 Thomas Kramer. 3 | # 4 | # This source describes Open Hardware and is licensed under the CERN-OHL-S v2. 5 | # 6 | # You may redistribute and modify this documentation and make products using it 7 | # under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl). 8 | # This documentation is distributed WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, 9 | # INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A PARTICULAR PURPOSE. 10 | # Please see the CERN-OHL-S v2 for applicable conditions. 11 | # 12 | # Source location: https://codeberg.org/tok/librecell 13 | # 14 | -------------------------------------------------------------------------------- /librecell-layout/lclayout/data_types.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2019-2020 Thomas Kramer. 3 | # 4 | # This source describes Open Hardware and is licensed under the CERN-OHL-S v2. 5 | # 6 | # You may redistribute and modify this documentation and make products using it 7 | # under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl). 8 | # This documentation is distributed WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, 9 | # INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A PARTICULAR PURPOSE. 10 | # Please see the CERN-OHL-S v2 for applicable conditions. 11 | # 12 | # Source location: https://codeberg.org/tok/librecell 13 | # 14 | from enum import Enum 15 | 16 | from itertools import islice, tee, chain, product 17 | from copy import deepcopy 18 | from typing import Any, Set, Tuple 19 | 20 | 21 | class ChannelType(Enum): 22 | NMOS = 1, 23 | PMOS = 2 24 | 25 | 26 | class Transistor: 27 | """ 28 | Abstract representation of a MOS transistor. 29 | """ 30 | 31 | def __init__(self, channel_type: ChannelType, 32 | source_net: str, gate_net: str, drain_net: str, 33 | channel_width=None, 34 | name: str = 'M?', 35 | allow_flip_source_drain: bool = True 36 | ): 37 | """ 38 | params: 39 | left: Either source or drain net. 40 | right: Either source or drain net. 41 | """ 42 | self.name = name 43 | self.channel_type = channel_type 44 | self.source_net = source_net 45 | self.gate_net = gate_net 46 | self.drain_net = drain_net 47 | 48 | self.channel_width = channel_width 49 | 50 | self.allow_flip_source_drain = allow_flip_source_drain 51 | 52 | # TODO 53 | self.threshold_voltage = None 54 | 55 | def flipped(self): 56 | """ Return the same transistor but with left/right terminals flipped. 57 | """ 58 | 59 | assert self.allow_flip_source_drain, "Flipping source and drain is not allowed." 60 | 61 | f = deepcopy(self) 62 | f.source_net = self.drain_net 63 | f.drain_net = self.source_net 64 | 65 | return f 66 | 67 | def terminals(self) -> Tuple[Any, Any, Any]: 68 | """ Return a tuple of all terminal names. 69 | :return: 70 | """ 71 | return self.source_net, self.gate_net, self.drain_net 72 | 73 | def __key(self): 74 | return self.name, self.channel_type, self.source_net, self.gate_net, self.drain_net, self.channel_width, self.threshold_voltage 75 | 76 | def __hash__(self): 77 | return hash(self.__key()) 78 | 79 | def __eq__(x, y): 80 | return x.__key() == y.__key() 81 | 82 | def __repr__(self): 83 | return "({}, {}, {})".format(self.source_net, self.gate_net, self.drain_net) 84 | 85 | 86 | class Cell: 87 | """ Dual row cell. 88 | """ 89 | 90 | def __init__(self, width: int): 91 | self.width = width 92 | self.upper = [None] * width 93 | self.lower = [None] * width 94 | 95 | def get_transistor_locations(self) -> Set[Tuple[Transistor, Tuple[int, int]]]: 96 | """ Get a list of all transistors together with their location. 97 | Transistor locations are given on a grid like: 98 | 99 | | (0,1) | (1,1) | ... 100 | | (0,0) | (1,0) | ... 101 | 102 | Returns 103 | ------- 104 | 105 | Returns a set of (transistor, (x,y)). 106 | """ 107 | 108 | assert len(self.lower) == len(self.upper) 109 | 110 | t = [self.lower, self.upper] 111 | idx = product(range(self.width), range(2)) 112 | 113 | return set((t[y][x], (x, y)) for x, y in idx if t[y][x] is not None) 114 | 115 | def __repr__(self): 116 | """ Pretty-print 117 | """ 118 | 119 | return ( 120 | " | ".join(['{:^16}'.format(str(t)) for t in self.upper]) + 121 | "\n" + 122 | " | ".join(['{:^16}'.format(str(t)) for t in self.lower]) 123 | ) 124 | -------------------------------------------------------------------------------- /librecell-layout/lclayout/drc_cleaner/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2019-2020 Thomas Kramer. 3 | # 4 | # This source describes Open Hardware and is licensed under the CERN-OHL-S v2. 5 | # 6 | # You may redistribute and modify this documentation and make products using it 7 | # under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl). 8 | # This documentation is distributed WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, 9 | # INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A PARTICULAR PURPOSE. 10 | # Please see the CERN-OHL-S v2 for applicable conditions. 11 | # 12 | # Source location: https://codeberg.org/tok/librecell 13 | # 14 | -------------------------------------------------------------------------------- /librecell-layout/lclayout/drc_cleaner/drc_theorem_proofs.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2019-2020 Thomas Kramer. 3 | # 4 | # This source describes Open Hardware and is licensed under the CERN-OHL-S v2. 5 | # 6 | # You may redistribute and modify this documentation and make products using it 7 | # under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl). 8 | # This documentation is distributed WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, 9 | # INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A PARTICULAR PURPOSE. 10 | # Please see the CERN-OHL-S v2 for applicable conditions. 11 | # 12 | # Source location: https://codeberg.org/tok/librecell 13 | # 14 | from pysmt.shortcuts import * 15 | import re 16 | 17 | from pysmt.environment import get_env 18 | 19 | """ 20 | Collection of theorem proofs. 21 | Just a scratch pad. This code is not directly used in lclayout. 22 | """ 23 | 24 | 25 | def proof(f): 26 | return is_valid(f) 27 | 28 | 29 | def is_valid(f): 30 | """ Proof the validity of a formula. 31 | """ 32 | s = Solver() 33 | s.add_assertion(Not(f)) 34 | 35 | has_counter_example = s.check_sat() 36 | 37 | if has_counter_example: 38 | m = s.get_model() 39 | print(m) 40 | 41 | return not has_counter_example 42 | 43 | 44 | def is_equal(f1, f2): 45 | return proof( 46 | Iff(f1, f2) 47 | ) 48 | 49 | 50 | def symbols(names, dtype): 51 | return [Symbol(n, dtype) for n in re.split(',\s*|\s+', names)] 52 | 53 | 54 | def _init_env(): 55 | """ 56 | Initialize pySMT environment at beginning of each test. 57 | """ 58 | pysmt.shortcuts.reset_env() 59 | get_env().enable_infix_notation = True 60 | 61 | 62 | def test_proof_de_morgan(): 63 | """ Proof de Morgans law. 64 | """ 65 | _init_env() 66 | b1, b2 = symbols('b1, b2', BOOL) 67 | 68 | f = b1 & b2 69 | demorgan = Not(b1) | Not(b2) 70 | 71 | theorem = Iff(Not(f), demorgan) 72 | 73 | assert proof(theorem) 74 | 75 | 76 | def test_proof_interval_overlap_formula(): 77 | """ Proof interval overlap formula. 78 | Proof that f2 checks if two intervals overlap given a1<=a2, b1<=b2. 79 | a1 a2 80 | |-----------------| 81 | b1 b2 82 | |----------| 83 | """ 84 | _init_env() 85 | 86 | a1, a2, b1, b2 = symbols('a1, a2, b1, b2', INT) 87 | 88 | # To proove: This should be sufficient to detect if intervals overlap given a1<=a2, b1<=b2. 89 | f2 = Or( 90 | (a1 <= b1) & (b1 <= a2), 91 | (b1 <= a1) & (a1 <= b2), 92 | ) 93 | 94 | """ 95 | f3 = Or( 96 | (a1 <= b1) & (b1 <= a2), 97 | (a1 <= b2) & (b2 <= a2), 98 | (b1 <= a1) & (a1 <= b2) 99 | ) 100 | 101 | f4 = Or( 102 | (a1 <= b1) & (b1 <= a2), 103 | (a1 <= b2) & (b2 <= a2), 104 | (b1 <= a1) & (a1 <= b2), 105 | (b1 <= a2) & (a2 <= b2), 106 | ) 107 | """ 108 | 109 | # Reference. 110 | # Check for strict ordering of a and b. 111 | # The intervals don't overlap iff a* < b* OR b* < a* 112 | no_overlap = Or( 113 | (a1 < b1) & (a1 < b2) & (a2 < b1) & (a2 < b2), 114 | (b1 < a1) & (b1 < a2) & (b2 < a1) & (b2 < a2), 115 | ) 116 | has_overlap = Not(no_overlap) 117 | 118 | # Assume edges are oriented in positive direction. 119 | assume_edge_direction = (a1 <= a2) & (b1 <= b2) 120 | 121 | # assume_edge_direction => (f2 <-> has_overlap) 122 | theorem = assume_edge_direction.Implies(Iff(f2, has_overlap)) 123 | 124 | assert proof(theorem) 125 | -------------------------------------------------------------------------------- /librecell-layout/lclayout/drc_cleaner/standalone.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2019-2020 Thomas Kramer. 3 | # 4 | # This source describes Open Hardware and is licensed under the CERN-OHL-S v2. 5 | # 6 | # You may redistribute and modify this documentation and make products using it 7 | # under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl). 8 | # This documentation is distributed WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, 9 | # INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A PARTICULAR PURPOSE. 10 | # Please see the CERN-OHL-S v2 for applicable conditions. 11 | # 12 | # Source location: https://codeberg.org/tok/librecell 13 | # 14 | import klayout.db as pya 15 | 16 | import argparse 17 | import logging 18 | 19 | from .. import tech_util 20 | 21 | from .drc_cleaner import clean 22 | 23 | logger = logging.getLogger(__name__) 24 | 25 | 26 | def main(): 27 | parser = argparse.ArgumentParser(description='DRC cleaning.') 28 | parser.add_argument('-i', '--input', required=True, metavar='GDS', type=str, help='GDS input file') 29 | parser.add_argument('-o', '--output', required=True, metavar='GDS', type=str, help='GDS output file') 30 | parser.add_argument('--debug', action='store_true', help='Enable debug mode.') 31 | parser.add_argument('--tech', required=True, metavar='FILE', type=str, help='technology file') 32 | parser.add_argument('--solver', default='z3', metavar='SOLVER', type=str, help='SMT solver name') 33 | parser.add_argument('--optimize', default=False, action='store_true', help='Enable area optimizations') 34 | 35 | # Parse arguments 36 | args = parser.parse_args() 37 | 38 | DEBUG = args.debug 39 | 40 | log_level = logging.DEBUG if DEBUG else logging.INFO 41 | 42 | logging.basicConfig(format='%(module)16s %(levelname)8s: %(message)s', level=log_level) 43 | 44 | layout = pya.Layout() 45 | logger.info("Reading GDS: %s", args.input) 46 | layout.read(args.input) 47 | top = layout.top_cell() 48 | 49 | tech = tech_util.load_tech_file(args.tech) 50 | 51 | # Fetch layers and create `shapes` object. 52 | # shapes: Dict[layer name, pya.Shapes] 53 | shapes = {} 54 | for name, (num, purpose) in tech.layermap.items(): 55 | layer = layout.find_layer(num, purpose) 56 | # assert layer is not None, Exception('Layer not found: %s (%d, %d)' % (name, num, purpose)) 57 | if layer is not None: 58 | shapes[name] = top.shapes(layer) 59 | 60 | logger.debug("shapes = %s", shapes) 61 | 62 | # Select all shapes that are completely inside `outline` on whitelisted layers 63 | # to be modified. (For instance excludes power rails from being modified.) 64 | white_list = set() 65 | outline = pya.Region(shapes['outline']) 66 | for layer in ['m1', 'm2', 'v1']: 67 | r = pya.Region(shapes[layer]) 68 | inside = r.inside(outline) 69 | for shape in inside.each(): 70 | white_list.add((layer, shape)) 71 | 72 | drc_clean_success = clean(tech, 73 | shapes, 74 | white_list=white_list, 75 | debug=DEBUG, 76 | solver_name=args.solver, 77 | optimize=args.optimize) 78 | 79 | if drc_clean_success: 80 | # Store result 81 | logger.info('Write GDS: %s', args.output) 82 | layout.write(args.output) 83 | else: 84 | logger.error("Could not clean design. GDS left unmodified.") 85 | -------------------------------------------------------------------------------- /librecell-layout/lclayout/extrema.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2019-2020 Thomas Kramer. 3 | # 4 | # This source describes Open Hardware and is licensed under the CERN-OHL-S v2. 5 | # 6 | # You may redistribute and modify this documentation and make products using it 7 | # under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl). 8 | # This documentation is distributed WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, 9 | # INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A PARTICULAR PURPOSE. 10 | # Please see the CERN-OHL-S v2 for applicable conditions. 11 | # 12 | # Source location: https://codeberg.org/tok/librecell 13 | # 14 | """ 15 | Helper functions for finding minima and maxima. 16 | """ 17 | 18 | from typing import Iterable, List 19 | 20 | 21 | def all_max(args: Iterable, key = None) -> List: 22 | """ Find all global maxima in `args`. 23 | :param args: 24 | :param key: Key function. 25 | :return: List of maxima. 26 | """ 27 | 28 | if key is None: 29 | def key(x): 30 | return x 31 | 32 | maxima = [] 33 | max_key = None 34 | 35 | for x in args: 36 | val = key(x) 37 | if max_key is None or val > max_key: 38 | maxima.clear() 39 | max_key = val 40 | if val == max_key: 41 | maxima.append(x) 42 | 43 | return maxima 44 | 45 | 46 | def all_min(args: Iterable, key = None) -> List: 47 | """ Find all global minima in `args`. 48 | :param args: 49 | :param key: Key function. 50 | :return: List of minima. 51 | """ 52 | 53 | if key is None: 54 | def key(x): 55 | return x 56 | 57 | minima = [] 58 | min_key = None 59 | 60 | for x in args: 61 | val = key(x) 62 | if min_key is None or val < min_key: 63 | minima.clear() 64 | min_key = val 65 | if val == min_key: 66 | minima.append(x) 67 | 68 | return minima 69 | -------------------------------------------------------------------------------- /librecell-layout/lclayout/graphrouter/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2019-2020 Thomas Kramer. 3 | # 4 | # This source describes Open Hardware and is licensed under the CERN-OHL-S v2. 5 | # 6 | # You may redistribute and modify this documentation and make products using it 7 | # under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl). 8 | # This documentation is distributed WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, 9 | # INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A PARTICULAR PURPOSE. 10 | # Please see the CERN-OHL-S v2 for applicable conditions. 11 | # 12 | # Source location: https://codeberg.org/tok/librecell 13 | # 14 | -------------------------------------------------------------------------------- /librecell-layout/lclayout/graphrouter/graphrouter.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2019-2020 Thomas Kramer. 3 | # 4 | # This source describes Open Hardware and is licensed under the CERN-OHL-S v2. 5 | # 6 | # You may redistribute and modify this documentation and make products using it 7 | # under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl). 8 | # This documentation is distributed WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, 9 | # INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A PARTICULAR PURPOSE. 10 | # Please see the CERN-OHL-S v2 for applicable conditions. 11 | # 12 | # Source location: https://codeberg.org/tok/librecell 13 | # 14 | import networkx as nx 15 | 16 | from typing import Any, Dict, List, AbstractSet, Optional 17 | 18 | 19 | class GraphRouter: 20 | 21 | def route(self, 22 | graph: nx.Graph, 23 | signals: Dict[Any, List[Any]], 24 | reserved_nodes: Optional[Dict[Any, AbstractSet[Any]]] = None, 25 | node_conflict: Optional[Dict[Any, AbstractSet[Any]]] = None, 26 | equivalent_nodes: Optional[Dict[Any, AbstractSet[Any]]] = None, 27 | is_virtual_node_fn=None 28 | ) -> Dict[Any, nx.Graph]: 29 | """ 30 | 31 | :param graph: Routing graph. 32 | :param signals: Mapping of signal names to terminal nodes in the graph. 33 | :param reserved_nodes: Mapping of signal names to graph nodes that are reserved for this signal. 34 | :param node_conflict: Mapping of a node to other nodes that can not be used for routing at the same time. 35 | :param equivalent_nodes: For each node a set of nodes that are physically equivalent. 36 | :param is_virtual_node_fn: Function that returns True iff the argument is a virtual node. 37 | :return: Returns a dict mapping signal names to routing trees. 38 | """ 39 | pass 40 | -------------------------------------------------------------------------------- /librecell-layout/lclayout/graphrouter/min_area_router.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2019-2020 Thomas Kramer. 3 | # 4 | # This source describes Open Hardware and is licensed under the CERN-OHL-S v2. 5 | # 6 | # You may redistribute and modify this documentation and make products using it 7 | # under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl). 8 | # This documentation is distributed WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, 9 | # INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A PARTICULAR PURPOSE. 10 | # Please see the CERN-OHL-S v2 for applicable conditions. 11 | # 12 | # Source location: https://codeberg.org/tok/librecell 13 | # 14 | from .signal_router import SignalRouter 15 | import networkx as nx 16 | from typing import Any, Dict, Set, List 17 | from itertools import product 18 | 19 | 20 | class MinAreaRouter(SignalRouter): 21 | """ Wrap a detail router function such that it respects minimum area constraints. 22 | 23 | Parameters 24 | ---------- 25 | 26 | router: Underlying detail router 27 | node_conflict: Dict[Node, Set[Node]] 28 | A mapping from a node `n` to a set of nodes that collide with `n`. 29 | """ 30 | 31 | def __init__(self, router: SignalRouter, node_conflict: Dict[Any, Set], min_area: Dict[Any, float]): 32 | self.router = router 33 | self.node_conflict = node_conflict 34 | self.min_area = min_area 35 | 36 | def route(self, G: nx.Graph, 37 | terminals: List[List[Any]], 38 | node_cost_fn, 39 | edge_cost_fn 40 | ) -> nx.Graph: 41 | return self._min_area_route(self.router, 42 | G, 43 | terminals, 44 | self.node_conflict, 45 | node_cost_fn, 46 | edge_cost_fn) 47 | 48 | def _min_area_route(self, router: SignalRouter, G: nx.Graph, terminals, node_conflict: Dict, node_cost_fn, 49 | edge_cost_fn): 50 | S1 = router.route(G, terminals, node_cost_fn, edge_cost_fn) 51 | 52 | nodes = list(S1.nodes) 53 | 54 | # Get layers for which min_area is defined. 55 | min_area_layers = set(self.min_area.keys()) 56 | 57 | return S1 58 | 59 | 60 | -------------------------------------------------------------------------------- /librecell-layout/lclayout/graphrouter/multi_via_router.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2019-2020 Thomas Kramer. 3 | # 4 | # This source describes Open Hardware and is licensed under the CERN-OHL-S v2. 5 | # 6 | # You may redistribute and modify this documentation and make products using it 7 | # under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl). 8 | # This documentation is distributed WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, 9 | # INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A PARTICULAR PURPOSE. 10 | # Please see the CERN-OHL-S v2 for applicable conditions. 11 | # 12 | # Source location: https://codeberg.org/tok/librecell 13 | # 14 | from .signal_router import SignalRouter 15 | import networkx as nx 16 | from typing import Any, Dict, Set 17 | from itertools import product 18 | 19 | 20 | class MultiViaRouter(SignalRouter): 21 | 22 | def __init__(self, router: SignalRouter, node_conflict: Dict[Any, Set]): 23 | """ 24 | Wrap a detail router function such that it can create double vias. 25 | 26 | Parameters 27 | ---------- 28 | 29 | :param router: Underlying detail router 30 | :param node_conflict: Dict[Node, Set[Node]] 31 | A mapping from a node `n` to a set of nodes that collide with `n`. 32 | """ 33 | self.router = router 34 | self.node_conflict = node_conflict if node_conflict is not None else dict() 35 | 36 | def route(self, graph: nx.Graph, 37 | terminals, 38 | node_cost_fn, 39 | edge_cost_fn 40 | ) -> nx.Graph: 41 | return _multi_via_spanning_subtree(self.router, 42 | graph, 43 | terminals, 44 | self.node_conflict, 45 | node_cost_fn, 46 | edge_cost_fn) 47 | 48 | 49 | def _multi_via_spanning_subtree(router: SignalRouter, 50 | graph: nx.Graph, 51 | terminals, 52 | node_conflict: Dict, node_cost_fn, 53 | edge_cost_fn): 54 | """ Wrap a detail router function such that it can create double vias. 55 | 56 | Parameters 57 | ---------- 58 | 59 | router: Underlying detail router 60 | graph: nx.Graph 61 | terminals: The nodes to connect. 62 | node_collisions: Dict[Node, Set[Node]] 63 | A mapping from a node `n` to a set of nodes that collide with `n`. 64 | """ 65 | 66 | S1 = router.route(graph, terminals, node_cost_fn, edge_cost_fn) 67 | 68 | multi_vias = set() 69 | for a, b in S1.edges: 70 | multi_via = graph[a][b].get('multi_via', 1) 71 | if multi_via > 1: 72 | multi_vias.add(((a, b), multi_via)) 73 | 74 | # Remove edges from Graph 75 | if multi_vias: 76 | G2 = graph.copy() 77 | 78 | for a, b in S1.edges(): 79 | G2.add_edge(a, b, weight=0.0001) 80 | 81 | for (a, b), n in multi_vias: 82 | 83 | a_equiv = node_conflict.get(a, []) 84 | b_equiv = node_conflict.get(b, []) 85 | 86 | for c, d in product(a_equiv, b_equiv): 87 | if (c, d) in G2.edges: 88 | G2.remove_edge(c, d) 89 | 90 | # Reconnect the disconnected nodes. 91 | for (a, b), n in multi_vias: 92 | # Connect two nodes. 93 | path = router.route(G2, [a, b], node_cost_fn, edge_cost_fn) 94 | for e in path.edges(): 95 | S1.add_edge(*e) 96 | 97 | return S1 98 | -------------------------------------------------------------------------------- /librecell-layout/lclayout/graphrouter/pyo3_graphrouter.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2019-2020 Thomas Kramer. 3 | # 4 | # This source describes Open Hardware and is licensed under the CERN-OHL-S v2. 5 | # 6 | # You may redistribute and modify this documentation and make products using it 7 | # under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl). 8 | # This documentation is distributed WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, 9 | # INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A PARTICULAR PURPOSE. 10 | # Please see the CERN-OHL-S v2 for applicable conditions. 11 | # 12 | # Source location: https://codeberg.org/tok/librecell 13 | # 14 | 15 | import pyo3_cell 16 | import networkx as nx 17 | 18 | def route(G, signals, reserved_nodes = None, node_conflict=None): 19 | 20 | if isinstance(signals, dict): 21 | signals = list(signals.values()) 22 | 23 | if isinstance(reserved_nodes, dict): 24 | reserved_nodes = list(reserved_nodes.values()) 25 | 26 | if reserved_nodes is None: 27 | reserved_nodes = []*len(signals) 28 | 29 | rust_edges, nodemap = graph_networkx2rust(G) 30 | rust_signals = [[nodemap[t] for t in terminals] for terminals in signals] 31 | 32 | node_collisions = list(node_conflict.items()) if node_conflict else [] 33 | node_collisions = [(nodemap[n], [nodemap[c] for c in collisions]) for n, collisions in node_collisions] 34 | 35 | reserved_nodes = [[nodemap[n] for n in nodes] for nodes in reserved_nodes] 36 | 37 | rust_routing_trees = pyo3_cell.route_mst(rust_edges, rust_signals, reserved_nodes, node_collisions) 38 | 39 | routing_trees = graph_rust2networkx(rust_routing_trees, nodemap) 40 | return routing_trees 41 | 42 | def graph_networkx2rust(G): 43 | # Map nodes to indices 44 | nodemap = {n: i for i,n in enumerate(G.nodes)} 45 | 46 | rustgraph = nx.Graph() 47 | rustgraph.add_nodes_from((nodemap[n] for n in G.nodes)) 48 | rustgraph.add_edges_from(((nodemap[a], nodemap[b], d) for a,b,d in G.edges(data=True))) 49 | 50 | rust_edges = list(rustgraph.edges(data=True)) 51 | 52 | for a,b,data in rust_edges: 53 | assert data['weight'] > 0 54 | 55 | return rust_edges, nodemap 56 | 57 | def graph_rust2networkx(rust_routing_trees, nodemap): 58 | 59 | reverse_map = {v:k for k,v in nodemap.items()} 60 | 61 | # Convert back to python nodes. 62 | routing_edges = [ 63 | [(reverse_map[a], reverse_map[b]) for a,b in rt] 64 | for rt in rust_routing_trees 65 | ] 66 | routing_trees = [] 67 | for re in routing_edges: 68 | rt = nx.Graph() 69 | rt.add_edges_from(re) 70 | routing_trees.append(rt) 71 | 72 | return routing_trees 73 | -------------------------------------------------------------------------------- /librecell-layout/lclayout/layout/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2019-2020 Thomas Kramer. 3 | # 4 | # This source describes Open Hardware and is licensed under the CERN-OHL-S v2. 5 | # 6 | # You may redistribute and modify this documentation and make products using it 7 | # under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl). 8 | # This documentation is distributed WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, 9 | # INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A PARTICULAR PURPOSE. 10 | # Please see the CERN-OHL-S v2 for applicable conditions. 11 | # 12 | # Source location: https://codeberg.org/tok/librecell 13 | # 14 | -------------------------------------------------------------------------------- /librecell-layout/lclayout/layout/cell_template.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2019-2020 Thomas Kramer. 3 | # 4 | # This source describes Open Hardware and is licensed under the CERN-OHL-S v2. 5 | # 6 | # You may redistribute and modify this documentation and make products using it 7 | # under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl). 8 | # This documentation is distributed WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, 9 | # INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A PARTICULAR PURPOSE. 10 | # Please see the CERN-OHL-S v2 for applicable conditions. 11 | # 12 | # Source location: https://codeberg.org/tok/librecell 13 | # 14 | from .layers import * 15 | from klayout import db 16 | from typing import Dict, Tuple 17 | 18 | """ 19 | # Fill half of the cell with nwell. 20 | # TODO: do this in the cell template or after placing the transistors. 21 | nwell_box = pya.Box( 22 | pya.Point(0, cell_height // 2), 23 | pya.Point(cell_width, cell_height) 24 | ) 25 | 26 | shapes[l_nwell].insert(nwell_box) 27 | """ 28 | 29 | 30 | def draw_cell_template(shapes: Dict[str, db.Shapes], 31 | cell_shape: Tuple[int, int], 32 | nwell_pwell_spacing: int = 0) -> None: 33 | """ 34 | Draw shapes of the cell that can be drawn without knowledge of the transistor placement. 35 | This includes the cell boundary, nwell/pwell. 36 | :param shapes: KLayout shapes that will be modified. 37 | :param cell_shape: Dimensions of the cell (width, height). 38 | :param nwell_pwell_spacing: Minimum spacing between nwell and pwell for twin-well layouts. 39 | :return: None 40 | """ 41 | cell_width, cell_height = cell_shape 42 | 43 | # Draw abutment box. 44 | shapes[l_abutment_box].insert(db.Box(0, 0, cell_width, cell_height)) 45 | 46 | # Draw nwell / pwell 47 | 48 | # Fill half of the cell with nwell. 49 | 50 | nwell_start_y = cell_height // 2 + nwell_pwell_spacing // 2 51 | nwell_end_y = cell_height 52 | 53 | pwell_start_y = 0 54 | pwell_end_y = cell_height // 2 - nwell_pwell_spacing // 2 55 | 56 | nwell_box = db.Box( 57 | db.Point(0, nwell_start_y), 58 | db.Point(cell_width, nwell_end_y) 59 | ) 60 | 61 | shapes[l_nwell].insert(nwell_box) 62 | 63 | pwell_box = db.Box( 64 | db.Point(0, pwell_start_y), 65 | db.Point(cell_width, pwell_end_y) 66 | ) 67 | shapes[l_pwell].insert(pwell_box) 68 | -------------------------------------------------------------------------------- /librecell-layout/lclayout/layout/geometry_helpers.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2019-2020 Thomas Kramer. 3 | # 4 | # This source describes Open Hardware and is licensed under the CERN-OHL-S v2. 5 | # 6 | # You may redistribute and modify this documentation and make products using it 7 | # under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl). 8 | # This documentation is distributed WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, 9 | # INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A PARTICULAR PURPOSE. 10 | # Please see the CERN-OHL-S v2 for applicable conditions. 11 | # 12 | # Source location: https://codeberg.org/tok/librecell 13 | # 14 | import sys 15 | 16 | import networkx as nx 17 | from typing import Tuple, Iterable 18 | 19 | # klayout.db should not be imported if script is run from KLayout GUI. 20 | if 'pya' not in sys.modules: 21 | import klayout.db as pya 22 | 23 | 24 | def is_inside(p: Tuple[int, int], r: pya.Region, margin: int): 25 | """ Test if point is inside region with some margin. 26 | """ 27 | p = pya.Point(*p) 28 | v = pya.Vector(margin, margin) 29 | box = pya.Region(pya.Box(p - v, p + v)) 30 | return not box.inside(r).is_empty() 31 | 32 | 33 | def interacts(p: Tuple[int, int], r: pya.Region, margin: int): 34 | """ Test if point is close (margin) to region. 35 | """ 36 | p = pya.Point(*p) 37 | v = pya.Vector(margin, margin) 38 | box = pya.Region(pya.Box(p - v, p + v)) 39 | return not r.interacting(box).is_empty() 40 | 41 | 42 | def is_edge_inside(graph_edge, r: pya.Region, margin: int): 43 | """Checks if the edge of the graph lies inside the region when mapped to a layout. 44 | """ 45 | 46 | assert margin > 0, "Path with width 0 is considered non-existent." 47 | 48 | (l1, (x1, y1)), (l2, (x2, y2)) = graph_edge 49 | 50 | p = pya.Region(pya.Path([pya.Point(x1, y1), pya.Point(x2, y2)], margin, margin, margin)) 51 | 52 | return not p.inside(r).is_empty() 53 | 54 | 55 | def inside(points: Iterable[Tuple[int, int]], r: pya.Region, margin: int): 56 | """ Get all points that lie inside the region. 57 | """ 58 | return [p for p in points if is_inside(p, r, margin)] 59 | 60 | 61 | def interacting(points: Iterable[Tuple[int, int]], r: pya.Region, margin: int): 62 | """ Get all points that are close (margin) to the region. 63 | """ 64 | return [p for p in points if interacts(p, r, margin)] 65 | 66 | 67 | def edges_inside(g: nx.Graph, r: pya.Region, margin: int): 68 | """ Get all graph edges that lie inside the region. 69 | """ 70 | return [e for e in g.edges if is_edge_inside(e, r, margin)] 71 | -------------------------------------------------------------------------------- /librecell-layout/lclayout/layout/grid.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2019-2020 Thomas Kramer. 3 | # 4 | # This source describes Open Hardware and is licensed under the CERN-OHL-S v2. 5 | # 6 | # You may redistribute and modify this documentation and make products using it 7 | # under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl). 8 | # This documentation is distributed WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, 9 | # INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A PARTICULAR PURPOSE. 10 | # Please see the CERN-OHL-S v2 for applicable conditions. 11 | # 12 | # Source location: https://codeberg.org/tok/librecell 13 | # 14 | from itertools import product 15 | import numpy as np 16 | from typing import Sequence, Tuple, Iterator 17 | 18 | 19 | class Grid: 20 | 21 | def __init__(self, start: Tuple[int, int], end: Tuple[int, int], step: Tuple[int, int]): 22 | self.start = start 23 | self.end = end 24 | self.step = step 25 | 26 | self._dimension = len(start) 27 | 28 | assert all([len(v) == self._dimension for v in (start, end, step)]), \ 29 | "start, end and step must have the same dimensions." 30 | 31 | def __iter__(self) -> Iterator[Tuple[int, int]]: 32 | """ Get iterator over grid points. 33 | :return: 34 | """ 35 | 36 | return product(*(range(a, b, c) 37 | for a, b, c in zip(self.start, self.end, self.step) 38 | )) 39 | 40 | def meshgrid(self): 41 | """ Return the grid points as a numpy meshgrid. 42 | :return: 43 | """ 44 | return np.meshgrid(*(np.arange(a, b, c) 45 | for a, b, c in zip(self.start, self.end, self.step) 46 | )) 47 | 48 | def _is_on_grid_axis(self, point: Sequence[int], dimension: int) -> bool: 49 | """ Check if `point` is aligned with grid regarding one dimension. 50 | :param point: 51 | :param dimension: 52 | :return: 53 | """ 54 | x = point[dimension] 55 | start = self.start[dimension] 56 | step = self.step[dimension] 57 | end = self.end[dimension] 58 | 59 | return (x - start) % step == 0 and start <= x < end 60 | 61 | def is_on_grid(self, point) -> bool: 62 | return all((self._is_on_grid_axis(point, d) for d in range(self._dimension))) 63 | 64 | def _grid_floor(self, x: int, dimension: int) -> int: 65 | """ Round a coordinate down to next grid coordinate. 66 | """ 67 | start = self.start[dimension] 68 | step = self.step[dimension] 69 | x = int(x) 70 | x = (x - start) // step * step + start 71 | 72 | return x 73 | 74 | def _grid_ceil(self, x: int, dimension: int) -> int: 75 | """ Round a coordinate up to next grid coordinate. 76 | """ 77 | return self._grid_floor(x + self.step[dimension] - 1, dimension) 78 | 79 | def _grid_round(self, x: int, dimension: int) -> int: 80 | return self._grid_floor(x + self.step[dimension] // 2, dimension) 81 | 82 | 83 | class Grid2D(Grid): 84 | 85 | def __init__(self, start: Tuple[int, int], end: Tuple[int, int], step: Tuple[int, int]): 86 | super().__init__(start, end, step) 87 | assert self._dimension == 2, "Dimension must be 2." 88 | 89 | def grid_floor_x(self, point): 90 | x, y = point 91 | return self._grid_floor(x, 0), y 92 | 93 | def grid_floor_y(self, point): 94 | x, y = point 95 | return x, self._grid_floor(y, 1) 96 | 97 | def grid_floor_xy(self, point): 98 | x, y = point 99 | return self._grid_floor(x, 0), self._grid_floor(y, 1) 100 | 101 | def grid_ceil_x(self, point): 102 | x, y = point 103 | return self._grid_ceil(x, 0), y 104 | 105 | def grid_ceil_y(self, point): 106 | x, y = point 107 | return x, self._grid_ceil(y, 1) 108 | 109 | def grid_ceil_xy(self, point): 110 | x, y = point 111 | return self._grid_ceil(x, 0), self._grid_ceil(y, 1) 112 | 113 | def grid_round_x(self, point): 114 | x, y = point 115 | return self._grid_round(x, 0), y 116 | 117 | def grid_round_y(self, point): 118 | x, y = point 119 | return x, self._grid_round(y, 1) 120 | 121 | def grid_round_xy(self, point): 122 | x, y = point 123 | return self._grid_round(x, 0), self._grid_round(y, 1) 124 | 125 | def neigborhood(self, point: Tuple[int, int], max_distance: int, norm_ord=2): 126 | """ Get all points on grid that are at most `max_distance` away from `point`. 127 | :param point: Reference point. 128 | :param max_distance: 129 | :param norm_ord: The order of the norm to be used. Default = 2 (euclidian norm) 130 | :return: 131 | """ 132 | offset = self.grid_floor_xy(point) 133 | start = self.grid_floor_xy((offset[0] - max_distance, offset[1] - max_distance)) 134 | end = self.grid_ceil_xy( 135 | (offset[0] + max_distance + self.step[0] + 1, offset[1] + max_distance + self.step[1] + 1)) 136 | 137 | kernel = Grid2D(start, end, self.step) 138 | 139 | mesh = kernel.meshgrid() 140 | xx, yy = mesh 141 | x, y = point 142 | diff = xx - x, yy - y 143 | dists = np.linalg.norm(np.array(diff), ord=norm_ord, axis=0) 144 | 145 | neighbor_mask = dists <= max_distance 146 | 147 | neighbor_points = zip(*(x[neighbor_mask].flat for x in mesh)) 148 | return [p for p in neighbor_points if self.is_on_grid(p)] 149 | 150 | 151 | def test_grid2d(): 152 | g = Grid2D((0, 0), (10, 20), (1, 2)) 153 | 154 | assert g.is_on_grid((0, 0)) 155 | assert not g.is_on_grid((1, 1)) 156 | assert g.is_on_grid((1, 2)) 157 | 158 | assert g.grid_floor_xy((1, 1)) == (1, 0) 159 | assert g.grid_ceil_xy((1, 1)) == (1, 2) 160 | 161 | 162 | def test_grid_neighbors(): 163 | for i in range(0, 1000): 164 | start = (np.random.randint(-10, 10), np.random.randint(-10, 10)) 165 | end = (np.random.randint(10, 20), np.random.randint(10, 20)) 166 | step = (np.random.randint(1, 4), np.random.randint(1, 4)) 167 | g = Grid2D(start, end, step) 168 | point = np.random.random(2) * 10 169 | max_dist = np.random.random(1) * 10 170 | norm_ord = np.random.randint(1, 3) 171 | neighbors_expected = [p for p in g if np.linalg.norm(np.array(p) - np.array(point), ord=norm_ord) <= max_dist] 172 | neighbors_actual = g.neigborhood(point, max_dist, norm_ord=norm_ord) 173 | 174 | # print(set(neighbors_actual).symmetric_difference(set(neighbors_expected))) 175 | 176 | assert set(neighbors_actual) == set(neighbors_expected) 177 | -------------------------------------------------------------------------------- /librecell-layout/lclayout/layout/grid_helpers.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2019-2020 Thomas Kramer. 3 | # 4 | # This source describes Open Hardware and is licensed under the CERN-OHL-S v2. 5 | # 6 | # You may redistribute and modify this documentation and make products using it 7 | # under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl). 8 | # This documentation is distributed WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, 9 | # INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A PARTICULAR PURPOSE. 10 | # Please see the CERN-OHL-S v2 for applicable conditions. 11 | # 12 | # Source location: https://codeberg.org/tok/librecell 13 | # 14 | 15 | def grid_floor(x, grid_spacing, grid_offset): 16 | """ Round down to next grid point. 17 | """ 18 | return (x-grid_offset)//grid_spacing * grid_spacing + grid_offset 19 | 20 | def grid_ceil(x, grid_spacing, grid_offset): 21 | """ Round up to next grid point. 22 | """ 23 | return grid_floor(x + grid_spacing-1, grid_spacing, grid_offset) 24 | 25 | def grid_round(x, grid_spacing, grid_offset): 26 | """ Round to next grid point. 27 | """ 28 | return grid_floor(x + grid_spacing//2, grid_spacing, grid_offset) 29 | -------------------------------------------------------------------------------- /librecell-layout/lclayout/layout/layers.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2019-2020 Thomas Kramer. 3 | # 4 | # This source describes Open Hardware and is licensed under the CERN-OHL-S v2. 5 | # 6 | # You may redistribute and modify this documentation and make products using it 7 | # under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl). 8 | # This documentation is distributed WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, 9 | # INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A PARTICULAR PURPOSE. 10 | # Please see the CERN-OHL-S v2 for applicable conditions. 11 | # 12 | # Source location: https://codeberg.org/tok/librecell 13 | # 14 | import networkx as nx 15 | 16 | import operator 17 | import klayout.db as db 18 | 19 | 20 | class LayerOp: 21 | def __init__(self, op, lhs, rhs): 22 | self.op = op 23 | self.lhs = lhs 24 | self.rhs = rhs 25 | 26 | def eval(self): 27 | pass 28 | 29 | def __add__(self, other): 30 | return LayerOp(operator.add, self, other) 31 | 32 | def __or__(self, other): 33 | return LayerOp(operator.add, self, other) 34 | 35 | def __and__(self, other): 36 | return LayerOp(operator.iand, self, other) 37 | 38 | def __sub__(self, other): 39 | return LayerOp(operator.sub, self, other) 40 | 41 | def __xor__(self, other): 42 | return LayerOp(operator.xor, self, other) 43 | 44 | 45 | class Leaf(LayerOp): 46 | def __init__(self, val): 47 | self.val = val 48 | 49 | def eval(self): 50 | return self.val 51 | 52 | 53 | class AbstractLayer(Leaf): 54 | 55 | def __init__(self, layer_num, layer_purpose): 56 | self.layer_num = layer_num 57 | self.layer_purpose = layer_purpose 58 | 59 | def eval(self): 60 | return self.layer_num, self.layer_purpose 61 | 62 | 63 | def layer(idx: int, 64 | purpose: int = 0, 65 | name: str = None) -> AbstractLayer: 66 | """ Get a handle to a layer by layer number. 67 | :param idx: GDS layer number or a string of the form '1/0'. 68 | :param purpose: GDS layer purpose. 69 | :param name: Name as a string. 70 | :return: Handle to the layer. 71 | """ 72 | 73 | if name is None: 74 | name = '{}/{}'.format(idx, purpose) 75 | 76 | # Allow idx to be a string like '1/0'. 77 | if isinstance(idx, str): 78 | s = idx.split('/', 2) 79 | a, b = s 80 | idx = int(a) 81 | purpose = int(b) 82 | 83 | return AbstractLayer(idx, purpose, material=material) 84 | 85 | 86 | class Mask: 87 | """ Wrapper around db.Region. 88 | """ 89 | 90 | def __init__(self, region: db.Region): 91 | self.region = region 92 | 93 | def __add__(self, other): 94 | return Mask(self.region + other.region) 95 | 96 | def __or__(self, other): 97 | return self + other 98 | 99 | def __and__(self, other): 100 | return Mask(self.region & other.region) 101 | 102 | def __sub__(self, other): 103 | m = Mask(self.region - other.region) 104 | m.material = self.material 105 | return m 106 | 107 | def __xor__(self, other): 108 | return Mask(self.region ^ other.region) 109 | 110 | def __hash__(self): 111 | return hash(self.region) 112 | 113 | def __equal__(self, other): 114 | return self.region == other.region 115 | 116 | 117 | def eval_op_tree(cell: db.Cell, op_node: LayerOp) -> Mask: 118 | """ Recursively evaluate the layer operation tree. 119 | :param op_node: Operand node or leaf. 120 | :return: Returns a `Mask` object containing a `pya.Region` of the layer. 121 | """ 122 | 123 | if isinstance(op_node, AbstractLayer): 124 | (idx, purpose) = op_node.eval() 125 | layer_index = layout.layer(idx, purpose) 126 | 127 | region = _flatten_cell(cell, layer_index, selection_box=selection_box) 128 | result = Mask(region) 129 | else: 130 | assert isinstance(op_node, LayerOp) 131 | op = op_node.op 132 | lhs = eval_op_tree(cell, op_node.lhs) 133 | rhs = eval_op_tree(cell, op_node.rhs) 134 | result = op(lhs, rhs) 135 | result.region.merge() 136 | 137 | return result 138 | 139 | 140 | l_ndiffusion = 'ndiffusion' 141 | l_pdiffusion = 'pdiffusion' 142 | l_nwell = 'nwell' 143 | l_pwell = 'pwell' 144 | l_poly = 'poly' 145 | l_poly_label = 'poly_label' 146 | l_pdiff_contact = 'pdiff_contact' 147 | l_ndiff_contact = 'ndiff_contact' 148 | l_poly_contact = 'poly_contact' 149 | l_metal1 = 'metal1' 150 | l_metal1_label = 'metal1_label' 151 | l_metal1_pin = 'metal1_pin' 152 | l_via1 = 'via1' 153 | l_metal2 = 'metal2' 154 | l_metal2_label = 'metal2_label' 155 | l_metal2_pin = 'metal2_pin' 156 | l_abutment_box = 'abutment_box' 157 | 158 | layermap = { 159 | l_nwell: (1, 0), 160 | l_pwell: (2, 0), 161 | l_ndiffusion: (3, 0), 162 | l_pdiffusion: (4, 0), 163 | l_poly: (5, 0), 164 | l_pdiff_contact: (6, 0), 165 | l_ndiff_contact: (6, 1), 166 | l_poly_contact: (7, 0), 167 | l_metal1: (8, 0), 168 | l_metal1_label: (8, 1), 169 | l_metal1_pin: (8, 2), 170 | l_via1: (9, 0), 171 | l_metal2: (10, 0), 172 | l_metal2_label: (10, 1), 173 | l_metal2_pin: (10, 2), 174 | l_abutment_box: (100, 0) 175 | } 176 | 177 | layermap_reverse = {v: k for k, v in layermap.items()} 178 | 179 | via_layers = nx.Graph() 180 | via_layers.add_edge(l_ndiffusion, l_metal1, layer=l_ndiff_contact) 181 | via_layers.add_edge(l_pdiffusion, l_metal1, layer=l_pdiff_contact) 182 | via_layers.add_edge(l_poly, l_metal1, layer=l_poly_contact) 183 | via_layers.add_edge(l_metal1, l_metal2, layer=l_via1) 184 | -------------------------------------------------------------------------------- /librecell-layout/lclayout/layout/notch_removal.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2019-2020 Thomas Kramer. 3 | # 4 | # This source describes Open Hardware and is licensed under the CERN-OHL-S v2. 5 | # 6 | # You may redistribute and modify this documentation and make products using it 7 | # under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl). 8 | # This documentation is distributed WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, 9 | # INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A PARTICULAR PURPOSE. 10 | # Please see the CERN-OHL-S v2 for applicable conditions. 11 | # 12 | # Source location: https://codeberg.org/tok/librecell 13 | # 14 | import klayout.db as pya 15 | 16 | 17 | def fill_notches(region: pya.Region, minimum_notch: int) -> pya.Region: 18 | """ Fill notches in a pya.Region. 19 | :param region: 20 | :param minimum_notch: 21 | :return: 22 | """ 23 | 24 | notches = region.notch_check(minimum_notch) 25 | spaces = region.space_check(minimum_notch) 26 | notches = list(notches) + list(spaces) 27 | s = pya.Shapes() 28 | s.insert(region) 29 | for edge_pair in notches: 30 | a, b = edge_pair.first, edge_pair.second 31 | # Find smaller edge (a) 32 | a, b = sorted((a, b), key=lambda e: e.length()) 33 | 34 | # Construct a minimal box to fill the notch 35 | box = a.bbox() 36 | # Extend box of shorted edge by points of longer edge 37 | box1 = box + b.p1 38 | box2 = box + b.p2 39 | 40 | # Take the smaller box. 41 | min_box = min([box1, box2], key=lambda b: b.area()) 42 | 43 | s.insert(min_box) 44 | 45 | result = pya.Region(s) 46 | result.merge() 47 | return result 48 | 49 | -------------------------------------------------------------------------------- /librecell-layout/lclayout/lef/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2019-2020 Thomas Kramer. 3 | # 4 | # This source describes Open Hardware and is licensed under the CERN-OHL-S v2. 5 | # 6 | # You may redistribute and modify this documentation and make products using it 7 | # under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl). 8 | # This documentation is distributed WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, 9 | # INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A PARTICULAR PURPOSE. 10 | # Please see the CERN-OHL-S v2 for applicable conditions. 11 | # 12 | # Source location: https://codeberg.org/tok/librecell 13 | # 14 | -------------------------------------------------------------------------------- /librecell-layout/lclayout/lvs/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2019-2020 Thomas Kramer. 3 | # 4 | # This source describes Open Hardware and is licensed under the CERN-OHL-S v2. 5 | # 6 | # You may redistribute and modify this documentation and make products using it 7 | # under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl). 8 | # This documentation is distributed WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, 9 | # INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A PARTICULAR PURPOSE. 10 | # Please see the CERN-OHL-S v2 for applicable conditions. 11 | # 12 | # Source location: https://codeberg.org/tok/librecell 13 | # 14 | -------------------------------------------------------------------------------- /librecell-layout/lclayout/place/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2019-2020 Thomas Kramer. 3 | # 4 | # This source describes Open Hardware and is licensed under the CERN-OHL-S v2. 5 | # 6 | # You may redistribute and modify this documentation and make products using it 7 | # under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl). 8 | # This documentation is distributed WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, 9 | # INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A PARTICULAR PURPOSE. 10 | # Please see the CERN-OHL-S v2 for applicable conditions. 11 | # 12 | # Source location: https://codeberg.org/tok/librecell 13 | # 14 | -------------------------------------------------------------------------------- /librecell-layout/lclayout/place/meta_placer.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2019-2021 Thomas Kramer. 3 | # 4 | # This source describes Open Hardware and is licensed under the CERN-OHL-S v2. 5 | # 6 | # You may redistribute and modify this documentation and make products using it 7 | # under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl). 8 | # This documentation is distributed WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, 9 | # INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A PARTICULAR PURPOSE. 10 | # Please see the CERN-OHL-S v2 for applicable conditions. 11 | # 12 | # Source location: https://codeberg.org/tok/librecell 13 | # 14 | from ..data_types import * 15 | from .place import TransistorPlacer 16 | 17 | from . import euler_placer 18 | from . import eulertours 19 | 20 | import itertools 21 | from typing import Iterable, List 22 | import logging 23 | 24 | logger = logging.getLogger(__name__) 25 | 26 | 27 | class MetaTransistorPlacer(TransistorPlacer): 28 | """ 29 | This placement engine is a wrapper around other engines. 30 | Based on simple heuristics it will call a suited engine. 31 | For example simple circuits will be placed with an algorithm that does not scale so well but is most 32 | accurate, big circuits will be placed with an algorithm that scales better but yields lower-quality results (in shorter time though). 33 | 34 | This involves extremely rough heuristics. Some more thorough theoretical analysis could make a big improvement. 35 | 36 | This is kind of a stupid fix because there's no good-enough placement engine. 37 | """ 38 | 39 | def __init__(self): 40 | pass 41 | 42 | def get_placer(self, transistors: List[Transistor]) -> TransistorPlacer: 43 | """ 44 | Heuristically find a suited placement engine. 45 | :param transistors: 46 | :return: 47 | """ 48 | logger.debug('Estimate placement complexity.') 49 | 50 | # Try to find a heuristical measure for the placement complexity. 51 | # This is very vague. 52 | 53 | nmos = [t for t in transistors if t.channel_type == ChannelType.NMOS] 54 | pmos = [t for t in transistors if t.channel_type == ChannelType.PMOS] 55 | nmos_graph = euler_placer._transistors2graph(nmos) 56 | pmos_graph = euler_placer._transistors2graph(pmos) 57 | 58 | 59 | even_degree_graphs_n = eulertours.construct_even_degree_graphs(nmos_graph) 60 | num_even_degree_graphs_n = len(even_degree_graphs_n) 61 | logger.debug('Number of even-degree graphs (NMOS): %d', num_even_degree_graphs_n) 62 | if num_even_degree_graphs_n > 20: 63 | return euler_placer.HierarchicalPlacer() 64 | even_degree_graphs_p = eulertours.construct_even_degree_graphs(pmos_graph) 65 | num_even_degree_graphs_p = len(even_degree_graphs_p) 66 | logger.debug('Number of even-degree graphs (PMOS): %d', num_even_degree_graphs_p) 67 | if num_even_degree_graphs_p > 20: 68 | return euler_placer.HierarchicalPlacer() 69 | 70 | # Lazily construct all euler tours. 71 | max_tours = 200 72 | 73 | logger.debug('Find eulerian tours.') 74 | all_eulertours_n = list(chain(*(eulertours.find_all_euler_tours(g, limit=max_tours) for g in even_degree_graphs_n))) 75 | all_eulertours_p = list(chain(*(eulertours.find_all_euler_tours(g, limit=max_tours) for g in even_degree_graphs_p))) 76 | 77 | num_tours_n = len(all_eulertours_n) 78 | num_tours_p = len(all_eulertours_p) 79 | 80 | complexity = num_tours_n * num_tours_p 81 | 82 | logger.debug(f'Estimated placement complexity: {complexity}') 83 | 84 | if complexity < 400000: 85 | return euler_placer.EulerPlacer() 86 | else: 87 | return euler_placer.HierarchicalPlacer() 88 | 89 | return euler_placer.EulerPlacer() 90 | 91 | def place(self, transistors: Iterable[Transistor]) -> Cell: 92 | 93 | placer = self.get_placer(transistors) 94 | 95 | logger.info(f"Placement engine: {type(placer).__name__}") 96 | 97 | return placer.place(transistors) 98 | 99 | 100 | -------------------------------------------------------------------------------- /librecell-layout/lclayout/place/partition.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2019-2020 Thomas Kramer. 3 | # 4 | # This source describes Open Hardware and is licensed under the CERN-OHL-S v2. 5 | # 6 | # You may redistribute and modify this documentation and make products using it 7 | # under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl). 8 | # This documentation is distributed WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, 9 | # INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A PARTICULAR PURPOSE. 10 | # Please see the CERN-OHL-S v2 for applicable conditions. 11 | # 12 | # Source location: https://codeberg.org/tok/librecell 13 | # 14 | import networkx as nx 15 | import logging 16 | 17 | from itertools import count 18 | from typing import List 19 | 20 | from lccommon import net_util 21 | 22 | logger = logging.getLogger(__name__) 23 | 24 | 25 | def partition(ciruit_graph: nx.MultiGraph) -> List[nx.MultiGraph]: 26 | """ Find sub-graphs that are connected when ignoring supply nets. 27 | :param ciruit_graph: nx.MultiGraph 28 | :return: 29 | """ 30 | 31 | logger.debug('Partitioning into connected sub-graphs.') 32 | 33 | # Split supply nodes. 34 | g = nx.MultiGraph() 35 | cnt = count() 36 | 37 | node_reverse_mapping = dict() 38 | 39 | def replace_supply_node(n): 40 | if net_util.is_power_net(n): 41 | new = (n, next(cnt)) 42 | else: 43 | new = (n, 0) 44 | node_reverse_mapping[new] = n 45 | return new 46 | 47 | for a, b, key, data in ciruit_graph.edges(keys=True, data=True): 48 | a = replace_supply_node(a) 49 | b = replace_supply_node(b) 50 | g.add_edge(a, b, key, **data) 51 | 52 | logger.debug('Connected components: %d', nx.number_connected_components(g)) 53 | 54 | connected = (g.subgraph(c) for c in nx.connected_components(g)) 55 | 56 | # Map node labels back to original labels. 57 | connected = [nx.relabel_nodes(c, node_reverse_mapping, copy=True) for c in connected] 58 | 59 | return connected 60 | -------------------------------------------------------------------------------- /librecell-layout/lclayout/place/place.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2019-2020 Thomas Kramer. 3 | # 4 | # This source describes Open Hardware and is licensed under the CERN-OHL-S v2. 5 | # 6 | # You may redistribute and modify this documentation and make products using it 7 | # under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl). 8 | # This documentation is distributed WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, 9 | # INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A PARTICULAR PURPOSE. 10 | # Please see the CERN-OHL-S v2 for applicable conditions. 11 | # 12 | # Source location: https://codeberg.org/tok/librecell 13 | # 14 | from ..data_types import * 15 | 16 | from typing import Iterable 17 | 18 | 19 | class TransistorPlacer: 20 | """ 21 | Interface definition of a transistor placement algorithm. 22 | """ 23 | 24 | def place(self, transistors: Iterable[Transistor]) -> Cell: 25 | pass 26 | -------------------------------------------------------------------------------- /librecell-layout/lclayout/tech_util.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2019-2020 Thomas Kramer. 3 | # 4 | # This source describes Open Hardware and is licensed under the CERN-OHL-S v2. 5 | # 6 | # You may redistribute and modify this documentation and make products using it 7 | # under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl). 8 | # This documentation is distributed WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, 9 | # INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A PARTICULAR PURPOSE. 10 | # Please see the CERN-OHL-S v2 for applicable conditions. 11 | # 12 | # Source location: https://codeberg.org/tok/librecell 13 | # 14 | import networkx as nx 15 | from typing import Any, Dict, Tuple 16 | import logging 17 | import importlib.machinery 18 | import types 19 | 20 | logger = logging.getLogger(__name__) 21 | 22 | 23 | def spacing_graph(min_spacing: Dict[Tuple[Any, Any], int]) -> nx.Graph: 24 | """ 25 | Build a spacing rule graph by mapping the minimal spacing between layer a and layer b to an edge 26 | a-b in the graph with weight=min_spacing. 27 | """ 28 | g = nx.Graph() 29 | for (l1, l2), spacing in min_spacing.items(): 30 | g.add_edge(l1, l2, min_spacing=spacing) 31 | return g 32 | 33 | 34 | def load_tech_file(path, module_name='tech'): 35 | """ 36 | Load a python module containing technology information. 37 | :param path: 38 | :param module_name: 39 | :return: Handle to the module. 40 | """ 41 | logger.info('Loading tech file: %s', path) 42 | loader = importlib.machinery.SourceFileLoader('module_name', path) 43 | tech = types.ModuleType(loader.name) 44 | loader.exec_module(tech) 45 | return tech 46 | -------------------------------------------------------------------------------- /librecell-layout/lclayout/writer/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2019-2020 Thomas Kramer. 3 | # 4 | # This source describes Open Hardware and is licensed under the CERN-OHL-S v2. 5 | # 6 | # You may redistribute and modify this documentation and make products using it 7 | # under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl). 8 | # This documentation is distributed WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, 9 | # INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A PARTICULAR PURPOSE. 10 | # Please see the CERN-OHL-S v2 for applicable conditions. 11 | # 12 | # Source location: https://codeberg.org/tok/librecell 13 | # 14 | -------------------------------------------------------------------------------- /librecell-layout/lclayout/writer/gds_writer.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2019-2020 Thomas Kramer. 3 | # 4 | # This source describes Open Hardware and is licensed under the CERN-OHL-S v2. 5 | # 6 | # You may redistribute and modify this documentation and make products using it 7 | # under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl). 8 | # This documentation is distributed WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, 9 | # INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A PARTICULAR PURPOSE. 10 | # Please see the CERN-OHL-S v2 for applicable conditions. 11 | # 12 | # Source location: https://codeberg.org/tok/librecell 13 | # 14 | import logging 15 | import time 16 | from typing import Dict, List, Tuple, Union 17 | from klayout import db 18 | import os 19 | 20 | from .writer import Writer, remap_layers 21 | from ..layout import layers 22 | 23 | logger = logging.getLogger(__name__) 24 | 25 | 26 | class GdsWriter(Writer): 27 | """ 28 | Writer for GDS2 output. 29 | """ 30 | 31 | def __init__(self, 32 | db_unit: float, 33 | output_map: Dict[str, Tuple[int, int]]): 34 | self.db_unit = db_unit 35 | self.output_map = output_map 36 | 37 | def write_layout(self, 38 | layout: db.Layout, 39 | pin_geometries: Dict[str, List[Tuple[str, db.Shape]]], 40 | top_cell: db.Cell, 41 | output_dir: str, 42 | ) -> None: 43 | # Re-map layers 44 | layout = remap_layers(layout, self.output_map) 45 | 46 | # Set database unit. 47 | # klayout expects dbu to be in µm, the tech file takes it in meters. 48 | layout.dbu = self.db_unit * 1e6 49 | logger.debug("dbu = {} µm".format(layout.dbu)) 50 | 51 | # Possibly scale the layout. 52 | scaling_factor = 1 53 | if scaling_factor != 1: 54 | logger.info("Scaling layout by factor {}".format(scaling_factor)) 55 | layout.transform(db.DCplxTrans(scaling_factor)) 56 | 57 | # Write GDS. 58 | gds_file_name = '{}.gds'.format(top_cell.name) 59 | gds_out_path = os.path.join(output_dir, gds_file_name) 60 | logger.info("Write GDS: %s", gds_out_path) 61 | layout.write(gds_out_path) 62 | -------------------------------------------------------------------------------- /librecell-layout/lclayout/writer/writer.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2019-2020 Thomas Kramer. 3 | # 4 | # This source describes Open Hardware and is licensed under the CERN-OHL-S v2. 5 | # 6 | # You may redistribute and modify this documentation and make products using it 7 | # under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl). 8 | # This documentation is distributed WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, 9 | # INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A PARTICULAR PURPOSE. 10 | # Please see the CERN-OHL-S v2 for applicable conditions. 11 | # 12 | # Source location: https://codeberg.org/tok/librecell 13 | # 14 | from ..layout import layers 15 | from klayout import db 16 | from typing import Dict, List, Tuple, Union 17 | 18 | import logging 19 | 20 | logger = logging.getLogger(__name__) 21 | 22 | 23 | class Writer: 24 | 25 | def write_layout(self, 26 | layout: db.Layout, 27 | pin_geometries: Dict[str, List[Tuple[str, db.Shape]]], 28 | top_cell: db.Cell, 29 | output_dir: str, 30 | ) -> None: 31 | pass 32 | 33 | 34 | def remap_layers(layout: db.Layout, output_map: Dict[str, Union[Tuple[int, int], List[Tuple[int, int]]]]) -> db.Layout: 35 | """ 36 | Rename layer to match the scheme defined in the technology file. 37 | :param layout: 38 | :param output_map: Output mapping from layer names to layer numbers. 39 | :return: 40 | """ 41 | logger.debug("Remap layers.") 42 | layout2 = db.Layout() 43 | 44 | for top1 in layout.each_cell(): 45 | top2 = layout2.create_cell(top1.name) 46 | layer_infos1 = layout.layer_infos() 47 | for layer_info in layer_infos1: 48 | 49 | src_layer = (layer_info.layer, layer_info.datatype) 50 | 51 | if src_layer not in layers.layermap_reverse: 52 | msg = "Layer {} not defined in `layermap_reverse`.".format(src_layer) 53 | logger.warning(msg) 54 | dest_layers = src_layer 55 | else: 56 | src_layer_name = layers.layermap_reverse[src_layer] 57 | 58 | if src_layer_name not in output_map: 59 | msg = "Layer '{}' will not be written to the output. This might be alright though.". \ 60 | format(src_layer_name) 61 | logger.warning(msg) 62 | continue 63 | 64 | dest_layers = output_map[src_layer_name] 65 | 66 | if not isinstance(dest_layers, list): 67 | dest_layers = [dest_layers] 68 | 69 | src_idx = layout.layer(layer_info) 70 | for dest_layer in dest_layers: 71 | dest_idx = layout2.layer(*dest_layer) 72 | top2.shapes(dest_idx).insert(top1.shapes(src_idx)) 73 | 74 | return layout2 75 | -------------------------------------------------------------------------------- /librecell-layout/setup.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2019-2020 Thomas Kramer. 3 | # 4 | # This source describes Open Hardware and is licensed under the CERN-OHL-S v2. 5 | # 6 | # You may redistribute and modify this documentation and make products using it 7 | # under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl). 8 | # This documentation is distributed WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, 9 | # INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A PARTICULAR PURPOSE. 10 | # Please see the CERN-OHL-S v2 for applicable conditions. 11 | # 12 | # Source location: https://codeberg.org/tok/librecell 13 | # 14 | from setuptools import setup, find_packages 15 | 16 | 17 | def readme(): 18 | with open("README.md", "r") as f: 19 | return f.read() 20 | 21 | 22 | setup(name='librecell-layout', 23 | version='0.0.9', 24 | description='CMOS standard cell layout generator.', 25 | long_description=readme(), 26 | long_description_content_type="text/markdown", 27 | keywords='cmos cell generator layout klayout vlsi asic', 28 | classifiers=[ 29 | # 'License :: OSI Approved :: GNU Affero General Public License v3', 30 | 'Development Status :: 3 - Alpha', 31 | 'Topic :: Scientific/Engineering', 32 | 'Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)', 33 | 'Programming Language :: Python :: 3' 34 | ], 35 | url='https://codeberg.org/tok/librecell', 36 | author='T. Kramer', 37 | author_email='code@tkramer.ch', 38 | license='OHL-S v2.0', 39 | packages=find_packages(), 40 | package_data={'': ['examples/*']}, 41 | entry_points={ 42 | 'console_scripts': [ 43 | 'lclayout = lclayout.standalone:main', 44 | # 'drc_cleaner = lclayout.drc_cleaner.standalone:main', 45 | ] 46 | }, 47 | install_requires=[ 48 | 'librecell-common>=0.0.9', 49 | 'toml==0.10.*', 50 | 'klayout==0.26.*', # GPLv3 51 | 'numpy==1.*', # BSD 52 | 'networkx==2.*', # BSD 53 | 'scipy>=1.5.*', # BSD 54 | 'liberty-parser>=0.0.8', # GPLv3 55 | 'pysmt==0.9.*', # Apache-2.0 56 | 'z3-solver==4.8.*', # 57 | ], 58 | zip_safe=False) 59 | -------------------------------------------------------------------------------- /librecell-lib/README.md: -------------------------------------------------------------------------------- 1 | # LibreCell - Lib 2 | Characterization kit for CMOS cells. 3 | 4 | ## Getting started 5 | 6 | See install instructions in top-project. 7 | 8 | ### Characterize a cell 9 | 10 | An ready-to-run example can be found in the `examples` folder. 11 | The script `run_example.sh` should characterize the `INVX1` inverter. 12 | 13 | The following example determines the input capacitances and timing delays of a combinational cell. 14 | 15 | It is assumed that `FreePDK45` is installed in the users home directory. 16 | 17 | Required inputs are: 18 | * --liberty: A template liberty file which defines how the cells should be characterized. 19 | * --include: SPICE files or models to be included. 20 | * --spice: A SPICE file which contains the transistor level circuit of the cell (best including extracted parasitic capacitances). 21 | * --cell: Name of the cell to be characterized. 22 | * --output: Output liberty file which will contain the characterization data. 23 | 24 | Characterize a single cell: 25 | ```sh 26 | lctime --liberty ~/FreePDK45/osu_soc/lib/files/gscl45nm.lib \ 27 | --include ~/FreePDK45/osu_soc/lib/files/gpdk45nm.m \ 28 | --spice ~/FreePDK45/osu_soc/lib/source/netlists/AND2X1.pex.netlist \ 29 | --cell AND2X1 \ 30 | --output /tmp/and2x1.lib 31 | ``` 32 | 33 | Characterize multiple cells in the same run: 34 | ```sh 35 | lctime --liberty ~/FreePDK45/osu_soc/lib/files/gscl45nm.lib \ 36 | --include ~/FreePDK45/osu_soc/lib/files/gpdk45nm.m \ 37 | --spice ~/FreePDK45/osu_soc/lib/source/netlists/*.pex.netlist \ 38 | --cell INVX1 AND2X1 XOR2X1 \ 39 | --output /tmp/invx1_and2x1_xor2x1.lib 40 | ``` 41 | 42 | 43 | Vizualize the result: 44 | ```sh 45 | libertyviz -l /tmp/and2x1.lib --cell AND2X1 --pin Y --related-pin A --table cell_rise 46 | ``` 47 | 48 | ### Characterize a cell with differential inputs 49 | 50 | Differential inputs can be specified in the liberty template with the `complementary_pin` attribute. 51 | Only the non-inverted pin should appear in the liberty file. 52 | 53 | Differential pairs can also be recognized based on their naming. For example if pairs are named with suffixes `_p` for 54 | the non-inverted pin and `_n` for the inverted pin: 55 | 56 | ```sh 57 | lctime --diff %_p,%_n ... 58 | ``` 59 | 60 | ### Merging liberty files 61 | `lctime` will output a liberty file containing only one cell. The `libertymerge` command allows to merge this kind of 62 | output file back into the liberty template. 63 | 64 | The following example will take `base_liberty.lib` as a template and update its `cell` entries with the data found in 65 | the liberty files in the `characterization` directory. 66 | ```sh 67 | libertymerge -b base_liberty.lib \ 68 | -o output_liberty.lib \ 69 | -u characterization/*.lib 70 | ``` 71 | This approach allows to run characterization runs of multiple cells independently and in parallel (e.g using `make`). 72 | 73 | ### Recognize a cell 74 | `lctime` can recognize the boolean function of cells based on the transistor network. Besides combinational functions 75 | also memory-loops can be found and abstracted into latches or flip-flops. 76 | The `sp2bool` command can be used to analyze cells and dump information about their behaviour. This can be useful for debugging and verification. 77 | 78 | Example: 79 | ```sh 80 | # Analyze a combinational cell. 81 | sp2bool sp2bool --spice ~/FreePDK45/osu_soc/lib/files/cells.sp --cell NAND2X1 82 | 83 | # Analyze a flip-flop with asynchronous set and reset signals. 84 | sp2bool sp2bool --spice ~/FreePDK45/osu_soc/lib/files/cells.sp --cell DFFSR 85 | ``` 86 | 87 | For cells with *differential* inputs the `--diff` argument must be used to specify differential pairs. 88 | -------------------------------------------------------------------------------- /librecell-lib/examples/AND2X1.pex.netlist: -------------------------------------------------------------------------------- 1 | * File: AND2X1.pex.netlist 2 | * Created: Wed Jan 2 18:23:33 2008 3 | * Program "Calibre xRC" 4 | * Version "v2007.2_34.24" 5 | * 6 | .subckt AND2X1 A B VDD GND Y 7 | * 8 | MM3 a_9_6# A a_2_6# GND NMOS_VTL L=5e-08 W=5e-07 9 | MM4 GND B a_9_6# GND NMOS_VTL L=5e-08 W=5e-07 10 | MM5 Y a_2_6# GND GND NMOS_VTL L=5e-08 W=2.5e-07 11 | MM0 a_2_6# A VDD VDD PMOS_VTL L=5e-08 W=5e-07 12 | MM1 VDD B a_2_6# VDD PMOS_VTL L=5e-08 W=5e-07 13 | MM2 Y a_2_6# VDD VDD PMOS_VTL L=5e-08 W=5e-07 14 | c_5 A 0 0.103545f 15 | c_10 B 0 0.0927726f 16 | c_16 a_2_6# 0 0.166441f 17 | c_21 VDD 0 0.141663f 18 | c_26 GND 0 0.127034f 19 | c_30 Y 0 0.0559375f 20 | * 21 | *.include "AND2X1.pex.netlist.AND2X1.pxi" 22 | * 23 | .ends 24 | * 25 | * 26 | -------------------------------------------------------------------------------- /librecell-lib/examples/INVX1.pex.netlist: -------------------------------------------------------------------------------- 1 | * File: INVX1.pex.netlist 2 | * Created: Wed Jan 2 18:42:35 2008 3 | * Program "Calibre xRC" 4 | * Version "v2007.2_34.24" 5 | * 6 | .subckt INVX1 A GND VDD Y 7 | * 8 | MM1 Y A GND GND NMOS_VTL L=5e-08 W=2.5e-07 9 | MM0 Y A VDD VDD PMOS_VTL L=5e-08 W=5e-07 10 | c_4 A 0 0.13599f 11 | c_7 GND 0 0.057208f 12 | c_10 VDD 0 0.0986293f 13 | c_14 Y 0 0.0799346f 14 | * 15 | *.include "INVX1.pex.netlist.INVX1.pxi" 16 | * 17 | .ends 18 | * 19 | * 20 | -------------------------------------------------------------------------------- /librecell-lib/examples/invx1_template.lib: -------------------------------------------------------------------------------- 1 | library (gscl45nm) { 2 | capacitive_load_unit (1.0, pf); 3 | current_unit: "1uA"; 4 | default_operating_conditions: typical; 5 | delay_model: table_lookup; 6 | in_place_swap_mode: match_footprint; 7 | input_threshold_pct_fall: 50.0; 8 | input_threshold_pct_rise: 50.0; 9 | leakage_power_unit: "1nW"; 10 | nom_process: 1.0; 11 | nom_temperature: 27.0; 12 | nom_voltage: 1.1; 13 | output_threshold_pct_fall: 50.0; 14 | output_threshold_pct_rise: 50.0; 15 | pulling_resistance_unit: "1kohm"; 16 | slew_lower_threshold_pct_fall: 20.0; 17 | slew_lower_threshold_pct_rise: 20.0; 18 | slew_upper_threshold_pct_fall: 80.0; 19 | slew_upper_threshold_pct_rise: 80.0; 20 | time_unit: "1ns"; 21 | voltage_unit: "1V"; 22 | operating_conditions (typical) { 23 | process: 1.0; 24 | temperature: 27.0; 25 | voltage: 1.1; 26 | } 27 | lu_table_template (delay_template_4x5) { 28 | index_1 ( 29 | "1000.0, 1001.0, 1002.0, 1003.0" 30 | ); 31 | index_2 ( 32 | "1000.0, 1001.0, 1002.0, 1003.0, 1004.0" 33 | ); 34 | variable_1: total_output_net_capacitance; 35 | variable_2: input_net_transition; 36 | } 37 | lu_table_template (delay_template_5x1) { 38 | index_1 ( 39 | "1000.0, 1001.0, 1002.0, 1003.0, 1004.0" 40 | ); 41 | variable_1: input_net_transition; 42 | } 43 | lu_table_template (delay_template_6x1) { 44 | index_1 ( 45 | "1000.0, 1001.0, 1002.0, 1003.0, 1004.0, 1005.0" 46 | ); 47 | variable_1: input_net_transition; 48 | } 49 | lu_table_template (delay_template_6x6) { 50 | index_1 ( 51 | "1000.0, 1001.0, 1002.0, 1003.0, 1004.0, 1005.0" 52 | ); 53 | index_2 ( 54 | "1000.0, 1001.0, 1002.0, 1003.0, 1004.0, 1005.0" 55 | ); 56 | variable_1: total_output_net_capacitance; 57 | variable_2: input_net_transition; 58 | } 59 | power_lut_template (energy_template_4x5) { 60 | index_1 ( 61 | "1000.0, 1001.0, 1002.0, 1003.0" 62 | ); 63 | index_2 ( 64 | "1000.0, 1001.0, 1002.0, 1003.0, 1004.0" 65 | ); 66 | variable_1: total_output_net_capacitance; 67 | variable_2: input_transition_time; 68 | } 69 | power_lut_template (energy_template_6x6) { 70 | index_1 ( 71 | "1000.0, 1001.0, 1002.0, 1003.0, 1004.0, 1005.0" 72 | ); 73 | index_2 ( 74 | "1000.0, 1001.0, 1002.0, 1003.0, 1004.0, 1005.0" 75 | ); 76 | variable_1: total_output_net_capacitance; 77 | variable_2: input_transition_time; 78 | } 79 | lu_table_template (hold_template_3x6) { 80 | index_1 ( 81 | "1000.0, 1001.0, 1002.0" 82 | ); 83 | index_2 ( 84 | "1000.0, 1001.0, 1002.0, 1003.0, 1004.0, 1005.0" 85 | ); 86 | variable_1: related_pin_transition; 87 | variable_2: constrained_pin_transition; 88 | } 89 | power_lut_template (passive_energy_template_5x1) { 90 | index_1 ( 91 | "1000.0, 1001.0, 1002.0, 1003.0, 1004.0" 92 | ); 93 | variable_1: input_transition_time; 94 | } 95 | power_lut_template (passive_energy_template_6x1) { 96 | index_1 ( 97 | "1000.0, 1001.0, 1002.0, 1003.0, 1004.0, 1005.0" 98 | ); 99 | variable_1: input_transition_time; 100 | } 101 | lu_table_template (recovery_template_3x6) { 102 | index_1 ( 103 | "1000.0, 1001.0, 1002.0" 104 | ); 105 | index_2 ( 106 | "1000.0, 1001.0, 1002.0, 1003.0, 1004.0, 1005.0" 107 | ); 108 | variable_1: related_pin_transition; 109 | variable_2: constrained_pin_transition; 110 | } 111 | lu_table_template (recovery_template_6x6) { 112 | index_1 ( 113 | "1000.0, 1001.0, 1002.0, 1003.0, 1004.0, 1005.0" 114 | ); 115 | index_2 ( 116 | "1000.0, 1001.0, 1002.0, 1003.0, 1004.0, 1005.0" 117 | ); 118 | variable_1: related_pin_transition; 119 | variable_2: constrained_pin_transition; 120 | } 121 | lu_table_template (removal_template_3x6) { 122 | index_1 ( 123 | "1000.0, 1001.0, 1002.0" 124 | ); 125 | index_2 ( 126 | "1000.0, 1001.0, 1002.0, 1003.0, 1004.0, 1005.0" 127 | ); 128 | variable_1: related_pin_transition; 129 | variable_2: constrained_pin_transition; 130 | } 131 | lu_table_template (setup_template_3x6) { 132 | index_1 ( 133 | "1000.0, 1001.0, 1002.0" 134 | ); 135 | index_2 ( 136 | "1000.0, 1001.0, 1002.0, 1003.0, 1004.0, 1005.0" 137 | ); 138 | variable_1: related_pin_transition; 139 | variable_2: constrained_pin_transition; 140 | } 141 | cell (INVX1) { 142 | area: 1.4079; 143 | cell_footprint: inv; 144 | pin (A) { 145 | direction: input; 146 | } 147 | pin (Y) { 148 | direction: output; 149 | function: "(!A)"; 150 | } 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /librecell-lib/examples/run_example.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Characterize the INVX1 cell and write the output into invx1.lib. 4 | 5 | lctime --liberty invx1_template.lib \ 6 | --include gpdk45nm.m \ 7 | --spice INVX1.pex.netlist \ 8 | --cell INVX1 \ 9 | --output-loads "0.05, 0.1, 0.2, 0.4, 0.8, 1.6" \ 10 | --slew-times "0.1, 0.2, 0.4, 0.8, 1.6, 3.2" \ 11 | --output invx1.lib 12 | -------------------------------------------------------------------------------- /librecell-lib/lclib/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2019-2020 Thomas Kramer. 3 | # 4 | # This file is part of librecell 5 | # (see https://codeberg.org/tok/librecell). 6 | # 7 | # This program is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | # 20 | name = "lclib" -------------------------------------------------------------------------------- /librecell-lib/lclib/characterization/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2019-2020 Thomas Kramer. 3 | # 4 | # This file is part of librecell 5 | # (see https://codeberg.org/tok/librecell). 6 | # 7 | # This program is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | # 20 | -------------------------------------------------------------------------------- /librecell-lib/lclib/characterization/main_sp2bool.py: -------------------------------------------------------------------------------- 1 | ## 2 | ## Copyright (c) 2019 Thomas Kramer. 3 | ## 4 | ## This file is part of librecell-lib 5 | ## (see https://codeberg.org/tok/librecell/src/branch/master/librecell-lib). 6 | ## 7 | ## This program is free software: you can redistribute it and/or modify 8 | ## it under the terms of the GNU General Public License as published by 9 | ## the Free Software Foundation, either version 3 of the License, or 10 | ## (at your option) any later version. 11 | ## 12 | ## This program is distributed in the hope that it will be useful, 13 | ## but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | ## GNU General Public License for more details. 16 | ## 17 | ## You should have received a copy of the GNU General Public License 18 | ## along with this program. If not, see . 19 | ## 20 | 21 | from liberty import parser as liberty_parser 22 | from liberty.types import * 23 | 24 | from ..liberty import util as liberty_util 25 | from ..logic import functional_abstraction 26 | from ..logic import seq_recognition 27 | from . import util 28 | 29 | import argparse 30 | from copy import deepcopy 31 | from PySpice.Unit import * 32 | from lccommon import net_util 33 | from lccommon.net_util import load_transistor_netlist, is_ground_net, is_supply_net 34 | import networkx as nx 35 | import sympy 36 | import re 37 | 38 | 39 | def main(): 40 | """ 41 | Command-line tool for cell characterization. 42 | Currently only combinatorial cells are supported excluding tri-state cells. 43 | :return: 44 | """ 45 | 46 | logger = logging.getLogger(__name__) 47 | logger.info("sp2bool main function") 48 | 49 | parser = argparse.ArgumentParser( 50 | description='Find boolean formulas that describe the behaviour of a CMOS circuit.', 51 | epilog='Example: sp2bool --spice INVX1.sp --cell INVX1') 52 | 53 | parser.add_argument('--cell', required=True, metavar='CELL_NAME', type=str, help='Cell name.') 54 | 55 | parser.add_argument('--spice', required=True, metavar='SPICE', type=str, 56 | help='SPICE netlist containing a subcircuit with the same name as the cell.') 57 | 58 | parser.add_argument('--diff', required=False, 59 | nargs="+", 60 | metavar='DIFFERENTIAL_PATTERN', 61 | type=str, 62 | help='Specify differential inputs as "NonInverting,Inverting" tuples.' 63 | 'The placeholder "%" can be used like "%_P,%_N" or "%,%_Diff", ...') 64 | 65 | parser.add_argument('--debug', action='store_true', help='Enable debug mode.') 66 | parser.add_argument('--plot-network', action='store_true', 67 | help='Show a plot of the transistor graph for debugging. ' 68 | 'Transistors are edges in the graph. The edges are labelled with the gate net.') 69 | 70 | # Parse arguments 71 | args = parser.parse_args() 72 | 73 | DEBUG = args.debug 74 | log_level = logging.DEBUG if DEBUG else logging.INFO 75 | 76 | if DEBUG: 77 | log_format = '%(module)16s %(levelname)8s: %(message)s' 78 | else: 79 | # Also output name of function in DEBUG mode. 80 | # log_format = '%(module)16s %(funcName)16s %(levelname)8s: %(message)s' 81 | log_format = '%(message)s' 82 | 83 | logging.basicConfig(format=log_format, level=log_level) 84 | 85 | cell_name = args.cell 86 | 87 | # Load netlist of cell 88 | netlist_path = args.spice 89 | logger.info('Load netlist: %s', netlist_path) 90 | transistors_abstract, cell_pins = load_transistor_netlist(netlist_path, cell_name) 91 | io_pins = net_util.get_io_pins(cell_pins) 92 | 93 | logger.info(f"Cell pins: {cell_pins}") 94 | print(transistors_abstract) 95 | 96 | # Detect power pins. 97 | # TODO: don't decide based only on net name. 98 | power_pins = [p for p in cell_pins if net_util.is_power_net(p)] 99 | assert len(power_pins) == 2, "Expected to have 2 power pins." 100 | vdd_pins = [p for p in power_pins if net_util.is_supply_net(p)] 101 | gnd_pins = [p for p in power_pins if net_util.is_ground_net(p)] 102 | assert len(vdd_pins) == 1, "Expected to find one VDD pin but found: {}".format(vdd_pins) 103 | assert len(gnd_pins) == 1, "Expected to find one GND pin but found: {}".format(gnd_pins) 104 | vdd_pin = vdd_pins[0] 105 | gnd_pin = gnd_pins[0] 106 | 107 | logger.info(f"Supply net: {vdd_pin}") 108 | logger.info(f"Ground net: {gnd_pin}") 109 | 110 | # Match differential inputs. 111 | if args.diff is not None: 112 | differential_inputs = util.find_differential_inputs_by_pattern(args.diff, io_pins) 113 | else: 114 | differential_inputs = dict() 115 | 116 | # Sanity check. 117 | if len(set(differential_inputs.keys())) != len(set(differential_inputs.values())): 118 | logger.error(f"Mismatch in the mapping of differential inputs.") 119 | exit(1) 120 | 121 | def _transistors2multigraph(transistors) -> nx.MultiGraph: 122 | """ Create a graph representing the transistor network. 123 | Each edge corresponds to a transistor, each node to a net. 124 | """ 125 | G = nx.MultiGraph() 126 | for t in transistors: 127 | G.add_edge(t.source_net, t.drain_net, (t.gate_net, t.channel_type)) 128 | 129 | connected = list(nx.connected_components(G)) 130 | print(connected) 131 | logger.debug(f"Number of connected graphs: {len(connected)}") 132 | assert nx.is_connected(G) 133 | return G 134 | 135 | # Derive boolean functions for the outputs from the netlist. 136 | logger.info("Derive boolean functions for the outputs based on the netlist.") 137 | transistor_graph = _transistors2multigraph(transistors_abstract) 138 | if args.plot_network: 139 | import matplotlib.pyplot as plt 140 | pos = nx.spring_layout(transistor_graph) 141 | nx.draw(transistor_graph, pos, with_labels=True) 142 | print(list(transistor_graph.edges(keys=True))) 143 | edge_labels = {(a, b): gate_net for a, b, (gate_net, channel_type) in transistor_graph.edges(keys=True)} 144 | nx.draw_networkx_edge_labels(transistor_graph, pos, edge_labels=edge_labels) 145 | plt.show() 146 | abstract = functional_abstraction.analyze_circuit_graph(graph=transistor_graph, 147 | pins_of_interest=io_pins, 148 | constant_input_pins={vdd_pin: True, 149 | gnd_pin: False}, 150 | differential_inputs=differential_inputs, 151 | user_input_nets=None) 152 | output_functions_deduced = abstract.outputs 153 | 154 | # Convert keys into strings (they are `sympy.Symbol`s now) 155 | output_functions_deduced = {output.name: comb.function for output, comb in output_functions_deduced.items()} 156 | 157 | # Log deduced output functions. 158 | for output_name, function in output_functions_deduced.items(): 159 | logger.info("Deduced output function: {} = {}".format(output_name, function)) 160 | 161 | # Try to recognize sequential cells. 162 | seq = seq_recognition.extract_sequential_circuit(abstract) 163 | 164 | if seq is not None: 165 | print() 166 | print(seq) 167 | -------------------------------------------------------------------------------- /librecell-lib/lclib/characterization/ngspice_simulation.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2019-2020 Thomas Kramer. 3 | # 4 | # This file is part of librecell 5 | # (see https://codeberg.org/tok/librecell). 6 | # 7 | # This program is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | # 20 | from PySpice.Probe.Plot import plot 21 | from PySpice.Probe.WaveForm import TransientAnalysis 22 | from PySpice.Spice.Netlist import Circuit 23 | from PySpice.Spice.NgSpice.Shared import NgSpiceShared 24 | from PySpice.Spice.Parser import SpiceParser 25 | from PySpice.Unit import * 26 | from PySpice.Unit.SiUnits import Farad, Second, Volt 27 | from typing import Any, Dict, Union, Optional 28 | 29 | from .piece_wise_linear import PieceWiseLinear 30 | 31 | logger = logging.getLogger(__name__) 32 | 33 | 34 | def simulate_circuit(circuit: Circuit, 35 | input_voltages: Dict[Any, Union[float, PieceWiseLinear]], 36 | step_time: Second, 37 | end_time: Second, 38 | temperature: float = 25, 39 | initial_voltages: Optional[Dict[str, Volt]] = None, 40 | simulator='ngspice-shared'): 41 | """ 42 | Simulate a circuit with given input voltages. 43 | :param circuit: 44 | :param input_voltages: Dict[node name, input voltage] 45 | Input voltages can either be a `float` for constant values or a `.util.PieceWiseLinearWave` 46 | changing wave forms. 47 | :param step_time: Time step of simulation. 48 | :param end_time: End time of simulation. 49 | :param temperature: Simulation temperature. 50 | :param initial_voltages: Dict[node name, voltage]. 51 | Initial voltages for nodes. Default = None. 52 | :param simulator: Choose the simulator. 53 | One of {'ngspice-shared', 'ngspice-subprocess', 'xyce-serial', 'xyce-parallel'} 54 | :return: PySpice Analysis object. 55 | """ 56 | circuit = circuit.clone() 57 | 58 | logger.info("Instantiate ngspice simulator.") 59 | # ngspice_shared = NgSpiceShared.new_instance(send_data=False) 60 | # simulator = circuit.simulator(temperature=temperature, 61 | # nominal_temperature=temperature, 62 | # simulator='ngspice-shared', 63 | # ngspice_shared=ngspice_shared 64 | # ) 65 | 66 | simulator = circuit.simulator(temperature=temperature, 67 | nominal_temperature=temperature, 68 | simulator=simulator 69 | ) 70 | 71 | # Create input drivers. 72 | # This will be either constant voltages for static input signals or piece-wise linear sources for dynamic inputs. 73 | logger.debug("Create input drivers.") 74 | for name, voltage in input_voltages.items(): 75 | if isinstance(voltage, PieceWiseLinear): 76 | piece_wise_linear_voltage_source(circuit, 'in_{}'.format(name), name, circuit.gnd, 77 | voltage 78 | ) 79 | # simulator.initial_condition(**{name: voltage(0) @ u_V}) 80 | else: 81 | # simulator.initial_condition(**{name: voltage @ u_V}) 82 | circuit.V('in_{}'.format(name), name, circuit.gnd, voltage @ u_V) 83 | 84 | if initial_voltages is not None: 85 | simulator.initial_condition(**initial_voltages) 86 | 87 | # Run transient analysis. 88 | # Set use_initial_condition (uic) to False to enable DC bias computation. See ngspice manual 15.2.2 2) 89 | logger.info("Run transient analysis. step_time = {}, end_time = {}".format(step_time, end_time)) 90 | 91 | analysis = simulator.transient(step_time=step_time, 92 | end_time=end_time, 93 | use_initial_condition=False 94 | ) 95 | logger.info("Transient analysis done.") 96 | return analysis 97 | 98 | 99 | def piece_wise_linear_voltage_source(circuit: Circuit, name: str, plus, minus, wave: PieceWiseLinear, 100 | repeat=None, time_delay=None): 101 | """ Create a piece wise linear voltage source. 102 | This is a helper function needed because PWL sources are not properly handled by PySpice at time of this writing. 103 | 104 | :param circuit: The netlist to add the source. 105 | :param name: Name of the voltage source. 106 | :param plus: Positive terminal. 107 | :param minus: Negative terminal. 108 | :param times: Time axis. 109 | :param voltages: Voltage axis. 110 | :param repeat: Number of times the sequence should be repeated. Default = 1. 0 means endless repetition. 111 | :param time_delay: Delay the signal by this amount of time. Default = 0. 112 | :return: Return a handle to the generated voltages source. 113 | """ 114 | pwl_string = ' '.join(( 115 | '%es %eV' % (float(time), float(voltage)) 116 | for time, voltage in zip(wave.x, wave.y) 117 | )) 118 | 119 | pwl_args = [] 120 | if repeat is not None: 121 | pwl_args.append('r={}'.format(repeat)) 122 | if time_delay is not None: 123 | pwl_args.append('td={}'.format(float(time_delay))) 124 | 125 | return circuit.V(name, plus, minus, 126 | 'PWL({}) DC=0'.format(' '.join([pwl_string] + pwl_args)) 127 | ) 128 | -------------------------------------------------------------------------------- /librecell-lib/lclib/characterization/test_ngspice_shared.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2019-2020 Thomas Kramer. 3 | # 4 | # This file is part of librecell 5 | # (see https://codeberg.org/tok/librecell). 6 | # 7 | # This program is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | # 20 | from PySpice.Spice.Netlist import Circuit 21 | from PySpice.Spice.NgSpice.Shared import NgSpiceShared 22 | from PySpice.Spice.Parser import SpiceParser 23 | from PySpice.Unit import * 24 | from PySpice.Unit.SiUnits import Farad, Second 25 | 26 | import PySpice.Logging.Logging as Logging 27 | import numpy as np 28 | 29 | from .ngspice_simulation import piece_wise_linear_voltage_source 30 | from .piece_wise_linear import PieceWiseLinear 31 | 32 | import matplotlib.pyplot as plt 33 | 34 | 35 | # def test_simulate_circuit(): 36 | # time_step = 1 @ u_ms 37 | # end_time = 10 @ u_s 38 | # 39 | # circuit = Circuit(title='test1') 40 | # 41 | # # circuit.V('VDD', 'vdd', circuit.gnd, 10 @ u_V) 42 | # circuit.R('1', 'input', 'a', 1 @ u_kOhm) 43 | # circuit.C('1', circuit.gnd, 'a', 1000 @ u_uF) 44 | # 45 | # ngspice_shared = NgSpiceShared.new_instance(send_data=False) 46 | # 47 | # piece_wise_linear_voltage_source(circuit, 'src', 'input', circuit.gnd, 48 | # PieceWiseLinear([0, 1, 2, 10], [0, 1, 1, 1])) 49 | # 50 | # # simulator = circuit.simulator(temperature=25, 51 | # # nominal_temperature=25, 52 | # # simulator='ngspice-shared', 53 | # # ngspice_shared=ngspice_shared) 54 | # 55 | # ngspice_shared.stop('v(a) > 0.5') 56 | # # ngspice_shared.destroy() 57 | # # print(str(simulator)) 58 | # # ngspice_shared.load_circuit(str(simulator)) 59 | # # ngspice_shared.run() 60 | # # analysis = ngspice_shared.plot(simulator, 'asdf').to_analysis() 61 | # 62 | # simulator = circuit.simulator(temperature=25, 63 | # nominal_temperature=25, 64 | # simulator='ngspice-shared', 65 | # ngspice_shared=ngspice_shared) 66 | # analysis = simulator.transient(step_time=time_step, end_time=end_time) 67 | # 68 | # print(np.array(analysis['a'])) 69 | # 70 | # # plt.plot(analysis['a']) 71 | # # plt.plot(analysis['input']) 72 | # # plt.show() 73 | 74 | 75 | # def test_simulate_circuit_lowlevel_control(): 76 | # """ 77 | # Use `NgSpiceShared` to get finer grained control over the simulation. 78 | # Especially needed for breakpoints. 79 | # """ 80 | # circuit = Circuit(title='test2') 81 | # 82 | # circuit.R('1', 'input', 'a', 1 @ u_kOhm) 83 | # circuit.C('1', circuit.gnd, 'a', 1000 @ u_uF) 84 | # 85 | # # piece_wise_linear_voltage_source(circuit, 'src', 'input', circuit.gnd, 86 | # # PieceWiseLinear([0, 1, 2, 10], [0, 1, 1, 0])) 87 | # circuit.V('src', 'input', circuit.gnd, 0) 88 | # 89 | # ngs = NgSpiceShared.new_instance(send_data=False) 90 | # 91 | # ngs.destroy() 92 | # ngs.remove_circuit() 93 | # 94 | # netlist = "{}\n.end".format(str(circuit)) 95 | # print(netlist) 96 | # ngs.load_circuit(netlist) 97 | # # Change capacitance. 98 | # # ngs.alter_device('C1', C="1000uF") 99 | # # Change signal of piece wise linar voltage source.. 100 | # wave = PieceWiseLinear([0, 1, 10], [0, 1, 1]) 101 | # pwl_string = ' '.join(( 102 | # '%es %eV' % (float(time), float(voltage)) 103 | # for time, voltage in zip(wave.x, wave.y) 104 | # )) 105 | # ngs.alter_device('Vsrc', PWL="({})".format(pwl_string)) 106 | # 107 | # # Set temperature. 108 | # ngs.option(temp=25) 109 | # ngs.option(nomtemp=25) 110 | # # Set breakpoint. 111 | # ngs.stop('v(a) > 0.9') 112 | # # Run simulation. 113 | # ngs.exec_command("tran 100ms 60s") 114 | # ngs.run(background=False) 115 | # 116 | # # Retreive signals. 117 | # plot_name = ngs.last_plot 118 | # print(plot_name) 119 | # if plot_name == 'const': 120 | # raise Exception("Simulation failed.") 121 | # plot = ngs.plot(None, plot_name) 122 | # analysis = plot.to_analysis() 123 | # 124 | # print(np.array(analysis['a'])) 125 | # plt.plot(analysis.time, analysis['input'], 'x-') 126 | # plt.plot(analysis.time, np.array(analysis['a']), 'x-') 127 | # plt.show() 128 | 129 | 130 | def test3(): 131 | 132 | netlist = r""".title Input capacitance measurement for pin "A" 133 | .include /home/kramert/unison/local/blackbird/git/librecell-examples/librecell_invx1_example/gpdk45nm.m 134 | .include /home/kramert/unison/local/blackbird/git/librecell-examples/librecell_invx1_example/INVX1.pex.netlist 135 | Xcircuit_unter_test A GND VDD Y INVX1 136 | Vpower_vdd VDD GND 1.1V 137 | Isrc_A GND A 10000nA 138 | 139 | .end 140 | 141 | """ 142 | ngs = NgSpiceShared.new_instance(send_data=False) 143 | 144 | ngs.destroy() 145 | ngs.remove_circuit() 146 | 147 | print(netlist) 148 | ngs.load_circuit(netlist) 149 | 150 | # Run simulation. 151 | ngs.exec_command("tran 1ns 100ns") 152 | ngs.run(background=False) 153 | 154 | # Retreive signals. 155 | plot_name = ngs.last_plot 156 | print(plot_name) 157 | if plot_name == 'const': 158 | raise Exception("Simulation failed.") 159 | plot = ngs.plot(None, plot_name) 160 | analysis = plot.to_analysis() 161 | 162 | plt.plot(analysis.time, analysis['y'], 'x-') 163 | plt.plot(analysis.time, np.array(analysis['a']), 'x-') 164 | plt.show() -------------------------------------------------------------------------------- /librecell-lib/lclib/characterization/test_ngspice_subprocess.py: -------------------------------------------------------------------------------- 1 | import tempfile 2 | import subprocess 3 | import numpy as np 4 | import matplotlib.pyplot as plt 5 | import os 6 | 7 | 8 | def test_simple_simulation(): 9 | """Run a simple transient simulation in a ngspice subprocess and retreive the results from a file.""" 10 | 11 | sim_file = tempfile.mktemp() 12 | sim_output_file = tempfile.mktemp() 13 | 14 | spice_simulation_netlist = f""" 15 | * 16 | .title Simple RC circuit. 17 | 18 | R1 VDD Y 1k 19 | C1 Y GND 1u ic=0V 20 | Vsrc_vdd VDD GND PWL(0 0 1ms 0V 2ms 1V) 21 | 22 | .control 23 | *option abstol=10e-15 24 | *option reltol=10e-11 25 | set filetype=ascii 26 | * Enable output of vector names in the first line. 27 | set wr_vecnames 28 | tran 1ms 10ms 29 | wrdata {sim_output_file} v(VDD) v(Y) 30 | exit 31 | .endc 32 | 33 | .end 34 | """ 35 | print(f"Write simulation file: {sim_file}") 36 | open(sim_file, 'w').write(spice_simulation_netlist) 37 | 38 | # Run simulation. 39 | ret = subprocess.run(["ngspice", sim_file]) 40 | print(f"Subprocess return value: {ret}") 41 | if ret.returncode != 0: 42 | print(f"ngspice simulation failed: {ret}") 43 | assert ret.returncode == 0 44 | 45 | print(f"Read output data: {sim_output_file}") 46 | data = np.loadtxt(sim_output_file, skiprows=1) # Skip the header. 47 | 48 | a_time = data[:, 0] 49 | a = data[:, 1] 50 | 51 | y_time = data[:, 2] 52 | y = data[:, 3] 53 | 54 | assert all(a_time == y_time) 55 | 56 | plt.plot(a_time, a, 'x-') 57 | plt.plot(y_time, y, 'x-') 58 | plt.show() 59 | 60 | os.remove(sim_output_file) 61 | os.remove(sim_file) 62 | -------------------------------------------------------------------------------- /librecell-lib/lclib/liberty/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2019-2020 Thomas Kramer. 3 | # 4 | # This file is part of librecell 5 | # (see https://codeberg.org/tok/librecell). 6 | # 7 | # This program is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | # 20 | -------------------------------------------------------------------------------- /librecell-lib/lclib/liberty/merge.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2019-2020 Thomas Kramer. 3 | # 4 | # This file is part of librecell 5 | # (see https://codeberg.org/tok/librecell). 6 | # 7 | # This program is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | # 20 | """ 21 | Tool for merging liberty libraries. 22 | """ 23 | 24 | from liberty.parser import parse_liberty 25 | from liberty.types import Group 26 | from typing import List 27 | import argparse 28 | import logging 29 | from itertools import chain 30 | from copy import copy 31 | import os 32 | 33 | logger = logging.getLogger(__name__) 34 | 35 | 36 | def add_named_group(base_library: Group, replacement: Group, replace_if_already_exists: bool = False) -> None: 37 | """ 38 | Add or replace a named group in the base library. The name of the group is `group.args[0]`. 39 | If the group does not yet exist it will be appended to the base library. If it exists, then 40 | depending on `replace_if_already_exists` the existing group will be replaced with the `replacement`. 41 | :param base_library: Group container to be updated. 42 | :param replacement: 43 | :param replace_if_already_exists: 44 | :return: None 45 | """ 46 | cell_name = replacement.args[0] 47 | 48 | for i in range(len(base_library.groups)): 49 | g = base_library.groups[i] 50 | if g.group_name == replacement.group_name and g.args[0] == cell_name: 51 | if replace_if_already_exists: 52 | logger.info("Replace group: {}({})".format(replacement.group_name, replacement.args[0])) 53 | base_library.groups[i] = replacement 54 | return 55 | 56 | # If cell has not been replaced append the new cell. 57 | logger.info("Add group: {}({})".format(replacement.group_name, replacement.args[0])) 58 | base_library.groups.append(replacement) 59 | 60 | 61 | def add_named_groups(base_library: Group, replacements: List[Group], replace_if_already_exists: bool = False) -> None: 62 | for repl in replacements: 63 | add_named_group(base_library, repl, replace_if_already_exists) 64 | 65 | 66 | def main(): 67 | """ 68 | Command-line for merging liberty libraries. 69 | :return: 70 | """ 71 | 72 | logger = logging.getLogger(__name__) 73 | 74 | parser = argparse.ArgumentParser(description='Merge liberty libraries. The content of the base library will' 75 | 'be replaced by the content in the update libraries.') 76 | 77 | parser.add_argument('-b', '--base', required=True, metavar='LIBERTY_BASE', type=str, help='Base liberty file.') 78 | 79 | parser.add_argument('-o', '--output', required=True, metavar='LIBERTY_OUT', type=str, help='Output liberty file.') 80 | 81 | parser.add_argument('-u', '--update', required=False, action='append', nargs='+', metavar='LIBERTY', type=str, 82 | help='Liberty files with updates.') 83 | 84 | parser.add_argument('--debug', action='store_true', help='Enable debug mode.') 85 | parser.add_argument('--force', action='store_true', help='Allow overwriting of output file.') 86 | 87 | merge_modes = {'replace_cells'} 88 | 89 | parser.add_argument('--merge', default='replace_cells', 90 | required=False, choices=merge_modes, 91 | metavar='MERGE_MODE', type=str, help='Choose how to merge.') 92 | 93 | # Parse arguments 94 | args = parser.parse_args() 95 | 96 | DEBUG = args.debug 97 | log_level = logging.DEBUG if DEBUG else logging.INFO 98 | 99 | logging.basicConfig(format='%(levelname)8s: %(message)s', level=log_level) 100 | 101 | # Check if output would overwrite something. 102 | if not args.force and os.path.exists(args.output): 103 | logger.error("Output file exists. Use --force to overwrite it.") 104 | exit(1) 105 | 106 | # Read base liberty. 107 | base_lib_file = args.base 108 | with open(base_lib_file) as f: 109 | logger.info("Reading base liberty: {}".format(base_lib_file)) 110 | data = f.read() 111 | base_library = parse_liberty(data) 112 | 113 | # Read updates 114 | update_libraries = [] 115 | for lib_file in chain(*args.update): 116 | with open(lib_file) as f: 117 | logger.info("Reading liberty: {}".format(lib_file)) 118 | data = f.read() 119 | lib = parse_liberty(data) 120 | update_libraries.append(lib) 121 | 122 | if args.merge == 'replace_cells': 123 | 124 | new_library = copy(base_library) 125 | 126 | # Add updates to new library. 127 | for lib in update_libraries: 128 | # Add cell groups 129 | add_named_groups(new_library, lib.get_groups('cell'), replace_if_already_exists=True) 130 | 131 | # Add non-existent lookup table groups 132 | add_named_groups(new_library, lib.get_groups('lu_table_template'), replace_if_already_exists=False) 133 | add_named_groups(new_library, lib.get_groups('power_lut_template'), replace_if_already_exists=False) 134 | 135 | num_cells_old = len(base_library.get_groups('cell')) 136 | num_cells_new = len(new_library.get_groups('cell')) 137 | 138 | logger.info("Number of cells in base: {}, number of cells in output: {}".format(num_cells_old, num_cells_new)) 139 | 140 | with open(args.output, 'w') as f: 141 | logger.info('Write liberty: {}'.format(args.output)) 142 | f.write(str(new_library)) 143 | -------------------------------------------------------------------------------- /librecell-lib/lclib/liberty/util.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2019-2020 Thomas Kramer. 3 | # 4 | # This file is part of librecell 5 | # (see https://codeberg.org/tok/librecell). 6 | # 7 | # This program is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | # 20 | from liberty.types import Group 21 | from liberty.parser import parse_boolean_function 22 | import sympy 23 | from sympy.utilities.lambdify import lambdify 24 | import logging 25 | 26 | logger = logging.getLogger(__name__) 27 | 28 | 29 | def get_pin_information(cell_group: Group): 30 | """ 31 | Get a list of input pins, output pins and the logic functions of output pins. 32 | :param cell_group: 33 | :return: (list of input pins, list of output pins, Dict[output pin, logic function]) 34 | """ 35 | input_pins = [] 36 | output_pins = [] 37 | output_functions = dict() 38 | for pin_group in cell_group.get_groups('pin'): 39 | # Get pin name 40 | pin_name = pin_group.args[0] 41 | 42 | # Get direction of pin (input/output) 43 | direction = pin_group.get('direction', None) 44 | 45 | # Get boolean function of pin (for outputs). 46 | expr = pin_group.get_boolean_function('function') 47 | if expr is not None: 48 | output_functions[pin_name] = expr 49 | else: 50 | # Assert that for all output pins the logic function is defined. 51 | if direction == 'output': 52 | msg = 'Output pin has no function defined: {}'.format(pin_name) 53 | logger.info(msg) 54 | expr = '' 55 | 56 | logger.info("Pin '{}' {} {}". 57 | format(pin_name, direction, expr) 58 | ) 59 | 60 | # Check that pin direction is defined. 61 | if direction is None: 62 | logger.warning("Pin has undefined direction: {}/{}".format(cell_group.args[0], pin_name)) 63 | 64 | # Remember input and output pins. 65 | if direction == 'input': 66 | input_pins.append(pin_name) 67 | elif direction == 'output': 68 | output_pins.append(pin_name) 69 | else: 70 | logger.warning("Pin direction type not handled: {}".format(direction)) 71 | 72 | return input_pins, output_pins, output_functions 73 | -------------------------------------------------------------------------------- /librecell-lib/lclib/liberty/visualize.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2019-2020 Thomas Kramer. 3 | # 4 | # This file is part of librecell 5 | # (see https://codeberg.org/tok/librecell). 6 | # 7 | # This program is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | # 20 | from liberty.parser import parse_liberty 21 | 22 | from liberty.types import * 23 | import matplotlib.pyplot as plt 24 | from mpl_toolkits.mplot3d import Axes3D 25 | import numpy as np 26 | 27 | import argparse 28 | import logging 29 | 30 | logger = logging.getLogger(__name__) 31 | 32 | 33 | def main_plot_timing(): 34 | """ 35 | Command-line tool to visualize NDLM timing models in liberty files. 36 | :return: 37 | """ 38 | parser = argparse.ArgumentParser(description='Visualize NDLM timing arrays in liberty files.') 39 | parser.add_argument('-l', '--liberty', required=True, metavar='LIBERTY', type=str, help='Liberty file.') 40 | parser.add_argument('--debug', action='store_true', help='Enable debug mode.') 41 | parser.add_argument('--cell', required=True, metavar='CELL_NAME', type=str, help='Cell name.') 42 | parser.add_argument('--pin', required=True, metavar='PIN_NAME', type=str, help='Pin name.') 43 | parser.add_argument('--related-pin', required=True, metavar='RELATED_PIN_NAME', type=str, 44 | help='Related pin name.') 45 | parser.add_argument('--timing-type', required=False, default=None, metavar='TIMING_TYPE', type=str, 46 | help='Value of timing_type attribute.') 47 | 48 | parser.add_argument('--table', required=True, metavar='TABLE_NAME', type=str, 49 | help='Type of table: cell_rise, cell_fall, rise_transition, fall_transition, ...') 50 | 51 | # Parse arguments 52 | args = parser.parse_args() 53 | 54 | DEBUG = args.debug 55 | log_level = logging.DEBUG if DEBUG else logging.INFO 56 | 57 | logging.basicConfig(format='%(module)16s %(levelname)8s: %(message)s', level=log_level) 58 | 59 | lib_file = args.liberty 60 | 61 | logger.info("Reading liberty: {}".format(lib_file)) 62 | with open(lib_file) as f: 63 | data = f.read() 64 | 65 | library = parse_liberty(data) 66 | 67 | num_cells = len([g for g in library.get_groups('cell')]) 68 | logger.info("Number of cells: {}".format(num_cells)) 69 | 70 | cell = select_cell(library, args.cell) 71 | pin = select_pin(cell, args.pin) 72 | 73 | timing_table = select_timing_table(pin, related_pin=args.related_pin, 74 | timing_type=args.timing_type, 75 | table_name=args.table) 76 | 77 | plot_timing_ndlm(library, timing_table) 78 | 79 | 80 | def plot3d(x_axis: np.ndarray, y_axis: np.ndarray, z_data: np.ndarray, 81 | x_label="", 82 | y_label="", 83 | z_label=""): 84 | """ 85 | Show a 3D surface plot. 86 | :param x_axis: 87 | :param y_axis: 88 | :param z_data: 89 | :param x_label: 90 | :param y_label: 91 | :param z_label: 92 | :return: 93 | """ 94 | xx, yy = np.meshgrid(x_axis, y_axis) 95 | 96 | fig = plt.figure() 97 | ax = fig.gca(projection='3d') 98 | ax.set_xlabel(x_label) 99 | ax.set_ylabel(y_label) 100 | ax.set_zlabel(z_label) 101 | 102 | ax.plot_surface(xx, yy, z_data) 103 | plt.show() 104 | 105 | 106 | def plot_timing_ndlm(library: Group, table: Group): 107 | """ 108 | Plot a NDLM timing table. 109 | :param library: 110 | :param table: 111 | :return: 112 | """ 113 | 114 | x_axis = table.get_array('index_2') 115 | y_axis = table.get_array('index_1') 116 | z_data = table.get_array('values') 117 | 118 | template_name = table.args[0] 119 | template = library.get_group('lu_table_template', template_name) 120 | 121 | time_unit = library['time_unit'].value 122 | 123 | x_label = template['variable_2'] 124 | y_label = template['variable_1'] 125 | 126 | z_label = "[{}]".format(time_unit) 127 | 128 | plot3d(x_axis, y_axis, z_data, x_label=x_label, y_label=y_label, z_label=z_label) 129 | 130 | 131 | def test_plot_nldm(): 132 | import os.path 133 | lib_file = os.path.join(os.path.dirname(__file__), '../../test_data/gscl45nm.lib') 134 | 135 | data = open(lib_file).read() 136 | 137 | library = parse_liberty(data) 138 | 139 | cell = select_cell(library, 'INVX2') 140 | pin = select_pin(cell, 'Y') 141 | 142 | timing_table = select_timing_table(pin, 'A', 'rise_transition') 143 | 144 | plot_timing_ndlm(library, timing_table) 145 | -------------------------------------------------------------------------------- /librecell-lib/lclib/logic/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2019-2020 Thomas Kramer. 3 | # 4 | # This file is part of librecell 5 | # (see https://codeberg.org/tok/librecell). 6 | # 7 | # This program is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | # 20 | -------------------------------------------------------------------------------- /librecell-lib/lclib/logic/cmos_sim.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2019-2020 Thomas Kramer. 3 | # 4 | # This file is part of librecell 5 | # (see https://codeberg.org/tok/librecell). 6 | # 7 | # This program is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | # 20 | import networkx as nx 21 | from itertools import product 22 | from typing import Any, Dict, List, Iterable, Tuple 23 | from enum import Enum 24 | 25 | import sympy 26 | from sympy.logic import SOPform 27 | 28 | from lclayout.data_types import ChannelType 29 | 30 | 31 | class Signal(Enum): 32 | LOW = 0 33 | HIGH = 1 34 | X = 2 35 | Z = 3 36 | SHORT = 4 37 | 38 | 39 | def extract_output_node_from_cmos_graph(cmos_graph: nx.MultiGraph) -> Any: 40 | """ Find the output node of the CMOS network 41 | by finding the only node which connects to both n-channel and p-channel Transistors. 42 | :param cmos_graph: nx.MultiGraph 43 | The CMOS network. Edges represent transistors. Each edge key has the form (input name, ChannelType). 44 | :return: Returns the node of the output signal. 45 | """ 46 | 47 | pn_nodes = [n for n in cmos_graph if 48 | len(set((ch for _, _, (_, ch) in cmos_graph.edges(n, keys=True)))) > 1 49 | ] 50 | assert len(pn_nodes) == 1, "Number of nodes connecting to n-channel and p-channel transistor must be exactly 1." 51 | output_node = pn_nodes[0] 52 | return output_node 53 | 54 | 55 | def evaluate_cmos_graph(cmos_graph: nx.MultiGraph, vdd_node, gnd_node, output_node, 56 | input_names: List, 57 | inputs: Iterable[List[bool]]) -> List[Signal]: 58 | """ Simulate a CMOS graph using a simple switch model for the transistors. 59 | The must be build from a pull-up and a pull-down network. 60 | 61 | :param cmos_graph: Transistor network. Each edge represents a transistor. Edge key must be a tuple (input signal name, ChannelType). 62 | :param vdd_node: The vdd node in `cmos_graph`. 63 | :param gnd_node: The gnd node in `cmos_graph`. 64 | :param output_node: The output node in `cmos_graph`. 65 | :param input_names: An list of input names. 66 | :param inputs: Iterable[List[bool]] 67 | A sequence of input signal assignments. The ordering of the bools must maatch `input_names`. 68 | :return: Returns a list of outputs for each input assignment. Each element will be Signal.LOW, Signal.HIGH, Signal.Z or Signal.SHORT. 69 | Signal.Z: Neither pull-up nor pull-down network is conductive. 70 | Signal.SHORT: Both pull-up and pull-down network are conductive. 71 | """ 72 | 73 | assert nx.is_connected(cmos_graph), '`cmos_graph` must be connected.' 74 | g = cmos_graph.copy() 75 | g.remove_node(output_node) 76 | assert not nx.is_connected(g), '`cmos_graph` is not a pull-up pull-down graph.' 77 | 78 | output_node_exp = extract_output_node_from_cmos_graph(cmos_graph) 79 | assert output_node == output_node_exp 80 | 81 | def _eval_cmos_graph(cmos_graph, input_mapping): 82 | g_eval = cmos_graph.copy() 83 | 84 | for a, b, (input_signal, channel_type) in cmos_graph.edges(keys=True): 85 | inp = input_mapping[input_signal] 86 | 87 | if channel_type == ChannelType.PMOS: 88 | # Invert for pmos transistors. 89 | inp = not inp 90 | 91 | if not inp: 92 | g_eval.remove_edge(a, b) 93 | 94 | is_pulling_up = nx.has_path(g_eval, vdd_node, output_node) 95 | is_pulling_down = nx.has_path(g_eval, gnd_node, output_node) 96 | 97 | if is_pulling_up and is_pulling_down: 98 | return Signal.SHORT 99 | 100 | if not is_pulling_up and not is_pulling_down: 101 | return Signal.Z 102 | 103 | if is_pulling_down: 104 | return Signal.LOW 105 | 106 | if is_pulling_up: 107 | return Signal.HIGH 108 | 109 | assert False 110 | 111 | outputs = [] 112 | for inp in inputs: 113 | input_mapping = {k: v for k, v in zip(input_names, inp)} 114 | out = _eval_cmos_graph(cmos_graph, input_mapping) 115 | outputs.append(out) 116 | 117 | return outputs 118 | 119 | 120 | def test_evaluate_cmos_graph(): 121 | # Create CMOS network of a nand gate and check if `evaluate_cmos_graph` behaves like the nand function. 122 | g = nx.MultiGraph() 123 | g.add_edge('vdd', 'output', ('a', ChannelType.PMOS)) 124 | g.add_edge('vdd', 'output', ('b', ChannelType.PMOS)) 125 | g.add_edge('gnd', '1', ('a', ChannelType.NMOS)) 126 | g.add_edge('1', 'output', ('b', ChannelType.NMOS)) 127 | 128 | input_names = ['a', 'b'] 129 | n = len(input_names) 130 | inputs = list(product(*([[0, 1]] * n))) 131 | 132 | # reference logic function 133 | def f(a, b): 134 | return not (a and b) 135 | 136 | outputs = evaluate_cmos_graph(g, 'vdd', 'gnd', 'output', input_names, inputs) 137 | 138 | outputs_expected = [Signal.HIGH if f(*inp) else Signal.LOW for inp in inputs] 139 | 140 | assert outputs == outputs_expected 141 | 142 | 143 | def minterms_from_cmos_graph(cmos_graph: nx.MultiGraph, vdd_node, gnd_node, output_node, input_names: List) \ 144 | -> List[Tuple]: 145 | """ Simulate a CMOS network with all possible inputs and return a list of inputs that lead to a HIGH output. 146 | :param cmos_graph: 147 | :param vdd_node: 148 | :param gnd_node: 149 | :param output_node: 150 | :param input_names: 151 | :return: 152 | """ 153 | # Grab input names 154 | # input_names = [input_name for _,_,(input_name,_) in cmos_graph.edges(keys=True)] 155 | 156 | n = len(input_names) 157 | inputs = list(product(*([[0, 1]] * n))) 158 | 159 | outputs = evaluate_cmos_graph(cmos_graph, vdd_node, gnd_node, output_node, input_names, inputs) 160 | 161 | return [inp for inp, o in zip(inputs, outputs) if o == Signal.HIGH] 162 | 163 | 164 | def cmos_graph_to_formula(cmos_graph: nx.MultiGraph, vdd_node, gnd_node, output_node, 165 | input_names: List) -> sympy.Symbol: 166 | """ 167 | Find the boolean formula implemented by the push-pull network `cmos_graph`. 168 | :param cmos_graph: 169 | :param vdd_node: 170 | :param gnd_node: 171 | :param output_node: 172 | :param input_names: Ordering of input names. 173 | :return: sympy.Symbol 174 | """ 175 | minterms = minterms_from_cmos_graph(cmos_graph, vdd_node, gnd_node, output_node, input_names) 176 | dontcares = [] 177 | input_symbols = [sympy.Symbol(n) for n in input_names] 178 | sop = SOPform(input_symbols, minterms, dontcares) 179 | sop = sympy.simplify_logic(sop) 180 | 181 | return sop 182 | 183 | 184 | def test_cmos_graph_to_formula(): 185 | # Create CMOS network of a nand gate and check if `evaluate_cmos_graph` behaves like the nand function. 186 | g = nx.MultiGraph() 187 | g.add_edge('vdd', 'output', ('a', ChannelType.PMOS)) 188 | g.add_edge('vdd', 'output', ('b', ChannelType.PMOS)) 189 | g.add_edge('gnd', '1', ('a', ChannelType.NMOS)) 190 | g.add_edge('1', 'output', ('b', ChannelType.NMOS)) 191 | 192 | input_names = ['a', 'b'] 193 | 194 | formula = cmos_graph_to_formula(g, 'vdd', 'gnd', 'output', input_names) 195 | 196 | a, b = sympy.symbols('a b') 197 | assert formula.equals(~(a & b)), "Transformation of CMOS graph into formula failed." 198 | -------------------------------------------------------------------------------- /librecell-lib/lclib/logic/graph_enumeration.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2019-2020 Thomas Kramer. 3 | # 4 | # This file is part of librecell 5 | # (see https://codeberg.org/tok/librecell). 6 | # 7 | # This program is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | # 20 | # import sympy 21 | # from sympy.logic.boolalg import to_cnf, to_dnf 22 | # from sympy.logic import POSform, SOPform 23 | # from sympy.utilities.lambdify import lambdify 24 | 25 | from itertools import chain, product, count, combinations 26 | 27 | import networkx as nx 28 | 29 | from typing import Any, Dict, Tuple, List, Iterable 30 | 31 | from lclayout.data_types import Transistor, ChannelType 32 | 33 | import logging 34 | 35 | logger = logging.getLogger(__name__) 36 | 37 | 38 | def is_unique_under_isomorphism(g: nx.Graph, references: Iterable[nx.Graph]): 39 | def node_match(attr1, attr2): 40 | return attr1.get('type', None) == attr2.get('type', None) 41 | 42 | return not any((nx.is_isomorphic(g, ref, node_match=node_match) for ref in references)) 43 | 44 | 45 | def enum_graphs(max_path_len: int) -> List[Tuple[nx.Graph, Dict[Any, int]]]: 46 | assert max_path_len >= 0 47 | 48 | if max_path_len == 0: 49 | # Create graph with maximum path length = 0. 50 | g = nx.Graph() 51 | g.add_node("source", type="source") 52 | return [(nx.Graph(), {"source": 0})] 53 | else: 54 | prev = enum_graphs(max_path_len - 1) 55 | 56 | graphs = [] 57 | 58 | for g, distances in prev: 59 | d_max = max(distances.values()) 60 | d_max_nodes = [n for n, d in distances.items() if d == d_max] 61 | assert len(d_max_nodes) == 1 62 | d_max_node = d_max_nodes[0] 63 | 64 | non_dmax_nodes = [n for n, d in distances.items() if d < d_max] 65 | 66 | name_counter = count() 67 | for i in range(len(non_dmax_nodes) + 1): 68 | for comb in combinations(non_dmax_nodes, i): 69 | 70 | g_new = g.copy() 71 | distances_new = distances.copy() 72 | new_node = "{}_{}".format(d_max + 1, next(name_counter)) 73 | g_new.add_node(new_node) 74 | g_new.add_edge(new_node, d_max_node) 75 | distances_new[new_node] = d_max + 1 76 | 77 | for n in comb: 78 | g_new.add_edge(new_node, n) 79 | 80 | if is_unique_under_isomorphism(g_new, (g for g,_ in graphs)): 81 | graphs.append((g_new, distances_new)) 82 | 83 | return graphs 84 | 85 | 86 | def test_enumerate_graphs(): 87 | import matplotlib.pyplot as plt 88 | graphs = enum_graphs(3) 89 | 90 | print("Num graphs: ", len(graphs)) 91 | 92 | # for g, dist in graphs: 93 | # print(g) 94 | # nx.draw_networkx(g, with_labels=True) 95 | # plt.draw() 96 | # plt.show() 97 | -------------------------------------------------------------------------------- /librecell-lib/lclib/logic/smt_4value_logic_scratch.py: -------------------------------------------------------------------------------- 1 | from pysmt.shortcuts import * 2 | 3 | # Define 4-valued logic type. 4 | #TL = Type('L') 5 | #TH = Type('H') 6 | #TX = Type('X') 7 | #TZ = Type('Z') 8 | 9 | FVLType = Type('FVL', arity=2) 10 | # FVL = Type('FVL', arity=0) 11 | # FVL = INT 12 | 13 | env = get_env() 14 | FVL = env.type_manager.get_type_instance(FVLType, BOOL, BOOL) 15 | #L = env.type_manager.get_type_instance(FVL, TL) 16 | #H = env.type_manager.get_type_instance(FVL, TH) 17 | #X = env.type_manager.get_type_instance(FVL, TX) 18 | #Z = env.type_manager.get_type_instance(FVL, TZ) 19 | 20 | # Low 21 | L = Symbol('L', FVL) 22 | # High 23 | H = Symbol('H', FVL) 24 | # Unknown 25 | X = Symbol('X', FVL) 26 | # High-impedance 27 | Z = Symbol('Z', FVL) 28 | 29 | 30 | # Helper shortcut 31 | Eq = EqualsOrIff 32 | 33 | # Define boolean functions. 34 | f_not = Symbol('f_not', FunctionType(FVL, [FVL])) 35 | 36 | definitions = [ 37 | # L,H,X,Z are all different. 38 | Not(Eq(L, H)), 39 | Not(Eq(L, X)), 40 | Not(Eq(L, Z)), 41 | Not(Eq(H, X)), 42 | Not(Eq(H, Z)), 43 | Not(Eq(X, Z)), 44 | 45 | # Define L,H,X,Z 46 | # Eq(L, Int(0)), 47 | # Eq(H, Int(1)), 48 | # Eq(X, Int(2)), 49 | # Eq(Z, Int(3)), 50 | 51 | # Define 'not' function. 52 | Eq(f_not(L), H), 53 | Eq(f_not(H), L), 54 | Eq(f_not(X), X), 55 | Eq(f_not(Z), X), 56 | ] 57 | 58 | solver = Solver() 59 | for d in definitions: 60 | solver.add_assertion(d) 61 | 62 | print(FVL.as_smtlib()) 63 | 64 | x = Symbol('x', FVL) 65 | solver.add_assertion(Eq(x, f_not(x))) 66 | solver.add_assertion(Not(Eq(x, L))) 67 | solver.add_assertion(Not(Eq(x, H))) 68 | solver.add_assertion(Not(Eq(x, X))) 69 | solver.add_assertion(Not(Eq(x, Z))) 70 | # solver.add_assertion(Eq(x, f_not(f_not(H)))) 71 | # solver.add_assertion(Not(Eq(x, X))) 72 | # solver.add_assertion(Not(Eq(x, Z))) 73 | sat = solver.check_sat() 74 | 75 | print('sat =', sat) 76 | if sat: 77 | model = solver.get_model() 78 | # print(model) 79 | # print(model[x]) 80 | -------------------------------------------------------------------------------- /librecell-lib/lclib/logic/util.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2019-2020 Thomas Kramer. 3 | # 4 | # This file is part of librecell 5 | # (see https://codeberg.org/tok/librecell). 6 | # 7 | # This program is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | # 20 | from itertools import product 21 | from enum import Enum 22 | import inspect 23 | 24 | 25 | class Unate(Enum): 26 | NON_UNATE = 0 27 | NEGATIVE_UNATE = -1 28 | POSITIVE_UNATE = 1 29 | 30 | 31 | def is_unate_in_xi(bool_function, param_name: str) -> Unate: 32 | """ Test if the boolean function is unate in input `i`. 33 | A function `f` is positive unate iff: f(..., x_i = 1, ...) >= f(..., x_i = 0, ...) 34 | A function `f` is negative unate iff: f(..., x_i = 1, ...) <= f(..., x_i = 0, ...) 35 | `f` is non-unate or binate if it is neither positive unate nor negative unate. 36 | :param bool_function: 37 | :param param_name: Name of input variable. 38 | :return: Unate.NON_UNATE, Unate.NEGATIVE_UNATE or Unate.POSITIVE_UNATE 39 | """ 40 | 41 | # TODO: use sympy to do this more elegantly (satisfiability solver) 42 | 43 | # Get number of inputs to function. 44 | 45 | params = list(inspect.signature(bool_function).parameters) 46 | assert param_name in params, "Function does not have parameter with name '{}'.".format(param_name) 47 | variable_params = [p for p in params if p != param_name] 48 | num_inputs = len(variable_params) 49 | 50 | is_positive_unate = True 51 | is_negative_unate = True 52 | 53 | fixed_inputs = list(product(*([[0, 1]] * num_inputs))) 54 | 55 | for inp in fixed_inputs: 56 | inp = list(inp) 57 | 58 | param_values = {n: v for n, v in zip(variable_params, inp)} 59 | param_values[param_name] = 0 60 | 61 | out0 = bool_function(**param_values) 62 | param_values[param_name] = 1 63 | out1 = bool_function(**param_values) 64 | 65 | _is_negative_unate = out1 <= out0 66 | _is_positive_unate = out1 >= out0 67 | 68 | is_positive_unate = is_positive_unate and _is_positive_unate 69 | is_negative_unate = is_negative_unate and _is_negative_unate 70 | 71 | is_non_unate = not is_positive_unate and not is_negative_unate 72 | if is_non_unate: 73 | break 74 | 75 | is_non_unate = is_positive_unate == is_negative_unate 76 | if is_non_unate: 77 | return Unate.NON_UNATE 78 | elif is_negative_unate: 79 | return Unate.NEGATIVE_UNATE 80 | elif is_positive_unate: 81 | return Unate.POSITIVE_UNATE 82 | else: 83 | assert False 84 | 85 | 86 | def test_is_unate(): 87 | AND = lambda a, b: a and b 88 | NAND = lambda a, b: not (a and b) 89 | XOR = lambda a, b: a ^ b 90 | 91 | assert is_unate_in_xi(AND, 'a') == Unate.POSITIVE_UNATE 92 | assert is_unate_in_xi(AND, 'b') == Unate.POSITIVE_UNATE 93 | assert is_unate_in_xi(NAND, 'a') == Unate.NEGATIVE_UNATE 94 | assert is_unate_in_xi(NAND, 'b') == Unate.NEGATIVE_UNATE 95 | 96 | assert is_unate_in_xi(XOR, 'a') == Unate.NON_UNATE 97 | -------------------------------------------------------------------------------- /librecell-lib/lclib/transistor_sizing/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2019-2020 Thomas Kramer. 3 | # 4 | # This file is part of librecell 5 | # (see https://codeberg.org/tok/librecell). 6 | # 7 | # This program is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | # 20 | -------------------------------------------------------------------------------- /librecell-lib/setup.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2019-2020 Thomas Kramer. 3 | # 4 | # This file is part of librecell 5 | # (see https://codeberg.org/tok/librecell). 6 | # 7 | # This program is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | # 20 | from setuptools import setup, find_packages 21 | 22 | 23 | def readme(): 24 | with open("README.md", "r") as f: 25 | return f.read() 26 | 27 | 28 | setup(name='librecell-lib', 29 | version='0.0.11', 30 | description='CMOS standard cell characterization kit.', 31 | long_description=readme(), 32 | long_description_content_type="text/markdown", 33 | keywords='cmos cell characterization vlsi asic', 34 | classifiers=[ 35 | 'License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)', 36 | 'Development Status :: 3 - Alpha', 37 | 'Topic :: Scientific/Engineering', 38 | 'Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)', 39 | 'Programming Language :: Python :: 3' 40 | ], 41 | url='https://codeberg.org/tok/librecell', 42 | author='T. Kramer', 43 | author_email='code@tkramer.ch', 44 | license='AGPL', 45 | packages=find_packages(), 46 | package_data={'': ['examples/*', 'test_data/*']}, 47 | entry_points={ 48 | 'console_scripts': [ 49 | 'libertyviz = lclib.liberty.visualize:main_plot_timing', 50 | 'libertymerge = lclib.liberty.merge:main', 51 | # 'lcsize = lclib.transistor_sizing.width_opt:main', 52 | 'lctime = lclib.characterization.main_lctime:main', 53 | 'sp2bool = lclib.characterization.main_sp2bool:main' 54 | ] 55 | }, 56 | install_requires=[ 57 | 'librecell-common>=0.0.9', 58 | 'numpy==1.*', # BSD 59 | 'sympy==1.6.*', # BSD 60 | 'matplotlib==3.*', 61 | 'networkx>=2.5', # BSD 62 | 'pyspice==1.4.*', # GPLv3 63 | 'scipy>=1.5.*', # BSD 64 | 'liberty-parser>=0.0.8', # GPLv3 65 | 'joblib>=0.14', # BSD-3-Clause 66 | ], 67 | zip_safe=False) 68 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/AND2X1.pex.netlist: -------------------------------------------------------------------------------- 1 | * File: AND2X1.pex.netlist 2 | * Created: Wed Jan 2 18:23:33 2008 3 | * Program "Calibre xRC" 4 | * Version "v2007.2_34.24" 5 | * 6 | .subckt AND2X1 A B VDD GND Y 7 | * 8 | MM3 a_9_6# A a_2_6# GND NMOS_VTL L=5e-08 W=5e-07 9 | MM4 GND B a_9_6# GND NMOS_VTL L=5e-08 W=5e-07 10 | MM5 Y a_2_6# GND GND NMOS_VTL L=5e-08 W=2.5e-07 11 | MM0 a_2_6# A VDD VDD PMOS_VTL L=5e-08 W=5e-07 12 | MM1 VDD B a_2_6# VDD PMOS_VTL L=5e-08 W=5e-07 13 | MM2 Y a_2_6# VDD VDD PMOS_VTL L=5e-08 W=5e-07 14 | c_5 A 0 0.103545f 15 | c_10 B 0 0.0927726f 16 | c_16 a_2_6# 0 0.166441f 17 | c_21 VDD 0 0.141663f 18 | c_26 GND 0 0.127034f 19 | c_30 Y 0 0.0559375f 20 | * 21 | .include "AND2X1.pex.netlist.AND2X1.pxi" 22 | * 23 | .ends 24 | * 25 | * 26 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/AND2X1.pex.netlist.AND2X1.pxi: -------------------------------------------------------------------------------- 1 | * File: AND2X1.pex.netlist.AND2X1.pxi 2 | * Created: Wed Jan 2 18:23:33 2008 3 | * 4 | cc_1 B A 0.0513961f 5 | cc_2 a_2_6# A 0.040702f 6 | cc_3 VDD A 0.0155393f 7 | cc_4 GND A 8.84198e-19 8 | cc_5 a_2_6# B 0.0882323f 9 | cc_6 VDD B 0.00476418f 10 | cc_7 GND B 0.00669566f 11 | cc_8 VDD a_2_6# 0.0741767f 12 | cc_9 GND a_2_6# 0.0188247f 13 | cc_10 Y a_2_6# 0.0360578f 14 | cc_11 Y VDD 0.017467f 15 | cc_12 Y GND 0.0129385f 16 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/AND2X2.pex.netlist: -------------------------------------------------------------------------------- 1 | * File: AND2X2.pex.netlist 2 | * Created: Wed Jan 2 18:24:48 2008 3 | * Program "Calibre xRC" 4 | * Version "v2007.2_34.24" 5 | * 6 | .subckt AND2X2 A B GND VDD Y 7 | * 8 | MM3 a_9_6# A a_2_6# GND NMOS_VTL L=5e-08 W=5e-07 9 | MM4 GND B a_9_6# GND NMOS_VTL L=5e-08 W=5e-07 10 | MM5 Y a_2_6# GND GND NMOS_VTL L=5e-08 W=5e-07 11 | MM0 a_2_6# A VDD VDD PMOS_VTL L=5e-08 W=5e-07 12 | MM1 VDD B a_2_6# VDD PMOS_VTL L=5e-08 W=5e-07 13 | MM2 Y a_2_6# VDD VDD PMOS_VTL L=5e-08 W=1e-06 14 | c_5 A 0 0.0907965f 15 | c_11 a_2_6# 0 0.219504f 16 | c_17 B 0 0.0852151f 17 | c_22 GND 0 0.0845147f 18 | c_27 VDD 0 0.148346f 19 | c_32 Y 0 0.092342f 20 | * 21 | .include "AND2X2.pex.netlist.AND2X2.pxi" 22 | * 23 | .ends 24 | * 25 | * 26 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/AND2X2.pex.netlist.AND2X2.pxi: -------------------------------------------------------------------------------- 1 | * File: AND2X2.pex.netlist.AND2X2.pxi 2 | * Created: Wed Jan 2 18:24:48 2008 3 | * 4 | cc_1 a_2_6# A 0.0510838f 5 | cc_2 B A 0.0433521f 6 | cc_3 GND A 0.00177662f 7 | cc_4 VDD A 0.0106877f 8 | cc_5 B a_2_6# 0.0985019f 9 | cc_6 GND a_2_6# 0.0509479f 10 | cc_7 VDD a_2_6# 0.125663f 11 | cc_8 Y a_2_6# 0.0505764f 12 | cc_9 GND B 0.00646913f 13 | cc_10 VDD B 0.00732661f 14 | cc_11 Y B 0.00996647f 15 | cc_12 Y GND 0.0242878f 16 | cc_13 Y VDD 0.0341879f 17 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/AOI21X1.pex.netlist: -------------------------------------------------------------------------------- 1 | * File: AOI21X1.pex.netlist 2 | * Created: Wed Jan 2 18:26:16 2008 3 | * Program "Calibre xRC" 4 | * Version "v2007.2_34.24" 5 | * 6 | .subckt AOI21X1 A B VDD C Y GND 7 | * 8 | MM3 a_12_6# A GND GND NMOS_VTL L=5e-08 W=5e-07 9 | MM4 Y B a_12_6# GND NMOS_VTL L=5e-08 W=5e-07 10 | MM5 GND C Y GND NMOS_VTL L=5e-08 W=2.5e-07 11 | MM0 VDD A a_2_54# VDD PMOS_VTL L=5e-08 W=1e-06 12 | MM1 a_2_54# B VDD VDD PMOS_VTL L=5e-08 W=1e-06 13 | MM2 Y C a_2_54# VDD PMOS_VTL L=5e-08 W=1e-06 14 | c_6 A 0 0.128402f 15 | c_13 B 0 0.0976016f 16 | c_19 VDD 0 0.0957611f 17 | c_26 a_2_54# 0 0.0797548f 18 | c_32 C 0 0.120371f 19 | c_39 Y 0 0.0891002f 20 | c_45 GND 0 0.118252f 21 | * 22 | .include "AOI21X1.pex.netlist.AOI21X1.pxi" 23 | * 24 | .ends 25 | * 26 | * 27 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/AOI21X1.pex.netlist.AOI21X1.pxi: -------------------------------------------------------------------------------- 1 | * File: AOI21X1.pex.netlist.AOI21X1.pxi 2 | * Created: Wed Jan 2 18:26:16 2008 3 | * 4 | cc_1 B A 0.0649693f 5 | cc_2 VDD A 0.00765447f 6 | cc_3 a_2_54# A 0.0266944f 7 | cc_4 Y A 0.0039585f 8 | cc_5 GND A 0.0171083f 9 | cc_6 VDD B 0.00759965f 10 | cc_7 a_2_54# B 0.0114298f 11 | cc_8 C B 0.0493623f 12 | cc_9 Y B 0.0338465f 13 | cc_10 GND B 0.00360319f 14 | cc_11 a_2_54# VDD 0.138901f 15 | cc_12 C VDD 0.00204561f 16 | cc_13 Y VDD 0.00447955f 17 | cc_14 C a_2_54# 0.00434406f 18 | cc_15 Y a_2_54# 0.0779147f 19 | cc_16 GND a_2_54# 8.01953e-19 20 | cc_17 Y C 0.0625441f 21 | cc_18 GND C 0.00915148f 22 | cc_19 GND Y 0.0428321f 23 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/AOI22X1.pex.netlist: -------------------------------------------------------------------------------- 1 | * File: AOI22X1.pex.netlist 2 | * Created: Wed Jan 2 18:27:25 2008 3 | * Program "Calibre xRC" 4 | * Version "v2007.2_34.24" 5 | * 6 | .subckt AOI22X1 C D Y B VDD A GND 7 | * 8 | MM7 GND C a_28_6# GND NMOS_VTL L=5e-08 W=5e-07 9 | MM6 a_28_6# D Y GND NMOS_VTL L=5e-08 W=5e-07 10 | MM5 Y B a_11_6# GND NMOS_VTL L=5e-08 W=5e-07 11 | MM4 a_11_6# A GND GND NMOS_VTL L=5e-08 W=5e-07 12 | MM3 a_2_54# C Y VDD PMOS_VTL L=5e-08 W=1e-06 13 | MM2 Y D a_2_54# VDD PMOS_VTL L=5e-08 W=1e-06 14 | MM1 a_2_54# B VDD VDD PMOS_VTL L=5e-08 W=1e-06 15 | MM0 VDD A a_2_54# VDD PMOS_VTL L=5e-08 W=1e-06 16 | c_6 C 0 0.140172f 17 | c_12 D 0 0.0878909f 18 | c_19 Y 0 0.0721643f 19 | c_26 B 0 0.0847939f 20 | c_31 VDD 0 0.111841f 21 | c_37 A 0 0.122357f 22 | c_45 a_2_54# 0 0.139553f 23 | c_52 GND 0 0.126903f 24 | * 25 | .include "AOI22X1.pex.netlist.AOI22X1.pxi" 26 | * 27 | .ends 28 | * 29 | * 30 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/AOI22X1.pex.netlist.AOI22X1.pxi: -------------------------------------------------------------------------------- 1 | * File: AOI22X1.pex.netlist.AOI22X1.pxi 2 | * Created: Wed Jan 2 18:27:25 2008 3 | * 4 | cc_1 D C 0.0572573f 5 | cc_2 Y C 0.0249475f 6 | cc_3 VDD C 4.995e-19 7 | cc_4 a_2_54# C 0.0397325f 8 | cc_5 GND C 0.0296866f 9 | cc_6 Y D 0.0724739f 10 | cc_7 B D 0.0950581f 11 | cc_8 a_2_54# D 0.0261488f 12 | cc_9 GND D 0.0011358f 13 | cc_10 B Y 0.00414912f 14 | cc_11 A Y 5.88269e-19 15 | cc_12 a_2_54# Y 0.148227f 16 | cc_13 GND Y 0.0992079f 17 | cc_14 VDD B 0.00535058f 18 | cc_15 A B 0.0951609f 19 | cc_16 a_2_54# B 0.0325558f 20 | cc_17 GND B 0.00333534f 21 | cc_18 A VDD 0.00678241f 22 | cc_19 a_2_54# VDD 0.155756f 23 | cc_20 a_2_54# A 0.0490873f 24 | cc_21 GND A 0.029506f 25 | cc_22 GND a_2_54# 6.0921e-19 26 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/BUFX2.pex.netlist: -------------------------------------------------------------------------------- 1 | * File: BUFX2.pex.netlist 2 | * Created: Wed Jan 2 18:28:41 2008 3 | * Program "Calibre xRC" 4 | * Version "v2007.2_34.24" 5 | * 6 | .subckt BUFX2 Y GND VDD A 7 | * 8 | MM3 Y a_2_6# GND GND NMOS_VTL L=5e-08 W=5e-07 9 | MM2 GND A a_2_6# GND NMOS_VTL L=5e-08 W=2.5e-07 10 | MM1 Y a_2_6# VDD VDD PMOS_VTL L=5e-08 W=1e-06 11 | MM0 VDD A a_2_6# VDD PMOS_VTL L=5e-08 W=5e-07 12 | c_4 Y 0 0.117784f 13 | c_8 GND 0 0.0661014f 14 | c_12 VDD 0 0.0922986f 15 | c_16 A 0 0.0837548f 16 | c_21 a_2_6# 0 0.240126f 17 | * 18 | .include "BUFX2.pex.netlist.BUFX2.pxi" 19 | * 20 | .ends 21 | * 22 | * 23 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/BUFX2.pex.netlist.BUFX2.pxi: -------------------------------------------------------------------------------- 1 | * File: BUFX2.pex.netlist.BUFX2.pxi 2 | * Created: Wed Jan 2 18:28:41 2008 3 | * 4 | cc_1 GND Y 0.0866284f 5 | cc_2 VDD Y 0.0886059f 6 | cc_3 a_2_6# Y 0.117455f 7 | cc_4 A GND 0.00209883f 8 | cc_5 a_2_6# GND 0.105626f 9 | cc_6 A VDD 0.00162454f 10 | cc_7 a_2_6# VDD 0.0772828f 11 | cc_8 a_2_6# A 0.155049f 12 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/BUFX4.pex.netlist: -------------------------------------------------------------------------------- 1 | * File: BUFX4.pex.netlist 2 | * Created: Wed Jan 2 18:30:33 2008 3 | * Program "Calibre xRC" 4 | * Version "v2007.2_34.24" 5 | * 6 | .subckt BUFX4 Y A GND VDD 7 | * 8 | MM4 GND a_2_6# Y GND NMOS_VTL L=5e-08 W=5e-07 9 | MM5 GND a_2_6# Y GND NMOS_VTL L=5e-08 W=5e-07 10 | MM3__2 GND A a_2_6# GND NMOS_VTL L=5e-08 W=7.5e-07 11 | MM3 GND A a_2_6# GND NMOS_VTL L=5e-08 W=7.5e-07 12 | MM1 VDD a_2_6# Y VDD PMOS_VTL L=5e-08 W=1e-06 13 | MM2 VDD a_2_6# Y VDD PMOS_VTL L=5e-08 W=1e-06 14 | MM0__2 VDD A a_2_6# VDD PMOS_VTL L=5e-08 W=3.75e-07 15 | MM0 VDD A a_2_6# VDD PMOS_VTL L=5e-08 W=3.75e-07 16 | c_4 Y 0 0.0658905f 17 | c_9 a_2_6# 0 0.291906f 18 | c_13 A 0 0.16605f 19 | c_18 GND 0 0.176193f 20 | c_23 VDD 0 0.21476f 21 | * 22 | .include "BUFX4.pex.netlist.BUFX4.pxi" 23 | * 24 | .ends 25 | * 26 | * 27 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/BUFX4.pex.netlist.BUFX4.pxi: -------------------------------------------------------------------------------- 1 | * File: BUFX4.pex.netlist.BUFX4.pxi 2 | * Created: Wed Jan 2 18:30:33 2008 3 | * 4 | cc_1 a_2_6# Y 0.080819f 5 | cc_2 GND Y 0.0746297f 6 | cc_3 VDD Y 0.10746f 7 | cc_4 A a_2_6# 0.113812f 8 | cc_5 GND a_2_6# 0.172354f 9 | cc_6 VDD a_2_6# 0.0910711f 10 | cc_7 GND A 0.0237695f 11 | cc_8 VDD A 0.0105141f 12 | cc_9 VDD GND 0.0184312f 13 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/CLKBUF1.pex.netlist: -------------------------------------------------------------------------------- 1 | * File: CLKBUF1.pex.netlist 2 | * Created: Wed Jan 2 18:31:41 2008 3 | * Program "Calibre xRC" 4 | * Version "v2007.2_34.24" 5 | * 6 | .subckt CLKBUF1 Y A GND VDD 7 | * 8 | MM14 GND a_41_6# Y GND NMOS_VTL L=5e-08 W=5e-07 9 | MM15 GND a_41_6# Y GND NMOS_VTL L=5e-08 W=5e-07 10 | MM12 GND a_25_6# a_41_6# GND NMOS_VTL L=5e-08 W=5e-07 11 | MM13 GND a_25_6# a_41_6# GND NMOS_VTL L=5e-08 W=5e-07 12 | MM10 GND a_9_6# a_25_6# GND NMOS_VTL L=5e-08 W=5e-07 13 | MM11 GND a_9_6# a_25_6# GND NMOS_VTL L=5e-08 W=5e-07 14 | MM8 GND A a_9_6# GND NMOS_VTL L=5e-08 W=5e-07 15 | MM9 GND A a_9_6# GND NMOS_VTL L=5e-08 W=5e-07 16 | MM6 VDD a_41_6# Y VDD PMOS_VTL L=5e-08 W=1e-06 17 | MM7 VDD a_41_6# Y VDD PMOS_VTL L=5e-08 W=1e-06 18 | MM4 VDD a_25_6# a_41_6# VDD PMOS_VTL L=5e-08 W=1e-06 19 | MM5 VDD a_25_6# a_41_6# VDD PMOS_VTL L=5e-08 W=1e-06 20 | MM2 VDD a_9_6# a_25_6# VDD PMOS_VTL L=5e-08 W=1e-06 21 | MM3 VDD a_9_6# a_25_6# VDD PMOS_VTL L=5e-08 W=1e-06 22 | MM0 VDD A a_9_6# VDD PMOS_VTL L=5e-08 W=1e-06 23 | MM1 VDD A a_9_6# VDD PMOS_VTL L=5e-08 W=1e-06 24 | c_4 Y 0 0.0699843f 25 | c_9 a_41_6# 0 0.294011f 26 | c_14 a_25_6# 0 0.290352f 27 | c_18 A 0 0.209724f 28 | c_23 a_9_6# 0 0.250503f 29 | c_30 GND 0 0.238528f 30 | c_37 VDD 0 0.309131f 31 | * 32 | .include "CLKBUF1.pex.netlist.CLKBUF1.pxi" 33 | * 34 | .ends 35 | * 36 | * 37 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/CLKBUF1.pex.netlist.CLKBUF1.pxi: -------------------------------------------------------------------------------- 1 | * File: CLKBUF1.pex.netlist.CLKBUF1.pxi 2 | * Created: Wed Jan 2 18:31:41 2008 3 | * 4 | cc_1 a_41_6# Y 0.0695355f 5 | cc_2 GND Y 0.0569665f 6 | cc_3 VDD Y 0.104045f 7 | cc_4 a_25_6# a_41_6# 0.129537f 8 | cc_5 GND a_41_6# 0.0828524f 9 | cc_6 VDD a_41_6# 0.125241f 10 | cc_7 a_9_6# a_25_6# 0.0918502f 11 | cc_8 GND a_25_6# 0.109151f 12 | cc_9 VDD a_25_6# 0.104316f 13 | cc_10 a_9_6# A 0.137134f 14 | cc_11 GND A 0.0159147f 15 | cc_12 VDD A 0.02559f 16 | cc_13 GND a_9_6# 0.103238f 17 | cc_14 VDD a_9_6# 0.215172f 18 | cc_15 VDD GND 0.00109744f 19 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/CLKBUF2.pex.netlist: -------------------------------------------------------------------------------- 1 | * File: CLKBUF2.pex.netlist 2 | * Created: Wed Jan 2 18:32:49 2008 3 | * Program "Calibre xRC" 4 | * Version "v2007.2_34.24" 5 | * 6 | .subckt CLKBUF2 A Y VDD GND 7 | * 8 | MM12 GND A a_9_6# GND NMOS_VTL L=5e-08 W=5e-07 9 | MM13 GND A a_9_6# GND NMOS_VTL L=5e-08 W=5e-07 10 | MM14 GND a_9_6# a_25_6# GND NMOS_VTL L=5e-08 W=5e-07 11 | MM15 GND a_9_6# a_25_6# GND NMOS_VTL L=5e-08 W=5e-07 12 | MM16 GND a_25_6# a_41_6# GND NMOS_VTL L=5e-08 W=5e-07 13 | MM17 GND a_25_6# a_41_6# GND NMOS_VTL L=5e-08 W=5e-07 14 | MM18 GND a_41_6# a_57_6# GND NMOS_VTL L=5e-08 W=5e-07 15 | MM19 GND a_41_6# a_57_6# GND NMOS_VTL L=5e-08 W=5e-07 16 | MM20 GND a_57_6# a_73_6# GND NMOS_VTL L=5e-08 W=5e-07 17 | MM21 GND a_57_6# a_73_6# GND NMOS_VTL L=5e-08 W=5e-07 18 | MM22 GND a_73_6# Y GND NMOS_VTL L=5e-08 W=5e-07 19 | MM23 GND a_73_6# Y GND NMOS_VTL L=5e-08 W=5e-07 20 | MM0 VDD A a_9_6# VDD PMOS_VTL L=5e-08 W=1e-06 21 | MM1 VDD A a_9_6# VDD PMOS_VTL L=5e-08 W=1e-06 22 | MM2 VDD a_9_6# a_25_6# VDD PMOS_VTL L=5e-08 W=1e-06 23 | MM3 VDD a_9_6# a_25_6# VDD PMOS_VTL L=5e-08 W=1e-06 24 | MM4 VDD a_25_6# a_41_6# VDD PMOS_VTL L=5e-08 W=1e-06 25 | MM5 VDD a_25_6# a_41_6# VDD PMOS_VTL L=5e-08 W=1e-06 26 | MM6 VDD a_41_6# a_57_6# VDD PMOS_VTL L=5e-08 W=1e-06 27 | MM7 VDD a_41_6# a_57_6# VDD PMOS_VTL L=5e-08 W=1e-06 28 | MM8 VDD a_57_6# a_73_6# VDD PMOS_VTL L=5e-08 W=1e-06 29 | MM9 VDD a_57_6# a_73_6# VDD PMOS_VTL L=5e-08 W=1e-06 30 | MM10 VDD a_73_6# Y VDD PMOS_VTL L=5e-08 W=1e-06 31 | MM11 VDD a_73_6# Y VDD PMOS_VTL L=5e-08 W=1e-06 32 | c_5 A 0 0.207657f 33 | c_10 a_9_6# 0 0.236845f 34 | c_17 a_25_6# 0 0.26518f 35 | c_22 a_41_6# 0 0.277558f 36 | c_29 a_57_6# 0 0.276187f 37 | c_34 a_73_6# 0 0.302256f 38 | c_39 Y 0 0.0691113f 39 | c_48 VDD 0 0.408008f 40 | c_57 GND 0 0.31321f 41 | * 42 | .include "CLKBUF2.pex.netlist.CLKBUF2.pxi" 43 | * 44 | .ends 45 | * 46 | * 47 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/CLKBUF2.pex.netlist.CLKBUF2.pxi: -------------------------------------------------------------------------------- 1 | * File: CLKBUF2.pex.netlist.CLKBUF2.pxi 2 | * Created: Wed Jan 2 18:32:49 2008 3 | * 4 | cc_1 a_9_6# A 0.152937f 5 | cc_2 a_25_6# A 2.38671e-19 6 | cc_3 VDD A 0.0257005f 7 | cc_4 GND A 0.0163281f 8 | cc_5 a_25_6# a_9_6# 0.122312f 9 | cc_6 VDD a_9_6# 0.223898f 10 | cc_7 GND a_9_6# 0.10362f 11 | cc_8 a_41_6# a_25_6# 0.169316f 12 | cc_9 a_57_6# a_25_6# 3.35252e-19 13 | cc_10 VDD a_25_6# 0.212149f 14 | cc_11 GND a_25_6# 0.0951906f 15 | cc_12 a_57_6# a_41_6# 0.134238f 16 | cc_13 VDD a_41_6# 0.128092f 17 | cc_14 GND a_41_6# 0.0989899f 18 | cc_15 a_73_6# a_57_6# 0.16904f 19 | cc_16 Y a_57_6# 2.89289e-19 20 | cc_17 VDD a_57_6# 0.128568f 21 | cc_18 GND a_57_6# 0.0770828f 22 | cc_19 Y a_73_6# 0.0738617f 23 | cc_20 VDD a_73_6# 0.139996f 24 | cc_21 GND a_73_6# 0.115857f 25 | cc_22 VDD Y 0.0973557f 26 | cc_23 GND Y 0.0719742f 27 | cc_24 GND VDD 0.0017241f 28 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/CLKBUF3.pex.netlist: -------------------------------------------------------------------------------- 1 | * File: CLKBUF3.pex.netlist 2 | * Created: Wed Jan 2 18:34:06 2008 3 | * Program "Calibre xRC" 4 | * Version "v2007.2_34.24" 5 | * 6 | .subckt CLKBUF3 A Y VDD GND 7 | * 8 | MM16 GND A a_9_6# GND NMOS_VTL L=5e-08 W=5e-07 9 | MM17 GND A a_9_6# GND NMOS_VTL L=5e-08 W=5e-07 10 | MM18 GND a_9_6# a_25_6# GND NMOS_VTL L=5e-08 W=5e-07 11 | MM19 GND a_9_6# a_25_6# GND NMOS_VTL L=5e-08 W=5e-07 12 | MM20 GND a_25_6# a_41_6# GND NMOS_VTL L=5e-08 W=5e-07 13 | MM21 GND a_25_6# a_41_6# GND NMOS_VTL L=5e-08 W=5e-07 14 | MM22 GND a_41_6# a_57_6# GND NMOS_VTL L=5e-08 W=5e-07 15 | MM23 GND a_41_6# a_57_6# GND NMOS_VTL L=5e-08 W=5e-07 16 | MM24 GND a_57_6# a_73_6# GND NMOS_VTL L=5e-08 W=5e-07 17 | MM25 GND a_57_6# a_73_6# GND NMOS_VTL L=5e-08 W=5e-07 18 | MM26 GND a_73_6# a_89_6# GND NMOS_VTL L=5e-08 W=5e-07 19 | MM27 GND a_73_6# a_89_6# GND NMOS_VTL L=5e-08 W=5e-07 20 | MM28 GND a_89_6# a_105_6# GND NMOS_VTL L=5e-08 W=5e-07 21 | MM29 GND a_89_6# a_105_6# GND NMOS_VTL L=5e-08 W=5e-07 22 | MM30 GND a_105_6# Y GND NMOS_VTL L=5e-08 W=5e-07 23 | MM31 GND a_105_6# Y GND NMOS_VTL L=5e-08 W=5e-07 24 | MM0 VDD A a_9_6# VDD PMOS_VTL L=5e-08 W=1e-06 25 | MM1 VDD A a_9_6# VDD PMOS_VTL L=5e-08 W=1e-06 26 | MM2 VDD a_9_6# a_25_6# VDD PMOS_VTL L=5e-08 W=1e-06 27 | MM3 VDD a_9_6# a_25_6# VDD PMOS_VTL L=5e-08 W=1e-06 28 | MM4 VDD a_25_6# a_41_6# VDD PMOS_VTL L=5e-08 W=1e-06 29 | MM5 VDD a_25_6# a_41_6# VDD PMOS_VTL L=5e-08 W=1e-06 30 | MM6 VDD a_41_6# a_57_6# VDD PMOS_VTL L=5e-08 W=1e-06 31 | MM7 VDD a_41_6# a_57_6# VDD PMOS_VTL L=5e-08 W=1e-06 32 | MM8 VDD a_57_6# a_73_6# VDD PMOS_VTL L=5e-08 W=1e-06 33 | MM9 VDD a_57_6# a_73_6# VDD PMOS_VTL L=5e-08 W=1e-06 34 | MM10 VDD a_73_6# a_89_6# VDD PMOS_VTL L=5e-08 W=1e-06 35 | MM11 VDD a_73_6# a_89_6# VDD PMOS_VTL L=5e-08 W=1e-06 36 | MM12 VDD a_89_6# a_105_6# VDD PMOS_VTL L=5e-08 W=1e-06 37 | MM13 VDD a_89_6# a_105_6# VDD PMOS_VTL L=5e-08 W=1e-06 38 | MM14 VDD a_105_6# Y VDD PMOS_VTL L=5e-08 W=1e-06 39 | MM15 VDD a_105_6# Y VDD PMOS_VTL L=5e-08 W=1e-06 40 | c_5 A 0 0.207657f 41 | c_10 a_9_6# 0 0.236845f 42 | c_17 a_25_6# 0 0.26518f 43 | c_23 a_41_6# 0 0.244923f 44 | c_29 a_57_6# 0 0.230999f 45 | c_35 a_73_6# 0 0.264596f 46 | c_41 a_89_6# 0 0.276226f 47 | c_46 a_105_6# 0 0.302256f 48 | c_51 Y 0 0.0691113f 49 | c_62 VDD 0 0.505031f 50 | c_73 GND 0 0.390216f 51 | * 52 | .include "CLKBUF3.pex.netlist.CLKBUF3.pxi" 53 | * 54 | .ends 55 | * 56 | * 57 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/CLKBUF3.pex.netlist.CLKBUF3.pxi: -------------------------------------------------------------------------------- 1 | * File: CLKBUF3.pex.netlist.CLKBUF3.pxi 2 | * Created: Wed Jan 2 18:34:06 2008 3 | * 4 | cc_1 a_9_6# A 0.152937f 5 | cc_2 a_25_6# A 2.38671e-19 6 | cc_3 VDD A 0.0257005f 7 | cc_4 GND A 0.0163281f 8 | cc_5 a_25_6# a_9_6# 0.122312f 9 | cc_6 VDD a_9_6# 0.223898f 10 | cc_7 GND a_9_6# 0.10362f 11 | cc_8 a_41_6# a_25_6# 0.167495f 12 | cc_9 a_57_6# a_25_6# 4.93178e-19 13 | cc_10 VDD a_25_6# 0.212149f 14 | cc_11 GND a_25_6# 0.0951906f 15 | cc_12 a_57_6# a_41_6# 0.110896f 16 | cc_13 a_73_6# a_41_6# 2.47698e-19 17 | cc_14 VDD a_41_6# 0.125978f 18 | cc_15 GND a_41_6# 0.098355f 19 | cc_16 a_73_6# a_57_6# 0.127599f 20 | cc_17 VDD a_57_6# 0.21899f 21 | cc_18 GND a_57_6# 0.0995028f 22 | cc_19 a_89_6# a_73_6# 0.138132f 23 | cc_20 VDD a_73_6# 0.212894f 24 | cc_21 GND a_73_6# 0.0987835f 25 | cc_22 a_105_6# a_89_6# 0.16904f 26 | cc_23 Y a_89_6# 2.89289e-19 27 | cc_24 VDD a_89_6# 0.126885f 28 | cc_25 GND a_89_6# 0.0766605f 29 | cc_26 Y a_105_6# 0.0738617f 30 | cc_27 VDD a_105_6# 0.139996f 31 | cc_28 GND a_105_6# 0.115857f 32 | cc_29 VDD Y 0.0973557f 33 | cc_30 GND Y 0.0719742f 34 | cc_31 GND VDD 0.0017241f 35 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/DFFNEGX1.pex.netlist: -------------------------------------------------------------------------------- 1 | * File: DFFNEGX1.pex.netlist 2 | * Created: Wed Jan 2 18:35:16 2008 3 | * Program "Calibre xRC" 4 | * Version "v2007.2_34.24" 5 | * 6 | .subckt DFFNEGX1 Q CLK D GND VDD 7 | * 8 | MM21 Q a_66_6# GND GND NMOS_VTL L=5e-08 W=5e-07 9 | MM19 a_76_6# CLK a_66_6# GND NMOS_VTL L=5e-08 W=2.5e-07 10 | MM20 GND Q a_76_6# GND NMOS_VTL L=5e-08 W=2.5e-07 11 | MM18 a_66_6# a_2_6# a_61_6# GND NMOS_VTL L=5e-08 W=2.5e-07 12 | MM17 a_61_6# a_34_4# GND GND NMOS_VTL L=5e-08 W=2.5e-07 13 | MM10 GND CLK a_2_6# GND NMOS_VTL L=5e-08 W=5e-07 14 | MM16 a_34_4# a_23_6# GND GND NMOS_VTL L=5e-08 W=2.5e-07 15 | MM15 GND a_34_4# a_31_6# GND NMOS_VTL L=5e-08 W=2.5e-07 16 | MM14 a_31_6# a_2_6# a_23_6# GND NMOS_VTL L=5e-08 W=2.5e-07 17 | MM13 a_23_6# CLK a_17_6# GND NMOS_VTL L=5e-08 W=2.5e-07 18 | MM12 a_17_6# D GND GND NMOS_VTL L=5e-08 W=2.5e-07 19 | MM11 Q a_66_6# VDD VDD PMOS_VTL L=5e-08 W=1e-06 20 | MM9 VDD Q a_76_84# VDD PMOS_VTL L=5e-08 W=2.5e-07 21 | MM8 a_76_84# a_2_6# a_66_6# VDD PMOS_VTL L=5e-08 W=2.5e-07 22 | MM7 a_66_6# CLK a_61_74# VDD PMOS_VTL L=5e-08 W=5e-07 23 | MM6 a_61_74# a_34_4# VDD VDD PMOS_VTL L=5e-08 W=5e-07 24 | MM0 VDD CLK a_2_6# VDD PMOS_VTL L=5e-08 W=1e-06 25 | MM5 a_34_4# a_23_6# VDD VDD PMOS_VTL L=5e-08 W=5e-07 26 | MM4 VDD a_34_4# a_31_74# VDD PMOS_VTL L=5e-08 W=5e-07 27 | MM3 a_31_74# CLK a_23_6# VDD PMOS_VTL L=5e-08 W=5e-07 28 | MM2 a_23_6# a_2_6# a_17_74# VDD PMOS_VTL L=5e-08 W=5e-07 29 | MM1 a_17_74# D VDD VDD PMOS_VTL L=5e-08 W=5e-07 30 | c_9 a_66_6# 0 0.290597f 31 | c_17 Q 0 0.216068f 32 | c_22 a_76_84# 0 0.021827f 33 | c_28 a_76_6# 0 0.0294239f 34 | c_36 a_34_4# 0 0.213562f 35 | c_47 CLK 0 0.471913f 36 | c_58 a_2_6# 0 0.22701f 37 | c_65 a_23_6# 0 0.160379f 38 | c_72 D 0 0.0811651f 39 | c_82 GND 0 0.288599f 40 | c_91 VDD 0 0.263083f 41 | * 42 | .include "DFFNEGX1.pex.netlist.DFFNEGX1.pxi" 43 | * 44 | .ends 45 | * 46 | * 47 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/DFFNEGX1.pex.netlist.DFFNEGX1.pxi: -------------------------------------------------------------------------------- 1 | * File: DFFNEGX1.pex.netlist.DFFNEGX1.pxi 2 | * Created: Wed Jan 2 18:35:16 2008 3 | * 4 | cc_1 Q a_66_6# 0.518833f 5 | cc_2 a_76_84# a_66_6# 0.377443f 6 | cc_3 a_76_6# a_66_6# 0.0480749f 7 | cc_4 a_34_4# a_66_6# 0.169248f 8 | cc_5 CLK a_66_6# 0.0690392f 9 | cc_6 a_2_6# a_66_6# 0.0973649f 10 | cc_7 GND a_66_6# 0.0127334f 11 | cc_8 VDD a_66_6# 0.729213f 12 | cc_9 a_76_84# Q 0.0171412f 13 | cc_10 a_76_6# Q 0.00957183f 14 | cc_11 CLK Q 4.05208e-19 15 | cc_12 a_2_6# Q 7.77678e-19 16 | cc_13 GND Q 0.0667515f 17 | cc_14 VDD Q 0.0292279f 18 | cc_15 CLK a_76_84# 0.00381712f 19 | cc_16 a_2_6# a_76_84# 0.0280445f 20 | cc_17 CLK a_76_6# 0.00558218f 21 | cc_18 a_2_6# a_76_6# 0.00354089f 22 | cc_19 GND a_76_6# 0.0840606f 23 | cc_20 CLK a_34_4# 0.0615446f 24 | cc_21 a_2_6# a_34_4# 0.279549f 25 | cc_22 a_23_6# a_34_4# 0.0752704f 26 | cc_23 D a_34_4# 4.72534e-19 27 | cc_24 GND a_34_4# 0.00223443f 28 | cc_25 VDD a_34_4# 0.0649576f 29 | cc_26 a_2_6# CLK 0.110603f 30 | cc_27 a_23_6# CLK 0.0164488f 31 | cc_28 D CLK 0.00968747f 32 | cc_29 GND CLK 0.036184f 33 | cc_30 VDD CLK 0.0622057f 34 | cc_31 a_23_6# a_2_6# 0.143358f 35 | cc_32 D a_2_6# 0.0275171f 36 | cc_33 GND a_2_6# 0.0597415f 37 | cc_34 VDD a_2_6# 0.00112381f 38 | cc_35 D a_23_6# 8.66576e-19 39 | cc_36 GND a_23_6# 0.0273898f 40 | cc_37 VDD a_23_6# 0.0328083f 41 | cc_38 GND D 0.00687012f 42 | cc_39 VDD D 0.0126158f 43 | cc_40 VDD GND 0.00144102f 44 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/DFFPOSX1.pex.netlist: -------------------------------------------------------------------------------- 1 | * File: DFFPOSX1.pex.netlist 2 | * Created: Wed Jan 2 18:36:24 2008 3 | * Program "Calibre xRC" 4 | * Version "v2007.2_34.24" 5 | * 6 | .subckt DFFPOSX1 CLK Q D GND VDD 7 | * 8 | MM21 Q a_66_6# GND GND NMOS_VTL L=5e-08 W=5e-07 9 | MM19 a_76_6# a_2_6# a_66_6# GND NMOS_VTL L=5e-08 W=2.5e-07 10 | MM20 GND Q a_76_6# GND NMOS_VTL L=5e-08 W=2.5e-07 11 | MM18 a_66_6# CLK a_61_6# GND NMOS_VTL L=5e-08 W=2.5e-07 12 | MM17 a_61_6# a_34_4# GND GND NMOS_VTL L=5e-08 W=2.5e-07 13 | MM10 GND CLK a_2_6# GND NMOS_VTL L=5e-08 W=5e-07 14 | MM16 a_34_4# a_22_6# GND GND NMOS_VTL L=5e-08 W=2.5e-07 15 | MM15 GND a_34_4# a_31_6# GND NMOS_VTL L=5e-08 W=2.5e-07 16 | MM14 a_31_6# CLK a_22_6# GND NMOS_VTL L=5e-08 W=2.5e-07 17 | MM13 a_22_6# a_2_6# a_17_6# GND NMOS_VTL L=5e-08 W=2.5e-07 18 | MM12 a_17_6# D GND GND NMOS_VTL L=5e-08 W=2.5e-07 19 | MM11 Q a_66_6# VDD VDD PMOS_VTL L=5e-08 W=1e-06 20 | MM9 VDD Q a_76_84# VDD PMOS_VTL L=5e-08 W=2.5e-07 21 | MM8 a_76_84# CLK a_66_6# VDD PMOS_VTL L=5e-08 W=2.5e-07 22 | MM7 a_66_6# a_2_6# a_61_74# VDD PMOS_VTL L=5e-08 W=5e-07 23 | MM6 a_61_74# a_34_4# VDD VDD PMOS_VTL L=5e-08 W=5e-07 24 | MM0 VDD CLK a_2_6# VDD PMOS_VTL L=5e-08 W=1e-06 25 | MM5 a_34_4# a_22_6# VDD VDD PMOS_VTL L=5e-08 W=5e-07 26 | MM4 VDD a_34_4# a_31_74# VDD PMOS_VTL L=5e-08 W=5e-07 27 | MM3 a_31_74# a_2_6# a_22_6# VDD PMOS_VTL L=5e-08 W=5e-07 28 | MM2 a_22_6# CLK a_17_74# VDD PMOS_VTL L=5e-08 W=5e-07 29 | MM1 a_17_74# D VDD VDD PMOS_VTL L=5e-08 W=5e-07 30 | c_9 a_66_6# 0 0.271997f 31 | c_20 CLK 0 0.350944f 32 | c_27 Q 0 0.202617f 33 | c_32 a_76_84# 0 0.0210573f 34 | c_38 a_76_6# 0 0.0204911f 35 | c_45 a_34_4# 0 0.172306f 36 | c_55 a_2_6# 0 0.283119f 37 | c_59 a_22_6# 0 0.157312f 38 | c_64 D 0 0.0816386f 39 | c_73 GND 0 0.254131f 40 | c_81 VDD 0 0.23624f 41 | * 42 | .include "DFFPOSX1.pex.netlist.DFFPOSX1.pxi" 43 | * 44 | .ends 45 | * 46 | * 47 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/DFFPOSX1.pex.netlist.DFFPOSX1.pxi: -------------------------------------------------------------------------------- 1 | * File: DFFPOSX1.pex.netlist.DFFPOSX1.pxi 2 | * Created: Wed Jan 2 18:36:24 2008 3 | * 4 | cc_1 CLK a_66_6# 0.757026f 5 | cc_2 Q a_66_6# 0.485011f 6 | cc_3 a_76_84# a_66_6# 0.652007f 7 | cc_4 a_76_6# a_66_6# 0.0359075f 8 | cc_5 a_34_4# a_66_6# 0.00468234f 9 | cc_6 a_2_6# a_66_6# 0.138393f 10 | cc_7 GND a_66_6# 0.029109f 11 | cc_8 VDD a_66_6# 0.680391f 12 | cc_9 Q CLK 0.00143412f 13 | cc_10 a_76_84# CLK 0.0123854f 14 | cc_11 a_76_6# CLK 0.0038051f 15 | cc_12 a_34_4# CLK 0.368664f 16 | cc_13 a_2_6# CLK 1.15738f 17 | cc_14 a_22_6# CLK 0.464259f 18 | cc_15 D CLK 0.0340596f 19 | cc_16 GND CLK 0.0134157f 20 | cc_17 VDD CLK 0.105254f 21 | cc_18 a_76_84# Q 0.0171208f 22 | cc_19 a_76_6# Q 0.00782064f 23 | cc_20 GND Q 0.0775526f 24 | cc_21 VDD Q 0.0295509f 25 | cc_22 a_2_6# a_76_84# 0.00370352f 26 | cc_23 a_2_6# a_76_6# 0.0039453f 27 | cc_24 GND a_76_6# 0.0550869f 28 | cc_25 a_2_6# a_34_4# 0.0893595f 29 | cc_26 a_22_6# a_34_4# 0.051028f 30 | cc_27 GND a_34_4# 0.0114704f 31 | cc_28 VDD a_34_4# 2.60092e-19 32 | cc_29 a_22_6# a_2_6# 0.298033f 33 | cc_30 D a_2_6# 0.0140442f 34 | cc_31 GND a_2_6# 0.0919654f 35 | cc_32 VDD a_2_6# 0.0801054f 36 | cc_33 GND D 0.00633479f 37 | cc_34 VDD D 0.0110285f 38 | cc_35 VDD GND 0.00156087f 39 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/DFFSR.pex.netlist: -------------------------------------------------------------------------------- 1 | * File: DFFSR.pex.netlist 2 | * Created: Wed Jan 2 18:39:27 2008 3 | * Program "Calibre xRC" 4 | * Version "v2007.2_34.24" 5 | * 6 | .subckt DFFSR CLK D S R VDD GND Q 7 | * 8 | MM24 a_47_71# CLK GND GND NMOS_VTL L=5e-08 W=2.5e-07 9 | MM22 GND D a_57_6# GND NMOS_VTL L=5e-08 W=2.5e-07 10 | MM23 GND a_47_71# a_47_4# GND NMOS_VTL L=5e-08 W=2.5e-07 11 | MM21 a_57_6# a_47_71# a_23_27# GND NMOS_VTL L=5e-08 W=2.5e-07 12 | MM20 a_23_27# a_47_4# a_2_6# GND NMOS_VTL L=5e-08 W=2.5e-07 13 | MM16 a_10_6# R a_2_6# GND NMOS_VTL L=5e-08 W=5e-07 14 | MM17 GND a_10_61# a_10_6# GND NMOS_VTL L=5e-08 W=5e-07 15 | MM18 a_26_6# a_23_27# GND GND NMOS_VTL L=5e-08 W=5e-07 16 | MM19 a_10_61# S a_26_6# GND NMOS_VTL L=5e-08 W=5e-07 17 | MM25 a_105_6# a_47_4# a_10_61# GND NMOS_VTL L=5e-08 W=2.5e-07 18 | MM26 a_113_6# a_47_71# a_105_6# GND NMOS_VTL L=5e-08 W=2.5e-07 19 | MM30 a_113_6# S a_146_6# GND NMOS_VTL L=5e-08 W=5e-07 20 | MM29 a_146_6# a_122_6# GND GND NMOS_VTL L=5e-08 W=5e-07 21 | MM28 GND R a_130_6# GND NMOS_VTL L=5e-08 W=5e-07 22 | MM27 a_130_6# a_105_6# a_122_6# GND NMOS_VTL L=5e-08 W=5e-07 23 | MM31 GND a_122_6# Q GND NMOS_VTL L=5e-08 W=2.5e-07 24 | MM8 a_47_71# CLK VDD VDD PMOS_VTL L=5e-08 W=5e-07 25 | MM6 VDD D a_57_6# VDD PMOS_VTL L=5e-08 W=5e-07 26 | MM5 a_57_6# a_47_4# a_23_27# VDD PMOS_VTL L=5e-08 W=2.5e-07 27 | MM4 a_23_27# a_47_71# a_2_6# VDD PMOS_VTL L=5e-08 W=2.5e-07 28 | MM7 VDD a_47_71# a_47_4# VDD PMOS_VTL L=5e-08 W=5e-07 29 | MM0 a_2_6# R VDD VDD PMOS_VTL L=5e-08 W=5e-07 30 | MM1 VDD a_10_61# a_2_6# VDD PMOS_VTL L=5e-08 W=5e-07 31 | MM3 VDD S a_10_61# VDD PMOS_VTL L=5e-08 W=5e-07 32 | MM9 a_105_6# a_47_71# a_10_61# VDD PMOS_VTL L=5e-08 W=2.5e-07 33 | MM2 a_10_61# a_23_27# VDD VDD PMOS_VTL L=5e-08 W=5e-07 34 | MM10 a_113_6# a_47_4# a_105_6# VDD PMOS_VTL L=5e-08 W=2.5e-07 35 | MM13 a_113_6# a_122_6# VDD VDD PMOS_VTL L=5e-08 W=5e-07 36 | MM14 VDD S a_113_6# VDD PMOS_VTL L=5e-08 W=5e-07 37 | MM12 VDD R a_122_6# VDD PMOS_VTL L=5e-08 W=5e-07 38 | MM11 a_122_6# a_105_6# VDD VDD PMOS_VTL L=5e-08 W=5e-07 39 | MM15 VDD a_122_6# Q VDD PMOS_VTL L=5e-08 W=5e-07 40 | c_14 a_47_4# 0 0.334871f 41 | c_29 a_47_71# 0 0.432635f 42 | c_35 CLK 0 0.0727998f 43 | c_42 D 0 0.0595369f 44 | c_48 a_57_6# 0 0.0164343f 45 | c_56 a_2_6# 0 0.0323757f 46 | c_67 a_23_27# 0 0.233891f 47 | c_77 a_10_61# 0 0.142227f 48 | c_88 S 0 0.207309f 49 | c_96 a_113_6# 0 0.0349704f 50 | c_108 R 0 0.213407f 51 | c_119 a_105_6# 0 0.163683f 52 | c_130 a_122_6# 0 0.396211f 53 | c_142 VDD 0 0.371445f 54 | c_155 GND 0 0.305932f 55 | c_160 Q 0 0.0656414f 56 | * 57 | .include "DFFSR.pex.netlist.DFFSR.pxi" 58 | * 59 | .ends 60 | * 61 | * 62 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/DFFSR.pex.netlist.DFFSR.pxi: -------------------------------------------------------------------------------- 1 | * File: DFFSR.pex.netlist.DFFSR.pxi 2 | * Created: Wed Jan 2 18:39:27 2008 3 | * 4 | cc_1 a_47_71# a_47_4# 1.0634f 5 | cc_2 D a_47_4# 0.0169989f 6 | cc_3 a_57_6# a_47_4# 0.12224f 7 | cc_4 a_2_6# a_47_4# 0.0026568f 8 | cc_5 a_23_27# a_47_4# 0.115018f 9 | cc_6 a_10_61# a_47_4# 0.0073118f 10 | cc_7 S a_47_4# 0.0330647f 11 | cc_8 a_113_6# a_47_4# 0.00967037f 12 | cc_9 R a_47_4# 0.0172899f 13 | cc_10 a_105_6# a_47_4# 0.00367922f 14 | cc_11 a_122_6# a_47_4# 0.00286972f 15 | cc_12 VDD a_47_4# 0.0862424f 16 | cc_13 GND a_47_4# 0.0324715f 17 | cc_14 CLK a_47_71# 0.0518881f 18 | cc_15 D a_47_71# 0.0151982f 19 | cc_16 a_57_6# a_47_71# 0.016434f 20 | cc_17 a_2_6# a_47_71# 0.288398f 21 | cc_18 a_23_27# a_47_71# 1.69588f 22 | cc_19 a_10_61# a_47_71# 0.133823f 23 | cc_20 S a_47_71# 0.472404f 24 | cc_21 a_113_6# a_47_71# 0.00547066f 25 | cc_22 R a_47_71# 0.127167f 26 | cc_23 a_105_6# a_47_71# 0.30498f 27 | cc_24 a_122_6# a_47_71# 2.98765e-19 28 | cc_25 VDD a_47_71# 0.0346402f 29 | cc_26 GND a_47_71# 0.24947f 30 | cc_27 D CLK 0.0239058f 31 | cc_28 a_57_6# CLK 0.00214392f 32 | cc_29 VDD CLK 0.00160301f 33 | cc_30 GND CLK 0.00378425f 34 | cc_31 a_57_6# D 0.0582395f 35 | cc_32 VDD D 0.00123253f 36 | cc_33 GND D 0.0284137f 37 | cc_34 GND a_57_6# 0.00924609f 38 | cc_35 a_23_27# a_2_6# 0.0303665f 39 | cc_36 a_10_61# a_2_6# 0.0680675f 40 | cc_37 S a_2_6# 3.38823e-19 41 | cc_38 R a_2_6# 0.0285544f 42 | cc_39 VDD a_2_6# 8.45548e-19 43 | cc_40 a_10_61# a_23_27# 0.0743628f 44 | cc_41 S a_23_27# 0.0339029f 45 | cc_42 R a_23_27# 0.0219555f 46 | cc_43 a_105_6# a_23_27# 3.86089e-19 47 | cc_44 a_122_6# a_23_27# 0.0172195f 48 | cc_45 VDD a_23_27# 0.0324776f 49 | cc_46 GND a_23_27# 0.0015265f 50 | cc_47 S a_10_61# 0.0671369f 51 | cc_48 a_113_6# a_10_61# 3.4993e-19 52 | cc_49 R a_10_61# 0.141867f 53 | cc_50 VDD a_10_61# 9.62684e-19 54 | cc_51 GND a_10_61# 0.00298927f 55 | cc_52 a_113_6# S 0.0475341f 56 | cc_53 R S 0.019859f 57 | cc_54 a_105_6# S 0.0203798f 58 | cc_55 a_122_6# S 0.0209078f 59 | cc_56 GND S 0.00101832f 60 | cc_57 R a_113_6# 0.00115073f 61 | cc_58 a_105_6# a_113_6# 0.0766896f 62 | cc_59 a_122_6# a_113_6# 0.0168342f 63 | cc_60 a_105_6# R 0.145705f 64 | cc_61 a_122_6# R 0.0378844f 65 | cc_62 VDD R 0.110975f 66 | cc_63 GND R 0.00162939f 67 | cc_64 a_122_6# a_105_6# 0.164096f 68 | cc_65 VDD a_105_6# 0.0864373f 69 | cc_66 GND a_105_6# 0.0526426f 70 | cc_67 Q a_105_6# 0.00721083f 71 | cc_68 VDD a_122_6# 0.0591277f 72 | cc_69 GND a_122_6# 0.0116928f 73 | cc_70 Q a_122_6# 0.0959938f 74 | cc_71 Q VDD 0.040141f 75 | cc_72 Q GND 0.0211392f 76 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/FAX1.pex.netlist: -------------------------------------------------------------------------------- 1 | * File: FAX1.pex.netlist 2 | * Created: Wed Jan 2 18:40:20 2008 3 | * Program "Calibre xRC" 4 | * Version "v2007.2_34.24" 5 | * 6 | .subckt FAX1 YC B C A GND VDD YS 7 | * 8 | MM14 GND A a_2_6# GND NMOS_VTL L=5e-08 W=5e-07 9 | MM15 a_2_6# B GND GND NMOS_VTL L=5e-08 W=5e-07 10 | MM18 GND A a_33_6# GND NMOS_VTL L=5e-08 W=5e-07 11 | MM17 a_33_6# B a_25_6# GND NMOS_VTL L=5e-08 W=5e-07 12 | MM16 a_25_6# C a_2_6# GND NMOS_VTL L=5e-08 W=5e-07 13 | MM27 YC a_25_6# GND GND NMOS_VTL L=5e-08 W=2.5e-07 14 | MM21 a_46_6# C GND GND NMOS_VTL L=5e-08 W=5e-07 15 | MM20 GND B a_46_6# GND NMOS_VTL L=5e-08 W=5e-07 16 | MM19 a_46_6# A GND GND NMOS_VTL L=5e-08 W=5e-07 17 | MM22 a_70_6# a_25_6# a_46_6# GND NMOS_VTL L=5e-08 W=5e-07 18 | MM23 a_79_6# C a_70_6# GND NMOS_VTL L=5e-08 W=5e-07 19 | MM24 a_84_6# B a_79_6# GND NMOS_VTL L=5e-08 W=5e-07 20 | MM25 GND A a_84_6# GND NMOS_VTL L=5e-08 W=5e-07 21 | MM26 YS a_70_6# GND GND NMOS_VTL L=5e-08 W=2.5e-07 22 | MM0 VDD A a_2_54# VDD PMOS_VTL L=5e-08 W=1e-06 23 | MM1 a_2_54# B VDD VDD PMOS_VTL L=5e-08 W=1e-06 24 | MM4 VDD A a_33_54# VDD PMOS_VTL L=5e-08 W=1e-06 25 | MM3 a_33_54# B a_25_6# VDD PMOS_VTL L=5e-08 W=1e-06 26 | MM2 a_25_6# C a_2_54# VDD PMOS_VTL L=5e-08 W=1e-06 27 | MM13 YC a_25_6# VDD VDD PMOS_VTL L=5e-08 W=5e-07 28 | MM7 a_46_54# C VDD VDD PMOS_VTL L=5e-08 W=9e-07 29 | MM6 VDD B a_46_54# VDD PMOS_VTL L=5e-08 W=9e-07 30 | MM5 a_46_54# A VDD VDD PMOS_VTL L=5e-08 W=1e-06 31 | MM8 a_70_6# a_25_6# a_46_54# VDD PMOS_VTL L=5e-08 W=9e-07 32 | MM9 a_79_46# C a_70_6# VDD PMOS_VTL L=5e-08 W=1.2e-06 33 | MM10 a_84_46# B a_79_46# VDD PMOS_VTL L=5e-08 W=1.2e-06 34 | MM11 VDD A a_84_46# VDD PMOS_VTL L=5e-08 W=1.2e-06 35 | MM12 YS a_70_6# VDD VDD PMOS_VTL L=5e-08 W=5e-07 36 | c_8 YC 0 0.0439081f 37 | c_20 B 0 0.509896f 38 | c_32 a_25_6# 0 0.350843f 39 | c_39 a_2_6# 0 0.0435762f 40 | c_45 a_2_54# 0 0.0778606f 41 | c_51 a_46_54# 0 0.0445869f 42 | c_59 a_46_6# 0 0.0409131f 43 | c_71 C 0 0.319904f 44 | c_84 A 0 0.52955f 45 | c_95 GND 0 0.315656f 46 | c_105 VDD 0 0.368681f 47 | c_114 a_70_6# 0 0.148884f 48 | c_119 YS 0 0.0627328f 49 | * 50 | .include "FAX1.pex.netlist.FAX1.pxi" 51 | * 52 | .ends 53 | * 54 | * 55 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/FAX1.pex.netlist.FAX1.pxi: -------------------------------------------------------------------------------- 1 | * File: FAX1.pex.netlist.FAX1.pxi 2 | * Created: Wed Jan 2 18:40:20 2008 3 | * 4 | cc_1 B YC 0.00860086f 5 | cc_2 a_25_6# YC 0.0311547f 6 | cc_3 a_2_6# YC 0.00989218f 7 | cc_4 a_46_6# YC 5.49509e-19 8 | cc_5 C YC 0.429391f 9 | cc_6 A YC 0.65714f 10 | cc_7 GND YC 0.0430258f 11 | cc_8 a_25_6# B 0.0293339f 12 | cc_9 a_2_6# B 0.0239118f 13 | cc_10 a_2_54# B 0.0220211f 14 | cc_11 a_46_54# B 0.0092574f 15 | cc_12 a_46_6# B 0.0123755f 16 | cc_13 C B 0.15986f 17 | cc_14 A B 0.252132f 18 | cc_15 GND B 0.12958f 19 | cc_16 VDD B 0.00838873f 20 | cc_17 a_70_6# B 0.00832746f 21 | cc_18 a_2_6# a_25_6# 0.0227962f 22 | cc_19 a_2_54# a_25_6# 0.0984866f 23 | cc_20 a_46_54# a_25_6# 0.0108388f 24 | cc_21 a_46_6# a_25_6# 0.00248805f 25 | cc_22 C a_25_6# 0.1144f 26 | cc_23 A a_25_6# 0.159025f 27 | cc_24 GND a_25_6# 0.0126528f 28 | cc_25 VDD a_25_6# 0.0455184f 29 | cc_26 a_70_6# a_25_6# 0.00696506f 30 | cc_27 C a_2_6# 0.00679116f 31 | cc_28 A a_2_6# 0.0456579f 32 | cc_29 GND a_2_6# 0.0406184f 33 | cc_30 C a_2_54# 0.0176494f 34 | cc_31 A a_2_54# 0.0250547f 35 | cc_32 VDD a_2_54# 0.0738859f 36 | cc_33 C a_46_54# 0.00377306f 37 | cc_34 A a_46_54# 0.105516f 38 | cc_35 VDD a_46_54# 0.086472f 39 | cc_36 C a_46_6# 0.00486868f 40 | cc_37 A a_46_6# 0.0305176f 41 | cc_38 GND a_46_6# 0.0701265f 42 | cc_39 a_70_6# a_46_6# 0.0352435f 43 | cc_40 A C 0.547229f 44 | cc_41 GND C 0.00621908f 45 | cc_42 VDD C 0.0071929f 46 | cc_43 a_70_6# C 0.0880589f 47 | cc_44 GND A 0.0337682f 48 | cc_45 VDD A 0.124783f 49 | cc_46 a_70_6# A 0.0474873f 50 | cc_47 YS A 0.00159064f 51 | cc_48 VDD GND 0.00199438f 52 | cc_49 a_70_6# GND 0.0246215f 53 | cc_50 YS GND 0.00515038f 54 | cc_51 a_70_6# VDD 0.0109964f 55 | cc_52 YS VDD 0.0268645f 56 | cc_53 YS a_70_6# 0.0396382f 57 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/HAX1.pex.netlist: -------------------------------------------------------------------------------- 1 | * File: HAX1.pex.netlist 2 | * Created: Wed Jan 2 18:41:28 2008 3 | * Program "Calibre xRC" 4 | * Version "v2007.2_34.24" 5 | * 6 | .subckt HAX1 YS B A VDD GND YC 7 | * 8 | MM13 YS a_41_74# GND GND NMOS_VTL L=5e-08 W=2.5e-07 9 | MM10 a_38_6# a_2_74# GND GND NMOS_VTL L=5e-08 W=5e-07 10 | MM11 a_41_74# B a_38_6# GND NMOS_VTL L=5e-08 W=5e-07 11 | MM12 a_38_6# A a_41_74# GND NMOS_VTL L=5e-08 W=5e-07 12 | MM8 a_2_74# B a_9_6# GND NMOS_VTL L=5e-08 W=5e-07 13 | MM7 a_9_6# A GND GND NMOS_VTL L=5e-08 W=5e-07 14 | MM9 GND a_2_74# YC GND NMOS_VTL L=5e-08 W=2.5e-07 15 | MM6 YS a_41_74# VDD VDD PMOS_VTL L=5e-08 W=5e-07 16 | MM3 a_41_74# a_2_74# VDD VDD PMOS_VTL L=5e-08 W=5e-07 17 | MM4 a_49_54# B a_41_74# VDD PMOS_VTL L=5e-08 W=1e-06 18 | MM5 VDD A a_49_54# VDD PMOS_VTL L=5e-08 W=1e-06 19 | MM1 a_2_74# B VDD VDD PMOS_VTL L=5e-08 W=5e-07 20 | MM0 VDD A a_2_74# VDD PMOS_VTL L=5e-08 W=5e-07 21 | MM2 VDD a_2_74# YC VDD PMOS_VTL L=5e-08 W=5e-07 22 | c_5 YS 0 0.057843f 23 | c_13 a_41_74# 0 0.15597f 24 | c_20 B 0 0.224741f 25 | c_27 a_38_6# 0 0.0535687f 26 | c_35 A 0 0.224671f 27 | c_43 a_2_74# 0 0.289338f 28 | c_51 VDD 0 0.259914f 29 | c_60 GND 0 0.177433f 30 | c_65 YC 0 0.0638725f 31 | * 32 | .include "HAX1.pex.netlist.HAX1.pxi" 33 | * 34 | .ends 35 | * 36 | * 37 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/HAX1.pex.netlist.HAX1.pxi: -------------------------------------------------------------------------------- 1 | * File: HAX1.pex.netlist.HAX1.pxi 2 | * Created: Wed Jan 2 18:41:28 2008 3 | * 4 | cc_1 a_41_74# YS 0.0435471f 5 | cc_2 a_38_6# YS 4.1202e-19 6 | cc_3 VDD YS 0.0376402f 7 | cc_4 GND YS 0.0198942f 8 | cc_5 B a_41_74# 0.0480708f 9 | cc_6 a_38_6# a_41_74# 0.11079f 10 | cc_7 A a_41_74# 0.00626455f 11 | cc_8 a_2_74# a_41_74# 0.113662f 12 | cc_9 VDD a_41_74# 0.0323979f 13 | cc_10 GND a_41_74# 0.0054068f 14 | cc_11 a_38_6# B 0.0073714f 15 | cc_12 A B 0.140821f 16 | cc_13 a_2_74# B 0.165881f 17 | cc_14 VDD B 0.00881845f 18 | cc_15 GND B 0.00194905f 19 | cc_16 A a_38_6# 0.0224306f 20 | cc_17 a_2_74# a_38_6# 0.0651058f 21 | cc_18 GND a_38_6# 0.0844007f 22 | cc_19 a_2_74# A 0.122143f 23 | cc_20 VDD A 0.0311983f 24 | cc_21 GND A 0.00968894f 25 | cc_22 YC A 4.76506e-19 26 | cc_23 VDD a_2_74# 0.0878109f 27 | cc_24 GND a_2_74# 0.0412907f 28 | cc_25 YC a_2_74# 0.0586739f 29 | cc_26 GND VDD 8.89862e-19 30 | cc_27 YC VDD 0.0134074f 31 | cc_28 YC GND 0.00948592f 32 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/INVX1.pex.netlist: -------------------------------------------------------------------------------- 1 | * File: INVX1.pex.netlist 2 | * Created: Wed Jan 2 18:42:35 2008 3 | * Program "Calibre xRC" 4 | * Version "v2007.2_34.24" 5 | * 6 | .subckt INVX1 A GND VDD Y 7 | * 8 | MM1 Y A GND GND NMOS_VTL L=5e-08 W=2.5e-07 9 | MM0 Y A VDD VDD PMOS_VTL L=5e-08 W=5e-07 10 | c_4 A 0 0.13599f 11 | c_7 GND 0 0.057208f 12 | c_10 VDD 0 0.0986293f 13 | c_14 Y 0 0.0799346f 14 | * 15 | .include "INVX1.pex.netlist.INVX1.pxi" 16 | * 17 | .ends 18 | * 19 | * 20 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/INVX1.pex.netlist.INVX1.pxi: -------------------------------------------------------------------------------- 1 | * File: INVX1.pex.netlist.INVX1.pxi 2 | * Created: Wed Jan 2 18:42:35 2008 3 | * 4 | cc_1 GND A 0.0229532f 5 | cc_2 VDD A 0.0117591f 6 | cc_3 Y A 0.0520761f 7 | cc_4 Y GND 0.032111f 8 | cc_5 Y VDD 0.0374985f 9 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/INVX2.pex.netlist: -------------------------------------------------------------------------------- 1 | * File: INVX2.pex.netlist 2 | * Created: Wed Jan 2 18:43:44 2008 3 | * Program "Calibre xRC" 4 | * Version "v2007.2_34.24" 5 | * 6 | .subckt INVX2 A GND VDD Y 7 | * 8 | MM1 Y A GND GND NMOS_VTL L=5e-08 W=5e-07 9 | MM0 Y A VDD VDD PMOS_VTL L=5e-08 W=1e-06 10 | c_4 A 0 0.166103f 11 | c_7 GND 0 0.0679337f 12 | c_10 VDD 0 0.0915331f 13 | c_14 Y 0 0.0930191f 14 | * 15 | .include "INVX2.pex.netlist.INVX2.pxi" 16 | * 17 | .ends 18 | * 19 | * 20 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/INVX2.pex.netlist.INVX2.pxi: -------------------------------------------------------------------------------- 1 | * File: INVX2.pex.netlist.INVX2.pxi 2 | * Created: Wed Jan 2 18:43:44 2008 3 | * 4 | cc_1 GND A 0.0177683f 5 | cc_2 VDD A 0.0247354f 6 | cc_3 Y A 0.0657784f 7 | cc_4 Y GND 0.0704234f 8 | cc_5 Y VDD 0.0695964f 9 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/INVX4.pex.netlist: -------------------------------------------------------------------------------- 1 | * File: INVX4.pex.netlist 2 | * Created: Wed Jan 2 18:45:02 2008 3 | * Program "Calibre xRC" 4 | * Version "v2007.2_34.24" 5 | * 6 | .subckt INVX4 Y A GND VDD 7 | * 8 | MM2 GND A Y GND NMOS_VTL L=5e-08 W=5e-07 9 | MM3 GND A Y GND NMOS_VTL L=5e-08 W=5e-07 10 | MM0 VDD A Y VDD PMOS_VTL L=5e-08 W=1e-06 11 | MM1 VDD A Y VDD PMOS_VTL L=5e-08 W=1e-06 12 | c_4 Y 0 0.0689645f 13 | c_8 A 0 0.227321f 14 | c_12 GND 0 0.117956f 15 | c_16 VDD 0 0.141907f 16 | * 17 | .include "INVX4.pex.netlist.INVX4.pxi" 18 | * 19 | .ends 20 | * 21 | * 22 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/INVX4.pex.netlist.INVX4.pxi: -------------------------------------------------------------------------------- 1 | * File: INVX4.pex.netlist.INVX4.pxi 2 | * Created: Wed Jan 2 18:45:02 2008 3 | * 4 | cc_1 A Y 0.083248f 5 | cc_2 GND Y 0.131327f 6 | cc_3 VDD Y 0.121335f 7 | cc_4 GND A 0.0150522f 8 | cc_5 VDD A 0.0396643f 9 | cc_6 VDD GND 0.00152422f 10 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/INVX8.pex.netlist: -------------------------------------------------------------------------------- 1 | * File: INVX8.pex.netlist 2 | * Created: Wed Jan 2 18:46:20 2008 3 | * Program "Calibre xRC" 4 | * Version "v2007.2_34.24" 5 | * 6 | .subckt INVX8 A GND Y VDD 7 | * 8 | MM4 GND A Y GND NMOS_VTL L=5e-08 W=6.675e-07 9 | MM5 GND A Y GND NMOS_VTL L=5e-08 W=6.675e-07 10 | MM7 GND A Y GND NMOS_VTL L=5e-08 W=6.65e-07 11 | MM0 VDD A Y VDD PMOS_VTL L=5e-08 W=1e-06 12 | MM1 VDD A Y VDD PMOS_VTL L=5e-08 W=1e-06 13 | MM2 VDD A Y VDD PMOS_VTL L=5e-08 W=1e-06 14 | MM3 VDD A Y VDD PMOS_VTL L=5e-08 W=1e-06 15 | c_4 A 0 0.394353f 16 | c_8 GND 0 0.137357f 17 | c_12 Y 0 0.168809f 18 | c_16 VDD 0 0.210511f 19 | * 20 | .include "INVX8.pex.netlist.INVX8.pxi" 21 | * 22 | .ends 23 | * 24 | * 25 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/INVX8.pex.netlist.INVX8.pxi: -------------------------------------------------------------------------------- 1 | * File: INVX8.pex.netlist.INVX8.pxi 2 | * Created: Wed Jan 2 18:46:20 2008 3 | * 4 | cc_1 GND A 0.0131501f 5 | cc_2 Y A 0.175453f 6 | cc_3 VDD A 0.044015f 7 | cc_4 Y GND 0.242977f 8 | cc_5 VDD GND 0.00190367f 9 | cc_6 VDD Y 0.331676f 10 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/LATCH.pex.netlist: -------------------------------------------------------------------------------- 1 | * File: LATCH.pex.netlist 2 | * Created: Wed Jan 2 18:48:08 2008 3 | * Program "Calibre xRC" 4 | * Version "v2007.2_34.24" 5 | * 6 | .subckt LATCH D CLK GND VDD Q 7 | * 8 | MM5 GND CLK a_2_6# GND NMOS_VTL L=5e-08 W=5e-07 9 | MM7 a_18_6# D GND GND NMOS_VTL L=5e-08 W=2.5e-07 10 | MM8 a_23_6# CLK a_18_6# GND NMOS_VTL L=5e-08 W=2.5e-07 11 | MM9 a_35_6# a_2_6# a_23_6# GND NMOS_VTL L=5e-08 W=2.5e-07 12 | MM10 GND Q a_35_6# GND NMOS_VTL L=5e-08 W=2.5e-07 13 | MM11 Q a_23_6# GND GND NMOS_VTL L=5e-08 W=5e-07 14 | MM0 VDD CLK a_2_6# VDD PMOS_VTL L=5e-08 W=1e-06 15 | MM1 a_18_74# D VDD VDD PMOS_VTL L=5e-08 W=5e-07 16 | MM2 a_23_6# a_2_6# a_18_74# VDD PMOS_VTL L=5e-08 W=5e-07 17 | MM3 a_35_84# CLK a_23_6# VDD PMOS_VTL L=5e-08 W=2.5e-07 18 | MM4 VDD Q a_35_84# VDD PMOS_VTL L=5e-08 W=2.5e-07 19 | MM6 Q a_23_6# VDD VDD PMOS_VTL L=5e-08 W=1e-06 20 | c_7 a_2_6# 0 0.251522f 21 | c_13 D 0 0.0718974f 22 | c_20 CLK 0 0.233896f 23 | c_27 a_23_6# 0 0.212567f 24 | c_33 GND 0 0.158887f 25 | c_39 VDD 0 0.187285f 26 | c_45 Q 0 0.153168f 27 | * 28 | .include "LATCH.pex.netlist.LATCH.pxi" 29 | * 30 | .ends 31 | * 32 | * 33 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/LATCH.pex.netlist.LATCH.pxi: -------------------------------------------------------------------------------- 1 | * File: LATCH.pex.netlist.LATCH.pxi 2 | * Created: Wed Jan 2 18:48:08 2008 3 | * 4 | cc_1 D a_2_6# 0.027542f 5 | cc_2 CLK a_2_6# 0.114787f 6 | cc_3 a_23_6# a_2_6# 0.018493f 7 | cc_4 GND a_2_6# 0.119747f 8 | cc_5 VDD a_2_6# 0.072412f 9 | cc_6 Q a_2_6# 0.00936464f 10 | cc_7 CLK D 0.0897784f 11 | cc_8 a_23_6# D 9.42125e-19 12 | cc_9 GND D 0.012571f 13 | cc_10 VDD D 0.00391588f 14 | cc_11 a_23_6# CLK 0.0541849f 15 | cc_12 GND CLK 0.0157045f 16 | cc_13 VDD CLK 0.0154478f 17 | cc_14 Q CLK 0.0142705f 18 | cc_15 GND a_23_6# 0.0176297f 19 | cc_16 VDD a_23_6# 0.0350875f 20 | cc_17 Q a_23_6# 0.106706f 21 | cc_18 Q GND 0.0263118f 22 | cc_19 Q VDD 0.066069f 23 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/MUX2X1.pex.netlist: -------------------------------------------------------------------------------- 1 | * File: MUX2X1.pex.netlist 2 | * Created: Wed Jan 2 18:49:16 2008 3 | * Program "Calibre xRC" 4 | * Version "v2007.2_34.24" 5 | * 6 | .subckt MUX2X1 A Y S B GND VDD 7 | * 8 | MM5 GND S a_2_10# GND NMOS_VTL L=5e-08 W=2.5e-07 9 | MM9 GND A a_30_10# GND NMOS_VTL L=5e-08 W=5e-07 10 | MM8 a_30_10# S Y GND NMOS_VTL L=5e-08 W=5e-07 11 | MM7 Y a_2_10# a_17_10# GND NMOS_VTL L=5e-08 W=5e-07 12 | MM6 a_17_10# B GND GND NMOS_VTL L=5e-08 W=5e-07 13 | MM0 VDD S a_2_10# VDD PMOS_VTL L=5e-08 W=5e-07 14 | MM4 VDD A a_30_54# VDD PMOS_VTL L=5e-08 W=1e-06 15 | MM3 a_30_54# a_2_10# Y VDD PMOS_VTL L=5e-08 W=1e-06 16 | MM2 Y S a_17_50# VDD PMOS_VTL L=5e-08 W=1e-06 17 | MM1 a_17_50# B VDD VDD PMOS_VTL L=5e-08 W=1e-06 18 | c_6 A 0 0.12188f 19 | c_13 a_2_10# 0 0.16457f 20 | c_19 Y 0 0.0637084f 21 | c_26 S 0 0.261188f 22 | c_32 B 0 0.132279f 23 | c_37 GND 0 0.148553f 24 | c_43 VDD 0 0.193017f 25 | * 26 | .include "MUX2X1.pex.netlist.MUX2X1.pxi" 27 | * 28 | .ends 29 | * 30 | * 31 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/MUX2X1.pex.netlist.MUX2X1.pxi: -------------------------------------------------------------------------------- 1 | * File: MUX2X1.pex.netlist.MUX2X1.pxi 2 | * Created: Wed Jan 2 18:49:16 2008 3 | * 4 | cc_1 a_2_10# A 0.0456552f 5 | cc_2 Y A 0.00110535f 6 | cc_3 S A 0.107628f 7 | cc_4 GND A 0.0202112f 8 | cc_5 VDD A 0.0160555f 9 | cc_6 Y a_2_10# 0.045549f 10 | cc_7 S a_2_10# 0.180445f 11 | cc_8 B a_2_10# 0.0225692f 12 | cc_9 GND a_2_10# 0.0176797f 13 | cc_10 VDD a_2_10# 0.0526184f 14 | cc_11 S Y 0.309023f 15 | cc_12 B Y 0.00123045f 16 | cc_13 VDD Y 0.0416975f 17 | cc_14 B S 0.059833f 18 | cc_15 GND S 0.130358f 19 | cc_16 VDD S 0.0141416f 20 | cc_17 GND B 0.0249587f 21 | cc_18 VDD B 0.0243111f 22 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/NAND2X1.pex.netlist: -------------------------------------------------------------------------------- 1 | * File: NAND2X1.pex.netlist 2 | * Created: Wed Jan 2 18:50:18 2008 3 | * Program "Calibre xRC" 4 | * Version "v2007.2_34.24" 5 | * 6 | .subckt NAND2X1 A GND B Y VDD 7 | * 8 | MM2 a_9_6# A GND GND NMOS_VTL L=5e-08 W=5e-07 9 | MM3 Y B a_9_6# GND NMOS_VTL L=5e-08 W=5e-07 10 | MM0 Y A VDD VDD PMOS_VTL L=5e-08 W=5e-07 11 | MM1 VDD B Y VDD PMOS_VTL L=5e-08 W=5e-07 12 | c_5 A 0 0.110167f 13 | c_9 GND 0 0.0763275f 14 | c_14 B 0 0.10534f 15 | c_19 Y 0 0.0641968f 16 | c_23 VDD 0 0.166265f 17 | * 18 | .include "NAND2X1.pex.netlist.NAND2X1.pxi" 19 | * 20 | .ends 21 | * 22 | * 23 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/NAND2X1.pex.netlist.NAND2X1.pxi: -------------------------------------------------------------------------------- 1 | * File: NAND2X1.pex.netlist.NAND2X1.pxi 2 | * Created: Wed Jan 2 18:50:18 2008 3 | * 4 | cc_1 GND A 0.0299137f 5 | cc_2 B A 0.0416874f 6 | cc_3 Y A 0.0619321f 7 | cc_4 VDD A 0.0311264f 8 | cc_5 B GND 0.00116311f 9 | cc_6 Y GND 0.104688f 10 | cc_7 Y B 0.07431f 11 | cc_8 VDD B 0.0308948f 12 | cc_9 VDD Y 0.162833f 13 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/NAND3X1.pex.netlist: -------------------------------------------------------------------------------- 1 | * File: NAND3X1.pex.netlist 2 | * Created: Wed Jan 2 18:51:28 2008 3 | * Program "Calibre xRC" 4 | * Version "v2007.2_34.24" 5 | * 6 | .subckt NAND3X1 A GND B C VDD Y 7 | * 8 | MM3 a_9_6# A GND GND NMOS_VTL L=5e-08 W=7.5e-07 9 | MM4 a_14_6# B a_9_6# GND NMOS_VTL L=5e-08 W=7.5e-07 10 | MM5 Y C a_14_6# GND NMOS_VTL L=5e-08 W=7.5e-07 11 | MM0 Y A VDD VDD PMOS_VTL L=5e-08 W=5e-07 12 | MM1 VDD B Y VDD PMOS_VTL L=5e-08 W=5e-07 13 | MM2 Y C VDD VDD PMOS_VTL L=5e-08 W=5e-07 14 | c_5 A 0 0.120904f 15 | c_10 GND 0 0.091831f 16 | c_16 B 0 0.0790037f 17 | c_21 C 0 0.116252f 18 | c_26 VDD 0 0.155618f 19 | c_32 Y 0 0.0986923f 20 | * 21 | .include "NAND3X1.pex.netlist.NAND3X1.pxi" 22 | * 23 | .ends 24 | * 25 | * 26 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/NAND3X1.pex.netlist.NAND3X1.pxi: -------------------------------------------------------------------------------- 1 | * File: NAND3X1.pex.netlist.NAND3X1.pxi 2 | * Created: Wed Jan 2 18:51:28 2008 3 | * 4 | cc_1 GND A 0.0288819f 5 | cc_2 B A 0.104567f 6 | cc_3 VDD A 0.0286999f 7 | cc_4 Y A 0.00296389f 8 | cc_5 B GND 0.170351f 9 | cc_6 C GND 0.0310619f 10 | cc_7 Y GND 0.0163054f 11 | cc_8 C B 0.232878f 12 | cc_9 VDD B 0.00324722f 13 | cc_10 Y B 0.0385445f 14 | cc_11 VDD C 0.00331627f 15 | cc_12 Y C 0.208247f 16 | cc_13 Y VDD 0.132987f 17 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/NOR2X1.pex.netlist: -------------------------------------------------------------------------------- 1 | * File: NOR2X1.pex.netlist 2 | * Created: Wed Jan 2 18:52:38 2008 3 | * Program "Calibre xRC" 4 | * Version "v2007.2_34.24" 5 | * 6 | .subckt NOR2X1 A VDD B Y GND 7 | * 8 | MM2 Y A GND GND NMOS_VTL L=5e-08 W=2.5e-07 9 | MM3 GND B Y GND NMOS_VTL L=5e-08 W=2.5e-07 10 | MM0 a_9_54# A VDD VDD PMOS_VTL L=5e-08 W=1e-06 11 | MM1 Y B a_9_54# VDD PMOS_VTL L=5e-08 W=1e-06 12 | c_5 A 0 0.097464f 13 | c_9 VDD 0 0.137301f 14 | c_14 B 0 0.096444f 15 | c_19 Y 0 0.0708282f 16 | c_23 GND 0 0.0804266f 17 | * 18 | .include "NOR2X1.pex.netlist.NOR2X1.pxi" 19 | * 20 | .ends 21 | * 22 | * 23 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/NOR2X1.pex.netlist.NOR2X1.pxi: -------------------------------------------------------------------------------- 1 | * File: NOR2X1.pex.netlist.NOR2X1.pxi 2 | * Created: Wed Jan 2 18:52:38 2008 3 | * 4 | cc_1 VDD A 0.0286873f 5 | cc_2 B A 0.0424093f 6 | cc_3 Y A 0.0283747f 7 | cc_4 GND A 0.0218786f 8 | cc_5 B VDD 0.0012073f 9 | cc_6 Y VDD 0.0230653f 10 | cc_7 Y B 0.0642447f 11 | cc_8 GND B 0.0216323f 12 | cc_9 GND Y 0.0537983f 13 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/NOR3X1.pex.netlist: -------------------------------------------------------------------------------- 1 | * File: NOR3X1.pex.netlist 2 | * Created: Wed Jan 2 18:53:50 2008 3 | * Program "Calibre xRC" 4 | * Version "v2007.2_34.24" 5 | * 6 | .subckt NOR3X1 A VDD B C GND Y 7 | * 8 | MM6 Y A GND GND NMOS_VTL L=5e-08 W=2.5e-07 9 | MM7 GND B Y GND NMOS_VTL L=5e-08 W=2.5e-07 10 | MM8 Y C GND GND NMOS_VTL L=5e-08 W=2.5e-07 11 | MM1 a_2_64# A VDD VDD PMOS_VTL L=5e-08 W=1.5e-06 12 | MM3 a_2_64# B a_25_64# VDD PMOS_VTL L=5e-08 W=1.5e-06 13 | MM5 a_25_64# C Y VDD PMOS_VTL L=5e-08 W=1.5e-06 14 | c_5 A 0 0.139787f 15 | c_10 VDD 0 0.143815f 16 | c_16 B 0 0.0941146f 17 | c_21 C 0 0.130836f 18 | c_26 GND 0 0.0877871f 19 | c_32 Y 0 0.118517f 20 | * 21 | .include "NOR3X1.pex.netlist.NOR3X1.pxi" 22 | * 23 | .ends 24 | * 25 | * 26 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/NOR3X1.pex.netlist.NOR3X1.pxi: -------------------------------------------------------------------------------- 1 | * File: NOR3X1.pex.netlist.NOR3X1.pxi 2 | * Created: Wed Jan 2 18:53:50 2008 3 | * 4 | cc_1 VDD A 0.0405249f 5 | cc_2 B A 0.063637f 6 | cc_3 GND A 0.0166957f 7 | cc_4 Y A 0.00700265f 8 | cc_5 B VDD 0.00370027f 9 | cc_6 C VDD 0.0025959f 10 | cc_7 Y VDD 0.0279671f 11 | cc_8 C B 0.0860169f 12 | cc_9 GND B 0.00285771f 13 | cc_10 Y B 0.0310838f 14 | cc_11 GND C 0.00344829f 15 | cc_12 Y C 0.100364f 16 | cc_13 Y GND 0.074416f 17 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/OAI21X1.pex.netlist: -------------------------------------------------------------------------------- 1 | * File: OAI21X1.pex.netlist 2 | * Created: Wed Jan 2 18:54:58 2008 3 | * Program "Calibre xRC" 4 | * Version "v2007.2_34.24" 5 | * 6 | .subckt OAI21X1 A B GND C Y VDD 7 | * 8 | MM3 GND A a_2_6# GND NMOS_VTL L=5e-08 W=5e-07 9 | MM4 a_2_6# B GND GND NMOS_VTL L=5e-08 W=5e-07 10 | MM5 Y C a_2_6# GND NMOS_VTL L=5e-08 W=5e-07 11 | MM0 a_9_54# A VDD VDD PMOS_VTL L=5e-08 W=1e-06 12 | MM1 Y B a_9_54# VDD PMOS_VTL L=5e-08 W=1e-06 13 | MM2 VDD C Y VDD PMOS_VTL L=5e-08 W=5e-07 14 | c_6 A 0 0.12581f 15 | c_13 B 0 0.0969534f 16 | c_19 GND 0 0.083241f 17 | c_26 a_2_6# 0 0.0565173f 18 | c_32 C 0 0.103215f 19 | c_39 Y 0 0.0631946f 20 | c_45 VDD 0 0.1632f 21 | * 22 | .include "OAI21X1.pex.netlist.OAI21X1.pxi" 23 | * 24 | .ends 25 | * 26 | * 27 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/OAI21X1.pex.netlist.OAI21X1.pxi: -------------------------------------------------------------------------------- 1 | * File: OAI21X1.pex.netlist.OAI21X1.pxi 2 | * Created: Wed Jan 2 18:54:58 2008 3 | * 4 | cc_1 B A 0.0760272f 5 | cc_2 GND A 0.0041545f 6 | cc_3 a_2_6# A 0.0220218f 7 | cc_4 Y A 7.30125e-19 8 | cc_5 VDD A 0.0253563f 9 | cc_6 GND B 0.0041403f 10 | cc_7 a_2_6# B 0.0121755f 11 | cc_8 C B 0.0422365f 12 | cc_9 Y B 0.018727f 13 | cc_10 VDD B 0.00865584f 14 | cc_11 a_2_6# GND 0.0979315f 15 | cc_12 C GND 0.00185979f 16 | cc_13 Y GND 0.00646299f 17 | cc_14 C a_2_6# 0.00291979f 18 | cc_15 Y a_2_6# 0.0518953f 19 | cc_16 VDD a_2_6# 6.98752e-19 20 | cc_17 Y C 0.0662452f 21 | cc_18 VDD C 0.0266496f 22 | cc_19 VDD Y 0.0696003f 23 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/OAI22X1.pex.netlist: -------------------------------------------------------------------------------- 1 | * File: OAI22X1.pex.netlist 2 | * Created: Wed Jan 2 18:55:58 2008 3 | * Program "Calibre xRC" 4 | * Version "v2007.2_34.24" 5 | * 6 | .subckt OAI22X1 C D Y B GND A VDD 7 | * 8 | MM7 a_2_6# C Y GND NMOS_VTL L=5e-08 W=5e-07 9 | MM6 Y D a_2_6# GND NMOS_VTL L=5e-08 W=5e-07 10 | MM5 a_2_6# B GND GND NMOS_VTL L=5e-08 W=5e-07 11 | MM4 GND A a_2_6# GND NMOS_VTL L=5e-08 W=5e-07 12 | MM3 VDD C a_28_54# VDD PMOS_VTL L=5e-08 W=1e-06 13 | MM2 a_28_54# D Y VDD PMOS_VTL L=5e-08 W=1e-06 14 | MM1 Y B a_9_54# VDD PMOS_VTL L=5e-08 W=1e-06 15 | MM0 a_9_54# A VDD VDD PMOS_VTL L=5e-08 W=1e-06 16 | c_5 C 0 0.124089f 17 | c_11 D 0 0.0839116f 18 | c_18 Y 0 0.0729179f 19 | c_25 B 0 0.0846012f 20 | c_29 GND 0 0.095914f 21 | c_35 A 0 0.121605f 22 | c_43 a_2_6# 0 0.0982545f 23 | c_50 VDD 0 0.172539f 24 | * 25 | .include "OAI22X1.pex.netlist.OAI22X1.pxi" 26 | * 27 | .ends 28 | * 29 | * 30 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/OAI22X1.pex.netlist.OAI22X1.pxi: -------------------------------------------------------------------------------- 1 | * File: OAI22X1.pex.netlist.OAI22X1.pxi 2 | * Created: Wed Jan 2 18:55:58 2008 3 | * 4 | cc_1 D C 0.0557299f 5 | cc_2 Y C 0.0329334f 6 | cc_3 a_2_6# C 0.0268364f 7 | cc_4 VDD C 0.0246682f 8 | cc_5 Y D 0.0598748f 9 | cc_6 B D 0.0805749f 10 | cc_7 a_2_6# D 0.0201093f 11 | cc_8 VDD D 0.00286431f 12 | cc_9 B Y 0.00811317f 13 | cc_10 A Y 9.65099e-19 14 | cc_11 a_2_6# Y 0.0950953f 15 | cc_12 VDD Y 0.038674f 16 | cc_13 GND B 0.0036203f 17 | cc_14 A B 0.0805749f 18 | cc_15 a_2_6# B 0.029469f 19 | cc_16 VDD B 0.00328833f 20 | cc_17 A GND 0.00397152f 21 | cc_18 a_2_6# GND 0.136777f 22 | cc_19 a_2_6# A 0.0415428f 23 | cc_20 VDD A 0.0270846f 24 | cc_21 VDD a_2_6# 3.02953e-19 25 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/OR2X1.pex.netlist: -------------------------------------------------------------------------------- 1 | * File: OR2X1.pex.netlist 2 | * Created: Wed Jan 2 18:56:59 2008 3 | * Program "Calibre xRC" 4 | * Version "v2007.2_34.24" 5 | * 6 | .subckt OR2X1 A B VDD GND Y 7 | * 8 | MM3 a_2_54# A GND GND NMOS_VTL L=5e-08 W=2.5e-07 9 | MM4 GND B a_2_54# GND NMOS_VTL L=5e-08 W=2.5e-07 10 | MM5 Y a_2_54# GND GND NMOS_VTL L=5e-08 W=2.5e-07 11 | MM0 a_9_54# A a_2_54# VDD PMOS_VTL L=5e-08 W=1e-06 12 | MM1 VDD B a_9_54# VDD PMOS_VTL L=5e-08 W=1e-06 13 | MM2 Y a_2_54# VDD VDD PMOS_VTL L=5e-08 W=5e-07 14 | c_5 A 0 0.111279f 15 | c_11 B 0 0.102464f 16 | c_16 VDD 0 0.120654f 17 | c_22 a_2_54# 0 0.184486f 18 | c_27 GND 0 0.127853f 19 | c_32 Y 0 0.0507368f 20 | * 21 | .include "OR2X1.pex.netlist.OR2X1.pxi" 22 | * 23 | .ends 24 | * 25 | * 26 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/OR2X1.pex.netlist.OR2X1.pxi: -------------------------------------------------------------------------------- 1 | * File: OR2X1.pex.netlist.OR2X1.pxi 2 | * Created: Wed Jan 2 18:56:59 2008 3 | * 4 | cc_1 B A 0.0643223f 5 | cc_2 VDD A 0.00299592f 6 | cc_3 a_2_54# A 0.068572f 7 | cc_4 GND A 0.00595037f 8 | cc_5 VDD B 0.0237434f 9 | cc_6 a_2_54# B 0.0577895f 10 | cc_7 GND B 0.00245301f 11 | cc_8 Y B 0.00200232f 12 | cc_9 a_2_54# VDD 0.0288589f 13 | cc_10 Y VDD 0.0143239f 14 | cc_11 GND a_2_54# 0.0685514f 15 | cc_12 Y a_2_54# 0.0459982f 16 | cc_13 Y GND 0.00890541f 17 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/OR2X2.pex.netlist: -------------------------------------------------------------------------------- 1 | * File: OR2X2.pex.netlist 2 | * Created: Wed Jan 2 18:58:07 2008 3 | * Program "Calibre xRC" 4 | * Version "v2007.2_34.24" 5 | * 6 | .subckt OR2X2 A B GND VDD Y 7 | * 8 | MM3 a_2_54# A GND GND NMOS_VTL L=5e-08 W=2.5e-07 9 | MM4 GND B a_2_54# GND NMOS_VTL L=5e-08 W=2.5e-07 10 | MM5 Y a_2_54# GND GND NMOS_VTL L=5e-08 W=5e-07 11 | MM0 a_9_54# A a_2_54# VDD PMOS_VTL L=5e-08 W=1e-06 12 | MM1 VDD B a_9_54# VDD PMOS_VTL L=5e-08 W=1e-06 13 | MM2 Y a_2_54# VDD VDD PMOS_VTL L=5e-08 W=1e-06 14 | c_5 A 0 0.150974f 15 | c_11 B 0 0.10021f 16 | c_17 a_2_54# 0 0.202237f 17 | c_22 GND 0 0.101842f 18 | c_27 VDD 0 0.101936f 19 | c_32 Y 0 0.101047f 20 | * 21 | .include "OR2X2.pex.netlist.OR2X2.pxi" 22 | * 23 | .ends 24 | * 25 | * 26 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/OR2X2.pex.netlist.OR2X2.pxi: -------------------------------------------------------------------------------- 1 | * File: OR2X2.pex.netlist.OR2X2.pxi 2 | * Created: Wed Jan 2 18:58:07 2008 3 | * 4 | cc_1 B A 0.0860951f 5 | cc_2 a_2_54# A 0.0476794f 6 | cc_3 GND A 0.029456f 7 | cc_4 VDD A 0.00330921f 8 | cc_5 a_2_54# B 0.12263f 9 | cc_6 GND B 0.00516789f 10 | cc_7 VDD B 0.0124707f 11 | cc_8 Y B 0.00244923f 12 | cc_9 GND a_2_54# 0.0976615f 13 | cc_10 VDD a_2_54# 0.0441176f 14 | cc_11 Y a_2_54# 0.159676f 15 | cc_12 Y GND 0.077225f 16 | cc_13 Y VDD 0.0797716f 17 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/TBUFX1.pex.netlist: -------------------------------------------------------------------------------- 1 | * File: TBUFX1.pex.netlist 2 | * Created: Wed Jan 2 18:59:18 2008 3 | * Program "Calibre xRC" 4 | * Version "v2007.2_34.24" 5 | * 6 | .subckt TBUFX1 EN GND VDD A Y 7 | * 8 | MM3 a_9_6# EN GND GND NMOS_VTL L=5e-08 W=2.5e-07 9 | MM5 GND A a_26_6# GND NMOS_VTL L=5e-08 W=5e-07 10 | MM4 a_26_6# EN Y GND NMOS_VTL L=5e-08 W=5e-07 11 | MM0 a_9_6# EN VDD VDD PMOS_VTL L=5e-08 W=5e-07 12 | MM2 VDD A a_26_54# VDD PMOS_VTL L=5e-08 W=1e-06 13 | MM1 a_26_54# a_9_6# Y VDD PMOS_VTL L=5e-08 W=1e-06 14 | c_6 EN 0 0.136867f 15 | c_11 GND 0 0.0879847f 16 | c_16 VDD 0 0.107062f 17 | c_22 A 0 0.10117f 18 | c_28 a_9_6# 0 0.137016f 19 | c_34 Y 0 0.0903518f 20 | * 21 | .include "TBUFX1.pex.netlist.TBUFX1.pxi" 22 | * 23 | .ends 24 | * 25 | * 26 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/TBUFX1.pex.netlist.TBUFX1.pxi: -------------------------------------------------------------------------------- 1 | * File: TBUFX1.pex.netlist.TBUFX1.pxi 2 | * Created: Wed Jan 2 18:59:18 2008 3 | * 4 | cc_1 GND EN 0.0152824f 5 | cc_2 VDD EN 0.00330156f 6 | cc_3 A EN 0.101551f 7 | cc_4 a_9_6# EN 0.0919099f 8 | cc_5 Y EN 0.0278065f 9 | cc_6 A GND 0.00863792f 10 | cc_7 a_9_6# GND 0.0180808f 11 | cc_8 Y GND 0.0222867f 12 | cc_9 A VDD 0.01626f 13 | cc_10 a_9_6# VDD 0.0561209f 14 | cc_11 Y VDD 0.0302427f 15 | cc_12 a_9_6# A 0.0739877f 16 | cc_13 Y A 0.00324546f 17 | cc_14 Y a_9_6# 0.101349f 18 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/TBUFX2.pex.netlist: -------------------------------------------------------------------------------- 1 | * File: TBUFX2.pex.netlist 2 | * Created: Wed Jan 2 19:00:28 2008 3 | * Program "Calibre xRC" 4 | * Version "v2007.2_34.24" 5 | * 6 | .subckt TBUFX2 EN Y A GND VDD 7 | * 8 | MM5 a_9_6# EN GND GND NMOS_VTL L=5e-08 W=5e-07 9 | MM8 a_18_6#__2 A GND GND NMOS_VTL L=5e-08 W=5e-07 10 | MM6 a_18_6#__2 EN Y GND NMOS_VTL L=5e-08 W=5e-07 11 | MM7 a_18_6# EN Y GND NMOS_VTL L=5e-08 W=5e-07 12 | MM9 a_18_6# A GND GND NMOS_VTL L=5e-08 W=5e-07 13 | MM0 a_9_6# EN VDD VDD PMOS_VTL L=5e-08 W=1e-06 14 | MM3 a_18_54#__2 A VDD VDD PMOS_VTL L=5e-08 W=1e-06 15 | MM1 a_18_54#__2 a_9_6# Y VDD PMOS_VTL L=5e-08 W=1e-06 16 | MM2 a_18_54# a_9_6# Y VDD PMOS_VTL L=5e-08 W=1e-06 17 | MM4 a_18_54# A VDD VDD PMOS_VTL L=5e-08 W=1e-06 18 | c_6 EN 0 0.207528f 19 | c_12 a_9_6# 0 0.194903f 20 | c_17 Y 0 0.0640995f 21 | c_23 A 0 0.247217f 22 | c_28 GND 0 0.134249f 23 | c_34 VDD 0 0.170782f 24 | * 25 | .include "TBUFX2.pex.netlist.TBUFX2.pxi" 26 | * 27 | .ends 28 | * 29 | * 30 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/TBUFX2.pex.netlist.TBUFX2.pxi: -------------------------------------------------------------------------------- 1 | * File: TBUFX2.pex.netlist.TBUFX2.pxi 2 | * Created: Wed Jan 2 19:00:28 2008 3 | * 4 | cc_1 a_9_6# EN 0.0523278f 5 | cc_2 Y EN 0.00668577f 6 | cc_3 A EN 0.117544f 7 | cc_4 GND EN 0.0477161f 8 | cc_5 VDD EN 0.00772676f 9 | cc_6 Y a_9_6# 0.048975f 10 | cc_7 A a_9_6# 0.0838825f 11 | cc_8 GND a_9_6# 0.0594033f 12 | cc_9 VDD a_9_6# 0.0746064f 13 | cc_10 A Y 0.0932661f 14 | cc_11 VDD Y 0.0389446f 15 | cc_12 GND A 0.218308f 16 | cc_13 VDD A 0.0318485f 17 | cc_14 VDD GND 0.00127947f 18 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/XNOR2X1.pex.netlist: -------------------------------------------------------------------------------- 1 | * File: XNOR2X1.pex.netlist 2 | * Created: Wed Jan 2 19:01:52 2008 3 | * Program "Calibre xRC" 4 | * Version "v2007.2_34.24" 5 | * 6 | .subckt XNOR2X1 B Y A GND VDD 7 | * 8 | MM11 a_12_41# B GND GND NMOS_VTL L=5e-08 W=5e-07 9 | MM10 GND B a_35_6# GND NMOS_VTL L=5e-08 W=5e-07 10 | MM9 a_35_6# a_2_6# Y GND NMOS_VTL L=5e-08 W=5e-07 11 | MM8 Y A a_18_6# GND NMOS_VTL L=5e-08 W=5e-07 12 | MM7 a_18_6# a_12_41# GND GND NMOS_VTL L=5e-08 W=5e-07 13 | MM6 GND A a_2_6# GND NMOS_VTL L=5e-08 W=5e-07 14 | MM5 a_12_41# B VDD VDD PMOS_VTL L=5e-08 W=1e-06 15 | MM4 VDD B a_35_54# VDD PMOS_VTL L=5e-08 W=1e-06 16 | MM3 a_35_54# A Y VDD PMOS_VTL L=5e-08 W=1e-06 17 | MM2 Y a_2_6# a_18_54# VDD PMOS_VTL L=5e-08 W=1e-06 18 | MM1 a_18_54# a_12_41# VDD VDD PMOS_VTL L=5e-08 W=1e-06 19 | MM0 VDD A a_2_6# VDD PMOS_VTL L=5e-08 W=1e-06 20 | c_7 B 0 0.206335f 21 | c_13 Y 0 0.0546395f 22 | c_20 a_12_41# 0 0.244159f 23 | c_27 A 0 0.245968f 24 | c_33 GND 0 0.147357f 25 | c_38 VDD 0 0.147606f 26 | c_45 a_2_6# 0 0.251613f 27 | * 28 | .include "XNOR2X1.pex.netlist.XNOR2X1.pxi" 29 | * 30 | .ends 31 | * 32 | * 33 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/XNOR2X1.pex.netlist.XNOR2X1.pxi: -------------------------------------------------------------------------------- 1 | * File: XNOR2X1.pex.netlist.XNOR2X1.pxi 2 | * Created: Wed Jan 2 19:01:52 2008 3 | * 4 | cc_1 Y B 9.45178e-19 5 | cc_2 a_12_41# B 0.0882513f 6 | cc_3 A B 0.0362524f 7 | cc_4 GND B 0.00906885f 8 | cc_5 VDD B 0.00661119f 9 | cc_6 a_2_6# B 0.0164149f 10 | cc_7 a_12_41# Y 0.22888f 11 | cc_8 A Y 0.0351984f 12 | cc_9 GND Y 0.0199951f 13 | cc_10 a_2_6# Y 0.0333201f 14 | cc_11 A a_12_41# 0.0728819f 15 | cc_12 GND a_12_41# 0.0585439f 16 | cc_13 VDD a_12_41# 0.0795616f 17 | cc_14 a_2_6# a_12_41# 0.0837809f 18 | cc_15 GND A 0.00797164f 19 | cc_16 VDD A 0.00980212f 20 | cc_17 a_2_6# A 0.179323f 21 | cc_18 a_2_6# GND 0.0764298f 22 | cc_19 a_2_6# VDD 0.0459287f 23 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/XOR2X1.pex.netlist: -------------------------------------------------------------------------------- 1 | * File: XOR2X1.pex.netlist 2 | * Created: Wed Jan 2 19:04:36 2008 3 | * Program "Calibre xRC" 4 | * Version "v2007.2_34.24" 5 | * 6 | .subckt XOR2X1 B Y A VDD GND 7 | * 8 | MM11 a_13_43# B GND GND NMOS_VTL L=5e-08 W=5e-07 9 | MM10 GND B a_35_6# GND NMOS_VTL L=5e-08 W=5e-07 10 | MM9 a_35_6# A Y GND NMOS_VTL L=5e-08 W=5e-07 11 | MM8 Y a_2_6# a_18_6# GND NMOS_VTL L=5e-08 W=5e-07 12 | MM7 a_18_6# a_13_43# GND GND NMOS_VTL L=5e-08 W=5e-07 13 | MM6 GND A a_2_6# GND NMOS_VTL L=5e-08 W=5e-07 14 | MM5 a_13_43# B VDD VDD PMOS_VTL L=5e-08 W=1e-06 15 | MM4 VDD B a_35_54# VDD PMOS_VTL L=5e-08 W=1e-06 16 | MM3 a_35_54# a_2_6# Y VDD PMOS_VTL L=5e-08 W=1e-06 17 | MM2 Y A a_18_54# VDD PMOS_VTL L=5e-08 W=1e-06 18 | MM1 a_18_54# a_13_43# VDD VDD PMOS_VTL L=5e-08 W=1e-06 19 | MM0 VDD A a_2_6# VDD PMOS_VTL L=5e-08 W=1e-06 20 | c_7 B 0 0.268706f 21 | c_12 Y 0 0.0282611f 22 | c_19 a_13_43# 0 0.303557f 23 | c_24 GND 0 0.149284f 24 | c_29 VDD 0 0.167715f 25 | c_36 A 0 0.288858f 26 | c_43 a_2_6# 0 0.202235f 27 | * 28 | .include "XOR2X1.pex.netlist.XOR2X1.pxi" 29 | * 30 | .ends 31 | * 32 | * 33 | -------------------------------------------------------------------------------- /librecell-lib/test_data/freepdk45/netlists_pex/XOR2X1.pex.netlist.XOR2X1.pxi: -------------------------------------------------------------------------------- 1 | * File: XOR2X1.pex.netlist.XOR2X1.pxi 2 | * Created: Wed Jan 2 19:04:36 2008 3 | * 4 | cc_1 Y B 0.00466903f 5 | cc_2 a_13_43# B 0.0742195f 6 | cc_3 GND B 0.0225754f 7 | cc_4 VDD B 0.0249261f 8 | cc_5 A B 0.0249138f 9 | cc_6 a_2_6# B 0.0342788f 10 | cc_7 a_13_43# Y 0.0389808f 11 | cc_8 A Y 0.24282f 12 | cc_9 a_2_6# Y 0.0367231f 13 | cc_10 GND a_13_43# 0.100459f 14 | cc_11 VDD a_13_43# 0.111193f 15 | cc_12 A a_13_43# 0.118296f 16 | cc_13 a_2_6# a_13_43# 0.0297622f 17 | cc_14 A GND 0.0815039f 18 | cc_15 a_2_6# GND 0.0144129f 19 | cc_16 A VDD 0.0157042f 20 | cc_17 a_2_6# VDD 0.021718f 21 | cc_18 a_2_6# A 0.193503f 22 | -------------------------------------------------------------------------------- /librecell-meta/README.md: -------------------------------------------------------------------------------- 1 | # LibreCell Meta 2 | This is a meta-package containing no code but just references to sub-packages. 3 | 4 | Installing this package will install 5 | * librecell-layout 6 | * librecell-lib -------------------------------------------------------------------------------- /librecell-meta/setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | 4 | def readme(): 5 | with open("README.md", "r") as f: 6 | return f.read() 7 | 8 | 9 | setup(name='librecell', 10 | version='0.0.9', 11 | description='Meta-package for the LibreCell suite.', 12 | long_description=readme(), 13 | long_description_content_type="text/markdown", 14 | keywords='cmos cell generator layout characterization vlsi asic', 15 | classifiers=[ 16 | 'Development Status :: 3 - Alpha', 17 | 'Topic :: Scientific/Engineering', 18 | 'Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)', 19 | 'Programming Language :: Python :: 3' 20 | ], 21 | url='https://codeberg.org/tok/librecell', 22 | author='T. Kramer', 23 | author_email='code@tkramer.ch', 24 | license='', # ??? 25 | install_requires=[ 26 | 'librecell-common==0.0.9', 27 | 'librecell-layout==0.0.9', 28 | 'librecell-lib==0.0.10', 29 | ], 30 | zip_safe=False) 31 | --------------------------------------------------------------------------------