mirror of https://github.com/VLSIDA/OpenRAM.git
Merge remote-tracking branch 'private/dev' into dev
This commit is contained in:
commit
b20036a867
|
|
@ -32,9 +32,8 @@ class _mirror_axis:
|
||||||
self.y = y
|
self.y = y
|
||||||
|
|
||||||
class _bitcell:
|
class _bitcell:
|
||||||
def __init__(self, mirror, split_wl, cell_s8_6t, cell_6t, cell_1rw1r, cell_1w1r):
|
def __init__(self, mirror, cell_s8_6t, cell_6t, cell_1rw1r, cell_1w1r):
|
||||||
self.mirror = mirror
|
self.mirror = mirror
|
||||||
self.split_wl = split_wl
|
|
||||||
self._s8_6t = cell_s8_6t
|
self._s8_6t = cell_s8_6t
|
||||||
self._6t = cell_6t
|
self._6t = cell_6t
|
||||||
self._1rw1r = cell_1rw1r
|
self._1rw1r = cell_1rw1r
|
||||||
|
|
@ -43,8 +42,8 @@ class _bitcell:
|
||||||
def _default():
|
def _default():
|
||||||
axis = _mirror_axis(True, False)
|
axis = _mirror_axis(True, False)
|
||||||
|
|
||||||
cell_s8_6t = _cell({'bl' : 'bl0',
|
cell_s8_6t = _cell({'bl' : 'bl',
|
||||||
'br' : 'bl1',
|
'br' : 'br',
|
||||||
'wl': 'wl'})
|
'wl': 'wl'})
|
||||||
|
|
||||||
cell_6t = _cell({'bl' : 'bl',
|
cell_6t = _cell({'bl' : 'bl',
|
||||||
|
|
@ -69,7 +68,6 @@ class _bitcell:
|
||||||
cell_6t=cell_6t,
|
cell_6t=cell_6t,
|
||||||
cell_1rw1r=cell_1rw1r,
|
cell_1rw1r=cell_1rw1r,
|
||||||
cell_1w1r=cell_1w1r,
|
cell_1w1r=cell_1w1r,
|
||||||
split_wl = [],
|
|
||||||
mirror=axis)
|
mirror=axis)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
|
||||||
|
|
@ -22,17 +22,12 @@ class bitcell(bitcell_base.bitcell_base):
|
||||||
|
|
||||||
# If we have a split WL bitcell, if not be backwards
|
# If we have a split WL bitcell, if not be backwards
|
||||||
# compatible in the tech file
|
# compatible in the tech file
|
||||||
|
pin_names = [props.bitcell.cell_6t.pin.bl,
|
||||||
if props.compare_ports(props.bitcell.split_wl):
|
props.bitcell.cell_6t.pin.br,
|
||||||
pin_names = ["bl", "br", "wl0", "wl1", "vdd", "gnd"]
|
props.bitcell.cell_6t.pin.wl,
|
||||||
type_list = ["OUTPUT", "OUTPUT", "INPUT", "INPUT", "POWER", "GROUND"]
|
props.bitcell.cell_6t.pin.vdd,
|
||||||
else:
|
props.bitcell.cell_6t.pin.gnd]
|
||||||
pin_names = [props.bitcell.cell_6t.pin.bl,
|
type_list = ["OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"]
|
||||||
props.bitcell.cell_6t.pin.br,
|
|
||||||
props.bitcell.cell_6t.pin.wl,
|
|
||||||
props.bitcell.cell_6t.pin.vdd,
|
|
||||||
props.bitcell.cell_6t.pin.gnd]
|
|
||||||
type_list = ["OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"]
|
|
||||||
storage_nets = ['Q', 'Q_bar']
|
storage_nets = ['Q', 'Q_bar']
|
||||||
|
|
||||||
(width, height) = utils.get_libcell_size("cell_6t",
|
(width, height) = utils.get_libcell_size("cell_6t",
|
||||||
|
|
@ -55,10 +50,7 @@ class bitcell(bitcell_base.bitcell_base):
|
||||||
|
|
||||||
def get_all_wl_names(self):
|
def get_all_wl_names(self):
|
||||||
""" Creates a list of all wordline pin names """
|
""" Creates a list of all wordline pin names """
|
||||||
if props.compare_ports(props.bitcell.split_wl):
|
row_pins = [props.bitcell.cell_6t.pin.wl]
|
||||||
row_pins = ["wl0", "wl1"]
|
|
||||||
else:
|
|
||||||
row_pins = [props.bitcell.cell_6t.pin.wl]
|
|
||||||
return row_pins
|
return row_pins
|
||||||
|
|
||||||
def get_all_bitline_names(self):
|
def get_all_bitline_names(self):
|
||||||
|
|
@ -87,11 +79,8 @@ class bitcell(bitcell_base.bitcell_base):
|
||||||
|
|
||||||
def get_wl_name(self, port=0):
|
def get_wl_name(self, port=0):
|
||||||
"""Get wl name"""
|
"""Get wl name"""
|
||||||
if props.compare_ports(props.bitcell.split_wl):
|
debug.check(port == 0, "One port for bitcell only.")
|
||||||
return "wl{}".format(port)
|
return props.bitcell.cell_6t.pin.wl
|
||||||
else:
|
|
||||||
debug.check(port == 0, "One port for bitcell only.")
|
|
||||||
return props.bitcell.cell_6t.pin.wl
|
|
||||||
|
|
||||||
def build_graph(self, graph, inst_name, port_nets):
|
def build_graph(self, graph, inst_name, port_nets):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -30,8 +30,8 @@ class bitcell_1rw_1r(bitcell_base.bitcell_base):
|
||||||
props.bitcell.cell_1rw1r.pin.vdd,
|
props.bitcell.cell_1rw1r.pin.vdd,
|
||||||
props.bitcell.cell_1rw1r.pin.gnd]
|
props.bitcell.cell_1rw1r.pin.gnd]
|
||||||
|
|
||||||
type_list = ["OUTPUT", "OUTPUT", "OUTPUT", "OUTPUT",
|
type_list = ["OUTPUT", "OUTPUT", "OUTPUT", "OUTPUT",
|
||||||
"INPUT", "INPUT", "POWER", "GROUND"]
|
"INPUT", "INPUT", "POWER", "GROUND"]
|
||||||
storage_nets = ['Q', 'Q_bar']
|
storage_nets = ['Q', 'Q_bar']
|
||||||
(width, height) = utils.get_libcell_size("cell_1rw_1r",
|
(width, height) = utils.get_libcell_size("cell_1rw_1r",
|
||||||
GDS["unit"],
|
GDS["unit"],
|
||||||
|
|
|
||||||
|
|
@ -20,17 +20,12 @@ class replica_bitcell(design.design):
|
||||||
is a hand-made cell, so the layout and netlist should be available in
|
is a hand-made cell, so the layout and netlist should be available in
|
||||||
the technology library. """
|
the technology library. """
|
||||||
|
|
||||||
if cell_properties.compare_ports(cell_properties.bitcell.split_wl):
|
pin_names = [props.bitcell.cell_6t.pin.bl,
|
||||||
pin_names = ["bl", "br", "wl0", "wl1", "vdd", "gnd"]
|
props.bitcell.cell_6t.pin.br,
|
||||||
type_list = ["OUTPUT", "OUTPUT", "INPUT", "INPUT" , "POWER", "GROUND"]
|
props.bitcell.cell_6t.pin.wl,
|
||||||
else:
|
props.bitcell.cell_6t.pin.vdd,
|
||||||
pin_names = [props.bitcell.cell_6t.pin.bl,
|
props.bitcell.cell_6t.pin.gnd]
|
||||||
props.bitcell.cell_6t.pin.br,
|
type_list = ["OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"]
|
||||||
props.bitcell.cell_6t.pin.wl,
|
|
||||||
props.bitcell.cell_6t.pin.vdd,
|
|
||||||
props.bitcell.cell_6t.pin.gnd]
|
|
||||||
|
|
||||||
type_list = ["OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"]
|
|
||||||
|
|
||||||
if not OPTS.netlist_only:
|
if not OPTS.netlist_only:
|
||||||
(width,height) = utils.get_libcell_size("replica_cell_6t", GDS["unit"], layer["boundary"])
|
(width,height) = utils.get_libcell_size("replica_cell_6t", GDS["unit"], layer["boundary"])
|
||||||
|
|
|
||||||
|
|
@ -527,12 +527,10 @@ class simulation():
|
||||||
"""
|
"""
|
||||||
Gets the signal name associated with the bitlines in the bank.
|
Gets the signal name associated with the bitlines in the bank.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
cell_mod = factory.create(module_type=OPTS.bitcell)
|
cell_mod = factory.create(module_type=OPTS.bitcell)
|
||||||
cell_bl = cell_mod.get_bl_name(port)
|
cell_bl = cell_mod.get_bl_name(port)
|
||||||
cell_br = cell_mod.get_br_name(port)
|
cell_br = cell_mod.get_br_name(port)
|
||||||
|
|
||||||
# Only a single path should contain a single s_en name. Anything else is an error.
|
|
||||||
bl_names = []
|
bl_names = []
|
||||||
exclude_set = self.get_bl_name_search_exclusions()
|
exclude_set = self.get_bl_name_search_exclusions()
|
||||||
for int_net in [cell_bl, cell_br]:
|
for int_net in [cell_bl, cell_br]:
|
||||||
|
|
|
||||||
|
|
@ -33,12 +33,22 @@ class stimuli():
|
||||||
self.sf = stim_file
|
self.sf = stim_file
|
||||||
|
|
||||||
(self.process, self.voltage, self.temperature) = corner
|
(self.process, self.voltage, self.temperature) = corner
|
||||||
|
found = False
|
||||||
|
self.device_libraries = []
|
||||||
|
self.device_models = []
|
||||||
try:
|
try:
|
||||||
self.device_libraries = tech.spice["fet_libraries"][self.process]
|
self.device_libraries += tech.spice["fet_libraries"][self.process]
|
||||||
except:
|
found = True
|
||||||
debug.info(2, "Not using spice library")
|
except KeyError:
|
||||||
self.device_models = tech.spice["fet_models"][self.process]
|
pass
|
||||||
|
try:
|
||||||
|
self.device_models += tech.spice["fet_models"][self.process]
|
||||||
|
found = True
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
if not found:
|
||||||
|
debug.error("Must define either fet_libraries or fet_models.", -1)
|
||||||
|
|
||||||
def inst_model(self, pins, model_name):
|
def inst_model(self, pins, model_name):
|
||||||
""" Function to instantiate a generic model with a set of pins """
|
""" Function to instantiate a generic model with a set of pins """
|
||||||
|
|
||||||
|
|
@ -265,16 +275,15 @@ class stimuli():
|
||||||
def write_include(self, circuit):
|
def write_include(self, circuit):
|
||||||
"""Writes include statements, inputs are lists of model files"""
|
"""Writes include statements, inputs are lists of model files"""
|
||||||
|
|
||||||
includes = self.device_models + [circuit]
|
|
||||||
self.sf.write("* {} process corner\n".format(self.process))
|
self.sf.write("* {} process corner\n".format(self.process))
|
||||||
if OPTS.tech_name == "sky130":
|
for item in self.device_libraries:
|
||||||
libraries = self.device_libraries
|
if os.path.isfile(item[0]):
|
||||||
for item in list(libraries):
|
self.sf.write(".lib \"{0}\" {1}\n".format(item[0], item[1]))
|
||||||
if os.path.isfile(item[0]):
|
else:
|
||||||
self.sf.write(".lib \"{0}\" {1}\n".format(item[0], item[1]))
|
debug.error("Could not find spice library: {0}\nSet SPICE_MODEL_DIR to over-ride path.\n".format(item[0]))
|
||||||
else:
|
|
||||||
debug.error("Could not find spice library: {0}\nSet SPICE_MODEL_DIR to over-ride path.\n".format(item[0]))
|
includes = self.device_models + [circuit]
|
||||||
|
|
||||||
for item in list(includes):
|
for item in list(includes):
|
||||||
if os.path.isfile(item):
|
if os.path.isfile(item):
|
||||||
self.sf.write(".include \"{0}\"\n".format(item))
|
self.sf.write(".include \"{0}\"\n".format(item))
|
||||||
|
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
word_size = 2
|
|
||||||
num_words = 16
|
|
||||||
|
|
||||||
tech_name = "scn4m_subm"
|
|
||||||
process_corners = ["TT"]
|
|
||||||
supply_voltages = [5.0]
|
|
||||||
temperatures = [25]
|
|
||||||
|
|
||||||
#netlist_only = True
|
|
||||||
route_supplies = True
|
|
||||||
check_lvsdrc = True
|
|
||||||
|
|
||||||
output_name = "sram_{0}_{1}_{2}".format(word_size,
|
|
||||||
num_words,
|
|
||||||
tech_name)
|
|
||||||
|
|
||||||
drc_name = "magic"
|
|
||||||
lvs_name = "netgen"
|
|
||||||
pex_name = "magic"
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
word_size = 8
|
|
||||||
num_words = 128
|
|
||||||
|
|
||||||
tech_name = "scn4m_subm"
|
|
||||||
process_corners = ["TT"]
|
|
||||||
supply_voltages = [5.0]
|
|
||||||
temperatures = [25]
|
|
||||||
|
|
||||||
route_supplies = True
|
|
||||||
check_lvsdrc = True
|
|
||||||
|
|
||||||
netlist_only = True
|
|
||||||
output_name = "sram_{0}_{1}_{2}".format(word_size,
|
|
||||||
num_words,
|
|
||||||
tech_name)
|
|
||||||
|
|
||||||
drc_name = "magic"
|
|
||||||
lvs_name = "netgen"
|
|
||||||
pex_name = "magic"
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
word_size = 16
|
|
||||||
num_words = 256
|
|
||||||
|
|
||||||
tech_name = "scn4m_subm"
|
|
||||||
process_corners = ["TT"]
|
|
||||||
supply_voltages = [5.0]
|
|
||||||
temperatures = [25]
|
|
||||||
|
|
||||||
route_supplies = True
|
|
||||||
check_lvsdrc = True
|
|
||||||
netlist_only = True
|
|
||||||
output_name = "sram_{0}_{1}_{2}".format(word_size,
|
|
||||||
num_words,
|
|
||||||
tech_name)
|
|
||||||
|
|
||||||
drc_name = "magic"
|
|
||||||
lvs_name = "netgen"
|
|
||||||
pex_name = "magic"
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
word_size = 32
|
|
||||||
num_words = 128
|
|
||||||
|
|
||||||
tech_name = "scn4m_subm"
|
|
||||||
process_corners = ["TT"]
|
|
||||||
supply_voltages = [5.0]
|
|
||||||
temperatures = [25]
|
|
||||||
|
|
||||||
route_supplies = True
|
|
||||||
check_lvsdrc = True
|
|
||||||
netlist_only = True
|
|
||||||
output_name = "sram_{0}_{1}_{2}".format(word_size,
|
|
||||||
num_words,
|
|
||||||
tech_name)
|
|
||||||
|
|
||||||
drc_name = "magic"
|
|
||||||
lvs_name = "netgen"
|
|
||||||
pex_name = "magic"
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
word_size = 64
|
|
||||||
num_words = 128
|
|
||||||
|
|
||||||
tech_name = "scn4m_subm"
|
|
||||||
process_corners = ["TT"]
|
|
||||||
supply_voltages = [5.0]
|
|
||||||
temperatures = [25]
|
|
||||||
|
|
||||||
route_supplies = True
|
|
||||||
check_lvsdrc = True
|
|
||||||
|
|
||||||
output_path = "/home/jesse/thesis/outputs/run5"
|
|
||||||
output_name = "sram_{0}_{1}_{2}".format(word_size,
|
|
||||||
num_words,
|
|
||||||
tech_name)
|
|
||||||
|
|
||||||
drc_name = "magic"
|
|
||||||
lvs_name = "netgen"
|
|
||||||
pex_name = "magic"
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
word_size = 16
|
|
||||||
num_words = 16
|
|
||||||
|
|
||||||
num_rw_ports = 1
|
|
||||||
num_r_ports = 1
|
|
||||||
num_w_ports = 0
|
|
||||||
|
|
||||||
tech_name = "sky130"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
accuracy_requirement = 0.05
|
|
||||||
magic_exe = ("magic", "magic")
|
|
||||||
nominal_corners_only = False
|
|
||||||
process_corners = ["TT"]
|
|
||||||
supply_voltages = [5.0]
|
|
||||||
temperatures = [25]
|
|
||||||
|
|
||||||
netlist_only = False
|
|
||||||
route_supplies = "grid"
|
|
||||||
check_lvsdrc = False
|
|
||||||
|
|
||||||
#replica_bitcell_array = "/home/jesse/openram/technology/sky130/modules/replica_bitcell_array.py"
|
|
||||||
|
|
||||||
output_path = "sram_" + str(accuracy_requirement)
|
|
||||||
output_name = "sram_{0}_{1}_{2}_{3}".format(word_size,
|
|
||||||
num_words,
|
|
||||||
tech_name,
|
|
||||||
accuracy_requirement
|
|
||||||
)
|
|
||||||
write_size=8
|
|
||||||
|
|
@ -48,8 +48,11 @@ class bitcell_base_array(design.design):
|
||||||
# Make a flat list too
|
# Make a flat list too
|
||||||
self.all_bitline_names = [x for sl in zip(*self.bitline_names) for x in sl]
|
self.all_bitline_names = [x for sl in zip(*self.bitline_names) for x in sl]
|
||||||
|
|
||||||
def create_all_wordline_names(self, remove_num_wordlines=0):
|
def create_all_wordline_names(self, row_size=None):
|
||||||
for row in range(self.row_size - remove_num_wordlines):
|
if row_size == None:
|
||||||
|
row_size = self.row_size
|
||||||
|
|
||||||
|
for row in range(row_size):
|
||||||
for port in self.all_ports:
|
for port in self.all_ports:
|
||||||
self.wordline_names[port].append("wl_{0}_{1}".format(port, row))
|
self.wordline_names[port].append("wl_{0}_{1}".format(port, row))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,13 @@ class col_cap_array(bitcell_base_array):
|
||||||
def create_netlist(self):
|
def create_netlist(self):
|
||||||
""" Create and connect the netlist """
|
""" Create and connect the netlist """
|
||||||
# This will create a default set of bitline/wordline names
|
# This will create a default set of bitline/wordline names
|
||||||
self.create_all_wordline_names()
|
try:
|
||||||
|
end_caps_enabled = cell_properties.bitcell.end_caps
|
||||||
|
except AttributeError:
|
||||||
|
end_caps_enabled = False
|
||||||
|
|
||||||
|
if not end_caps_enabled:
|
||||||
|
self.create_all_wordline_names()
|
||||||
self.create_all_bitline_names()
|
self.create_all_bitline_names()
|
||||||
|
|
||||||
self.add_modules()
|
self.add_modules()
|
||||||
|
|
@ -63,7 +69,7 @@ class col_cap_array(bitcell_base_array):
|
||||||
indexed by column and row, for instance use in bitcell_array
|
indexed by column and row, for instance use in bitcell_array
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if len(self.ports) == 1:
|
if len(self.all_ports) == 1:
|
||||||
pin_name = cell_properties.bitcell.cell_6t.pin
|
pin_name = cell_properties.bitcell.cell_6t.pin
|
||||||
bitcell_pins = ["{0}_{1}".format(pin_name.bl0, col),
|
bitcell_pins = ["{0}_{1}".format(pin_name.bl0, col),
|
||||||
"{0}_{1}".format(pin_name.br0, col),
|
"{0}_{1}".format(pin_name.br0, col),
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,9 @@ class dummy_array(bitcell_base_array):
|
||||||
|
|
||||||
def add_pins(self):
|
def add_pins(self):
|
||||||
# bitline pins are not added because they are floating
|
# bitline pins are not added because they are floating
|
||||||
|
for bl_name in self.get_bitline_names():
|
||||||
|
self.add_pin(bl_name, "INOUT")
|
||||||
|
# bitline pins are not added because they are floating
|
||||||
for wl_name in self.get_wordline_names():
|
for wl_name in self.get_wordline_names():
|
||||||
self.add_pin(wl_name, "INPUT")
|
self.add_pin(wl_name, "INPUT")
|
||||||
self.add_pin("vdd", "POWER")
|
self.add_pin("vdd", "POWER")
|
||||||
|
|
@ -85,25 +88,15 @@ class dummy_array(bitcell_base_array):
|
||||||
height=self.height)
|
height=self.height)
|
||||||
|
|
||||||
wl_names = self.cell.get_all_wl_names()
|
wl_names = self.cell.get_all_wl_names()
|
||||||
if not props.compare_ports(props.bitcell.split_wl):
|
for row in range(self.row_size):
|
||||||
for row in range(self.row_size):
|
for port in self.all_ports:
|
||||||
for port in self.all_ports:
|
wl_pins = self.cell_inst[row, 0].get_pins(wl_names[port])
|
||||||
wl_pin = self.cell_inst[row, 0].get_pin(wl_names[port])
|
for wl_pin in wl_pins:
|
||||||
self.add_layout_pin(text="wl_{0}_{1}".format(port, row),
|
self.add_layout_pin(text="wl_{0}_{1}".format(port, row),
|
||||||
layer=wl_pin.layer,
|
layer=wl_pin.layer,
|
||||||
offset=wl_pin.ll().scale(0, 1),
|
offset=wl_pin.ll().scale(0, 1),
|
||||||
width=self.width,
|
width=self.width,
|
||||||
height=wl_pin.height())
|
height=wl_pin.height())
|
||||||
else:
|
|
||||||
for row in range(self.row_size):
|
|
||||||
for port in self.all_ports:
|
|
||||||
for wl in range(len(wl_names)):
|
|
||||||
wl_pin = self.cell_inst[row, 0].get_pin("wl{}".format(wl))
|
|
||||||
self.add_layout_pin(text="wl{0}_{1}_{2}".format(wl, port, row),
|
|
||||||
layer=wl_pin.layer,
|
|
||||||
offset=wl_pin.ll().scale(0, 1),
|
|
||||||
width=self.width,
|
|
||||||
height=wl_pin.height())
|
|
||||||
|
|
||||||
# Copy a vdd/gnd layout pin from every cell
|
# Copy a vdd/gnd layout pin from every cell
|
||||||
for row in range(self.row_size):
|
for row in range(self.row_size):
|
||||||
|
|
@ -112,7 +105,6 @@ class dummy_array(bitcell_base_array):
|
||||||
for pin_name in ["vdd", "gnd"]:
|
for pin_name in ["vdd", "gnd"]:
|
||||||
self.copy_layout_pin(inst, pin_name)
|
self.copy_layout_pin(inst, pin_name)
|
||||||
|
|
||||||
|
|
||||||
def input_load(self):
|
def input_load(self):
|
||||||
# FIXME: This appears to be old code from previous characterization. Needs to be updated.
|
# FIXME: This appears to be old code from previous characterization. Needs to be updated.
|
||||||
wl_wire = self.gen_wl_wire()
|
wl_wire = self.gen_wl_wire()
|
||||||
|
|
|
||||||
|
|
@ -59,9 +59,19 @@ class replica_bitcell_array(bitcell_base_array):
|
||||||
"Invalid number of RBLs for port configuration.")
|
"Invalid number of RBLs for port configuration.")
|
||||||
|
|
||||||
# Two dummy rows plus replica even if we don't add the column
|
# Two dummy rows plus replica even if we don't add the column
|
||||||
self.extra_rows = 2 + sum(self.rbl)
|
self.extra_rows = sum(self.rbl)
|
||||||
# Two dummy cols plus replica if we add the column
|
# Two dummy cols plus replica if we add the column
|
||||||
self.extra_cols = 2 + len(self.left_rbl) + len(self.right_rbl)
|
self.extra_cols = len(self.left_rbl) + len(self.right_rbl)
|
||||||
|
|
||||||
|
|
||||||
|
try:
|
||||||
|
end_caps_enabled = cell_properties.bitcell.end_caps
|
||||||
|
except AttributeError:
|
||||||
|
end_caps_enabled = False
|
||||||
|
# If we aren't using row/col caps, then we need to use the bitcell
|
||||||
|
if not end_caps_enabled:
|
||||||
|
self.extra_rows += 2
|
||||||
|
self.extra_cols += 2
|
||||||
|
|
||||||
self.create_netlist()
|
self.create_netlist()
|
||||||
if not OPTS.netlist_only:
|
if not OPTS.netlist_only:
|
||||||
|
|
@ -184,7 +194,7 @@ class replica_bitcell_array(bitcell_base_array):
|
||||||
# + left replica column(s)
|
# + left replica column(s)
|
||||||
# + bitcell columns
|
# + bitcell columns
|
||||||
# + right replica column(s)
|
# + right replica column(s)
|
||||||
column_offset = 1 + len(self.left_rbl) + self.column_size + self.rbl[0],
|
column_offset=1 + len(self.left_rbl) + self.column_size + self.rbl[0],
|
||||||
rows=self.row_size + self.extra_rows,
|
rows=self.row_size + self.extra_rows,
|
||||||
mirror=(self.rbl[0] + 1) %2)
|
mirror=(self.rbl[0] + 1) %2)
|
||||||
self.add_mod(self.row_cap_right)
|
self.add_mod(self.row_cap_right)
|
||||||
|
|
@ -230,6 +240,11 @@ class replica_bitcell_array(bitcell_base_array):
|
||||||
self.add_pin_list(self.rbl_bitline_names[port], "INOUT")
|
self.add_pin_list(self.rbl_bitline_names[port], "INOUT")
|
||||||
|
|
||||||
def add_wordline_pins(self):
|
def add_wordline_pins(self):
|
||||||
|
try:
|
||||||
|
end_caps_enabled = cell_properties.bitcell.end_caps
|
||||||
|
except AttributeError:
|
||||||
|
end_caps_enabled = False
|
||||||
|
|
||||||
|
|
||||||
# Wordlines to ground
|
# Wordlines to ground
|
||||||
self.gnd_wordline_names = []
|
self.gnd_wordline_names = []
|
||||||
|
|
@ -245,7 +260,6 @@ class replica_bitcell_array(bitcell_base_array):
|
||||||
self.wordline_names = self.bitcell_array.wordline_names
|
self.wordline_names = self.bitcell_array.wordline_names
|
||||||
self.all_wordline_names = self.bitcell_array.all_wordline_names
|
self.all_wordline_names = self.bitcell_array.all_wordline_names
|
||||||
|
|
||||||
|
|
||||||
# All wordlines including dummy and RBL
|
# All wordlines including dummy and RBL
|
||||||
self.replica_array_wordline_names = []
|
self.replica_array_wordline_names = []
|
||||||
self.replica_array_wordline_names.extend(["gnd"] * len(self.col_cap_top.get_wordline_names()))
|
self.replica_array_wordline_names.extend(["gnd"] * len(self.col_cap_top.get_wordline_names()))
|
||||||
|
|
@ -290,25 +304,25 @@ class replica_bitcell_array(bitcell_base_array):
|
||||||
for port in self.all_ports:
|
for port in self.all_ports:
|
||||||
self.dummy_row_replica_insts.append(self.add_inst(name="dummy_row_{}".format(port),
|
self.dummy_row_replica_insts.append(self.add_inst(name="dummy_row_{}".format(port),
|
||||||
mod=self.dummy_row))
|
mod=self.dummy_row))
|
||||||
self.connect_inst([x if x not in self.gnd_wordline_names else "gnd" for x in self.rbl_wordline_names[port]] + self.supplies)
|
self.connect_inst(self.all_bitline_names + [x if x not in self.gnd_wordline_names else "gnd" for x in self.rbl_wordline_names[port]] + self.supplies)
|
||||||
|
|
||||||
# Top/bottom dummy rows or col caps
|
# Top/bottom dummy rows or col caps
|
||||||
self.dummy_row_insts = []
|
self.dummy_row_insts = []
|
||||||
self.dummy_row_insts.append(self.add_inst(name="dummy_row_bot",
|
self.dummy_row_insts.append(self.add_inst(name="dummy_row_bot",
|
||||||
mod=self.col_cap_bottom))
|
mod=self.col_cap_bottom))
|
||||||
self.connect_inst(["gnd"] * len(self.col_cap_bottom.get_wordline_names()) + self.supplies)
|
self.connect_inst(self.all_bitline_names + ["gnd"] * len(self.col_cap_bottom.get_wordline_names()) + self.supplies)
|
||||||
self.dummy_row_insts.append(self.add_inst(name="dummy_row_top",
|
self.dummy_row_insts.append(self.add_inst(name="dummy_row_top",
|
||||||
mod=self.col_cap_top))
|
mod=self.col_cap_top))
|
||||||
self.connect_inst(["gnd"] * len(self.col_cap_top.get_wordline_names()) + self.supplies)
|
self.connect_inst(self.all_bitline_names + ["gnd"] * len(self.col_cap_top.get_wordline_names()) + self.supplies)
|
||||||
|
|
||||||
# Left/right Dummy columns
|
# Left/right Dummy columns
|
||||||
self.dummy_col_insts = []
|
self.dummy_col_insts = []
|
||||||
self.dummy_col_insts.append(self.add_inst(name="dummy_col_left",
|
self.dummy_col_insts.append(self.add_inst(name="dummy_col_left",
|
||||||
mod=self.row_cap_left))
|
mod=self.row_cap_left))
|
||||||
self.connect_inst(self.replica_array_wordline_names + self.supplies)
|
self.connect_inst(["dummy_left_" + bl for bl in self.row_cap_left.all_bitline_names] + self.replica_array_wordline_names + self.supplies)
|
||||||
self.dummy_col_insts.append(self.add_inst(name="dummy_col_right",
|
self.dummy_col_insts.append(self.add_inst(name="dummy_col_right",
|
||||||
mod=self.row_cap_right))
|
mod=self.row_cap_right))
|
||||||
self.connect_inst(self.replica_array_wordline_names + self.supplies)
|
self.connect_inst(["dummy_right_" + bl for bl in self.row_cap_right.all_bitline_names] + self.replica_array_wordline_names + self.supplies)
|
||||||
|
|
||||||
def create_layout(self):
|
def create_layout(self):
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,13 @@ class replica_column(bitcell_base_array):
|
||||||
self.right_rbl = rbl[1]
|
self.right_rbl = rbl[1]
|
||||||
self.replica_bit = replica_bit
|
self.replica_bit = replica_bit
|
||||||
# left, right, regular rows plus top/bottom dummy cells
|
# left, right, regular rows plus top/bottom dummy cells
|
||||||
self.total_size = self.left_rbl + rows + self.right_rbl + 2
|
self.total_size = self.left_rbl + rows + self.right_rbl
|
||||||
|
try:
|
||||||
|
if not cell_properties.bitcell.end_caps:
|
||||||
|
self.total_size += 2
|
||||||
|
except AttributeError:
|
||||||
|
self.total_size += 2
|
||||||
|
|
||||||
self.column_offset = column_offset
|
self.column_offset = column_offset
|
||||||
|
|
||||||
debug.check(replica_bit != 0 and replica_bit != rows,
|
debug.check(replica_bit != 0 and replica_bit != rows,
|
||||||
|
|
@ -62,14 +67,7 @@ class replica_column(bitcell_base_array):
|
||||||
def add_pins(self):
|
def add_pins(self):
|
||||||
|
|
||||||
self.create_all_bitline_names()
|
self.create_all_bitline_names()
|
||||||
try:
|
self.create_all_wordline_names(self.total_size)
|
||||||
if cell_properties.bitcell.end_caps:
|
|
||||||
# remove 2 wordlines to account for top/bot
|
|
||||||
self.create_all_wordline_names(remove_num_wordlines=2)
|
|
||||||
else:
|
|
||||||
self.create_all_wordline_names()
|
|
||||||
except AttributeError:
|
|
||||||
self.create_all_wordline_names()
|
|
||||||
|
|
||||||
self.add_pin_list(self.all_bitline_names, "OUTPUT")
|
self.add_pin_list(self.all_bitline_names, "OUTPUT")
|
||||||
self.add_pin_list(self.all_wordline_names, "INPUT")
|
self.add_pin_list(self.all_wordline_names, "INPUT")
|
||||||
|
|
@ -91,7 +89,6 @@ class replica_column(bitcell_base_array):
|
||||||
# Used for pin names only
|
# Used for pin names only
|
||||||
self.cell = factory.create(module_type="bitcell")
|
self.cell = factory.create(module_type="bitcell")
|
||||||
|
|
||||||
|
|
||||||
def create_instances(self):
|
def create_instances(self):
|
||||||
self.cell_inst = {}
|
self.cell_inst = {}
|
||||||
try:
|
try:
|
||||||
|
|
@ -106,22 +103,22 @@ class replica_column(bitcell_base_array):
|
||||||
# Replic bit specifies which other bit (in the full range (0,rows) to make a replica cell.
|
# Replic bit specifies which other bit (in the full range (0,rows) to make a replica cell.
|
||||||
if (row > self.left_rbl and row < self.total_size - self.right_rbl - 1):
|
if (row > self.left_rbl and row < self.total_size - self.right_rbl - 1):
|
||||||
self.cell_inst[row]=self.add_inst(name=name,
|
self.cell_inst[row]=self.add_inst(name=name,
|
||||||
mod=self.replica_cell)
|
mod=self.replica_cell)
|
||||||
self.connect_inst(self.get_bitcell_pins(row, 0))
|
self.connect_inst(self.get_bitcell_pins(row, 0))
|
||||||
elif row==self.replica_bit:
|
elif row==self.replica_bit:
|
||||||
self.cell_inst[row]=self.add_inst(name=name,
|
self.cell_inst[row]=self.add_inst(name=name,
|
||||||
mod=self.replica_cell)
|
mod=self.replica_cell)
|
||||||
self.connect_inst(self.get_bitcell_pins(row, 0))
|
self.connect_inst(self.get_bitcell_pins(row, 0))
|
||||||
elif (row == 0 or row == self.total_size - 1):
|
elif (row == 0 or row == self.total_size - 1):
|
||||||
self.cell_inst[row]=self.add_inst(name=name,
|
self.cell_inst[row]=self.add_inst(name=name,
|
||||||
mod=self.edge_cell)
|
mod=self.edge_cell)
|
||||||
if end_caps_enabled:
|
if end_caps_enabled:
|
||||||
self.connect_inst(self.get_bitcell_pins_col_cap(row, 0))
|
self.connect_inst(self.get_bitcell_pins_col_cap(row, 0))
|
||||||
else:
|
else:
|
||||||
self.connect_inst(self.get_bitcell_pins(row, 0))
|
self.connect_inst(self.get_bitcell_pins(row, 0))
|
||||||
else:
|
else:
|
||||||
self.cell_inst[row]=self.add_inst(name=name,
|
self.cell_inst[row]=self.add_inst(name=name,
|
||||||
mod=self.dummy_cell)
|
mod=self.dummy_cell)
|
||||||
self.connect_inst(self.get_bitcell_pins(row, 0))
|
self.connect_inst(self.get_bitcell_pins(row, 0))
|
||||||
|
|
||||||
def place_instances(self):
|
def place_instances(self):
|
||||||
|
|
@ -153,8 +150,7 @@ class replica_column(bitcell_base_array):
|
||||||
dir_key = ""
|
dir_key = ""
|
||||||
|
|
||||||
self.cell_inst[row].place(offset=offset,
|
self.cell_inst[row].place(offset=offset,
|
||||||
mirror=dir_key)
|
mirror=dir_key)
|
||||||
|
|
||||||
|
|
||||||
def add_layout_pins(self):
|
def add_layout_pins(self):
|
||||||
""" Add the layout pins """
|
""" Add the layout pins """
|
||||||
|
|
|
||||||
|
|
@ -88,8 +88,8 @@ class pinv(pgate.pgate):
|
||||||
self.nmos_width = self.nmos_size * drc("minwidth_tx")
|
self.nmos_width = self.nmos_size * drc("minwidth_tx")
|
||||||
self.pmos_width = self.pmos_size * drc("minwidth_tx")
|
self.pmos_width = self.pmos_size * drc("minwidth_tx")
|
||||||
if OPTS.tech_name == "sky130":
|
if OPTS.tech_name == "sky130":
|
||||||
(self.nmos_width, self.tx_mults) = self.bin_width("nmos", self.nmos_width)
|
(self.nmos_width, self.tx_mults) = pgate.pgate.best_bin("nmos", self.nmos_width)
|
||||||
(self.pmos_width, self.tx_mults) = self.bin_width("pmos", self.pmos_width)
|
(self.pmos_width, self.tx_mults) = pgate.pgate.best_bin("pmos", self.pmos_width)
|
||||||
return
|
return
|
||||||
|
|
||||||
# Do a quick sanity check and bail if unlikely feasible height
|
# Do a quick sanity check and bail if unlikely feasible height
|
||||||
|
|
|
||||||
|
|
@ -132,7 +132,7 @@ class ptx(design.design):
|
||||||
if OPTS.tech_name == "sky130":
|
if OPTS.tech_name == "sky130":
|
||||||
# sky130 simulation cannot use the mult parameter in simulation
|
# sky130 simulation cannot use the mult parameter in simulation
|
||||||
(self.tx_width, self.mults) = pgate.best_bin(self.tx_type, self.tx_width)
|
(self.tx_width, self.mults) = pgate.best_bin(self.tx_type, self.tx_width)
|
||||||
main_str = "M{{0}} {{1}} {0} m={1} w={2} l={3} ".format(spice[self.tx_type],
|
main_str = "X{{0}} {{1}} {0} m={1} w={2} l={3} ".format(spice[self.tx_type],
|
||||||
self.mults,
|
self.mults,
|
||||||
self.tx_width,
|
self.tx_width,
|
||||||
drc("minwidth_poly"))
|
drc("minwidth_poly"))
|
||||||
|
|
@ -152,15 +152,20 @@ class ptx(design.design):
|
||||||
|
|
||||||
if OPTS.tech_name == "sky130" and OPTS.lvs_exe and OPTS.lvs_exe[0] == "calibre":
|
if OPTS.tech_name == "sky130" and OPTS.lvs_exe and OPTS.lvs_exe[0] == "calibre":
|
||||||
# sky130 requires mult parameter too
|
# sky130 requires mult parameter too
|
||||||
self.lvs_device = "M{{0}} {{1}} {0} m={1} w={2} l={3} mult={1}".format(spice[self.tx_type],
|
# self.lvs_device = "X{{0}} {{1}} {0} m={1} w={2} l={3} mult={1}".format(spice[self.tx_type],
|
||||||
self.mults,
|
# self.mults,
|
||||||
self.tx_width,
|
# self.tx_width,
|
||||||
drc("minwidth_poly"))
|
# drc("minwidth_poly"))
|
||||||
|
self.lvs_device = "M{{0}} {{1}} {0} m={1} w={2} l={3} mult={1}".format("nshort" if self.tx_type == "nmos" else "pshort",
|
||||||
|
self.mults,
|
||||||
|
self.tx_width,
|
||||||
|
drc("minwidth_poly"))
|
||||||
else:
|
else:
|
||||||
self.lvs_device = "M{{0}} {{1}} {0} m={1} w={2}u l={3}u ".format(spice[self.tx_type],
|
self.lvs_device = "M{{0}} {{1}} {0} m={1} w={2}u l={3}u ".format(spice[self.tx_type],
|
||||||
self.mults,
|
self.mults,
|
||||||
self.tx_width,
|
self.tx_width,
|
||||||
drc("minwidth_poly"))
|
drc("minwidth_poly"))
|
||||||
|
|
||||||
def setup_layout_constants(self):
|
def setup_layout_constants(self):
|
||||||
"""
|
"""
|
||||||
Pre-compute some handy layout parameters.
|
Pre-compute some handy layout parameters.
|
||||||
|
|
|
||||||
|
|
@ -552,7 +552,7 @@ class pin_group:
|
||||||
Add the enclosure shape to the given cell.
|
Add the enclosure shape to the given cell.
|
||||||
"""
|
"""
|
||||||
for enclosure in self.enclosures:
|
for enclosure in self.enclosures:
|
||||||
debug.info(2, "Adding enclosure {0} {1}".format(self.name,
|
debug.info(4, "Adding enclosure {0} {1}".format(self.name,
|
||||||
enclosure))
|
enclosure))
|
||||||
cell.add_rect(layer=enclosure.layer,
|
cell.add_rect(layer=enclosure.layer,
|
||||||
offset=enclosure.ll(),
|
offset=enclosure.ll(),
|
||||||
|
|
@ -612,7 +612,7 @@ class pin_group:
|
||||||
blockage_set = set()
|
blockage_set = set()
|
||||||
|
|
||||||
for pin in self.pins:
|
for pin in self.pins:
|
||||||
debug.info(2, " Converting {0}".format(pin))
|
debug.info(4, " Converting {0}".format(pin))
|
||||||
# Determine which tracks the pin overlaps
|
# Determine which tracks the pin overlaps
|
||||||
(sufficient, insufficient) = self.router.convert_pin_to_tracks(self.name,
|
(sufficient, insufficient) = self.router.convert_pin_to_tracks(self.name,
|
||||||
pin)
|
pin)
|
||||||
|
|
@ -628,15 +628,15 @@ class pin_group:
|
||||||
# Remember, this excludes the pin blockages already
|
# Remember, this excludes the pin blockages already
|
||||||
shared_set = pin_set & self.router.blocked_grids
|
shared_set = pin_set & self.router.blocked_grids
|
||||||
if len(shared_set) > 0:
|
if len(shared_set) > 0:
|
||||||
debug.info(2, "Removing pins {}".format(shared_set))
|
debug.info(4, "Removing pins {}".format(shared_set))
|
||||||
pin_set.difference_update(shared_set)
|
pin_set.difference_update(shared_set)
|
||||||
shared_set = partial_set & self.router.blocked_grids
|
shared_set = partial_set & self.router.blocked_grids
|
||||||
if len(shared_set) > 0:
|
if len(shared_set) > 0:
|
||||||
debug.info(2, "Removing pins {}".format(shared_set))
|
debug.info(4, "Removing pins {}".format(shared_set))
|
||||||
partial_set.difference_update(shared_set)
|
partial_set.difference_update(shared_set)
|
||||||
shared_set = blockage_set & self.router.blocked_grids
|
shared_set = blockage_set & self.router.blocked_grids
|
||||||
if len(shared_set) > 0:
|
if len(shared_set) > 0:
|
||||||
debug.info(2, "Removing blocks {}".format(shared_set))
|
debug.info(4, "Removing blocks {}".format(shared_set))
|
||||||
blockage_set.difference_update(shared_set)
|
blockage_set.difference_update(shared_set)
|
||||||
|
|
||||||
# At least one of the groups must have some valid tracks
|
# At least one of the groups must have some valid tracks
|
||||||
|
|
@ -666,5 +666,5 @@ class pin_group:
|
||||||
# Remember the secondary grids for removing adjacent pins
|
# Remember the secondary grids for removing adjacent pins
|
||||||
self.secondary_grids = partial_set
|
self.secondary_grids = partial_set
|
||||||
|
|
||||||
debug.info(2, " pins {}".format(self.grids))
|
debug.info(4, " pins {}".format(self.grids))
|
||||||
debug.info(2, " secondary {}".format(self.secondary_grids))
|
debug.info(4, " secondary {}".format(self.secondary_grids))
|
||||||
|
|
|
||||||
|
|
@ -301,7 +301,6 @@ class router(router_tech):
|
||||||
adj_grids))
|
adj_grids))
|
||||||
self.remove_adjacent_grid(pg1, pg2, adj_grids)
|
self.remove_adjacent_grid(pg1, pg2, adj_grids)
|
||||||
|
|
||||||
|
|
||||||
debug.info(1, "Removed {} adjacent grids.".format(removed_grids))
|
debug.info(1, "Removed {} adjacent grids.".format(removed_grids))
|
||||||
|
|
||||||
def remove_adjacent_grid(self, pg1, pg2, adj_grids):
|
def remove_adjacent_grid(self, pg1, pg2, adj_grids):
|
||||||
|
|
@ -539,7 +538,7 @@ class router(router_tech):
|
||||||
sufficient_list.update([full_overlap])
|
sufficient_list.update([full_overlap])
|
||||||
if partial_overlap:
|
if partial_overlap:
|
||||||
insufficient_list.update([partial_overlap])
|
insufficient_list.update([partial_overlap])
|
||||||
debug.info(2,
|
debug.info(3,
|
||||||
"Converting [ {0} , {1} ] full={2}".format(x,
|
"Converting [ {0} , {1} ] full={2}".format(x,
|
||||||
y,
|
y,
|
||||||
full_overlap))
|
full_overlap))
|
||||||
|
|
@ -632,26 +631,26 @@ class router(router_tech):
|
||||||
pin.layer)
|
pin.layer)
|
||||||
|
|
||||||
overlap_length = pin.overlap_length(track_pin)
|
overlap_length = pin.overlap_length(track_pin)
|
||||||
debug.info(2,"Check overlap: {0} {1} . {2} = {3}".format(coord,
|
debug.info(4,"Check overlap: {0} {1} . {2} = {3}".format(coord,
|
||||||
pin.rect,
|
pin.rect,
|
||||||
track_pin,
|
track_pin,
|
||||||
overlap_length))
|
overlap_length))
|
||||||
inflated_overlap_length = inflated_pin.overlap_length(track_pin)
|
inflated_overlap_length = inflated_pin.overlap_length(track_pin)
|
||||||
debug.info(2,"Check overlap: {0} {1} . {2} = {3}".format(coord,
|
debug.info(4,"Check overlap: {0} {1} . {2} = {3}".format(coord,
|
||||||
inflated_pin.rect,
|
inflated_pin.rect,
|
||||||
track_pin,
|
track_pin,
|
||||||
inflated_overlap_length))
|
inflated_overlap_length))
|
||||||
|
|
||||||
# If it overlaps with the pin, it is sufficient
|
# If it overlaps with the pin, it is sufficient
|
||||||
if overlap_length == math.inf or overlap_length > 0:
|
if overlap_length == math.inf or overlap_length > 0:
|
||||||
debug.info(2," Overlap: {0} >? {1}".format(overlap_length, 0))
|
debug.info(4," Overlap: {0} >? {1}".format(overlap_length, 0))
|
||||||
return (coord, None)
|
return (coord, None)
|
||||||
# If it overlaps with the inflated pin, it is partial
|
# If it overlaps with the inflated pin, it is partial
|
||||||
elif inflated_overlap_length == math.inf or inflated_overlap_length > 0:
|
elif inflated_overlap_length == math.inf or inflated_overlap_length > 0:
|
||||||
debug.info(2," Partial overlap: {0} >? {1}".format(inflated_overlap_length, 0))
|
debug.info(4," Partial overlap: {0} >? {1}".format(inflated_overlap_length, 0))
|
||||||
return (None, coord)
|
return (None, coord)
|
||||||
else:
|
else:
|
||||||
debug.info(2, " No overlap: {0} {1}".format(overlap_length, 0))
|
debug.info(4, " No overlap: {0} {1}".format(overlap_length, 0))
|
||||||
return (None, None)
|
return (None, None)
|
||||||
|
|
||||||
def convert_track_to_pin(self, track):
|
def convert_track_to_pin(self, track):
|
||||||
|
|
@ -846,7 +845,7 @@ class router(router_tech):
|
||||||
"Pin component index too large.")
|
"Pin component index too large.")
|
||||||
|
|
||||||
pin_in_tracks = self.pin_groups[pin_name][index].grids
|
pin_in_tracks = self.pin_groups[pin_name][index].grids
|
||||||
debug.info(2,"Set source: " + str(pin_name) + " " + str(pin_in_tracks))
|
debug.info(3,"Set source: " + str(pin_name) + " " + str(pin_in_tracks))
|
||||||
self.rg.add_source(pin_in_tracks)
|
self.rg.add_source(pin_in_tracks)
|
||||||
|
|
||||||
def add_path_target(self, paths):
|
def add_path_target(self, paths):
|
||||||
|
|
@ -914,7 +913,7 @@ class router(router_tech):
|
||||||
"""
|
"""
|
||||||
path = self.prepare_path(path)
|
path = self.prepare_path(path)
|
||||||
|
|
||||||
debug.info(2, "Adding route: {}".format(str(path)))
|
debug.info(4, "Adding route: {}".format(str(path)))
|
||||||
# If it is only a square, add an enclosure to the track
|
# If it is only a square, add an enclosure to the track
|
||||||
if len(path) == 1:
|
if len(path) == 1:
|
||||||
self.add_single_enclosure(path[0][0])
|
self.add_single_enclosure(path[0][0])
|
||||||
|
|
@ -1007,8 +1006,7 @@ class router(router_tech):
|
||||||
# returns the path in tracks
|
# returns the path in tracks
|
||||||
(path, cost) = self.rg.route(detour_scale)
|
(path, cost) = self.rg.route(detour_scale)
|
||||||
if path:
|
if path:
|
||||||
debug.info(1, "Found path: cost={0} ".format(cost))
|
debug.info(2, "Found path: cost={0} {1}".format(cost, str(path)))
|
||||||
debug.info(1, str(path))
|
|
||||||
|
|
||||||
self.paths.append(path)
|
self.paths.append(path)
|
||||||
self.add_route(path)
|
self.add_route(path)
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
04_pbitcell_test.py
|
04_pbitcell_test.py
|
||||||
04_precharge_pbitcell_test.py
|
04_precharge_pbitcell_test.py
|
||||||
04_replica_pbitcell_test.py
|
04_replica_pbitcell_test.py
|
||||||
04_single_level_column_mux_pbitcell_test.py
|
04_column_mux_pbitcell_test.py
|
||||||
05_bitcell_1rw_1r_array_test.py
|
05_bitcell_1rw_1r_array_test.py
|
||||||
05_bitcell_array_test.py
|
05_bitcell_array_test.py
|
||||||
05_dummy_array_test.py
|
05_dummy_array_test.py
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
06_hierarchical_predecode3x8_pbitcell_test.py
|
06_hierarchical_predecode3x8_pbitcell_test.py
|
||||||
06_hierarchical_predecode3x8_test.py
|
06_hierarchical_predecode3x8_test.py
|
||||||
06_hierarchical_predecode4x16_test.py
|
06_hierarchical_predecode4x16_test.py
|
||||||
07_single_level_column_mux_array_pbitcell_test.py
|
07_column_mux_array_pbitcell_test.py
|
||||||
08_wordline_driver_array_pbitcell_test.py
|
08_wordline_driver_array_pbitcell_test.py
|
||||||
08_wordline_driver_array_test.py
|
08_wordline_driver_array_test.py
|
||||||
09_sense_amp_array_test_pbitcell.py
|
09_sense_amp_array_test_pbitcell.py
|
||||||
|
|
|
||||||
|
|
@ -363,16 +363,16 @@ spice["nmos"] = "nmos_vtg"
|
||||||
spice["pmos"] = "pmos_vtg"
|
spice["pmos"] = "pmos_vtg"
|
||||||
# This is a map of corners to model files
|
# This is a map of corners to model files
|
||||||
SPICE_MODEL_DIR=os.environ.get("SPICE_MODEL_DIR")
|
SPICE_MODEL_DIR=os.environ.get("SPICE_MODEL_DIR")
|
||||||
spice["fet_models"] = { "TT" : [SPICE_MODEL_DIR+"/models_nom/PMOS_VTG.inc",SPICE_MODEL_DIR+"/models_nom/NMOS_VTG.inc"],
|
spice["fet_models"] = {"TT": [SPICE_MODEL_DIR + "/models_nom/PMOS_VTG.inc", SPICE_MODEL_DIR + "/models_nom/NMOS_VTG.inc"],
|
||||||
"FF" : [SPICE_MODEL_DIR+"/models_ff/PMOS_VTG.inc",SPICE_MODEL_DIR+"/models_ff/NMOS_VTG.inc"],
|
"FF": [SPICE_MODEL_DIR + "/models_ff/PMOS_VTG.inc", SPICE_MODEL_DIR + "/models_ff/NMOS_VTG.inc"],
|
||||||
"SF" : [SPICE_MODEL_DIR+"/models_ss/PMOS_VTG.inc",SPICE_MODEL_DIR+"/models_ff/NMOS_VTG.inc"],
|
"SF": [SPICE_MODEL_DIR + "/models_ss/PMOS_VTG.inc", SPICE_MODEL_DIR + "/models_ff/NMOS_VTG.inc"],
|
||||||
"FS" : [SPICE_MODEL_DIR+"/models_ff/PMOS_VTG.inc",SPICE_MODEL_DIR+"/models_ss/NMOS_VTG.inc"],
|
"FS": [SPICE_MODEL_DIR + "/models_ff/PMOS_VTG.inc", SPICE_MODEL_DIR + "/models_ss/NMOS_VTG.inc"],
|
||||||
"SS" : [SPICE_MODEL_DIR+"/models_ss/PMOS_VTG.inc",SPICE_MODEL_DIR+"/models_ss/NMOS_VTG.inc"],
|
"SS": [SPICE_MODEL_DIR + "/models_ss/PMOS_VTG.inc", SPICE_MODEL_DIR + "/models_ss/NMOS_VTG.inc"],
|
||||||
"ST" : [SPICE_MODEL_DIR+"/models_ss/PMOS_VTG.inc",SPICE_MODEL_DIR+"/models_nom/NMOS_VTG.inc"],
|
"ST": [SPICE_MODEL_DIR + "/models_ss/PMOS_VTG.inc", SPICE_MODEL_DIR + "/models_nom/NMOS_VTG.inc"],
|
||||||
"TS" : [SPICE_MODEL_DIR+"/models_nom/PMOS_VTG.inc",SPICE_MODEL_DIR+"/models_ss/NMOS_VTG.inc"],
|
"TS": [SPICE_MODEL_DIR + "/models_nom/PMOS_VTG.inc", SPICE_MODEL_DIR + "/models_ss/NMOS_VTG.inc"],
|
||||||
"FT" : [SPICE_MODEL_DIR+"/models_ff/PMOS_VTG.inc",SPICE_MODEL_DIR+"/models_nom/NMOS_VTG.inc"],
|
"FT": [SPICE_MODEL_DIR + "/models_ff/PMOS_VTG.inc", SPICE_MODEL_DIR + "/models_nom/NMOS_VTG.inc"],
|
||||||
"TF" : [SPICE_MODEL_DIR+"/models_nom/PMOS_VTG.inc",SPICE_MODEL_DIR+"/models_ff/NMOS_VTG.inc"],
|
"TF": [SPICE_MODEL_DIR + "/models_nom/PMOS_VTG.inc", SPICE_MODEL_DIR + "/models_ff/NMOS_VTG.inc"],
|
||||||
}
|
}
|
||||||
|
|
||||||
#spice stimulus related variables
|
#spice stimulus related variables
|
||||||
spice["feasible_period"] = 5 # estimated feasible period in ns
|
spice["feasible_period"] = 5 # estimated feasible period in ns
|
||||||
|
|
|
||||||
|
|
@ -321,16 +321,16 @@ spice["nmos"]="n"
|
||||||
spice["pmos"]="p"
|
spice["pmos"]="p"
|
||||||
# This is a map of corners to model files
|
# This is a map of corners to model files
|
||||||
SPICE_MODEL_DIR=os.environ.get("SPICE_MODEL_DIR")
|
SPICE_MODEL_DIR=os.environ.get("SPICE_MODEL_DIR")
|
||||||
spice["fet_models"] = { "TT" : [SPICE_MODEL_DIR+"/nom/pmos.sp",SPICE_MODEL_DIR+"/nom/nmos.sp"],
|
spice["fet_models"] = {"TT": [SPICE_MODEL_DIR + "/nom/pmos.sp", SPICE_MODEL_DIR + "/nom/nmos.sp"],
|
||||||
"FF" : [SPICE_MODEL_DIR+"/ff/pmos.sp",SPICE_MODEL_DIR+"/ff/nmos.sp"],
|
"FF": [SPICE_MODEL_DIR + "/ff/pmos.sp", SPICE_MODEL_DIR + "/ff/nmos.sp"],
|
||||||
"FS" : [SPICE_MODEL_DIR+"/ff/pmos.sp",SPICE_MODEL_DIR+"/ss/nmos.sp"],
|
"FS": [SPICE_MODEL_DIR + "/ff/pmos.sp", SPICE_MODEL_DIR + "/ss/nmos.sp"],
|
||||||
"SF" : [SPICE_MODEL_DIR+"/ss/pmos.sp",SPICE_MODEL_DIR+"/ff/nmos.sp"],
|
"SF": [SPICE_MODEL_DIR + "/ss/pmos.sp", SPICE_MODEL_DIR + "/ff/nmos.sp"],
|
||||||
"SS" : [SPICE_MODEL_DIR+"/ss/pmos.sp",SPICE_MODEL_DIR+"/ss/nmos.sp"],
|
"SS": [SPICE_MODEL_DIR + "/ss/pmos.sp", SPICE_MODEL_DIR + "/ss/nmos.sp"],
|
||||||
"ST" : [SPICE_MODEL_DIR+"/ss/pmos.sp",SPICE_MODEL_DIR+"/nom/nmos.sp"],
|
"ST": [SPICE_MODEL_DIR + "/ss/pmos.sp", SPICE_MODEL_DIR + "/nom/nmos.sp"],
|
||||||
"TS" : [SPICE_MODEL_DIR+"/nom/pmos.sp",SPICE_MODEL_DIR+"/ss/nmos.sp"],
|
"TS": [SPICE_MODEL_DIR + "/nom/pmos.sp", SPICE_MODEL_DIR + "/ss/nmos.sp"],
|
||||||
"FT" : [SPICE_MODEL_DIR+"/ff/pmos.sp",SPICE_MODEL_DIR+"/nom/nmos.sp"],
|
"FT": [SPICE_MODEL_DIR + "/ff/pmos.sp", SPICE_MODEL_DIR + "/nom/nmos.sp"],
|
||||||
"TF" : [SPICE_MODEL_DIR+"/nom/pmos.sp",SPICE_MODEL_DIR+"/ff/nmos.sp"],
|
"TF": [SPICE_MODEL_DIR + "/nom/pmos.sp", SPICE_MODEL_DIR + "/ff/nmos.sp"],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#spice stimulus related variables
|
#spice stimulus related variables
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue