Clean up new code for add_modules, add_pins and netlist/layouts.

This commit is contained in:
Matt Guthaus 2018-08-28 10:24:09 -07:00
parent 6401cbf2a6
commit e17c69be3e
23 changed files with 466 additions and 333 deletions

View File

@ -199,7 +199,7 @@ class instance(geometry):
""" This updates the placement of an instance. """
debug.info(3, "placing instance {}".format(self.name))
# Update the placement of an already added instance
self.offset = offset
self.offset = vector(offset)
self.mirror = mirror
self.rotate = rotate
self.update_boundary()

View File

@ -8,5 +8,5 @@ supply_voltages = [1.0]
temperatures = [25]
output_path = "temp"
output_name = "sram_2_16_1_freepdk45"
output_name = "sram_{0}_{1}_{2}_{3}".format(word_size,num_words,num_banks,tech_name)

View File

@ -7,7 +7,6 @@ process_corners = ["TT"]
supply_voltages = [ 5.0 ]
temperatures = [ 25 ]
output_path = "temp"
output_name = "sram_2_16_1_scn3me_subm"
output_name = "sram_{0}_{1}_{2}_{3}".format(word_size,num_words,num_banks,tech_name)

View File

@ -207,7 +207,6 @@ def read_config(config_file, is_unit_test=True):
# If we are only generating a netlist, we can't do DRC/LVS
if OPTS.netlist_only:
OPTS.check_lvsdrc=False
# If config didn't set output name, make a reasonable default.
if (OPTS.output_name == ""):

View File

@ -22,17 +22,6 @@ class bank(design.design):
def __init__(self, word_size, num_words, words_per_row, num_banks=1, name=""):
mod_list = ["bitcell", "decoder", "ms_flop_array", "wordline_driver",
"bitcell_array", "sense_amp_array", "precharge_array",
"column_mux_array", "write_driver_array",
"dff", "bank_select"]
from importlib import reload
for mod_name in mod_list:
config_mod_name = getattr(OPTS, mod_name)
class_file = reload(__import__(config_mod_name))
mod_class = getattr(class_file , config_mod_name)
setattr (self, "mod_"+mod_name, mod_class)
if name == "":
name = "bank_{0}_{1}".format(word_size, num_words)
design.design.__init__(self, name)
@ -206,6 +195,19 @@ class bank(design.design):
def add_modules(self):
""" Create all the modules using the class loader """
mod_list = ["bitcell", "decoder", "ms_flop_array", "wordline_driver",
"bitcell_array", "sense_amp_array", "precharge_array",
"column_mux_array", "write_driver_array",
"dff", "bank_select"]
from importlib import reload
for mod_name in mod_list:
config_mod_name = getattr(OPTS, mod_name)
class_file = reload(__import__(config_mod_name))
mod_class = getattr(class_file , config_mod_name)
setattr (self, "mod_"+mod_name, mod_class)
self.bitcell = self.mod_bitcell()
self.bitcell_array = self.mod_bitcell_array(cols=self.num_cols,

View File

@ -21,16 +21,6 @@ class bitcell_array(design.design):
self.column_size = cols
self.row_size = rows
from importlib import reload
c = reload(__import__(OPTS.bitcell))
self.mod_bitcell = getattr(c, OPTS.bitcell)
self.cell = self.mod_bitcell()
self.add_mod(self.cell)
# We increase it by a well enclosure so the precharges don't overlap our wells
self.height = self.row_size*self.cell.height + drc["well_enclosure_active"] + self.m1_width
self.width = self.column_size*self.cell.width + self.m1_width
self.create_netlist()
if not OPTS.netlist_only:
self.create_layout()
@ -42,17 +32,16 @@ class bitcell_array(design.design):
def create_netlist(self):
""" Create and connect the netlist """
self.add_modules()
self.add_pins()
self.cell_inst = {}
for col in range(self.column_size):
for row in range(self.row_size):
name = "bit_r{0}_c{1}".format(row, col)
self.cell_inst[row,col]=self.add_inst(name=name,
mod=self.cell)
self.connect_inst(self.cell.list_bitcell_pins(col, row))
self.create_modules()
def create_layout(self):
# We increase it by a well enclosure so the precharges don't overlap our wells
self.height = self.row_size*self.cell.height + drc["well_enclosure_active"] + self.m1_width
self.width = self.column_size*self.cell.width + self.m1_width
xoffset = 0.0
for col in range(self.column_size):
yoffset = 0.0
@ -87,7 +76,25 @@ class bitcell_array(design.design):
self.add_pin("vdd")
self.add_pin("gnd")
def add_modules(self):
""" Add the modules used in this design """
from importlib import reload
c = reload(__import__(OPTS.bitcell))
self.mod_bitcell = getattr(c, OPTS.bitcell)
self.cell = self.mod_bitcell()
self.add_mod(self.cell)
def create_modules(self):
""" Create the module instances used in this design """
self.cell_inst = {}
for col in range(self.column_size):
for row in range(self.row_size):
name = "bit_r{0}_c{1}".format(row, col)
self.cell_inst[row,col]=self.add_inst(name=name,
mod=self.cell)
self.connect_inst(self.cell.list_bitcell_pins(col, row))
def add_layout_pins(self):
""" Add the layout pins """

View File

@ -30,8 +30,8 @@ class delay_chain(design.design):
def create_netlist(self):
self.add_pins()
self.add_modules()
self.add_pins()
self.create_inverters()
def create_layout(self):

View File

@ -20,27 +20,30 @@ class dff_array(design.design):
design.design.__init__(self, name)
debug.info(1, "Creating {0} rows={1} cols={2}".format(self.name, self.rows, self.columns))
self.create_netlist()
if not OPTS.netlist_only:
self.create_layout()
def create_netlist(self):
self.add_modules()
self.add_pins()
self.create_dff_array()
def create_layout(self):
self.width = self.columns * self.dff.width
self.height = self.rows * self.dff.height
self.place_dff_array()
self.add_layout_pins()
self.DRC_LVS()
def add_modules(self):
from importlib import reload
c = reload(__import__(OPTS.dff))
self.mod_dff = getattr(c, OPTS.dff)
self.dff = self.mod_dff("dff")
self.add_mod(self.dff)
self.width = self.columns * self.dff.width
self.height = self.rows * self.dff.height
self.create_netlist()
self.create_layout()
def create_netlist(self):
self.add_pins()
self.create_dff_array()
def create_layout(self):
self.place_dff_array()
self.add_layout_pins()
self.DRC_LVS()
def add_pins(self):
for row in range(self.rows):
for col in range(self.columns):

View File

@ -26,29 +26,41 @@ class dff_buf(design.design):
debug.check(inv1_size>=2, "Inverter must be greater than two for rail spacing DRC rules.")
debug.check(inv2_size>=2, "Inverter must be greater than two for rail spacing DRC rules.")
self.inv1_size=inv1_size
self.inv2_size=inv2_size
self.create_netlist()
if not OPTS.netlist_only:
self.create_layout()
def create_netlist(self):
self.add_modules()
self.add_pins()
self.create_modules()
def create_layout(self):
self.width = self.dff.width + self.inv1.width + self.inv2.width
self.height = self.dff.height
self.place_modules()
self.route_wires()
self.add_layout_pins()
self.DRC_LVS()
def add_modules(self):
from importlib import reload
c = reload(__import__(OPTS.dff))
self.mod_dff = getattr(c, OPTS.dff)
self.dff = self.mod_dff("dff")
self.add_mod(self.dff)
self.inv1 = pinv(size=inv1_size,height=self.dff.height)
self.inv1 = pinv(size=self.inv1_size,height=self.dff.height)
self.add_mod(self.inv1)
self.inv2 = pinv(size=inv2_size,height=self.dff.height)
self.inv2 = pinv(size=self.inv2_size,height=self.dff.height)
self.add_mod(self.inv2)
self.width = self.dff.width + self.inv1.width + self.inv2.width
self.height = self.dff.height
self.create_layout()
def create_layout(self):
self.add_pins()
self.add_insts()
self.add_wires()
self.add_layout_pins()
self.DRC_LVS()
def add_pins(self):
self.add_pin("D")
@ -58,26 +70,30 @@ class dff_buf(design.design):
self.add_pin("vdd")
self.add_pin("gnd")
def add_insts(self):
# Add the DFF
def create_modules(self):
self.dff_inst=self.add_inst(name="dff_buf_dff",
mod=self.dff,
offset=vector(0,0))
mod=self.dff)
self.connect_inst(["D", "qint", "clk", "vdd", "gnd"])
# Add INV1 to the right
self.inv1_inst=self.add_inst(name="dff_buf_inv1",
mod=self.inv1,
offset=vector(self.dff_inst.rx(),0))
mod=self.inv1)
self.connect_inst(["qint", "Qb", "vdd", "gnd"])
# Add INV2 to the right
self.inv2_inst=self.add_inst(name="dff_buf_inv2",
mod=self.inv2,
offset=vector(self.inv1_inst.rx(),0))
mod=self.inv2)
self.connect_inst(["Qb", "Q", "vdd", "gnd"])
def place_modules(self):
# Add the DFF
self.dff_inst.place(vector(0,0))
# Add INV1 to the right
self.inv1_inst.place(vector(self.dff_inst.rx(),0))
def add_wires(self):
# Add INV2 to the right
self.inv2_inst.place(vector(self.inv1_inst.rx(),0))
def route_wires(self):
# Route dff q to inv1 a
q_pin = self.dff_inst.get_pin("Q")
a1_pin = self.inv1_inst.get_pin("A")

