diff --git a/compiler/base/custom_cell_properties.py b/compiler/base/custom_cell_properties.py index e7e2253b..2407f9c2 100644 --- a/compiler/base/custom_cell_properties.py +++ b/compiler/base/custom_cell_properties.py @@ -22,7 +22,11 @@ class _cell: self._port_map = {x: x for x in port_order} # Update mapping of names + self._original_port_order = port_order self._port_order = port_order + + # Create an index array + self._port_indices = [self._port_order.index(x) for x in self._original_port_order] # Update ordered name list self._port_names = [self._port_map[x] for x in self._port_order] @@ -49,7 +53,13 @@ class _cell: self._port_names = [self._port_map[x] for x in self._port_order] # Update ordered type list in the new order self._port_types = [self._port_types_map[x] for x in self._port_order] + # Update the index array + self._port_indices = [self._port_order.index(x) for x in self._original_port_order] + @property + def port_indices(self): + return self._port_indices + @property def port_map(self): return self._port_map diff --git a/compiler/base/design.py b/compiler/base/design.py index f90ea12c..2c3ba2ea 100644 --- a/compiler/base/design.py +++ b/compiler/base/design.py @@ -39,6 +39,7 @@ class design(hierarchy_design): # that they matched here debug.check(prop.port_names == self.pins, "Custom cell pin names do not match spice file:\n{0} vs {1}".format(prop.port_names, self.pins)) + self.add_pin_indices(prop.port_indices) self.add_pin_names(prop.port_map) self.add_pin_types(prop.port_types) diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index d2313d99..4e473397 100644 --- a/compiler/base/hierarchy_layout.py +++ b/compiler/base/hierarchy_layout.py @@ -62,14 +62,7 @@ class layout(): self.pwr_grid_layer = power_grid[0] except ImportError: self.pwr_grid_layer = "m3" - - def add_pin_names(self, pin_dict): - """ - Create a mapping from internal pin names to external pin names. - """ - self.pin_names = pin_dict - - + ############################################################ # GDS layout ############################################################ @@ -325,11 +318,8 @@ class layout(): """ Return the pin or list of pins """ - if text in self.pin_names: - name = self.pin_names[text] - else: - name = text - + name = self.get_pin_name(text) + try: if len(self.pin_map[name]) > 1: debug.error("Should use a pin iterator since more than one pin {}".format(text), -1) @@ -345,16 +335,42 @@ class layout(): """ Return a pin list (instead of a single pin) """ - if text in self.pin_names: - name = self.pin_names[text] - else: - name = text + name = self.get_pin_name(text) if name in self.pin_map.keys(): return self.pin_map[name] else: return set() + def add_pin_names(self, pin_dict): + """ + Create a mapping from internal pin names to external pin names. + """ + self.pin_names = pin_dict + + self.original_pin_names = {y: x for (x, y) in self.pin_names.items()} + + def get_pin_name(self, text): + """ Return the custom cell pin name """ + + if text in self.pin_names: + return self.pin_names[text] + else: + return text + + def get_original_pin_names(self): + """ Return the internal cell pin name """ + + # This uses the hierarchy_spice pins (in order) + return [self.get_original_pin_name(x) for x in self.pins] + + def get_original_pin_name(self, text): + """ Return the internal cell pin names in custom port order """ + if text in self.original_pin_names: + return self.original_pin_names[text] + else: + return text + def get_pin_names(self): """ Return a pin list of all pins diff --git a/compiler/base/hierarchy_spice.py b/compiler/base/hierarchy_spice.py index 9e2a3e41..a51b9575 100644 --- a/compiler/base/hierarchy_spice.py +++ b/compiler/base/hierarchy_spice.py @@ -35,11 +35,13 @@ class spice(): self.valid_signal_types = ["INOUT", "INPUT", "OUTPUT", "POWER", "GROUND"] # Holds subckts/mods for this module self.mods = [] - # Holds the pins for this module + # Holds the pins for this module (in order) self.pins = [] # The type map of each pin: INPUT, OUTPUT, INOUT, POWER, GROUND # for each instance, this is the set of nets/nodes that map to the pins for this instance self.pin_type = {} + # An (optional) list of indices to reorder the pins to match the spice. + self.pin_indices = [] # THE CONNECTIONS MUST MATCH THE ORDER OF THE PINS (restriction imposed by the # Spice format) self.conns = [] @@ -95,10 +97,25 @@ class spice(): else: debug.error("Mismatch in type and pin list lengths.", -1) + def add_pin_indices(self, index_list): + """ + Add pin indices for all the cell's pins. + """ + self.pin_indices = index_list + + def get_ordered_inputs(self, input_list): + """ + Return the inputs reordered to match the pins. + """ + if not self.pin_indices: + return input_list + + new_list = [input_list[x] for x in self.pin_indices] + return new_list + def add_pin_types(self, type_list): """ Add pin types for all the cell's pins. - Typically, should only be used for handmade cells. """ # This only works if self.pins == bitcell.pin_names if len(type_list) != len(self.pins): @@ -107,7 +124,7 @@ class spice(): \n Module names={}\ ".format(self.name, self.pins, type_list), 1) self.pin_type = {pin: type for pin, type in zip(self.pins, type_list)} - + def get_pin_type(self, name): """ Returns the type of the signal pin. """ pin_type = self.pin_type[name] @@ -159,19 +176,26 @@ class spice(): self.mods.append(mod) def connect_inst(self, args, check=True): - """Connects the pins of the last instance added + """ + Connects the pins of the last instance added It is preferred to use the function with the check to find if there is a problem. The check option can be set to false where we dynamically generate groups of connections after a - group of modules are generated.""" + group of modules are generated. + """ + num_pins = len(self.insts[-1].mod.pins) num_args = len(args) + + # Order the arguments if the hard cell has a custom port order + ordered_args = self.get_ordered_inputs(args) + if (check and num_pins != num_args): if num_pins < num_args: mod_pins = self.insts[-1].mod.pins + [""] * (num_args - num_pins) - arg_pins = args + arg_pins = ordered_args else: - arg_pins = args + [""] * (num_pins - num_args) + arg_pins = ordered_args + [""] * (num_pins - num_args) mod_pins = self.insts[-1].mod.pins modpins_string = "\n".join(["{0} -> {1}".format(arg, mod) for (arg, mod) in zip(arg_pins, mod_pins)]) @@ -180,8 +204,9 @@ class spice(): modpins_string), 1) - self.conns.append(args) + self.conns.append(ordered_args) + # This checks if we don't have enough instance port connections for the number of insts if check and (len(self.insts)!=len(self.conns)): insts_string=pformat(self.insts) conns_string=pformat(self.conns) diff --git a/compiler/base/verilog.py b/compiler/base/verilog.py index 636e3bd6..f5ef9107 100644 --- a/compiler/base/verilog.py +++ b/compiler/base/verilog.py @@ -5,9 +5,9 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -import debug import math + class verilog: """ Create a behavioral Verilog file for simulation. @@ -16,7 +16,7 @@ class verilog: def __init__(self): pass - def verilog_write(self,verilog_name): + def verilog_write(self, verilog_name): """ Write a behavioral Verilog model. """ self.vf = open(verilog_name, "w") @@ -220,6 +220,9 @@ class verilog: self.vf.write(" dout{0} <= #(DELAY) mem[addr{0}_reg];\n".format(port)) self.vf.write(" end\n") + self.vf.write(" always @(csb{0})\n".format(port)) + self.vf.write(" dout{0} = 0)\n".format(port)) + def add_address_check(self, wport, rport): """ Output a warning if the two addresses match """ # If the rport is actually reading... and addresses match. diff --git a/compiler/characterizer/setup_hold.py b/compiler/characterizer/setup_hold.py index 9ce5a899..688e6535 100644 --- a/compiler/characterizer/setup_hold.py +++ b/compiler/characterizer/setup_hold.py @@ -48,7 +48,7 @@ class setup_hold(): # instantiate the master-slave d-flip-flop self.sf.write("\n* Instantiation of the Master-Slave D-flip-flop\n") - self.stim.inst_model(pins=self.dff.get_ordered_inputs(self.dff.pins), + self.stim.inst_model(pins=self.dff.get_original_pin_names(), model_name=self.dff.cell_name) self.write_data(mode=mode,