mirror of https://github.com/VLSIDA/OpenRAM.git
Added graph fixes to handmade multiport cells.
This commit is contained in:
parent
c12dd987dc
commit
24b1fa38a0
|
|
@ -139,6 +139,6 @@ class bitcell_1w_1r(design.design):
|
|||
pin_dict = {pin:port for pin,port in zip(self.pins, port_nets)}
|
||||
#Edges hardcoded here. Essentially wl->bl/br for both ports.
|
||||
# Port 0 edges
|
||||
graph.add_edge(pin_dict["wl0"], pin_dict["bl0"])
|
||||
graph.add_edge(pin_dict["wl0"], pin_dict["br0"])
|
||||
graph.add_edge(pin_dict["wl1"], pin_dict["bl1"])
|
||||
graph.add_edge(pin_dict["wl1"], pin_dict["br1"])
|
||||
# Port 1 is a write port, so its timing is not considered here.
|
||||
|
|
|
|||
|
|
@ -41,13 +41,5 @@ class dummy_bitcell_1rw_1r(design.design):
|
|||
return 2*access_tx_cin
|
||||
|
||||
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."""
|
||||
pin_dict = {pin:port for pin,port in zip(self.pins, port_nets)}
|
||||
#Edges hardcoded here. Essentially wl->bl/br for both ports.
|
||||
# Port 0 edges
|
||||
graph.add_edge(pin_dict["wl0"], pin_dict["bl0"])
|
||||
graph.add_edge(pin_dict["wl0"], pin_dict["br0"])
|
||||
# Port 1 edges
|
||||
graph.add_edge(pin_dict["wl1"], pin_dict["bl1"])
|
||||
graph.add_edge(pin_dict["wl1"], pin_dict["br1"])
|
||||
"""Dummy bitcells are cannot form a path and be part of the timing graph"""
|
||||
return
|
||||
|
|
|
|||
|
|
@ -41,11 +41,5 @@ class dummy_bitcell_1w_1r(design.design):
|
|||
return 2*access_tx_cin
|
||||
|
||||
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."""
|
||||
pin_dict = {pin:port for pin,port in zip(self.pins, port_nets)}
|
||||
#Edges hardcoded here. Essentially wl->bl/br for both ports.
|
||||
# Port 0 edges
|
||||
graph.add_edge(pin_dict["wl0"], pin_dict["bl0"])
|
||||
graph.add_edge(pin_dict["wl0"], pin_dict["br0"])
|
||||
# Port 1 is a write port, so its timing is not considered here.
|
||||
"""Dummy bitcells are cannot form a path and be part of the timing graph"""
|
||||
return
|
||||
|
|
|
|||
|
|
@ -43,9 +43,10 @@ class replica_bitcell_1w_1r(design.design):
|
|||
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."""
|
||||
debug.info(1,'Adding edges for {}'.format(inst_name))
|
||||
pin_dict = {pin:port for pin,port in zip(self.pins, port_nets)}
|
||||
#Edges hardcoded here. Essentially wl->bl/br for both ports.
|
||||
# Port 0 edges
|
||||
graph.add_edge(pin_dict["wl0"], pin_dict["bl0"])
|
||||
graph.add_edge(pin_dict["wl0"], pin_dict["br0"])
|
||||
# Port 1 is a write port, so its timing is not considered here.
|
||||
#Edges hardcoded here. Essentially wl->bl/br for the read port.
|
||||
# Port 1 edges
|
||||
graph.add_edge(pin_dict["wl1"], pin_dict["bl1"])
|
||||
graph.add_edge(pin_dict["wl1"], pin_dict["br1"])
|
||||
# Port 0 is a write port, so its timing is not considered here.
|
||||
|
|
@ -258,14 +258,14 @@ class delay(simulation):
|
|||
def set_internal_spice_names(self):
|
||||
"""Sets important names for characterization such as Sense amp enable and internal bit nets."""
|
||||
|
||||
port = 0
|
||||
port = self.read_ports[0]
|
||||
self.graph.get_all_paths('{}{}'.format(tech.spice["clk"], port),
|
||||
'{}{}_{}'.format(self.dout_name, port, self.probe_data))
|
||||
|
||||
self.sen_name = self.get_sen_name(self.graph.all_paths)
|
||||
debug.info(2,"s_en name = {}".format(self.sen_name))
|
||||
|
||||
self.bl_name,self.br_name = self.get_bl_name(self.graph.all_paths)
|
||||
self.bl_name,self.br_name = self.get_bl_name(self.graph.all_paths, port)
|
||||
debug.info(2,"bl name={}, br name={}".format(self.bl_name,self.br_name))
|
||||
|
||||
def get_sen_name(self, paths):
|
||||
|
|
@ -282,12 +282,12 @@ class delay(simulation):
|
|||
sen_name = self.get_alias_in_path(paths, enable_name, sa_mods[0])
|
||||
return sen_name
|
||||
|
||||
def get_bl_name(self, paths):
|
||||
def get_bl_name(self, paths, port):
|
||||
"""Gets the signal name associated with the bitlines in the bank."""
|
||||
|
||||
cell_mod = factory.create(module_type=OPTS.bitcell)
|
||||
cell_bl = cell_mod.get_bl_name()
|
||||
cell_br = cell_mod.get_br_name()
|
||||
cell_bl = cell_mod.get_bl_name(port)
|
||||
cell_br = cell_mod.get_br_name(port)
|
||||
|
||||
bl_found = False
|
||||
# Only a single path should contain a single s_en name. Anything else is an error.
|
||||
|
|
|
|||
|
|
@ -411,14 +411,15 @@ class functional(simulation):
|
|||
def set_internal_spice_names(self):
|
||||
"""Sets important names for characterization such as Sense amp enable and internal bit nets."""
|
||||
|
||||
port = 0
|
||||
# For now, only testing these using first read port.
|
||||
port = self.read_ports[0]
|
||||
self.graph.get_all_paths('{}{}'.format(tech.spice["clk"], port),
|
||||
'{}{}_{}'.format(self.dout_name, port, 0).lower())
|
||||
|
||||
self.sen_name = self.get_sen_name(self.graph.all_paths)
|
||||
debug.info(2,"s_en name = {}".format(self.sen_name))
|
||||
|
||||
self.bl_name,self.br_name = self.get_bl_name(self.graph.all_paths)
|
||||
self.bl_name,self.br_name = self.get_bl_name(self.graph.all_paths, port)
|
||||
debug.info(2,"bl name={}, br name={}".format(self.bl_name,self.br_name))
|
||||
|
||||
self.q_name,self.qbar_name = self.get_bit_name()
|
||||
|
|
@ -451,12 +452,12 @@ class functional(simulation):
|
|||
return sen_name
|
||||
|
||||
# FIXME: refactor to share with delay.py
|
||||
def get_bl_name(self, paths):
|
||||
def get_bl_name(self, paths, port):
|
||||
"""Gets the signal name associated with the bitlines in the bank."""
|
||||
|
||||
cell_mod = factory.create(module_type=OPTS.bitcell)
|
||||
cell_bl = cell_mod.get_bl_name()
|
||||
cell_br = cell_mod.get_br_name()
|
||||
cell_bl = cell_mod.get_bl_name(port)
|
||||
cell_br = cell_mod.get_br_name(port)
|
||||
|
||||
bl_found = False
|
||||
# Only a single path should contain a single s_en name. Anything else is an error.
|
||||
|
|
@ -473,37 +474,6 @@ class functional(simulation):
|
|||
# Exclude the RBL as it contains bitcells which are not in the main bitcell array
|
||||
# so it makes the search awkward
|
||||
return set(factory.get_mods(OPTS.replica_bitline))
|
||||
|
||||
def get_primary_cell_mod(self, cell_mods):
|
||||
"""
|
||||
Distinguish bitcell array mod from replica bitline array.
|
||||
Assume there are no replica bitcells in the primary array.
|
||||
"""
|
||||
if len(cell_mods) == 1:
|
||||
return cell_mods[0]
|
||||
rbc_mods = factory.get_mods(OPTS.replica_bitcell)
|
||||
non_rbc_mods = []
|
||||
for bitcell in cell_mods:
|
||||
has_cell = False
|
||||
for replica_cell in rbc_mods:
|
||||
has_cell = has_cell or replica_cell.contains(bitcell, replica_cell.mods)
|
||||
if not has_cell:
|
||||
non_rbc_mods.append(bitcell)
|
||||
|
||||
if len(non_rbc_mods) != 1:
|
||||
debug.error('{} possible bitcell mods found. Cannot distinguish for characterization'.format(len(non_rbc_mods)),1)
|
||||
return non_rbc_mods[0]
|
||||
|
||||
def are_mod_pins_equal(self, mods):
|
||||
"""Determines if there are pins differences in the input mods"""
|
||||
|
||||
if len(mods) == 0:
|
||||
return True
|
||||
pins = mods[0].pins
|
||||
for mod in mods[1:]:
|
||||
if pins != mod.pins:
|
||||
return False
|
||||
return True
|
||||
|
||||
def get_alias_in_path(self, paths, int_net, mod, exclusion_set=None):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -138,8 +138,6 @@ class replica_bitcell_array(design.design):
|
|||
# Create the full WL names include dummy, replica, and regular bit cells
|
||||
self.replica_col_wl_names = []
|
||||
self.replica_col_wl_names.extend(["{0}_bot".format(x) for x in self.dummy_cell_wl_names])
|
||||
#Save where the RBL wordlines start for graph purposes. Even positions are changed then graph will break
|
||||
self.rbl_row_pos = len(self.replica_col_wl_names)
|
||||
# Left port WLs (one dummy for each port when we allow >1 port)
|
||||
for port in range(self.left_rbl):
|
||||
# Make names for all RBLs
|
||||
|
|
@ -445,9 +443,10 @@ class replica_bitcell_array(design.design):
|
|||
self.bitcell_array.graph_exclude_bits(targ_row, targ_col)
|
||||
|
||||
def graph_exclude_replica_col_bits(self):
|
||||
"""Exclude all replica/dummy cells in the replica columns except the replica bit."""
|
||||
|
||||
for port in range(self.left_rbl+self.right_rbl):
|
||||
#While the rbl_wl bits may be on a few rows. Only keep one for simplicity.
|
||||
self.replica_columns[port].exclude_bits_except_one(self.rbl_row_pos)
|
||||
self.replica_columns[port].exclude_all_but_replica()
|
||||
|
||||
def get_cell_name(self, inst_name, row, col):
|
||||
"""Gets the spice name of the target bitcell."""
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ class replica_column(design.design):
|
|||
self.replica_bit = replica_bit
|
||||
# left, right, regular rows plus top/bottom dummy cells
|
||||
self.total_size = self.left_rbl+rows+self.right_rbl+2
|
||||
|
||||
|
||||
debug.check(replica_bit!=0 and replica_bit!=rows,"Replica bit cannot be the dummy row.")
|
||||
debug.check(replica_bit<=left_rbl or replica_bit>=self.total_size-right_rbl-1,
|
||||
"Replica bit cannot be in the regular array.")
|
||||
|
|
@ -152,8 +152,9 @@ class replica_column(design.design):
|
|||
|
||||
return bitcell_pins
|
||||
|
||||
def exclude_bits_except_one(self, selected_row):
|
||||
def exclude_all_but_replica(self):
|
||||
"""Excludes all bits except the replica cell (self.replica_bit)."""
|
||||
|
||||
for row, cell in self.cell_inst.items():
|
||||
if row == selected_row:
|
||||
continue
|
||||
self.graph_inst_exclude.add(cell)
|
||||
if row != self.replica_bit:
|
||||
self.graph_inst_exclude.add(cell)
|
||||
|
|
|
|||
Loading…
Reference in New Issue