View File

@ -29,7 +29,7 @@ class dff_buf_array(design.design):
def create_netlist(self):
self.add_pins()
self.add_dff()
self.add_modules()
self.create_dff_array()
def create_layout(self):
@ -51,7 +51,7 @@ class dff_buf_array(design.design):
self.add_pin("vdd")
self.add_pin("gnd")
def add_dff(self):
def add_modules(self):
self.dff = dff_buf.dff_buf(self.inv1_size, self.inv2_size)
self.add_mod(self.dff)

View File

@ -63,12 +63,10 @@ class dff_inv(design.design):
self.add_mod(self.inv1)
def create_modules(self):
# Add the DFF
self.dff_inst=self.add_inst(name="dff_inv_dff",
mod=self.dff)
self.connect_inst(["D", "Q", "clk", "vdd", "gnd"])
# Add INV1 to the right
self.inv1_inst=self.add_inst(name="dff_inv_inv1",
mod=self.inv1)
self.connect_inst(["Q", "Qb", "vdd", "gnd"])

View File

@ -28,7 +28,7 @@ class dff_inv_array(design.design):
def create_netlist(self):
self.add_pins()
self.add_dff()
self.add_modules()
self.create_dff_array()
def create_layout(self):
@ -39,7 +39,7 @@ class dff_inv_array(design.design):
self.add_layout_pins()
self.DRC_LVS()
def add_dff(self):
def add_modules(self):
self.dff = dff_inv.dff_inv(self.inv_size)
self.add_mod(self.dff)

View File

@ -20,27 +20,31 @@ class ms_flop_array(design.design):
design.design.__init__(self, name)
debug.info(1, "Creating {}".format(self.name))
self.words_per_row = int(self.columns / self.word_size)
self.create_netlist()
if not OPTS.netlist_only:
self.create_layout()
def create_netlist(self):
self.add_modules()
self.add_pins()
self.create_ms_flop_array()
def create_layout(self):
self.width = self.columns * self.ms.width
self.height = self.ms.height
self.place_ms_flop_array()
self.add_layout_pins()
self.DRC_LVS()
def add_modules(self):
from importlib import reload
c = reload(__import__(OPTS.ms_flop))
self.mod_ms_flop = getattr(c, OPTS.ms_flop)
self.ms = self.mod_ms_flop("ms_flop")
self.add_mod(self.ms)
self.width = self.columns * self.ms.width
self.height = self.ms.height
self.words_per_row = int(self.columns / self.word_size)
self.create_netlist()
self.create_layout()
def create_netlist(self):
self.add_pins()
self.create_ms_flop_array()
def create_layout(self):
self.place_ms_flop_array()
self.add_layout_pins()
self.DRC_LVS()
def add_pins(self):
for i in range(self.word_size):

View File

