├── .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 |
--------------------------------------------------------------------------------