diff --git a/compiler/bitcells/bitcell_1w_1r.py b/compiler/bitcells/bitcell_1w_1r.py index b36c38bf..6063cf86 100644 --- a/compiler/bitcells/bitcell_1w_1r.py +++ b/compiler/bitcells/bitcell_1w_1r.py @@ -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. diff --git a/compiler/bitcells/dummy_bitcell_1rw_1r.py b/compiler/bitcells/dummy_bitcell_1rw_1r.py index 189c4894..f8986f2d 100644 --- a/compiler/bitcells/dummy_bitcell_1rw_1r.py +++ b/compiler/bitcells/dummy_bitcell_1rw_1r.py @@ -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 diff --git a/compiler/bitcells/dummy_bitcell_1w_1r.py b/compiler/bitcells/dummy_bitcell_1w_1r.py index 95d514f8..ef451b8c 100644 --- a/compiler/bitcells/dummy_bitcell_1w_1r.py +++ b/compiler/bitcells/dummy_bitcell_1w_1r.py @@ -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 diff --git a/compiler/bitcells/replica_bitcell_1w_1r.py b/compiler/bitcells/replica_bitcell_1w_1r.py index c0d31a69..79171bf5 100644 --- a/compiler/bitcells/replica_bitcell_1w_1r.py +++ b/compiler/bitcells/replica_bitcell_1w_1r.py @@ -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. \ No newline at end of file + #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. \ No newline at end of file diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 854739cb..37c38353 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -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. diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index dc4fe48a..9f8e3d43 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -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): """ diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index c748e83d..6f4e96c5 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -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.""" diff --git a/compiler/modules/replica_column.py b/compiler/modules/replica_column.py index b18c49fe..fb11a8f5 100644 --- a/compiler/modules/replica_column.py +++ b/compiler/modules/replica_column.py @@ -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)