@ -20,9 +20,9 @@ class precharge_array(design.design):
debug.info(1, "Creating {0}".format(self.name))
self.columns = columns
self.pc_cell = precharge(name="precharge", size=size, bitcell_bl=bitcell_bl, bitcell_br=bitcell_br)
self.add_mod(self.pc_cell)
self.size = size
self.bitcell_bl = bitcell_bl
self.bitcell_br = bitcell_br
self.create_netlist()
if not OPTS.netlist_only:
@ -37,6 +37,7 @@ class precharge_array(design.design):
self.add_pin("vdd")
def create_netlist(self):
self.add_modules()
self.add_pins()
self.create_insts()
@ -47,8 +48,15 @@ class precharge_array(design.design):
self.place_insts()
self.add_layout_pins()
self.DRC_LVS()
def add_modules(self):
self.pc_cell = precharge(name="precharge",
size=self.size,
bitcell_bl=self.bitcell_bl,
bitcell_br=self.bitcell_br)
self.add_mod(self.pc_cell)
def add_layout_pins(self):
self.add_layout_pin(text="en",

View File

@ -18,13 +18,6 @@ class replica_bitline(design.design):
def __init__(self, delay_stages, delay_fanout, bitcell_loads, name="replica_bitline"):
design.design.__init__(self, name)
from importlib import reload
g = reload(__import__(OPTS.delay_chain))
self.mod_delay_chain = getattr(g, OPTS.delay_chain)
g = reload(__import__(OPTS.replica_bitcell))
self.mod_replica_bitcell = getattr(g, OPTS.replica_bitcell)
self.bitcell_loads = bitcell_loads
self.delay_stages = delay_stages
self.delay_fanout = delay_fanout
@ -34,19 +27,17 @@ class replica_bitline(design.design):
self.create_layout()
def create_netlist(self):
for pin in ["en", "out", "vdd", "gnd"]:
self.add_pin(pin)
self.add_modules()
self.add_pins()
self.create_modules()
def create_layout(self):
self.calculate_module_offsets()
self.place_modules()
self.route()
self.add_layout_pins()
self.offset_all_coordinates()
self.add_layout_pins()
#self.add_lvs_correspondence_points()
@ -56,6 +47,9 @@ class replica_bitline(design.design):
self.DRC_LVS()
def add_pins(self):
for pin in ["en", "out", "vdd", "gnd"]:
self.add_pin(pin)
def calculate_module_offsets(self):
""" Calculate all the module offsets """
@ -85,6 +79,14 @@ class replica_bitline(design.design):
def add_modules(self):
""" Add the modules for later usage """
from importlib import reload
g = reload(__import__(OPTS.delay_chain))
self.mod_delay_chain = getattr(g, OPTS.delay_chain)
g = reload(__import__(OPTS.replica_bitcell))
self.mod_replica_bitcell = getattr(g, OPTS.replica_bitcell)
self.bitcell = self.replica_bitcell = self.mod_replica_bitcell()
self.add_mod(self.bitcell)
@ -267,8 +269,6 @@ class replica_bitline(design.design):
self.copy_layout_pin(self.dc_inst,"vdd")
self.copy_layout_pin(self.rbc_inst,"vdd")
# Connect the WL and vdd pins directly to the center and right vdd rails
# Connect RBL vdd pins to center and right rails
rbl_vdd_pins = self.rbl_inst.get_pins("vdd")
@ -288,9 +288,6 @@ class replica_bitline(design.design):
offset=end,
rotate=90)
# Add via for the inverter
pin = self.rbl_inv_inst.get_pin("vdd")
start = vector(self.left_vdd_pin.cx(),pin.cy())

View File

@ -14,44 +14,46 @@ class sense_amp_array(design.design):
design.design.__init__(self, "sense_amp_array")
debug.info(1, "Creating {0}".format(self.name))
self.word_size = word_size
self.words_per_row = words_per_row
self.row_size = self.word_size * self.words_per_row
self.create_netlist()
if not OPTS.netlist_only:
self.create_layout()
def create_netlist(self):
self.add_modules()
self.add_pins()
self.create_sense_amp_array()
def create_layout(self):
self.height = self.amp.height
self.width = self.amp.width * self.word_size * self.words_per_row
self.place_sense_amp_array()
self.add_layout_pins()
self.route_rails()
self.DRC_LVS()
def add_pins(self):
for i in range(0,self.word_size):
self.add_pin("data[{0}]".format(i))
self.add_pin("bl[{0}]".format(i))
self.add_pin("br[{0}]".format(i))
self.add_pin("en")
self.add_pin("vdd")
self.add_pin("gnd")
def add_modules(self):
from importlib import reload
c = reload(__import__(OPTS.sense_amp))
self.mod_sense_amp = getattr(c, OPTS.sense_amp)
self.amp = self.mod_sense_amp("sense_amp")
self.add_mod(self.amp)
self.word_size = word_size
self.words_per_row = words_per_row
self.row_size = self.word_size * self.words_per_row
self.height = self.amp.height
self.width = self.amp.width * self.word_size * self.words_per_row
self.create_netlist()
self.create_layout()
self.DRC_LVS()
def add_pins(self):
for i in range(0,self.word_size):
self.add_pin("data[{0}]".format(i))
self.add_pin("bl[{0}]".format(i))
self.add_pin("br[{0}]".format(i))
self.add_pin("en")
self.add_pin("vdd")
self.add_pin("gnd")
def create_netlist(self):
self.add_pins()
self.create_sense_amp_array()
def create_layout(self):
self.place_sense_amp_array()
self.add_layout_pins()
self.route_rails()
def create_sense_amp_array(self):
self.local_insts = []
for i in range(0,self.word_size):

View File

@ -6,7 +6,7 @@ from tech import drc
import debug
import math
from vector import vector
from globals import OPTS
class single_level_column_mux_array(design.design):
"""
@ -20,23 +20,14 @@ class single_level_column_mux_array(design.design):
self.columns = columns
self.word_size = word_size
self.words_per_row = int(self.columns / self.word_size)
self.create_netlist()
self.create_layout()
def add_pins(self):
for i in range(self.columns):
self.add_pin("bl[{}]".format(i))
self.add_pin("br[{}]".format(i))
for i in range(self.words_per_row):
self.add_pin("sel[{}]".format(i))
for i in range(self.word_size):
self.add_pin("bl_out[{}]".format(i))
self.add_pin("br_out[{}]".format(i))
self.add_pin("gnd")
if not OPTS.netlist_only:
self.create_layout()
def create_netlist(self):
self.add_pins()
self.add_modules()
self.add_pins()
self.create_array()
def create_layout(self):
@ -51,6 +42,17 @@ class single_level_column_mux_array(design.design):
self.DRC_LVS()
def add_pins(self):
for i in range(self.columns):
self.add_pin("bl[{}]".format(i))
self.add_pin("br[{}]".format(i))
for i in range(self.words_per_row):
self.add_pin("sel[{}]".format(i))
for i in range(self.word_size):
self.add_pin("bl_out[{}]".format(i))
self.add_pin("br_out[{}]".format(i))
self.add_pin("gnd")
def add_modules(self):
# FIXME: Why is this 8x?

View File

@ -14,31 +14,34 @@ class tri_gate_array(design.design):
design.design.__init__(self, "tri_gate_array")
debug.info(1, "Creating {0}".format(self.name))
self.columns = columns
self.word_size = word_size
self.words_per_row = int(self.columns / self.word_size)
self.create_netlist()
if not OPTS.netlist_only:
self.create_layout()
def create_netlist(self):
self.add_modules()
self.add_pins()
self.create_array()
def create_layout(self):
self.width = (self.columns / self.words_per_row) * self.tri.width
self.height = self.tri.height
self.place_array()
self.add_layout_pins()
self.DRC_LVS()
def add_modules(self):
from importlib import reload
c = reload(__import__(OPTS.tri_gate))
self.mod_tri_gate = getattr(c, OPTS.tri_gate)
self.tri = self.mod_tri_gate("tri_gate")
self.add_mod(self.tri)
self.columns = columns
self.word_size = word_size
self.words_per_row = int(self.columns / self.word_size)
self.width = (self.columns / self.words_per_row) * self.tri.width
self.height = self.tri.height
self.create_netlist()
self.create_layout()
def create_netlist(self):
self.add_pins()
self.create_array()
def create_layout(self):
self.place_array()
self.add_layout_pins()
self.DRC_LVS()
def add_pins(self):
"""create the name of pins depend on the word size"""
for i in range(self.word_size):

View File

@ -20,13 +20,14 @@ class wordline_driver(design.design):
design.design.__init__(self, "wordline_driver")
self.rows = rows
self.create_netlist()
if not OPTS.netlist_only:
self.create_layout()
def create_netlist(self):
self.add_pins()
self.add_modules()
self.add_pins()
self.create_drivers()
def create_layout(self):

View File

@ -15,21 +15,27 @@ class write_driver_array(design.design):
design.design.__init__(self, "write_driver_array")
debug.info(1, "Creating {0}".format(self.name))
from importlib import reload
c = reload(__import__(OPTS.write_driver))
self.mod_write_driver = getattr(c, OPTS.write_driver)
self.driver = self.mod_write_driver("write_driver")
self.add_mod(self.driver)
self.columns = columns
self.word_size = word_size
self.words_per_row = int(columns / word_size)
self.width = self.columns * self.driver.width
self.height = self.height = self.driver.height
self.create_netlist()
self.create_layout()
if not OPTS.netlist_only:
self.create_layout()
def create_netlist(self):
self.add_modules()
self.add_pins()
self.create_write_array()
def create_layout(self):
self.width = self.columns * self.driver.width
self.height = self.driver.height
self.place_write_array()
self.add_layout_pins()
self.DRC_LVS()
def add_pins(self):
for i in range(self.word_size):
@ -41,14 +47,12 @@ class write_driver_array(design.design):
self.add_pin("vdd")
self.add_pin("gnd")
def create_netlist(self):
self.add_pins()
self.create_write_array()
def create_layout(self):
self.place_write_array()
self.add_layout_pins()
self.DRC_LVS()
def add_modules(self):
from importlib import reload
c = reload(__import__(OPTS.write_driver))
self.mod_write_driver = getattr(c, OPTS.write_driver)
self.driver = self.mod_write_driver("write_driver")
self.add_mod(self.driver)
def create_write_array(self):
self.driver_insts = {}

View File

@ -37,10 +37,39 @@ class pbitcell(pgate.pgate):
pbitcell.height = self.height
def create_netlist(self):
self.add_pins()
self.add_modules()
self.create_storage()
if(self.num_readwrite > 0):
self.create_readwrite_ports()
if(self.num_write > 0):
self.create_write_ports()
if(self.num_read > 0):
self.create_read_ports()
def create_layout(self):
self.calculate_spacing()
self.calculate_postions()
self.place_storage()
self.route_storage()
self.route_rails()
if(self.num_readwrite > 0):
self.place_readwrite_ports()
if(self.num_write > 0):
self.place_write_ports()
if(self.num_read > 0):
self.place_read_ports()
self.extend_well()
self.offset_all_coordinates()
self.DRC_LVS()
def add_pins(self):
"""
Adding pins for pbitcell module
"""
for k in range(self.num_readwrite):
self.add_pin("rwbl{}".format(k))
self.add_pin("rwbl_bar{}".format(k))
@ -61,33 +90,8 @@ class pbitcell(pgate.pgate):
self.add_pin("vdd")
self.add_pin("gnd")
def create_netlist(self):
self.add_pins()
def create_layout(self):
self.create_ptx()
self.calculate_spacing()
self.calculate_postions()
self.add_storage()
self.add_rails()
if(self.num_readwrite > 0):
self.add_readwrite_ports()
if(self.num_write > 0):
self.add_write_ports()
if(self.num_read > 0):
self.add_read_ports()
self.extend_well()
self.offset_all_coordinates()
self.DRC_LVS()
def create_ptx(self):
"""
Calculate transistor sizes and create ptx for read/write, write, and read ports
"""
""" calculate transistor sizes """
def add_modules(self):
# if there are any read/write ports, then the inverter nmos is sized based the number of them
if(self.num_readwrite > 0):
inverter_nmos_width = self.num_readwrite*3*parameter["min_tx_size"]
@ -131,11 +135,9 @@ class pbitcell(pgate.pgate):
def calculate_spacing(self):
"""
Calculate transistor spacings
"""
""" Calculate transistor spacings """
""" calculate metal contact extensions over transistor active """
# calculate metal contact extensions over transistor active
self.inverter_pmos_contact_extension = 0.5*(self.inverter_pmos.active_contact.height - self.inverter_pmos.active_height)
self.readwrite_nmos_contact_extension = 0.5*(self.readwrite_nmos.active_contact.height - self.readwrite_nmos.active_height)
self.write_nmos_contact_extension = 0.5*(self.write_nmos.active_contact.height - self.write_nmos.active_height)
@ -144,7 +146,7 @@ class pbitcell(pgate.pgate):
# calculate the distance threshold for different gate contact spacings
self.gate_contact_thres = drc["poly_to_active"] - drc["minwidth_metal2"]
""" calculations for horizontal transistor to tansistor spacing """
#calculations for horizontal transistor to tansistor spacing
# inverter spacings
self.inverter_to_inverter_spacing = contact.poly.height + drc["minwidth_metal1"]
self.inverter_to_write_spacing = drc["pwell_to_nwell"] + 2*drc["well_enclosure_active"]
@ -266,9 +268,9 @@ class pbitcell(pgate.pgate):
self.height = self.topmost_ypos - self.botmost_ypos - array_vdd_overlap
def add_storage(self):
def place_storage(self):
"""
Creates the crossed coupled inverters that act as storage for the bitcell.
Places the crossed coupled inverters that act as storage for the bitcell.
The stored value of the cell is denoted as "Q", and the inverted value as "Q_bar".
"""
@ -278,26 +280,14 @@ class pbitcell(pgate.pgate):
inverter_pmos_ypos = self.inverter_nmos.active_height + self.inverter_gap
# create active for nmos
self.inverter_nmos_left = self.add_inst(name="inverter_nmos_left",
mod=self.inverter_nmos,
offset=[left_inverter_xpos,0])
self.connect_inst(["Q_bar", "Q", "gnd", "gnd"])
self.inverter_nmos_right = self.add_inst(name="inverter_nmos_right",
mod=self.inverter_nmos,
offset=[right_inverter_xpos,0])
self.connect_inst(["gnd", "Q_bar", "Q", "gnd"])
self.inverter_nmos_left.place([left_inverter_xpos,0])
self.inverter_nmos_right.place([right_inverter_xpos,0])
# create active for pmos
self.inverter_pmos_left = self.add_inst(name="inverter_pmos_left",
mod=self.inverter_pmos,
offset=[left_inverter_xpos, inverter_pmos_ypos])
self.connect_inst(["Q_bar", "Q", "vdd", "vdd"])
self.inverter_pmos_right = self.add_inst(name="inverter_pmos_right",
mod=self.inverter_pmos,
offset=[right_inverter_xpos, inverter_pmos_ypos])
self.connect_inst(["vdd", "Q_bar", "Q", "vdd"])
self.inverter_pmos_left.place([left_inverter_xpos, inverter_pmos_ypos])
self.inverter_pmos_right.place([right_inverter_xpos, inverter_pmos_ypos])
def route_storage(self):
# connect input (gate) of inverters
self.add_path("poly", [self.inverter_nmos_left.get_pin("G").uc(), self.inverter_pmos_left.get_pin("G").bc()])
@ -329,13 +319,38 @@ class pbitcell(pgate.pgate):
self.left_building_edge = -self.inverter_tile_width
self.right_building_edge = self.inverter_tile_width
def add_rails(self):
def create_storage(self):
"""
Creates the crossed coupled inverters that act as storage for the bitcell.
The stored value of the cell is denoted as "Q", and the inverted value as "Q_bar".
"""
# create active for nmos
self.inverter_nmos_left = self.add_inst(name="inverter_nmos_left",
mod=self.inverter_nmos)
self.connect_inst(["Q_bar", "Q", "gnd", "gnd"])
self.inverter_nmos_right = self.add_inst(name="inverter_nmos_right",
mod=self.inverter_nmos)
self.connect_inst(["gnd", "Q_bar", "Q", "gnd"])
# create active for pmos
self.inverter_pmos_left = self.add_inst(name="inverter_pmos_left",
mod=self.inverter_pmos)
self.connect_inst(["Q_bar", "Q", "vdd", "vdd"])
self.inverter_pmos_right = self.add_inst(name="inverter_pmos_right",
mod=self.inverter_pmos)
self.connect_inst(["vdd", "Q_bar", "Q", "vdd"])
def route_rails(self):
"""
Add gnd and vdd rails and connects them to the inverters
"""
""" Add rails for vdd and gnd """
# Add rails for vdd and gnd
self.gnd_position = vector(self.leftmost_xpos, -self.rail_tile_height)
self.gnd = self.add_layout_pin(text="gnd",
layer="metal1",
@ -352,7 +367,7 @@ class pbitcell(pgate.pgate):
width=self.width,
height=drc["minwidth_metal1"])
""" Connect inverters to rails """
# Connect inverters to rails
# connect inverter nmos to gnd
gnd_pos_left = vector(self.inverter_nmos_left.get_pin("S").bc().x, self.gnd_position.y)
self.add_path("metal1", [self.inverter_nmos_left.get_pin("S").bc(), gnd_pos_left])
@ -368,9 +383,9 @@ class pbitcell(pgate.pgate):
self.add_path("metal1", [self.inverter_pmos_right.get_pin("D").uc(), vdd_pos_right])
def add_readwrite_ports(self):
def create_readwrite_ports(self):
"""
Adds read/write ports to the bit cell. A differential pair of transistor can both read and write, like in a 6T cell.
Creates read/write ports to the bit cell. A differential pair of transistor can both read and write, like in a 6T cell.
A read or write is enabled by setting a Read-Write-Wordline (RWWL) high, subsequently turning on the transistor.
The transistor is connected between a Read-Write-Bitline (RWBL) and the storage component of the cell (Q).
In a write operation, driving RWBL high or low sets the value of the cell.
@ -378,20 +393,38 @@ class pbitcell(pgate.pgate):
This is a differential design, so each write port has a mirrored port that connects RWBL_bar to Q_bar.
"""
""" Define variables relevant to write transistors """
# define offset correction due to rotation of the ptx module
readwrite_rotation_correct = self.readwrite_nmos.active_height
# define write transistor variables as empty arrays based on the number of write ports
self.readwrite_nmos_left = [None] * self.num_readwrite
self.readwrite_nmos_right = [None] * self.num_readwrite
# iterate over the number of read/write ports
for k in range(0,self.num_readwrite):
# add read/write transistors
self.readwrite_nmos_left[k] = self.add_inst(name="readwrite_nmos_left{}".format(k),
mod=self.readwrite_nmos)
self.connect_inst(["Q", "rwwl{}".format(k), "rwbl{}".format(k), "gnd"])
self.readwrite_nmos_right[k] = self.add_inst(name="readwrite_nmos_right{}".format(k),
mod=self.readwrite_nmos)
self.connect_inst(["Q_bar", "rwwl{}".format(k), "rwbl_bar{}".format(k), "gnd"])
def place_readwrite_ports(self):
"""
Places read/write ports in the bit cell.
"""
# Define variables relevant to write transistors
self.rwwl_positions = [None] * self.num_readwrite
self.rwbl_positions = [None] * self.num_readwrite
self.rwbl_bar_positions = [None] * self.num_readwrite
# define offset correction due to rotation of the ptx module
readwrite_rotation_correct = self.readwrite_nmos.active_height
# iterate over the number of read/write ports
for k in range(0,self.num_readwrite):
""" Add transistors """
# Add transistors
# calculate read/write transistor offsets
left_readwrite_transistor_xpos = self.left_building_edge \
- self.inverter_to_write_spacing \
@ -404,19 +437,13 @@ class pbitcell(pgate.pgate):
+ readwrite_rotation_correct
# add read/write transistors
self.readwrite_nmos_left[k] = self.add_inst(name="readwrite_nmos_left{}".format(k),
mod=self.readwrite_nmos,
offset=[left_readwrite_transistor_xpos,0],
rotate=90)
self.connect_inst(["Q", "rwwl{}".format(k), "rwbl{}".format(k), "gnd"])
self.readwrite_nmos_left[k].place(offset=[left_readwrite_transistor_xpos,0],
rotate=90)
self.readwrite_nmos_right[k] = self.add_inst(name="readwrite_nmos_right{}".format(k),
mod=self.readwrite_nmos,
offset=[right_readwrite_transistor_xpos,0],
rotate=90)
self.connect_inst(["Q_bar", "rwwl{}".format(k), "rwbl_bar{}".format(k), "gnd"])
self.readwrite_nmos_right[k].place(offset=[right_readwrite_transistor_xpos,0],
rotate=90)
""" Add RWWL lines """
# Add RWWL lines
# calculate RWWL position
rwwl_ypos = self.gnd_position.y - (k+1)*self.rowline_tile_height
self.rwwl_positions[k] = vector(self.leftmost_xpos, rwwl_ypos)
@ -428,7 +455,7 @@ class pbitcell(pgate.pgate):
width=self.width,
height=contact.m1m2.width)
""" Source/RWBL/RWBL_bar connections """
# Source/RWBL/RWBL_bar connections
# add metal1-to-metal2 contacts on top of read/write transistor source pins for connection to WBL and WBL_bar
offset_left = self.readwrite_nmos_left[k].get_pin("S").center()
self.add_contact_center(layers=("metal1", "via1", "metal2"),
@ -455,7 +482,7 @@ class pbitcell(pgate.pgate):
width=drc["minwidth_metal2"],
height=self.height)
""" Gate/RWWL connections """
# Gate/RWWL connections
# add poly-to-meltal2 contacts to connect gate of read/write transistors to RWWL (contact next to gate)
# contact must be placed a metal1 width below the source pin to avoid drc from source pin routings
if(self.readwrite_nmos_contact_extension > self.gate_contact_thres):
@ -504,7 +531,7 @@ class pbitcell(pgate.pgate):
self.add_path("metal2", [left_gate_contact, left_rwwl_contact])
self.add_path("metal2", [right_gate_contact, right_rwwl_contact])
""" Drain/Storage connections """
# Drain/Storage connections
# this path only needs to be drawn once on the last iteration of the loop
if(k == self.num_readwrite-1):
# add contacts to connect gate of inverters to drain of read/write transistors
@ -538,34 +565,56 @@ class pbitcell(pgate.pgate):
# end if
# end for
""" update furthest left and right transistor edges """
# update furthest left and right transistor edges
self.left_building_edge = left_readwrite_transistor_xpos - self.readwrite_nmos.active_height
self.right_building_edge = right_readwrite_transistor_xpos
def add_write_ports(self):
def create_write_ports(self):
"""
Adds write ports to the bit cell. A differential pair of transistors can write only.
Creates write ports in the bit cell. A differential pair of transistors can write only.
A write is enabled by setting a Write-Rowline (WWL) high, subsequently turning on the transistor.
The transistor is connected between a Write-Bitline (WBL) and the storage component of the cell (Q).
In a write operation, driving WBL high or low sets the value of the cell.
This is a differential design, so each write port has a mirrored port that connects WBL_bar to Q_bar.
"""
""" Define variables relevant to write transistors """
# Define variables relevant to write transistors
# define offset correction due to rotation of the ptx module
write_rotation_correct = self.write_nmos.active_height
# define write transistor variables as empty arrays based on the number of write ports
self.write_nmos_left = [None] * self.num_write
self.write_nmos_right = [None] * self.num_write
self.wwl_positions = [None] * self.num_write
self.wbl_positions = [None] * self.num_write
self.wbl_bar_positions = [None] * self.num_write
# iterate over the number of write ports
for k in range(0,self.num_write):
""" Add transistors """
# add write transistors
self.write_nmos_left[k] = self.add_inst(name="write_nmos_left{}".format(k),
mod=self.write_nmos)
self.connect_inst(["Q", "wwl{}".format(k), "wbl{}".format(k), "gnd"])
self.write_nmos_right[k] = self.add_inst(name="write_nmos_right{}".format(k),
mod=self.write_nmos)
self.connect_inst(["Q_bar", "wwl{}".format(k), "wbl_bar{}".format(k), "gnd"])
def place_write_ports(self):
"""
Places write ports in the bit cell.
"""
# Define variables relevant to write transistors
self.wwl_positions = [None] * self.num_write
self.wbl_positions = [None] * self.num_write
self.wbl_bar_positions = [None] * self.num_write
# define offset correction due to rotation of the ptx module
write_rotation_correct = self.write_nmos.active_height
# iterate over the number of write ports
for k in range(0,self.num_write):
# Add transistors
# calculate write transistor offsets
left_write_transistor_xpos = self.left_building_edge \
- (not self.readwrite_port_flag)*self.inverter_to_write_spacing \
@ -580,19 +629,13 @@ class pbitcell(pgate.pgate):
+ write_rotation_correct
# add write transistors
self.write_nmos_left[k] = self.add_inst(name="write_nmos_left{}".format(k),
mod=self.write_nmos,
offset=[left_write_transistor_xpos,0],
rotate=90)
self.connect_inst(["Q", "wwl{}".format(k), "wbl{}".format(k), "gnd"])
self.write_nmos_left[k].place(offset=[left_write_transistor_xpos,0],
rotate=90)
self.write_nmos_right[k] = self.add_inst(name="write_nmos_right{}".format(k),
mod=self.write_nmos,
offset=[right_write_transistor_xpos,0],
rotate=90)
self.connect_inst(["Q_bar", "wwl{}".format(k), "wbl_bar{}".format(k), "gnd"])
self.write_nmos_right[k].place(offset=[right_write_transistor_xpos,0],
rotate=90)
""" Add WWL lines """
# Add WWL lines
# calculate WWL position
wwl_ypos = self.gnd_position.y \
- self.num_readwrite*self.rowline_tile_height \
@ -606,7 +649,7 @@ class pbitcell(pgate.pgate):
width=self.width,
height=contact.m1m2.width)
""" Source/WBL/WBL_bar connections """
# Source/WBL/WBL_bar connections
# add metal1-to-metal2 contacts on top of write transistor source pins for connection to WBL and WBL_bar
offset_left = self.write_nmos_left[k].get_pin("S").center()
self.add_contact_center(layers=("metal1", "via1", "metal2"),
@ -633,7 +676,7 @@ class pbitcell(pgate.pgate):
width=drc["minwidth_metal2"],
height=self.height)
""" Gate/WWL connections """
# Gate/WWL connections
# add poly-to-meltal2 contacts to connect gate of write transistors to WWL (contact next to gate)
# contact must be placed a metal width below the source pin to avoid drc from source pin routings
if(self.write_nmos_contact_extension > self.gate_contact_thres):
@ -682,7 +725,7 @@ class pbitcell(pgate.pgate):
self.add_path("metal2", [left_gate_contact, left_wwl_contact])
self.add_path("metal2", [right_gate_contact, right_wwl_contact])
""" Drain/Storage connections """
# Drain/Storage connections
# this path only needs to be drawn once on the last iteration of the loop
if(k == self.num_write-1):
# add contacts to connect gate of inverters to drain of write transistors
@ -713,17 +756,15 @@ class pbitcell(pgate.pgate):
midR1 = vector(self.inverter_nmos_right.get_pin("D").rc().x + 1.5*drc["minwidth_metal1"], self.write_nmos_right[k].get_pin("D").rc().y)
self.add_path("metal1", [right_storage_contact, midR0], width=contact.poly.second_layer_width)
self.add_path("metal1", [midR0+vector(0,0.5*contact.poly.second_layer_width), midR1, self.write_nmos_right[k].get_pin("D").rc()])
# end if
# end for
""" update furthest left and right transistor edges """
# update furthest left and right transistor edges
self.left_building_edge = left_write_transistor_xpos - self.write_nmos.active_height
self.right_building_edge = right_write_transistor_xpos
def add_read_ports(self):
def create_read_ports(self):
"""
Adds read ports to the bit cell. A differential pair of ports can read only.
Creates read ports in the bit cell. A differential pair of ports can read only.
Two transistors function as a read port, denoted as the "read transistor" and the "read-access transistor".
The read transistor is connected to RWL (gate), RBL (drain), and the read-access transistor (source).
The read-access transistor is connected to Q_bar (gate), gnd (source), and the read transistor (drain).
@ -733,7 +774,42 @@ class pbitcell(pgate.pgate):
using sense amps. This is a differential design, so each read port has a mirrored port that connects RBL_bar to Q.
"""
""" Define variables relevant to read transistors """
# define read transistor variables as empty arrays based on the number of read ports
self.read_nmos_left = [None] * self.num_read
self.read_nmos_right = [None] * self.num_read
self.read_access_nmos_left = [None] * self.num_read
self.read_access_nmos_right = [None] * self.num_read
# iterate over the number of read ports
for k in range(0,self.num_read):
# add read-access transistors
self.read_access_nmos_left[k] = self.add_inst(name="read_access_nmos_left{}".format(k),
mod=self.read_nmos)
self.connect_inst(["RA_to_R_left{}".format(k), " Q_bar", "gnd", "gnd"])
self.read_access_nmos_right[k] = self.add_inst(name="read_access_nmos_right{}".format(k),
mod=self.read_nmos)
self.connect_inst(["RA_to_R_right{}".format(k), "Q", "gnd", "gnd"])
# add read transistors
self.read_nmos_left[k] = self.add_inst(name="read_nmos_left{}".format(k),
mod=self.read_nmos)
self.connect_inst(["rbl{}".format(k), "rwl{}".format(k), "RA_to_R_left{}".format(k), "gnd"])
self.read_nmos_right[k] = self.add_inst(name="read_nmos_right{}".format(k),
mod=self.read_nmos)
self.connect_inst(["rbl_bar{}".format(k), "rwl{}".format(k), "RA_to_R_right{}".format(k), "gnd"])
def place_read_ports(self):
"""
Places the read ports in the bit cell.
"""
# Define variables relevant to read transistors
self.rwl_positions = [None] * self.num_read
self.rbl_positions = [None] * self.num_read
self.rbl_bar_positions = [None] * self.num_read
# define offset correction due to rotation of the ptx module
read_rotation_correct = self.read_nmos.active_height
@ -751,7 +827,7 @@ class pbitcell(pgate.pgate):
# iterate over the number of read ports
for k in range(0,self.num_read):
""" Add transistors """
# Add transistors
# calculate transistor offsets
left_read_transistor_xpos = self.left_building_edge \
- self.write_to_read_spacing \
@ -789,7 +865,7 @@ class pbitcell(pgate.pgate):
rotate=90)
self.connect_inst(["rbl_bar{}".format(k), "rwl{}".format(k), "RA_to_R_right{}".format(k), "gnd"])
""" Add RWL lines """
# Add RWL lines
# calculate RWL position
rwl_ypos = self.gnd_position.y \
- self.num_readwrite*self.rowline_tile_height \
@ -804,7 +880,7 @@ class pbitcell(pgate.pgate):
width=self.width,
height=contact.m1m2.width)
""" Drain of read transistor / RBL & RBL_bar connection """
# Drain of read transistor / RBL & RBL_bar connection
# add metal1-to-metal2 contacts on top of read transistor drain pins for connection to RBL and RBL_bar
offset_left = self.read_nmos_left[k].get_pin("D").center()
self.add_contact_center(layers=("metal1", "via1", "metal2"),
@ -831,7 +907,7 @@ class pbitcell(pgate.pgate):
width=drc["minwidth_metal2"],
height=self.height)
""" Gate of read transistor / RWL connection """
# Gate of read transistor / RWL connection
# add poly-to-meltal2 contacts to connect gate of read transistors to RWL (contact next to gate)
if(self.read_nmos_contact_extension > self.gate_contact_thres):
contact_xpos = self.read_nmos_left[k].get_pin("S").lc().x - drc["minwidth_metal2"] - 0.5*contact.m1m2.width
@ -876,7 +952,7 @@ class pbitcell(pgate.pgate):
self.add_path("metal2", [left_gate_contact, left_rwl_contact])
self.add_path("metal2", [right_gate_contact, right_rwl_contact])
""" Source of read-access transistor / GND connection """
# Source of read-access transistor / GND connection
# connect source of read-access transistor to GND (metal1 path)
gnd_offset_left = vector(self.read_access_nmos_left[k].get_pin("S").bc().x, self.gnd_position.y)
self.add_path("metal1", [self.read_access_nmos_left[k].get_pin("S").bc(), gnd_offset_left])
@ -884,7 +960,7 @@ class pbitcell(pgate.pgate):
gnd_offset_right = vector(self.read_access_nmos_right[k].get_pin("S").bc().x, self.gnd_position.y)
self.add_path("metal1", [self.read_access_nmos_right[k].get_pin("S").bc(), gnd_offset_right])
""" Gate of read-access transistor / storage connection """
# Gate of read-access transistor / storage connection
# add poly-to-metal1 contacts to connect gate of read-access transistors to output of inverters (contact next to gate)
if(self.read_nmos_contact_extension > self.gate_contact_thres):
contact_xpos = self.read_nmos_left[k].get_pin("S").rc().x + drc["minwidth_metal2"] + 0.5*contact.m1m2.width
@ -933,7 +1009,7 @@ class pbitcell(pgate.pgate):
self.add_path("metal1", [right_gate_contact, midR0, midR1, midR2, right_inverter_offset])
# end for
def extend_well(self):
"""
Connects wells between ptx modules to avoid drc spacing issues.
@ -941,7 +1017,7 @@ class pbitcell(pgate.pgate):
the well connections must be done piecewise to avoid pwell and nwell overlap.
"""
""" extend pwell to encompass entire nmos region of the cell up to the height of the inverter nmos well """
# extend pwell to encompass entire nmos region of the cell up to the height of the inverter nmos well
offset = vector(self.leftmost_xpos, self.botmost_ypos)
well_height = -self.botmost_ypos + self.inverter_nmos.cell_well_height - drc["well_enclosure_active"]
self.add_rect(layer="pwell",
@ -949,7 +1025,9 @@ class pbitcell(pgate.pgate):
width=self.width,
height=well_height)
""" extend pwell over read/write and write transistors to the height of the write transistor well (read/write and write transistors are the same height) """
# extend pwell over read/write and write transistors to the
# height of the write transistor well (read/write and write
# transistors are the same height)
if(self.num_write > 0):
# calculate the edge of the write transistor well closest to the center
left_write_well_xpos = self.write_nmos_left[0].offset.x + drc["well_enclosure_active"]
@ -975,7 +1053,7 @@ class pbitcell(pgate.pgate):
width=write_well_width,
height=write_well_height)
""" extend pwell over the read transistors to the height of the bitcell """
# extend pwell over the read transistors to the height of the bitcell
if(self.num_read > 0):
# calculate the edge of the read transistor well clostest to the center
left_read_well_xpos = self.read_nmos_left[0].offset.x + drc["well_enclosure_active"]
@ -997,7 +1075,7 @@ class pbitcell(pgate.pgate):
width=read_well_width,
height=read_well_height)
""" extend nwell to encompass inverter_pmos """
# extend nwell to encompass inverter_pmos
# calculate offset of the left pmos well
inverter_well_xpos = -self.inverter_tile_width - drc["well_enclosure_active"]
inverter_well_ypos = self.inverter_nmos.active_height + self.inverter_gap - drc["well_enclosure_active"]
@ -1014,7 +1092,7 @@ class pbitcell(pgate.pgate):
height=well_height)
""" add well contacts """
# add well contacts
# connect pimplants to gnd
offset = vector(0, self.gnd_position.y + 0.5*contact.well.second_layer_width)
self.add_contact_center(layers=("active", "contact", "metal1"),

View File

@ -17,21 +17,19 @@ class single_level_column_mux(design.design):
design.design.__init__(self, name)
debug.info(2, "create single column mux cell: {0}".format(name))
from importlib import reload
c = reload(__import__(OPTS.bitcell))
self.mod_bitcell = getattr(c, OPTS.bitcell)
self.bitcell = self.mod_bitcell()
self.ptx_width = tx_size * drc["minwidth_tx"]
self.tx_size = tx_size
self.create_netlist()
self.create_layout()
if not OPTS.netlist_only:
self.create_layout()
def create_netlist(self):
self.add_pin_list(["bl", "br", "bl_out", "br_out", "sel", "gnd"])
self.add_modules()
self.add_pins()
self.add_ptx()
def create_layout(self):
self.pin_height = 2*self.m2_width
self.width = self.bitcell.width
self.height = self.nmos_upper.uy() + self.pin_height
@ -39,7 +37,23 @@ class single_level_column_mux(design.design):
self.add_bitline_pins()
self.connect_bitlines()
self.add_wells()
def add_modules(self):
from importlib import reload
c = reload(__import__(OPTS.bitcell))
self.mod_bitcell = getattr(c, OPTS.bitcell)
self.bitcell = self.mod_bitcell()
# Adds nmos_lower,nmos_upper to the module
self.ptx_width = self.tx_size * drc["minwidth_tx"]
self.nmos = ptx(width=self.ptx_width)
self.add_mod(self.nmos)
def add_pins(self):
self.add_pin_list(["bl", "br", "bl_out", "br_out", "sel", "gnd"])
def add_bitline_pins(self):
""" Add the top and bottom pins to this cell """
@ -70,10 +84,6 @@ class single_level_column_mux(design.design):
def add_ptx(self):
""" Create the two pass gate NMOS transistors to switch the bitlines"""
# Adds nmos_lower,nmos_upper to the module
self.nmos = ptx(width=self.ptx_width)
self.add_mod(self.nmos)
# Space it in the center
nmos_lower_position = self.nmos.active_offset.scale(0,1) + vector(0.5*self.bitcell.width-0.5*self.nmos.active_width,0)
self.nmos_lower=self.add_inst(name="mux_tx1",

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python2.7
#!/usr/bin/env python3
"""
Run regresion tests on a parameterized bitcell
"""