Added graph fixes to handmade multiport cells.

This commit is contained in:
Hunter Nichols 2019-07-30 20:31:32 -07:00
parent c12dd987dc
commit 24b1fa38a0
8 changed files with 32 additions and 75 deletions

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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):
"""

View File

@ -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."""

View File

@ -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)