diff --git a/compiler/base/custom_cell_properties.py b/compiler/base/custom_cell_properties.py index 2fab7a2a..d45bad10 100644 --- a/compiler/base/custom_cell_properties.py +++ b/compiler/base/custom_cell_properties.py @@ -8,30 +8,28 @@ class _cell: def __init__(self, port_order, port_types, port_map=None, hard_cell=True, boundary_layer="boundary"): + # Specifies if this is a hard (i.e. GDS) cell self._hard_cell = hard_cell self._boundary_layer = boundary_layer + # Specifies the port directions self._port_types_map = {x: y for (x, y) in zip(port_order, port_types)} + # Specifies a map from OpenRAM names to cell names # by default it is 1:1 if not port_map: - port_map = {x: x for x in port_order} + self._port_map = {x: x for x in port_order} # Update mapping of names - self._pins = _pins(port_map) self._port_order = port_order # Update ordered name list - self._port_names = [getattr(self._pins, x) for x in self._port_order] + self._port_names = [self._port_map[x] for x in self._port_order] # Update ordered type list - self._port_types = [self._port_types_map[x] for x in port_order] + self._port_types = [self._port_types_map[x] for x in self._port_order] - @property - def pin(self): - return self._pins - @property def hard_cell(self): return self._hard_cell diff --git a/compiler/base/design.py b/compiler/base/design.py index 8b2fe826..f90ea12c 100644 --- a/compiler/base/design.py +++ b/compiler/base/design.py @@ -35,9 +35,11 @@ class design(hierarchy_design): # This means it is a custom cell. # It could have properties and not be a hard cell too (e.g. dff_buf) if prop and prop.hard_cell: - # The pins get added from the spice file + # The pins get added from the spice file, so just check + # 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_names(prop.port_map) self.add_pin_types(prop.port_types) (width, height) = utils.get_libcell_size(self.cell_name, diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index a4e121f7..516b3988 100644 --- a/compiler/base/hierarchy_layout.py +++ b/compiler/base/hierarchy_layout.py @@ -39,12 +39,21 @@ class layout(): self.width = None self.height = None self.bounding_box = None - self.insts = [] # Holds module/cell layout instances - self.inst_names = set() # Set of names to check for duplicates - self.objs = [] # Holds all other objects (labels, geometries, etc) - self.pin_map = {} # Holds name->pin_layout map for all pins - self.visited = [] # List of modules we have already visited - self.is_library_cell = False # Flag for library cells + # Holds module/cell layout instances + self.insts = [] + # Set of names to check for duplicates + self.inst_names = set() + # Holds all other objects (labels, geometries, etc) + self.objs = [] + # This is a mapping of internal pin names to cell pin names + # If the key is not found, the internal pin names is assumed + self.pin_names = {} + # Holds name->pin_layout map for all pins + self.pin_map = {} + # List of modules we have already visited + self.visited = [] + # Flag for library cells + self.is_library_cell = False self.gds_read() @@ -54,8 +63,13 @@ class layout(): 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 ############################################################ @@ -311,23 +325,33 @@ class layout(): """ Return the pin or list of pins """ + if text in self.pin_names: + name = self.pin_names[text] + else: + name = text + try: - if len(self.pin_map[text]) > 1: + if len(self.pin_map[name]) > 1: debug.error("Should use a pin iterator since more than one pin {}".format(text), -1) # If we have one pin, return it and not the list. # Otherwise, should use get_pins() - any_pin = next(iter(self.pin_map[text])) + any_pin = next(iter(self.pin_map[name])) return any_pin except Exception: self.gds_write("missing_pin.gds") - debug.error("No pin found with name {0} on {1}. Saved as missing_pin.gds.".format(text, self.cell_name), -1) + debug.error("No pin found with name {0} on {1}. Saved as missing_pin.gds.".format(name, self.cell_name), -1) def get_pins(self, text): """ Return a pin list (instead of a single pin) """ - if text in self.pin_map.keys(): - return self.pin_map[text] + if text in self.pin_names: + name = self.pin_names[text] + else: + name = text + + if name in self.pin_map.keys(): + return self.pin_map[name] else: return set() diff --git a/compiler/bitcells/bitcell_1port.py b/compiler/bitcells/bitcell_1port.py index 947b9435..f3ff4d10 100644 --- a/compiler/bitcells/bitcell_1port.py +++ b/compiler/bitcells/bitcell_1port.py @@ -24,37 +24,35 @@ class bitcell_1port(bitcell_base.bitcell_base): def get_all_wl_names(self): """ Creates a list of all wordline pin names """ - row_pins = [props.bitcell_1port.pin.wl] + row_pins = ["wl"] return row_pins def get_all_bitline_names(self): """ Creates a list of all bitline pin names (both bl and br) """ - pin = props.bitcell_1port.pin - column_pins = [pin.bl, pin.br] - return column_pins + return ["bl", "br"] def get_all_bl_names(self): """ Creates a list of all bl pins names """ - return [props.bitcell_1port.pin.bl] + return ["bl"] def get_all_br_names(self): """ Creates a list of all br pins names """ - return [props.bitcell_1port.pin.br] + return ["br"] def get_bl_name(self, port=0): """Get bl name""" debug.check(port == 0, "One port for bitcell only.") - return props.bitcell_1port.pin.bl + return "bl" def get_br_name(self, port=0): """Get bl name""" debug.check(port == 0, "One port for bitcell only.") - return props.bitcell_1port.pin.br + return "br" def get_wl_name(self, port=0): """Get wl name""" debug.check(port == 0, "One port for bitcell only.") - return props.bitcell_1port.pin.wl + return "wl" def build_graph(self, graph, inst_name, port_nets): """ diff --git a/compiler/bitcells/bitcell_2port.py b/compiler/bitcells/bitcell_2port.py index a99f8219..4833d7c3 100644 --- a/compiler/bitcells/bitcell_2port.py +++ b/compiler/bitcells/bitcell_2port.py @@ -22,65 +22,56 @@ class bitcell_2port(bitcell_base.bitcell_base): super().__init__(name, prop=props.bitcell_2port) debug.info(2, "Create bitcell with 2 ports") - self.bl_names = [props.bitcell_2port.pin.bl0, props.bitcell_2port.pin.bl1] - self.br_names = [props.bitcell_2port.pin.br0, props.bitcell_2port.pin.br1] - self.wl_names = [props.bitcell_2port.pin.wl0, props.bitcell_2port.pin.wl1] + self.bl_names = ["bl0", "bl1"] + self.br_names = ["br0", "br1"] + self.wl_names = ["wl0", "wl1"] def get_bitcell_pins(self, col, row): """ Creates a list of connections in the bitcell, indexed by column and row, for instance use in bitcell_array """ - pin_name = props.bitcell_2port.pin - bitcell_pins = ["{0}_{1}".format(pin_name.bl0, col), - "{0}_{1}".format(pin_name.br0, col), - "{0}_{1}".format(pin_name.bl1, col), - "{0}_{1}".format(pin_name.br1, col), - "{0}_{1}".format(pin_name.wl0, row), - "{0}_{1}".format(pin_name.wl1, row), + bitcell_pins = ["bl0_{0}".format(col), + "br0_{0}".format(col), + "bl1_{0}".format(col), + "br1_{0}".format(col), + "wl0_{0}".format(row), + "wl1_{0}".format(row), "vdd", "gnd"] return bitcell_pins def get_all_wl_names(self): """ Creates a list of all wordline pin names """ - return [props.bitcell_2port.pin.wl0, - props.bitcell_2port.pin.wl1] + return self.wl_names def get_all_bitline_names(self): """ Creates a list of all bitline pin names (both bl and br) """ - return [props.bitcell_2port.pin.bl0, - props.bitcell_2port.pin.br0, - props.bitcell_2port.pin.bl1, - props.bitcell_2port.pin.br1] + return ["bl0", "br0", "bl1", "br1"] def get_all_bl_names(self): """ Creates a list of all bl pins names """ - return [props.bitcell_2port.pin.bl0, - props.bitcell_2port.pin.bl1] + return ["bl0", "bl1"] def get_all_br_names(self): """ Creates a list of all br pins names """ - return [props.bitcell_2port.pin.br0, - props.bitcell_2port.pin.br1] + return ["br0", "br1"] def get_read_bl_names(self): """ Creates a list of bl pin names associated with read ports """ - return [props.bitcell_2port.pin.bl0, - props.bitcell_2port.pin.bl1] + return ["bl0", "bl1"] def get_read_br_names(self): """ Creates a list of br pin names associated with read ports """ - return [props.bitcell_2port.pin.br0, - props.bitcell_2port.pin.br1] + return ["br0", "br1"] def get_write_bl_names(self): """ Creates a list of bl pin names associated with write ports """ - return [props.bitcell_2port.pin.bl0] + return ["bl0"] def get_write_br_names(self): """ Creates a list of br pin names asscociated with write ports""" - return [props.bitcell_2port.pin.br1] + return ["br1"] def get_bl_name(self, port=0): """Get bl name by port""" diff --git a/compiler/bitcells/bitcell_base.py b/compiler/bitcells/bitcell_base.py index 6ab81320..09f33482 100644 --- a/compiler/bitcells/bitcell_base.py +++ b/compiler/bitcells/bitcell_base.py @@ -26,9 +26,8 @@ class bitcell_base(design.design): self.nets_match = self.do_nets_exist(prop.storage_nets) self.mirror = prop.mirror self.end_caps = prop.end_caps - self.supplies = [prop.pin.vdd, prop.pin.gnd] - else: - self.supplies = ["vdd", "gnd"] + + self.supplies = ["vdd", "gnd"] def get_stage_effort(self, load): parasitic_delay = 1 diff --git a/compiler/bitcells/replica_bitcell_2port.py b/compiler/bitcells/replica_bitcell_2port.py index 2a3fbb48..0709ca10 100644 --- a/compiler/bitcells/replica_bitcell_2port.py +++ b/compiler/bitcells/replica_bitcell_2port.py @@ -42,11 +42,10 @@ class replica_bitcell_2port(bitcell_base.bitcell_base): """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)} - pins = props.bitcell_2port.pin # Edges hardcoded here. Essentially wl->bl/br for both ports. # Port 0 edges - graph.add_edge(pin_dict[pins.wl0], pin_dict[pins.bl0], self) - graph.add_edge(pin_dict[pins.wl0], pin_dict[pins.br0], self) + graph.add_edge(pin_dict["wl0"], pin_dict["bl0"], self) + graph.add_edge(pin_dict["wl0"], pin_dict["br0"], self) # Port 1 edges - graph.add_edge(pin_dict[pins.wl1], pin_dict[pins.bl1], self) - graph.add_edge(pin_dict[pins.wl1], pin_dict[pins.br1], self) + graph.add_edge(pin_dict["wl1"], pin_dict["bl1"], self) + graph.add_edge(pin_dict["wl1"], pin_dict["br1"], self) diff --git a/compiler/custom/sense_amp.py b/compiler/custom/sense_amp.py index 4376bf85..10156e2c 100644 --- a/compiler/custom/sense_amp.py +++ b/compiler/custom/sense_amp.py @@ -25,18 +25,18 @@ class sense_amp(design.design): debug.info(2, "Create sense_amp") def get_bl_names(self): - return props.sense_amp.pin.bl + return "bl" def get_br_names(self): - return props.sense_amp.pin.br + return "br" @property def dout_name(self): - return props.sense_amp.pin.dout + return "dout" @property def en_name(self): - return props.sense_amp.pin.en + return "en" def get_cin(self): diff --git a/compiler/custom/write_driver.py b/compiler/custom/write_driver.py index c30501c9..755fdb03 100644 --- a/compiler/custom/write_driver.py +++ b/compiler/custom/write_driver.py @@ -23,18 +23,18 @@ class write_driver(design.design): debug.info(2, "Create write_driver") def get_bl_names(self): - return props.write_driver.pin.bl + return "bl" def get_br_names(self): - return props.write_driver.pin.br + return "br" @property def din_name(self): - return props.write_driver.pin.din + return "din" @property def en_name(self): - return props.write_driver.pin.en + return "en" def get_w_en_cin(self): """Get the relative capacitance of a single input""" diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index 0402eba3..cbef7dfb 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -6,7 +6,6 @@ # All rights reserved. # import design -from tech import cell_properties as props import debug from sram_factory import factory import math diff --git a/compiler/modules/dff_array.py b/compiler/modules/dff_array.py index 6b708552..82746a06 100644 --- a/compiler/modules/dff_array.py +++ b/compiler/modules/dff_array.py @@ -7,7 +7,6 @@ # import debug import design -from tech import cell_properties as props from vector import vector from sram_factory import factory from globals import OPTS @@ -138,7 +137,7 @@ class dff_array(design.design): height=dout_pin.height()) # Create vertical spines to a single horizontal rail - clk_pin = self.dff_insts[0, 0].get_pin(props.dff.pin.clk) + clk_pin = self.dff_insts[0, 0].get_pin("clk") clk_ypos = 2 * self.m3_pitch + self.m3_width debug.check(clk_pin.layer == "m2", "DFF clk pin not on metal2") self.add_layout_pin_segment_center(text="clk", @@ -146,7 +145,7 @@ class dff_array(design.design): start=vector(0, clk_ypos), end=vector(self.width, clk_ypos)) for col in range(self.columns): - clk_pin = self.dff_insts[0, col].get_pin(props.dff.pin.clk) + clk_pin = self.dff_insts[0, col].get_pin("clk") # Make a vertical strip for each column self.add_rect(layer="m2", offset=clk_pin.ll().scale(1, 0), diff --git a/compiler/modules/dff_buf.py b/compiler/modules/dff_buf.py index a650214e..aea98ea5 100644 --- a/compiler/modules/dff_buf.py +++ b/compiler/modules/dff_buf.py @@ -72,6 +72,7 @@ class dff_buf(design.design): self.add_mod(self.inv2) def add_pins(self): + self.add_pin_names(props.dff_buf.port_map) self.add_pin_list(props.dff_buf.port_names, props.dff_buf.port_types) @@ -79,15 +80,15 @@ class dff_buf(design.design): self.dff_inst=self.add_inst(name="dff_buf_dff", mod=self.dff) - self.connect_inst([props.dff_buf.pin.D, "qint", props.dff_buf.pin.clk, props.dff_buf.pin.vdd, props.dff_buf.pin.gnd]) + self.connect_inst(["D", "qint", "clk", "vdd", "gnd"]) self.inv1_inst=self.add_inst(name="dff_buf_inv1", mod=self.inv1) - self.connect_inst(["qint", "Qb", props.dff_buf.pin.vdd, props.dff_buf.pin.gnd]) + self.connect_inst(["qint", "Qb", "vdd", "gnd"]) self.inv2_inst=self.add_inst(name="dff_buf_inv2", mod=self.inv2) - self.connect_inst(["Qb", props.dff_buf.pin.Q, props.dff_buf.pin.vdd, props.dff_buf.pin.gnd]) + self.connect_inst(["Qb", "Q", "vdd", "gnd"]) def place_instances(self): # Add the DFF @@ -121,7 +122,7 @@ class dff_buf(design.design): self.route_layer = "m1" # Route dff q to inv1 a - q_pin = self.dff_inst.get_pin(props.dff.pin.Q) + q_pin = self.dff_inst.get_pin("Q") a1_pin = self.inv1_inst.get_pin("A") mid1 = vector(a1_pin.cx(), q_pin.cy()) self.add_path(q_pin.layer, [q_pin.center(), mid1, a1_pin.center()], width=q_pin.height()) @@ -138,30 +139,30 @@ class dff_buf(design.design): def add_layout_pins(self): # Continous vdd rail along with label. - vdd_pin=self.dff_inst.get_pin(props.dff.pin.vdd) - self.add_layout_pin(text=props.dff_buf.pin.vdd, + vdd_pin=self.dff_inst.get_pin("vdd") + self.add_layout_pin(text="vdd", layer=vdd_pin.layer, offset=vdd_pin.ll(), width=self.width, height=vdd_pin.height()) # Continous gnd rail along with label. - gnd_pin=self.dff_inst.get_pin(props.dff.pin.gnd) - self.add_layout_pin(text=props.dff_buf.pin.gnd, + gnd_pin=self.dff_inst.get_pin("gnd") + self.add_layout_pin(text="gnd", layer=gnd_pin.layer, offset=gnd_pin.ll(), width=self.width, height=vdd_pin.height()) - clk_pin = self.dff_inst.get_pin(props.dff.pin.clk) - self.add_layout_pin(text=props.dff_buf.pin.clk, + clk_pin = self.dff_inst.get_pin("clk") + self.add_layout_pin(text="clk", layer=clk_pin.layer, offset=clk_pin.ll(), width=clk_pin.width(), height=clk_pin.height()) - din_pin = self.dff_inst.get_pin(props.dff_buf.pin.D) - self.add_layout_pin(text=props.dff_buf.pin.D, + din_pin = self.dff_inst.get_pin("D") + self.add_layout_pin(text="D", layer=din_pin.layer, offset=din_pin.ll(), width=din_pin.width(), @@ -170,7 +171,7 @@ class dff_buf(design.design): dout_pin = self.inv2_inst.get_pin("Z") mid_pos = dout_pin.center() + vector(self.m2_nonpref_pitch, 0) q_pos = mid_pos - vector(0, 2 * self.m2_nonpref_pitch) - self.add_layout_pin_rect_center(text=props.dff_buf.pin.Q, + self.add_layout_pin_rect_center(text="Q", layer="m2", offset=q_pos) self.add_path(self.route_layer, [dout_pin.center(), mid_pos, q_pos]) diff --git a/compiler/modules/dff_buf_array.py b/compiler/modules/dff_buf_array.py index dacc5451..ea811e76 100644 --- a/compiler/modules/dff_buf_array.py +++ b/compiler/modules/dff_buf_array.py @@ -7,7 +7,6 @@ # import debug import design -from tech import cell_properties as props from vector import vector from globals import OPTS from sram_factory import factory @@ -148,7 +147,7 @@ class dff_buf_array(design.design): def route_supplies(self): for row in range(self.rows): - vdd0_pin=self.dff_insts[row, 0].get_pin(props.dff.pin.vdd) + vdd0_pin=self.dff_insts[row, 0].get_pin("vdd") vddn_pin=self.dff_insts[row, self.columns - 1].get_pin("vdd") self.add_path(vdd0_pin.layer, [vdd0_pin.lc(), vddn_pin.rc()], width=vdd0_pin.height())