mirror of https://github.com/VLSIDA/OpenRAM.git
Added multiport bitcell support for storage node checks
This commit is contained in:
parent
099bc4e258
commit
d08181455c
|
|
@ -197,7 +197,12 @@ class spice():
|
|||
return True
|
||||
return False
|
||||
|
||||
|
||||
def do_nets_exist(self, nets):
|
||||
"""For handmade cell, checks sp file contains the storage nodes."""
|
||||
nets_match = True
|
||||
for net in nets:
|
||||
nets_match = nets_match and self.check_net_in_spice(net)
|
||||
return nets_match
|
||||
|
||||
def contains(self, mod, modlist):
|
||||
for x in modlist:
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ class bitcell(design.design):
|
|||
"""
|
||||
|
||||
pin_names = ["bl", "br", "wl", "vdd", "gnd"]
|
||||
internal_nets = ['Q', 'Qbar']
|
||||
storage_nets = ['Q', 'Qbar']
|
||||
type_list = ["OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"]
|
||||
(width,height) = utils.get_libcell_size("cell_6t", GDS["unit"], layer["boundary"])
|
||||
pin_map = utils.get_libcell_pins(pin_names, "cell_6t", GDS["unit"])
|
||||
|
|
@ -34,7 +34,7 @@ class bitcell(design.design):
|
|||
self.height = bitcell.height
|
||||
self.pin_map = bitcell.pin_map
|
||||
self.add_pin_types(self.type_list)
|
||||
self.nets_match = self.check_internal_nets()
|
||||
self.nets_match = self.do_nets_exist(self.storage_nets)
|
||||
|
||||
def analytical_delay(self, corner, slew, load=0, swing = 0.5):
|
||||
parasitic_delay = 1
|
||||
|
|
@ -78,21 +78,14 @@ class bitcell(design.design):
|
|||
dynamic = 0 #temporary
|
||||
total_power = self.return_power(dynamic, leakage)
|
||||
return total_power
|
||||
|
||||
def check_internal_nets(self):
|
||||
"""For handmade cell, checks sp file contains the storage nodes."""
|
||||
nets_match = True
|
||||
for net in self.internal_nets:
|
||||
nets_match = nets_match and self.check_net_in_spice(net)
|
||||
return nets_match
|
||||
|
||||
|
||||
def get_storage_net_names(self):
|
||||
"""Returns names of storage nodes in bitcell in [non-inverting, inverting] format."""
|
||||
#Checks that they do exist
|
||||
if self.nets_match:
|
||||
return self.internal_nets
|
||||
return self.storage_nets
|
||||
else:
|
||||
debug.info(1,"Storage nodes={} not found in spice file.".format(self.internal_nets))
|
||||
debug.info(1,"Storage nodes={} not found in spice file.".format(self.storage_nets))
|
||||
return None
|
||||
|
||||
def get_wl_cin(self):
|
||||
|
|
|
|||
|
|
@ -20,7 +20,8 @@ class bitcell_1rw_1r(design.design):
|
|||
"""
|
||||
|
||||
pin_names = ["bl0", "br0", "bl1", "br1", "wl0", "wl1", "vdd", "gnd"]
|
||||
type_list = ["OUTPUT", "OUTPUT", "OUTPUT", "OUTPUT", "INPUT", "INPUT", "POWER", "GROUND"]
|
||||
type_list = ["OUTPUT", "OUTPUT", "OUTPUT", "OUTPUT", "INPUT", "INPUT", "POWER", "GROUND"]
|
||||
storage_nets = ['Q', 'Q_bar']
|
||||
(width,height) = utils.get_libcell_size("cell_1rw_1r", GDS["unit"], layer["boundary"])
|
||||
pin_map = utils.get_libcell_pins(pin_names, "cell_1rw_1r", GDS["unit"])
|
||||
|
||||
|
|
@ -33,6 +34,7 @@ class bitcell_1rw_1r(design.design):
|
|||
self.height = bitcell_1rw_1r.height
|
||||
self.pin_map = bitcell_1rw_1r.pin_map
|
||||
self.add_pin_types(self.type_list)
|
||||
self.nets_match = self.do_nets_exist(self.storage_nets)
|
||||
|
||||
def analytical_delay(self, corner, slew, load=0, swing = 0.5):
|
||||
parasitic_delay = 1
|
||||
|
|
@ -109,6 +111,15 @@ class bitcell_1rw_1r(design.design):
|
|||
access_tx_cin = parameter["6T_access_size"]/drc["minwidth_tx"]
|
||||
return 2*access_tx_cin
|
||||
|
||||
def get_storage_net_names(self):
|
||||
"""Returns names of storage nodes in bitcell in [non-inverting, inverting] format."""
|
||||
#Checks that they do exist
|
||||
if self.nets_match:
|
||||
return self.storage_nets
|
||||
else:
|
||||
debug.info(1,"Storage nodes={} not found in spice file.".format(self.storage_nets))
|
||||
return None
|
||||
|
||||
def build_graph(self, graph, inst_name, port_nets):
|
||||
"""Adds edges to graph. Multiport bitcell timing graph is too complex
|
||||
to use the add_graph_edges function."""
|
||||
|
|
|
|||
|
|
@ -20,7 +20,8 @@ class bitcell_1w_1r(design.design):
|
|||
"""
|
||||
|
||||
pin_names = ["bl0", "br0", "bl1", "br1", "wl0", "wl1", "vdd", "gnd"]
|
||||
type_list = ["OUTPUT", "OUTPUT", "INPUT", "INPUT", "INPUT", "INPUT", "POWER", "GROUND"]
|
||||
type_list = ["OUTPUT", "OUTPUT", "INPUT", "INPUT", "INPUT", "INPUT", "POWER", "GROUND"]
|
||||
storage_nets = ['Q', 'Q_bar']
|
||||
(width,height) = utils.get_libcell_size("cell_1w_1r", GDS["unit"], layer["boundary"])
|
||||
pin_map = utils.get_libcell_pins(pin_names, "cell_1w_1r", GDS["unit"])
|
||||
|
||||
|
|
@ -33,6 +34,7 @@ class bitcell_1w_1r(design.design):
|
|||
self.height = bitcell_1w_1r.height
|
||||
self.pin_map = bitcell_1w_1r.pin_map
|
||||
self.add_pin_types(self.type_list)
|
||||
self.nets_match = self.do_nets_exist(self.storage_nets)
|
||||
|
||||
def analytical_delay(self, corner, slew, load=0, swing = 0.5):
|
||||
parasitic_delay = 1
|
||||
|
|
@ -109,6 +111,15 @@ class bitcell_1w_1r(design.design):
|
|||
access_tx_cin = parameter["6T_access_size"]/drc["minwidth_tx"]
|
||||
return 2*access_tx_cin
|
||||
|
||||
def get_storage_net_names(self):
|
||||
"""Returns names of storage nodes in bitcell in [non-inverting, inverting] format."""
|
||||
#Checks that they do exist
|
||||
if self.nets_match:
|
||||
return self.storage_nets
|
||||
else:
|
||||
debug.info(1,"Storage nodes={} not found in spice file.".format(self.storage_nets))
|
||||
return None
|
||||
|
||||
def build_graph(self, graph, inst_name, port_nets):
|
||||
"""Adds edges to graph. Multiport bitcell timing graph is too complex
|
||||
to use the add_graph_edges function."""
|
||||
|
|
|
|||
|
|
@ -138,7 +138,9 @@ class pbitcell(design.design):
|
|||
self.Q_bar = "vdd"
|
||||
else:
|
||||
self.Q_bar = "Q_bar"
|
||||
|
||||
self.Q = "Q"
|
||||
self.storage_nets = [self.Q, self.Q_bar]
|
||||
|
||||
def add_modules(self):
|
||||
""" Determine size of transistors and add ptx modules """
|
||||
# if there are any read/write ports, then the inverter nmos is sized based the number of read/write ports
|
||||
|
|
@ -258,20 +260,20 @@ class pbitcell(design.design):
|
|||
# create active for nmos
|
||||
self.inverter_nmos_left = self.add_inst(name="inverter_nmos_left",
|
||||
mod=self.inverter_nmos)
|
||||
self.connect_inst(["Q", self.Q_bar, "gnd", "gnd"])
|
||||
self.connect_inst([self.Q, self.Q_bar, "gnd", "gnd"])
|
||||
|
||||
self.inverter_nmos_right = self.add_inst(name="inverter_nmos_right",
|
||||
mod=self.inverter_nmos)
|
||||
self.connect_inst(["gnd", "Q", self.Q_bar, "gnd"])
|
||||
self.connect_inst(["gnd", self.Q, self.Q_bar, "gnd"])
|
||||
|
||||
# create active for pmos
|
||||
self.inverter_pmos_left = self.add_inst(name="inverter_pmos_left",
|
||||
mod=self.inverter_pmos)
|
||||
self.connect_inst(["Q", self.Q_bar, "vdd", "vdd"])
|
||||
self.connect_inst([self.Q, self.Q_bar, "vdd", "vdd"])
|
||||
|
||||
self.inverter_pmos_right = self.add_inst(name="inverter_pmos_right",
|
||||
mod=self.inverter_pmos)
|
||||
self.connect_inst(["vdd", "Q", self.Q_bar, "vdd"])
|
||||
self.connect_inst(["vdd", self.Q, self.Q_bar, "vdd"])
|
||||
|
||||
def place_storage(self):
|
||||
""" Places the transistors for the crossed coupled inverters in the bitcell """
|
||||
|
|
@ -363,7 +365,7 @@ class pbitcell(design.design):
|
|||
# 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([self.rw_bl_names[k], self.rw_wl_names[k], "Q", "gnd"])
|
||||
self.connect_inst([self.rw_bl_names[k], self.rw_wl_names[k], self.Q, "gnd"])
|
||||
|
||||
self.readwrite_nmos_right[k] = self.add_inst(name="readwrite_nmos_right{}".format(k),
|
||||
mod=self.readwrite_nmos)
|
||||
|
|
@ -437,7 +439,7 @@ class pbitcell(design.design):
|
|||
# add write transistors
|
||||
self.write_nmos_left[k] = self.add_inst(name="write_nmos_left{}".format(k),
|
||||
mod=self.write_nmos)
|
||||
self.connect_inst([self.w_bl_names[k], self.w_wl_names[k], "Q", "gnd"])
|
||||
self.connect_inst([self.w_bl_names[k], self.w_wl_names[k], self.Q, "gnd"])
|
||||
|
||||
self.write_nmos_right[k] = self.add_inst(name="write_nmos_right{}".format(k),
|
||||
mod=self.write_nmos)
|
||||
|
|
@ -522,7 +524,7 @@ class pbitcell(design.design):
|
|||
|
||||
self.read_access_nmos_right[k] = self.add_inst(name="read_access_nmos_right{}".format(k),
|
||||
mod=self.read_nmos)
|
||||
self.connect_inst(["gnd", "Q", "RA_to_R_right{}".format(k), "gnd"])
|
||||
self.connect_inst(["gnd", self.Q, "RA_to_R_right{}".format(k), "gnd"])
|
||||
|
||||
# add read transistors
|
||||
self.read_nmos_left[k] = self.add_inst(name="read_nmos_left{}".format(k),
|
||||
|
|
@ -866,6 +868,11 @@ class pbitcell(design.design):
|
|||
Q_bar_pos = self.inverter_pmos_right.get_pin("S").center()
|
||||
vdd_pos = self.inverter_pmos_right.get_pin("D").center()
|
||||
self.add_path("metal1", [Q_bar_pos, vdd_pos])
|
||||
|
||||
def get_storage_net_names(self):
|
||||
"""Returns names of storage nodes in bitcell in [non-inverting, inverting] format."""
|
||||
return self.storage_nets
|
||||
|
||||
|
||||
def analytical_delay(self, corner, slew, load=0, swing = 0.5):
|
||||
parasitic_delay = 1
|
||||
|
|
|
|||
Loading…
Reference in New Issue