diff --git a/compiler/base/custom_cell_properties.py b/compiler/base/custom_cell_properties.py index eafad33a..5c5947d9 100644 --- a/compiler/base/custom_cell_properties.py +++ b/compiler/base/custom_cell_properties.py @@ -5,9 +5,49 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -from globals import OPTS +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 + # Specifies the order in the spice modules + self._port_order = port_order + # Specifies the port directions + self._port_types = port_types + # Specifies a map from OpenRAM names to cell names + # by default it is 1:1 + if not port_map: + port_map = {} + for pin in port_order: + port_map[pin] = pin + self._pins = _pins(port_map) + else: + self._pins = _pins(port_map) + self._port_names = [getattr(self._pins, x) for x in self._port_order] + self._boundary_layer = boundary_layer + + @property + def pin(self): + return self._pins + + @property + def hard_cell(self): + return self._hard_cell + + @property + def port_names(self): + return self._port_names + + @property + def port_types(self): + return self._port_types + + @property + def boundary_layer(self): + return self._boundary_layer + + class _pins: def __init__(self, pin_dict): # make the pins elements of the class to allow "." access. @@ -16,20 +56,6 @@ class _pins: self.__dict__[k] = v -class _cell: - def __init__(self, pin_dict): - pin_dict.update(self._default_power_pins()) - self._pins = _pins(pin_dict) - - @property - def pin(self): - return self._pins - - def _default_power_pins(self): - return {'vdd': 'vdd', - 'gnd': 'gnd'} - - class _mirror_axis: def __init__(self, x, y): self.x = x @@ -47,65 +73,38 @@ class _pgate: self.add_implants = add_implants -class _bitcell: - def __init__(self, mirror, cell_1port, cell_2port): - self.mirror = mirror - self._1rw = cell_1port - self._2rw = cell_2port +class _bitcell(_cell): + def __init__(self, port_order, port_types, port_map=None, storage_nets=["Q", "Q_bar"], mirror=None, end_caps=False): + super().__init__(port_order, port_types, port_map) - def _default(): - axis = _mirror_axis(True, False) - - cell_1port = _cell({'bl': 'bl', - 'br': 'br', - 'wl': 'wl'}) - - cell_2port = _cell({'bl0': 'bl0', - 'br0': 'br0', - 'bl1': 'bl1', - 'br1': 'br1', - 'wl0': 'wl0', - 'wl1': 'wl1'}) - - return _bitcell(cell_1port=cell_1port, - cell_2port=cell_2port, - mirror=axis) + self._end_caps = end_caps + + if not mirror: + self._mirror = _mirror_axis(True, False) + else: + self._mirror = mirror + self._storage_nets = storage_nets + @property - def cell_1port(self): - return self._1rw - + def end_caps(self): + return self._end_caps + @property - def cell_2port(self): - return self._2rw + def mirror(self): + return self._mirror + + @property + def storage_nets(self): + return self._storage_nets - -class _dff: - def __init__(self, use_custom_ports, custom_port_list, custom_type_list, clk_pin): - self.use_custom_ports = use_custom_ports - self.custom_port_list = custom_port_list - self.custom_type_list = custom_type_list + +class _dff(_cell): + def __init__(self, clk_pin, port_order, port_types, port_map=None, hard_cell=True): + super().__init__(port_order, port_types, port_map, hard_cell) self.clk_pin = clk_pin - -class _dff_buff: - def __init__(self, use_custom_ports, custom_buff_ports, add_body_contacts): - self.use_custom_ports = use_custom_ports - self.buf_ports = custom_buff_ports - self.add_body_contacts = add_body_contacts - - -class _dff_buff_array: - def __init__(self, use_custom_ports, add_body_contacts): - self.use_custom_ports = use_custom_ports - self.add_body_contacts = add_body_contacts - - -class _bitcell_array: - def __init__(self, use_custom_cell_arrangement): - self.use_custom_cell_arrangement = use_custom_cell_arrangement - - + class cell_properties(): """ This contains meta information about the custom designed cells. For @@ -125,41 +124,41 @@ class cell_properties(): self.names["col_cap_bitcell_2port"] = "col_cap_cell_2rw" self.names["row_cap_bitcell_1port"] = "row_cap_cell_1rw" self.names["row_cap_bitcell_2port"] = "row_cap_cell_2rw" - - self._bitcell = _bitcell._default() self._ptx = _ptx(model_is_subckt=False, bin_spice_models=False) self._pgate = _pgate(add_implants=False) - self._dff = _dff(use_custom_ports=False, - custom_port_list=["D", "Q", "clk", "vdd", "gnd"], - custom_type_list=["INPUT", "OUTPUT", "INPUT", "POWER", "GROUND"], - clk_pin="clk") + self._nand2_dec = _cell(["A", "B", "Z", "vdd", "gnd"], + ["INPUT", "INPUT", "OUTPUT", "POWER", "GROUND"]) + + self._nand2_dec = _cell(["A", "B", "C", "Z", "vdd", "gnd"], + ["INPUT", "INPUT", "INPUT", "OUTPUT", "POWER", "GROUND"]) + + self._nand2_dec = _cell(["A", "B", "C", "D", "Z", "vdd", "gnd"], + ["INPUT", "INPUT", "INPUT", "INPUT", "OUTPUT", "POWER", "GROUND"]) + + self._dff = _dff("clk", + ["D", "Q", "clk", "vdd", "gnd"], + ["INPUT", "OUTPUT", "INPUT", "POWER", "GROUND"]) - self._dff_buff = _dff_buff(use_custom_ports=False, - custom_buff_ports=["D", "qint", "clk", "vdd", "gnd"], - add_body_contacts=False) + self._dff_buf = _dff("clk", + ["D", "Q", "Qb", "clk", "vdd", "gnd"], + ["INPUT", "OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"], + hard_cell=False) + + self._write_driver = _cell(['din', 'bl', 'br', 'en', 'vdd', 'gnd'], + ["INPUT", "OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"]) - self._dff_buff_array = _dff_buff_array(use_custom_ports=False, - add_body_contacts=False) + self._sense_amp = _cell(['bl', 'br', 'dout', 'en', 'vdd', 'gnd'], + ["INPUT", "INPUT", "OUTPUT", "INPUT", "POWER", "GROUND"]) - self._write_driver = _cell({'din': 'din', - 'bl': 'bl', - 'br': 'br', - 'en': 'en'}) + self._bitcell_1port = _bitcell(["bl", "br", "wl", "vdd", "gnd"], + ["OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"]) - self._sense_amp = _cell({'bl': 'bl', - 'br': 'br', - 'dout': 'dout', - 'en': 'en'}) - - self._bitcell_array = _bitcell_array(use_custom_cell_arrangement=[]) - - @property - def bitcell(self): - return self._bitcell + self._bitcell_2port = _bitcell(["bl0", "br0", "bl1", "br1", "wl0", "wl1", "vdd", "gnd"], + ["OUTPUT", "OUTPUT", "OUTPUT", "OUTPUT", "INPUT", "INPUT", "POWER", "GROUND"]) @property def ptx(self): @@ -174,13 +173,9 @@ class cell_properties(): return self._dff @property - def dff_buff(self): - return self._dff_buff - - @property - def dff_buff_array(self): - return self._dff_buff_array - + def dff_buf(self): + return self._dff_buf + @property def write_driver(self): return self._write_driver @@ -190,13 +185,10 @@ class cell_properties(): return self._sense_amp @property - def bitcell_array(self): - return self._bitcell_array + def bitcell_1port(self): + return self._bitcell_1port + + @property + def bitcell_2port(self): + return self._bitcell_2port - def compare_ports(self, port_list): - use_custom_arrangement = False - for ports in port_list: - if ports == "{}R_{}W_{}RW".format(OPTS.num_r_ports, OPTS.num_w_ports, OPTS.num_rw_ports): - use_custom_arrangement = True - break - return use_custom_arrangement diff --git a/compiler/base/design.py b/compiler/base/design.py index 93169f6a..98c03981 100644 --- a/compiler/base/design.py +++ b/compiler/base/design.py @@ -6,8 +6,9 @@ # All rights reserved. # from hierarchy_design import hierarchy_design -from utils import round_to_grid +import utils import contact +from tech import GDS, layer from tech import preferred_directions from tech import cell_properties as props from globals import OPTS @@ -31,6 +32,26 @@ class design(hierarchy_design): cell_name = name super().__init__(name, cell_name) + # This means it is a custom cell... + if hasattr(props, name): + prop = getattr(props, name) + if prop.hard_cell: + # The pins get added from the spice file + 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_types(prop.port_types) + + (width, height) = utils.get_libcell_size(self.cell_name, + GDS["unit"], + layer[prop.boundary_layer]) + + self.pin_map = utils.get_libcell_pins(self.pins, + self.cell_name, + GDS["unit"]) + + self.width = width + self.height = height + self.setup_multiport_constants() def check_pins(self): @@ -232,8 +253,7 @@ class design(hierarchy_design): #print(contact1) pitch = contact_width + layer_space - return round_to_grid(pitch) - + return utils.round_to_grid(pitch) def setup_multiport_constants(self): """ diff --git a/compiler/base/hierarchy_spice.py b/compiler/base/hierarchy_spice.py index 340cf074..60d80513 100644 --- a/compiler/base/hierarchy_spice.py +++ b/compiler/base/hierarchy_spice.py @@ -78,6 +78,7 @@ class spice(): """ Adds a pin_list to the pins list """ # The type list can be a single type for all pins # or a list that is the same length as the pin list. + if type(pin_type)==str: for pin in pin_list: debug.check(pin_type in self.valid_signal_types, @@ -100,12 +101,12 @@ class spice(): Typically, should only be used for handmade cells. """ # This only works if self.pins == bitcell.pin_names - if self.pin_names != self.pins: - debug.error("{} spice subcircuit port names do not match pin_names\ + if len(type_list) != len(self.pins): + debug.error("{} spice subcircuit number of port types does not match number of pins\ \n SPICE names={}\ \n Module names={}\ - ".format(self.name, self.pins, self.pin_names), 1) - self.pin_type = {pin: type for pin, type in zip(self.pin_names, type_list)} + ".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. """ diff --git a/compiler/bitcells/bitcell_1port.py b/compiler/bitcells/bitcell_1port.py index 83098c55..e8f330f1 100644 --- a/compiler/bitcells/bitcell_1port.py +++ b/compiler/bitcells/bitcell_1port.py @@ -18,53 +18,43 @@ class bitcell_1port(bitcell_base.bitcell_base): library. """ - pin_names = [props.bitcell.cell_1port.pin.bl, - props.bitcell.cell_1port.pin.br, - props.bitcell.cell_1port.pin.wl, - props.bitcell.cell_1port.pin.vdd, - props.bitcell.cell_1port.pin.gnd] - type_list = ["OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"] - storage_nets = ['Q', 'Q_bar'] - def __init__(self, name): - super().__init__(name) + super().__init__(name, props.bitcell_1port) debug.info(2, "Create bitcell") - self.nets_match = self.do_nets_exist(self.storage_nets) - def get_all_wl_names(self): """ Creates a list of all wordline pin names """ - row_pins = [props.bitcell.cell_1port.pin.wl] + row_pins = [props.bitcell_1port.pin.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.cell_1port.pin + pin = props.bitcell_1port.pin column_pins = [pin.bl, pin.br] return column_pins def get_all_bl_names(self): """ Creates a list of all bl pins names """ - return [props.bitcell.cell_1port.pin.bl] + return [props.bitcell_1port.pin.bl] def get_all_br_names(self): """ Creates a list of all br pins names """ - return [props.bitcell.cell_1port.pin.br] + return [props.bitcell_1port.pin.br] def get_bl_name(self, port=0): """Get bl name""" debug.check(port == 0, "One port for bitcell only.") - return props.bitcell.cell_1port.pin.bl + return props.bitcell_1port.pin.bl def get_br_name(self, port=0): """Get bl name""" debug.check(port == 0, "One port for bitcell only.") - return props.bitcell.cell_1port.pin.br + return props.bitcell_1port.pin.br def get_wl_name(self, port=0): """Get wl name""" debug.check(port == 0, "One port for bitcell only.") - return props.bitcell.cell_1port.pin.wl + return props.bitcell_1port.pin.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 827a23b0..2293cb71 100644 --- a/compiler/bitcells/bitcell_2port.py +++ b/compiler/bitcells/bitcell_2port.py @@ -18,35 +18,20 @@ class bitcell_2port(bitcell_base.bitcell_base): library. """ - pin_names = [props.bitcell.cell_2port.pin.bl0, - props.bitcell.cell_2port.pin.br0, - props.bitcell.cell_2port.pin.bl1, - props.bitcell.cell_2port.pin.br1, - props.bitcell.cell_2port.pin.wl0, - props.bitcell.cell_2port.pin.wl1, - props.bitcell.cell_2port.pin.vdd, - props.bitcell.cell_2port.pin.gnd] - type_list = ["OUTPUT", "OUTPUT", "OUTPUT", "OUTPUT", - "INPUT", "INPUT", "POWER", "GROUND"] - storage_nets = ['Q', 'Q_bar'] - def __init__(self, name): - super().__init__(name) + super().__init__(name, props.bitcell_2port) debug.info(2, "Create bitcell with 2 ports") - self.nets_match = self.do_nets_exist(self.storage_nets) - - pin_names = self.pin_names - self.bl_names = [pin_names[0], pin_names[2]] - self.br_names = [pin_names[1], pin_names[3]] - self.wl_names = [pin_names[4], pin_names[5]] + 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] 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.cell_2port.pin + 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), @@ -59,43 +44,43 @@ class bitcell_2port(bitcell_base.bitcell_base): def get_all_wl_names(self): """ Creates a list of all wordline pin names """ - return [props.bitcell.cell_2port.pin.wl0, - props.bitcell.cell_2port.pin.wl1] + return [props.bitcell_2port.pin.wl0, + props.bitcell_2port.pin.wl1] def get_all_bitline_names(self): """ Creates a list of all bitline pin names (both bl and br) """ - return [props.bitcell.cell_2port.pin.bl0, - props.bitcell.cell_2port.pin.br0, - props.bitcell.cell_2port.pin.bl1, - props.bitcell.cell_2port.pin.br1] + return [props.bitcell_2port.pin.bl0, + props.bitcell_2port.pin.br0, + props.bitcell_2port.pin.bl1, + props.bitcell_2port.pin.br1] def get_all_bl_names(self): """ Creates a list of all bl pins names """ - return [props.bitcell.cell_2port.pin.bl0, - props.bitcell.cell_2port.pin.bl1] + return [props.bitcell_2port.pin.bl0, + props.bitcell_2port.pin.bl1] def get_all_br_names(self): """ Creates a list of all br pins names """ - return [props.bitcell.cell_2port.pin.br0, - props.bitcell.cell_2port.pin.br1] + return [props.bitcell_2port.pin.br0, + props.bitcell_2port.pin.br1] def get_read_bl_names(self): """ Creates a list of bl pin names associated with read ports """ - return [props.bitcell.cell_2port.pin.bl0, - props.bitcell.cell_2port.pin.bl1] + return [props.bitcell_2port.pin.bl0, + props.bitcell_2port.pin.bl1] def get_read_br_names(self): """ Creates a list of br pin names associated with read ports """ - return [props.bitcell.cell_2port.pin.br0, - props.bitcell.cell_2port.pin.br1] + return [props.bitcell_2port.pin.br0, + props.bitcell_2port.pin.br1] def get_write_bl_names(self): """ Creates a list of bl pin names associated with write ports """ - return [props.bitcell.cell_2port.pin.bl0] + return [props.bitcell_2port.pin.bl0] def get_write_br_names(self): """ Creates a list of br pin names asscociated with write ports""" - return [props.bitcell.cell_2port.pin.br1] + return [props.bitcell_2port.pin.br1] def get_bl_name(self, port=0): """Get bl name by port""" @@ -118,7 +103,7 @@ class bitcell_2port(bitcell_base.bitcell_base): 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 - pins = props.bitcell.cell_2port.pin + pins = props.bitcell_2port.pin graph.add_edge(pin_dict[pins.wl0], pin_dict[pins.bl0], self) graph.add_edge(pin_dict[pins.wl0], pin_dict[pins.br0], self) # Port 1 edges diff --git a/compiler/bitcells/bitcell_base.py b/compiler/bitcells/bitcell_base.py index 5ae468b2..0e821774 100644 --- a/compiler/bitcells/bitcell_base.py +++ b/compiler/bitcells/bitcell_base.py @@ -18,19 +18,22 @@ class bitcell_base(design.design): """ Base bitcell parameters to be over-riden. """ - cell_size_layer = "boundary" - - def __init__(self, name, hard_cell=True): + def __init__(self, name, prop=None): design.design.__init__(self, name) - if hard_cell: + if prop: + self.pins = prop.port_names + self.add_pin_types(prop.port_types) + self.nets_match = self.do_nets_exist(prop.storage_nets) + self.mirror = prop.mirror + self.end_caps = prop.end_caps + (self.width, self.height) = utils.get_libcell_size(self.cell_name, GDS["unit"], - layer[self.cell_size_layer]) - self.pin_map = utils.get_libcell_pins(self.pin_names, + layer[prop.boundary_layer]) + self.pin_map = utils.get_libcell_pins(self.pins, self.cell_name, GDS["unit"]) - self.add_pin_types(self.type_list) def get_stage_effort(self, load): parasitic_delay = 1 diff --git a/compiler/bitcells/dummy_bitcell_1port.py b/compiler/bitcells/dummy_bitcell_1port.py index 5b54ff04..c6f98536 100644 --- a/compiler/bitcells/dummy_bitcell_1port.py +++ b/compiler/bitcells/dummy_bitcell_1port.py @@ -17,15 +17,8 @@ class dummy_bitcell_1port(bitcell_base.bitcell_base): the layout and netlist should be available in the technology library. """ - pin_names = [props.bitcell.cell_1port.pin.bl, - props.bitcell.cell_1port.pin.br, - props.bitcell.cell_1port.pin.wl, - props.bitcell.cell_1port.pin.vdd, - props.bitcell.cell_1port.pin.gnd] - type_list = ["OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"] - def __init__(self, name): - super().__init__(name) + super().__init__(name, props.bitcell_1port) debug.info(2, "Create dummy bitcell") diff --git a/compiler/bitcells/dummy_bitcell_2port.py b/compiler/bitcells/dummy_bitcell_2port.py index 64ca08fb..4d6d5c49 100644 --- a/compiler/bitcells/dummy_bitcell_2port.py +++ b/compiler/bitcells/dummy_bitcell_2port.py @@ -17,19 +17,8 @@ class dummy_bitcell_2port(bitcell_base.bitcell_base): is a hand-made cell, so the layout and netlist should be available in the technology library. """ - pin_names = [props.bitcell.cell_2port.pin.bl0, - props.bitcell.cell_2port.pin.br0, - props.bitcell.cell_2port.pin.bl1, - props.bitcell.cell_2port.pin.br1, - props.bitcell.cell_2port.pin.wl0, - props.bitcell.cell_2port.pin.wl1, - props.bitcell.cell_2port.pin.vdd, - props.bitcell.cell_2port.pin.gnd] - type_list = ["OUTPUT", "OUTPUT", "OUTPUT", "OUTPUT", - "INPUT", "INPUT", "POWER", "GROUND"] - def __init__(self, name): - super().__init__(name) + super().__init__(name, props.bitcel_2port) debug.info(2, "Create dummy bitcell 2 port object") diff --git a/compiler/bitcells/pbitcell.py b/compiler/bitcells/pbitcell.py index 120bb48e..61360e99 100644 --- a/compiler/bitcells/pbitcell.py +++ b/compiler/bitcells/pbitcell.py @@ -8,6 +8,7 @@ import contact import debug from tech import drc, parameter, layer +from tech import cell_properties as props from vector import vector from ptx import ptx from globals import OPTS @@ -29,8 +30,9 @@ class pbitcell(bitcell_base.bitcell_base): self.replica_bitcell = replica_bitcell self.dummy_bitcell = dummy_bitcell + self.mirror = props.bitcell_1port.mirror - bitcell_base.bitcell_base.__init__(self, name, hard_cell=False) + bitcell_base.bitcell_base.__init__(self, name) fmt_str = "{0} rw ports, {1} w ports and {2} r ports" info_string = fmt_str.format(self.num_rw_ports, self.num_w_ports, diff --git a/compiler/bitcells/replica_bitcell_1port.py b/compiler/bitcells/replica_bitcell_1port.py index 92b74c24..1f2826ec 100644 --- a/compiler/bitcells/replica_bitcell_1port.py +++ b/compiler/bitcells/replica_bitcell_1port.py @@ -19,15 +19,8 @@ class replica_bitcell_1port(bitcell_base.bitcell_base): is a hand-made cell, so the layout and netlist should be available in the technology library. """ - pin_names = [props.bitcell.cell_1port.pin.bl, - props.bitcell.cell_1port.pin.br, - props.bitcell.cell_1port.pin.wl, - props.bitcell.cell_1port.pin.vdd, - props.bitcell.cell_1port.pin.gnd] - type_list = ["OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"] - def __init__(self, name): - super().__init__(name) + super().__init__(name, props.bitcell_1port) debug.info(2, "Create replica bitcell object") def get_stage_effort(self, load): diff --git a/compiler/bitcells/replica_bitcell_2port.py b/compiler/bitcells/replica_bitcell_2port.py index bc95ba25..d5922b80 100644 --- a/compiler/bitcells/replica_bitcell_2port.py +++ b/compiler/bitcells/replica_bitcell_2port.py @@ -19,18 +19,8 @@ class replica_bitcell_2port(bitcell_base.bitcell_base): is a hand-made cell, so the layout and netlist should be available in the technology library. """ - pin_names = [props.bitcell.cell_2port.pin.bl0, - props.bitcell.cell_2port.pin.br0, - props.bitcell.cell_2port.pin.bl1, - props.bitcell.cell_2port.pin.br1, - props.bitcell.cell_2port.pin.wl0, - props.bitcell.cell_2port.pin.wl1, - props.bitcell.cell_2port.pin.vdd, - props.bitcell.cell_2port.pin.gnd] - type_list = ["OUTPUT", "OUTPUT", "OUTPUT", "OUTPUT", "INPUT", "INPUT", "POWER", "GROUND"] - def __init__(self, name): - super().__init__(name) + super().__init__(name, props.bitcell_2port) debug.info(2, "Create replica bitcell 2 port object") def get_stage_effort(self, load): diff --git a/compiler/custom/dff.py b/compiler/custom/dff.py index 38e3bd75..36000ac5 100644 --- a/compiler/custom/dff.py +++ b/compiler/custom/dff.py @@ -6,40 +6,19 @@ # All rights reserved. # import design -from tech import GDS, layer, spice +from tech import spice from tech import cell_properties as props -import utils class dff(design.design): """ Memory address flip-flop """ - if not props.dff.use_custom_ports: - pin_names = ["D", "Q", "clk", "vdd", "gnd"] - type_list = ["INPUT", "OUTPUT", "INPUT", "POWER", "GROUND"] - clk_pin = "clk" - else: - pin_names = props.dff.custom_port_list - type_list = props.dff.custom_type_list - clk_pin = props.dff.clk_pin - cell_size_layer = "boundary" def __init__(self, name="dff"): super().__init__(name) - (width, height) = utils.get_libcell_size(self.cell_name, - GDS["unit"], - layer[self.cell_size_layer]) - - pin_map = utils.get_libcell_pins(self.pin_names, - self.cell_name, - GDS["unit"]) - - self.width = width - self.height = height - self.pin_map = pin_map - self.add_pin_types(self.type_list) + self.clk_pin = props.dff.clk_pin def analytical_power(self, corner, load): """Returns dynamic and leakage power. Results in nW""" @@ -54,9 +33,9 @@ class dff(design.design): def calculate_effective_capacitance(self, load): """Computes effective capacitance. Results in fF""" c_load = load - c_para = spice["dff_out_cap"]#ff + c_para = spice["dff_out_cap"] # ff transition_prob = 0.5 - return transition_prob*(c_load + c_para) + return transition_prob * (c_load + c_para) def build_graph(self, graph, inst_name, port_nets): """Adds edges based on inputs/outputs. Overrides base class function.""" diff --git a/compiler/custom/inv_dec.py b/compiler/custom/inv_dec.py index b150a38e..be4099aa 100644 --- a/compiler/custom/inv_dec.py +++ b/compiler/custom/inv_dec.py @@ -6,9 +6,8 @@ # All rights reserved. # import design -from tech import GDS, layer, spice, parameter import logical_effort -import utils +from tech import spice, parameter class inv_dec(design.design): @@ -16,26 +15,9 @@ class inv_dec(design.design): INV for address decoders. """ - pin_names = ["A", "Z", "vdd", "gnd"] - type_list = ["INPUT", "OUTPUT", "POWER", "GROUND"] - cell_size_layer = "boundary" - def __init__(self, name="inv_dec", height=None): super().__init__(name) - (width, height) = utils.get_libcell_size(self.cell_name, - GDS["unit"], - layer[self.cell_size_layer]) - - pin_map = utils.get_libcell_pins(self.pin_names, - self.cell_name, - GDS["unit"]) - - self.width = width - self.height = height - self.pin_map = pin_map - self.add_pin_types(self.type_list) - def analytical_power(self, corner, load): """Returns dynamic and leakage power. Results in nW""" c_eff = self.calculate_effective_capacitance(load) @@ -52,7 +34,7 @@ class inv_dec(design.design): # In fF c_para = spice["min_tx_drain_c"] * (self.nmos_size / parameter["min_tx_size"]) - return transition_prob * (c_load + c_para) + return 0.5 * (c_load + c_para) def input_load(self): """ diff --git a/compiler/custom/nand2_dec.py b/compiler/custom/nand2_dec.py index efec63b6..2ea07ed6 100644 --- a/compiler/custom/nand2_dec.py +++ b/compiler/custom/nand2_dec.py @@ -6,9 +6,8 @@ # All rights reserved. # import design -from tech import GDS, layer, spice, parameter, drc +from tech import spice, parameter, drc import logical_effort -import utils class nand2_dec(design.design): @@ -16,26 +15,9 @@ class nand2_dec(design.design): 2-input NAND decoder for address decoders. """ - pin_names = ["A", "B", "Z", "vdd", "gnd"] - type_list = ["INPUT", "INPUT", "OUTPUT", "POWER", "GROUND"] - cell_size_layer = "boundary" - def __init__(self, name="nand2_dec", height=None): super().__init__(name) - (width, height) = utils.get_libcell_size(self.cell_name, - GDS["unit"], - layer[self.cell_size_layer]) - - pin_map = utils.get_libcell_pins(self.pin_names, - self.cell_name, - GDS["unit"]) - - self.width = width - self.height = height - self.pin_map = pin_map - self.add_pin_types(self.type_list) - # FIXME: For now... size = 1 self.size = size diff --git a/compiler/custom/nand3_dec.py b/compiler/custom/nand3_dec.py index 3fc2b949..d362e2d6 100644 --- a/compiler/custom/nand3_dec.py +++ b/compiler/custom/nand3_dec.py @@ -6,9 +6,8 @@ # All rights reserved. # import design -from tech import GDS, layer, spice, parameter, drc +from tech import spice, parameter, drc import logical_effort -import utils class nand3_dec(design.design): @@ -16,26 +15,9 @@ class nand3_dec(design.design): 3-input NAND decoder for address decoders. """ - pin_names = ["A", "B", "C", "Z", "vdd", "gnd"] - type_list = ["INPUT", "INPUT", "INPUT", "OUTPUT", "POWER", "GROUND"] - cell_size_layer = "boundary" - def __init__(self, name="nand3_dec", height=None): super().__init__(name) - (width, height) = utils.get_libcell_size(self.cell_name, - GDS["unit"], - layer[self.cell_size_layer]) - - pin_map = utils.get_libcell_pins(self.pin_names, - self.cell_name, - GDS["unit"]) - - self.width = width - self.height = height - self.pin_map = pin_map - self.add_pin_types(self.type_list) - # FIXME: For now... size = 1 self.size = size diff --git a/compiler/custom/nand4_dec.py b/compiler/custom/nand4_dec.py index abcfd2f3..0df86845 100644 --- a/compiler/custom/nand4_dec.py +++ b/compiler/custom/nand4_dec.py @@ -6,36 +6,18 @@ # All rights reserved. # import design -from tech import GDS, layer, spice, parameter, drc +from tech import spice, parameter, drc import logical_effort -import utils class nand4_dec(design.design): """ - 2-input NAND decoder for address decoders. + 4-input NAND decoder for address decoders. """ - pin_names = ["A", "B", "C", "D", "Z", "vdd", "gnd"] - type_list = ["INPUT", "INPUT", "INPUT", "INPUT", "OUTPUT", "POWER", "GROUND"] - cell_size_layer = "boundary" - def __init__(self, name="nand4_dec", height=None): super().__init__(name) - (width, height) = utils.get_libcell_size(self.cell_name, - GDS["unit"], - layer[self.cell_size_layer]) - - pin_map = utils.get_libcell_pins(self.pin_names, - self.cell_name, - GDS["unit"]) - - self.width = width - self.height = height - self.pin_map = pin_map - self.add_pin_types(self.type_list) - # FIXME: For now... size = 1 self.size = size diff --git a/compiler/custom/sense_amp.py b/compiler/custom/sense_amp.py index 4e84b7fe..61ab39a5 100644 --- a/compiler/custom/sense_amp.py +++ b/compiler/custom/sense_amp.py @@ -7,8 +7,7 @@ # import design import debug -import utils -from tech import GDS, layer, parameter, drc +from tech import parameter, drc from tech import cell_properties as props import logical_effort @@ -20,32 +19,11 @@ class sense_amp(design.design): the technology library. Sense amplifier to read a pair of bit-lines. """ - pin_names = [props.sense_amp.pin.bl, - props.sense_amp.pin.br, - props.sense_amp.pin.dout, - props.sense_amp.pin.en, - props.sense_amp.pin.vdd, - props.sense_amp.pin.gnd] - type_list = ["INPUT", "INPUT", "OUTPUT", "INPUT", "POWER", "GROUND"] - cell_size_layer = "boundary" def __init__(self, name="sense_amp"): super().__init__(name) debug.info(2, "Create sense_amp") - (width, height) = utils.get_libcell_size(self.cell_name, - GDS["unit"], - layer[self.cell_size_layer]) - - pin_map = utils.get_libcell_pins(self.pin_names, - self.cell_name, - GDS["unit"]) - - self.width = width - self.height = height - self.pin_map = pin_map - self.add_pin_types(self.type_list) - def get_bl_names(self): return props.sense_amp.pin.bl diff --git a/compiler/custom/tri_gate.py b/compiler/custom/tri_gate.py index 476cc886..6be58104 100644 --- a/compiler/custom/tri_gate.py +++ b/compiler/custom/tri_gate.py @@ -7,8 +7,7 @@ # import debug import design -import utils -from tech import GDS, layer +from tech import spice class tri_gate(design.design): @@ -18,10 +17,6 @@ class tri_gate(design.design): netlist should be available in the technology library. """ - pin_names = ["in", "out", "en", "en_bar", "vdd", "gnd"] - type_list = ["INPUT", "OUTPUT", "INPUT", "INPUT", "POWER", "GROUND"] - cell_size_layer = "boundary" - unique_id = 1 def __init__(self, name=""): @@ -31,19 +26,6 @@ class tri_gate(design.design): super().__init__(self, name) debug.info(2, "Create tri_gate") - (width, height) = utils.get_libcell_size(self.cell_name, - GDS["unit"], - layer[self.cell_size_layer]) - - pin_map = utils.get_libcell_pins(self.pin_names, - self.cell_name, - GDS["unit"]) - - self.width = width - self.height = height - self.pin_map = pin_map - self.add_pin_types(self.type_list) - def analytical_power(self, corner, load): """Returns dynamic and leakage power. Results in nW""" #Power in this module currently not defined. Returns 0 nW (leakage and dynamic). @@ -51,7 +33,7 @@ class tri_gate(design.design): return total_power def get_cin(self): - return 9*spice["min_tx_gate_c"] + return 9 * spice["min_tx_gate_c"] def build_graph(self, graph, inst_name, port_nets): """Adds edges based on inputs/outputs. Overrides base class function.""" diff --git a/compiler/custom/write_driver.py b/compiler/custom/write_driver.py index 41375ab3..bcef46e1 100644 --- a/compiler/custom/write_driver.py +++ b/compiler/custom/write_driver.py @@ -7,8 +7,6 @@ # import debug import design -import utils -from tech import GDS, layer from tech import cell_properties as props @@ -20,33 +18,10 @@ class write_driver(design.design): the technology library. """ - pin_names = [props.write_driver.pin.din, - props.write_driver.pin.bl, - props.write_driver.pin.br, - props.write_driver.pin.en, - props.write_driver.pin.vdd, - props.write_driver.pin.gnd] - - type_list = ["INPUT", "OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"] - cell_size_layer = "boundary" - def __init__(self, name): super().__init__(name) debug.info(2, "Create write_driver") - (width, height) = utils.get_libcell_size(self.cell_name, - GDS["unit"], - layer[self.cell_size_layer]) - - pin_map = utils.get_libcell_pins(self.pin_names, - self.cell_name, - GDS["unit"]) - - self.width = width - self.height = height - self.pin_map = pin_map - self.add_pin_types(self.type_list) - def get_bl_names(self): return props.write_driver.pin.bl @@ -64,7 +39,7 @@ class write_driver(design.design): def get_w_en_cin(self): """Get the relative capacitance of a single input""" # This is approximated from SCMOS. It has roughly 5 3x transistor gates. - return 5*3 + return 5 * 3 def build_graph(self, graph, inst_name, port_nets): """Adds edges based on inputs/outputs. Overrides base class function.""" diff --git a/compiler/modules/bitcell_base_array.py b/compiler/modules/bitcell_base_array.py index b1ee88a4..95e8a4ec 100644 --- a/compiler/modules/bitcell_base_array.py +++ b/compiler/modules/bitcell_base_array.py @@ -7,7 +7,6 @@ # import debug import design -from tech import cell_properties from sram_factory import factory from globals import OPTS @@ -174,7 +173,7 @@ class bitcell_base_array(design.design): tempx = xoffset dir_y = False # If we mirror the current cell on the y axis adjust the x position - if cell_properties.bitcell.mirror.y and (col + col_offset) % 2: + if self.cell.mirror.y and (col + col_offset) % 2: tempx = xoffset + self.cell.width dir_y = True return (tempx, dir_y) @@ -183,7 +182,7 @@ class bitcell_base_array(design.design): tempy = yoffset dir_x = False # If we mirror the current cell on the x axis adjust the y position - if cell_properties.bitcell.mirror.x and (row + row_offset) % 2: + if self.cell.mirror.x and (row + row_offset) % 2: tempy = yoffset + self.cell.height dir_x = True return (tempy, dir_x) diff --git a/compiler/modules/col_cap_array.py b/compiler/modules/col_cap_array.py index ffbf6413..6bc77805 100644 --- a/compiler/modules/col_cap_array.py +++ b/compiler/modules/col_cap_array.py @@ -26,12 +26,9 @@ class col_cap_array(bitcell_base_array): def create_netlist(self): """ Create and connect the netlist """ # This will create a default set of bitline/wordline names - try: - end_caps_enabled = cell_properties.bitcell.end_caps - except AttributeError: - end_caps_enabled = False + self.cell = factory.create(module_type=OPTS.bitcell) - if not end_caps_enabled: + if not self.cell.end_caps: self.create_all_wordline_names() self.create_all_bitline_names() @@ -51,8 +48,6 @@ class col_cap_array(bitcell_base_array): self.dummy_cell = factory.create(module_type="col_cap_{}".format(OPTS.bitcell)) self.add_mod(self.dummy_cell) - self.cell = factory.create(module_type=OPTS.bitcell) - def create_instances(self): """ Create the module instances used in this design """ self.cell_inst = {} diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index b0620a38..0402eba3 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -662,9 +662,6 @@ class control_logic(design.design): self.ctrl_dff_inst=self.add_inst(name="ctrl_dffs", mod=self.ctrl_dff_array) inst_pins = self.input_list + self.dff_output_list + ["clk_buf"] + self.supply_list - if props.dff_buff_array.add_body_contacts: - inst_pins.append("vpb") - inst_pins.append("vnb") self.connect_inst(inst_pins) def place_dffs(self): diff --git a/compiler/modules/dff_array.py b/compiler/modules/dff_array.py index 0cbe8fe5..a2ea7eeb 100644 --- a/compiler/modules/dff_array.py +++ b/compiler/modules/dff_array.py @@ -70,7 +70,7 @@ class dff_array(design.design): mod=self.dff) instance_ports = [self.get_din_name(row, col), self.get_dout_name(row, col)] - for port in self.dff.pin_names: + for port in self.dff.pins: if port != 'D' and port != 'Q': instance_ports.append(port) self.connect_inst(instance_ports) diff --git a/compiler/modules/dff_buf.py b/compiler/modules/dff_buf.py index b218a9bb..a650214e 100644 --- a/compiler/modules/dff_buf.py +++ b/compiler/modules/dff_buf.py @@ -72,30 +72,22 @@ class dff_buf(design.design): self.add_mod(self.inv2) def add_pins(self): - self.add_pin("D", "INPUT") - self.add_pin("Q", "OUTPUT") - self.add_pin("Qb", "OUTPUT") - self.add_pin("clk", "INPUT") - self.add_pin("vdd", "POWER") - self.add_pin("gnd", "GROUND") - - if props.dff_buff.add_body_contacts: - self.add_pin("vpb", "INPUT") - self.add_pin("vpn", "INPUT") + self.add_pin_list(props.dff_buf.port_names, + props.dff_buf.port_types) def create_instances(self): self.dff_inst=self.add_inst(name="dff_buf_dff", mod=self.dff) - self.connect_inst(["D", "qint", "clk", "vdd", "gnd"]) + 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.inv1_inst=self.add_inst(name="dff_buf_inv1", mod=self.inv1) - self.connect_inst(["qint", "Qb", "vdd", "gnd"]) + self.connect_inst(["qint", "Qb", props.dff_buf.pin.vdd, props.dff_buf.pin.gnd]) self.inv2_inst=self.add_inst(name="dff_buf_inv2", mod=self.inv2) - self.connect_inst(["Qb", "Q", "vdd", "gnd"]) + self.connect_inst(["Qb", props.dff_buf.pin.Q, props.dff_buf.pin.vdd, props.dff_buf.pin.gnd]) def place_instances(self): # Add the DFF @@ -129,7 +121,7 @@ class dff_buf(design.design): self.route_layer = "m1" # Route dff q to inv1 a - q_pin = self.dff_inst.get_pin("Q") + q_pin = self.dff_inst.get_pin(props.dff.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()) @@ -146,30 +138,30 @@ class dff_buf(design.design): def add_layout_pins(self): # Continous vdd rail along with label. - vdd_pin=self.dff_inst.get_pin("vdd") - self.add_layout_pin(text="vdd", + vdd_pin=self.dff_inst.get_pin(props.dff.pin.vdd) + self.add_layout_pin(text=props.dff_buf.pin.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("gnd") - self.add_layout_pin(text="gnd", + gnd_pin=self.dff_inst.get_pin(props.dff.pin.gnd) + self.add_layout_pin(text=props.dff_buf.pin.gnd, layer=gnd_pin.layer, offset=gnd_pin.ll(), width=self.width, height=vdd_pin.height()) - clk_pin = self.dff_inst.get_pin("clk") - self.add_layout_pin(text="clk", + clk_pin = self.dff_inst.get_pin(props.dff.pin.clk) + self.add_layout_pin(text=props.dff_buf.pin.clk, layer=clk_pin.layer, offset=clk_pin.ll(), width=clk_pin.width(), height=clk_pin.height()) - din_pin = self.dff_inst.get_pin("D") - self.add_layout_pin(text="D", + din_pin = self.dff_inst.get_pin(props.dff_buf.pin.D) + self.add_layout_pin(text=props.dff_buf.pin.D, layer=din_pin.layer, offset=din_pin.ll(), width=din_pin.width(), @@ -178,7 +170,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="Q", + self.add_layout_pin_rect_center(text=props.dff_buf.pin.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 2d885ccc..dacc5451 100644 --- a/compiler/modules/dff_buf_array.py +++ b/compiler/modules/dff_buf_array.py @@ -65,10 +65,6 @@ class dff_buf_array(design.design): self.add_pin("vdd", "POWER") self.add_pin("gnd", "GROUND") - if props.dff_buff_array.add_body_contacts: - self.add_pin("vpb", "INPUT") - self.add_pin("vnb", "INPUT") - def add_modules(self): self.dff = factory.create(module_type="dff_buf", inv1_size=self.inv1_size, @@ -88,9 +84,6 @@ class dff_buf_array(design.design): "clk", "vdd", "gnd"] - if props.dff_buff_array.add_body_contacts: - inst_ports.append("vpb") - inst_ports.append("vnb") self.connect_inst(inst_ports) def place_dff_array(self): @@ -155,7 +148,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("vdd") + vdd0_pin=self.dff_insts[row, 0].get_pin(props.dff.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()) diff --git a/compiler/modules/precharge_array.py b/compiler/modules/precharge_array.py index a9cf2824..590dadce 100644 --- a/compiler/modules/precharge_array.py +++ b/compiler/modules/precharge_array.py @@ -10,7 +10,6 @@ import debug from vector import vector from sram_factory import factory from globals import OPTS -from tech import cell_properties class precharge_array(design.design): @@ -79,6 +78,8 @@ class precharge_array(design.design): bitcell_br=self.bitcell_br) self.add_mod(self.pc_cell) + self.cell = factory.create(module_type=OPTS.bitcell) + def add_layout_pins(self): en_pin = self.pc_cell.get_pin("en_bar") @@ -120,7 +121,7 @@ class precharge_array(design.design): self.offsets = [n * self.pc_cell.width for n in range(self.columns)] for i, xoffset in enumerate(self.offsets): - if cell_properties.bitcell.mirror.y and (i + self.column_offset) % 2: + if self.cell.mirror.y and (i + self.column_offset) % 2: mirror = "MY" tempx = xoffset + self.pc_cell.width else: diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index cc6373db..ebfd06ba 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -63,13 +63,8 @@ class replica_bitcell_array(bitcell_base_array): # Two dummy cols plus replica if we add the column self.extra_cols = len(self.left_rbl) + len(self.right_rbl) - - try: - end_caps_enabled = cell_properties.bitcell.end_caps - except AttributeError: - end_caps_enabled = False # If we aren't using row/col caps, then we need to use the bitcell - if not end_caps_enabled: + if not self.cell.end_caps: self.extra_rows += 2 self.extra_cols += 2 @@ -144,10 +139,6 @@ class replica_bitcell_array(bitcell_base_array): column_offset=column_offset, replica_bit=replica_bit) self.add_mod(self.replica_columns[port]) - try: - end_caps_enabled = cell_properties.bitcell.end_caps - except AttributeError: - end_caps_enabled = False # Dummy row self.dummy_row = factory.create(module_type="dummy_array", @@ -159,7 +150,7 @@ class replica_bitcell_array(bitcell_base_array): self.add_mod(self.dummy_row) # Dummy Row or Col Cap, depending on bitcell array properties - col_cap_module_type = ("col_cap_array" if end_caps_enabled else "dummy_array") + col_cap_module_type = ("col_cap_array" if self.cell.end_caps else "dummy_array") self.col_cap_top = factory.create(module_type=col_cap_module_type, cols=self.column_size, rows=1, @@ -179,7 +170,7 @@ class replica_bitcell_array(bitcell_base_array): self.add_mod(self.col_cap_bottom) # Dummy Col or Row Cap, depending on bitcell array properties - row_cap_module_type = ("row_cap_array" if end_caps_enabled else "dummy_array") + row_cap_module_type = ("row_cap_array" if self.cell.end_caps else "dummy_array") self.row_cap_left = factory.create(module_type=row_cap_module_type, cols=1, @@ -240,11 +231,6 @@ class replica_bitcell_array(bitcell_base_array): self.add_pin_list(self.rbl_bitline_names[port], "INOUT") def add_wordline_pins(self): - try: - end_caps_enabled = cell_properties.bitcell.end_caps - except AttributeError: - end_caps_enabled = False - # Wordlines to ground self.gnd_wordline_names = [] @@ -385,14 +371,10 @@ class replica_bitcell_array(bitcell_base_array): def add_replica_columns(self): """ Add replica columns on left and right of array """ - try: - end_caps_enabled = cell_properties.bitcell.end_caps - except AttributeError: - end_caps_enabled = False # Grow from left to right, toward the array for bit, port in enumerate(self.left_rbl): - if not end_caps_enabled: + if not self.cell.end_caps: offset = self.bitcell_offset.scale(-len(self.left_rbl) + bit, -self.rbl[0] - 1) + self.strap_offset.scale(-len(self.left_rbl) + bit, 0) + self.unused_offset else: offset = self.bitcell_offset.scale(-len(self.left_rbl) + bit, -self.rbl[0] - (self.col_end_offset.y/self.cell.height)) + self.strap_offset.scale(-len(self.left_rbl) + bit, 0) + self.unused_offset @@ -400,7 +382,7 @@ class replica_bitcell_array(bitcell_base_array): self.replica_col_insts[bit].place(offset) # Grow to the right of the bitcell array, array outward for bit, port in enumerate(self.right_rbl): - if not end_caps_enabled: + if not self.cell.end_caps: offset = self.bitcell_array_inst.lr() + self.bitcell_offset.scale(bit, -self.rbl[0] - 1) + self.strap_offset.scale(bit, -self.rbl[0] - 1) else: offset = self.bitcell_array_inst.lr() + self.bitcell_offset.scale(bit, -self.rbl[0] - (self.col_end_offset.y/self.cell.height)) + self.strap_offset.scale(bit, -self.rbl[0] - 1) @@ -422,15 +404,11 @@ class replica_bitcell_array(bitcell_base_array): def add_end_caps(self): """ Add dummy cells or end caps around the array """ - try: - end_caps_enabled = cell_properties.bitcell.end_caps - except AttributeError: - end_caps_enabled = False # FIXME: These depend on the array size itself # Far top dummy row (first row above array is NOT flipped) flip_dummy = self.rbl[1] % 2 - if not end_caps_enabled: + if not self.cell.end_caps: dummy_row_offset = self.bitcell_offset.scale(0, self.rbl[1] + flip_dummy) + self.bitcell_array_inst.ul() else: dummy_row_offset = self.bitcell_offset.scale(0, self.rbl[1] + flip_dummy) + self.bitcell_array_inst.ul() @@ -440,7 +418,7 @@ class replica_bitcell_array(bitcell_base_array): # FIXME: These depend on the array size itself # Far bottom dummy row (first row below array IS flipped) flip_dummy = (self.rbl[0] + 1) % 2 - if not end_caps_enabled: + if not self.cell.end_caps: dummy_row_offset = self.bitcell_offset.scale(0, -self.rbl[0] - 1 + flip_dummy) + self.unused_offset else: dummy_row_offset = self.bitcell_offset.scale(0, -self.rbl[0] - (self.col_end_offset.y/self.cell.height) + flip_dummy) + self.unused_offset @@ -448,7 +426,7 @@ class replica_bitcell_array(bitcell_base_array): mirror="MX" if flip_dummy else "R0") # Far left dummy col # Shifted down by the number of left RBLs even if we aren't adding replica column to this bitcell array - if not end_caps_enabled: + if not self.cell.end_caps: dummy_col_offset = self.bitcell_offset.scale(-len(self.left_rbl) - 1, -self.rbl[0] - 1) + self.unused_offset else: dummy_col_offset = self.bitcell_offset.scale(-(len(self.left_rbl)*(1+self.strap_offset.x/self.cell.width)) - (self.row_end_offset.x/self.cell.width), -len(self.left_rbl) - (self.col_end_offset.y/self.cell.height)) @@ -456,7 +434,7 @@ class replica_bitcell_array(bitcell_base_array): self.dummy_col_insts[0].place(offset=dummy_col_offset) # Far right dummy col # Shifted down by the number of left RBLs even if we aren't adding replica column to this bitcell array - if not end_caps_enabled: + if not self.cell.end_caps: dummy_col_offset = self.bitcell_offset.scale(len(self.right_rbl), -self.rbl[0] - 1) + self.bitcell_array_inst.lr() else: dummy_col_offset = self.bitcell_offset.scale(len(self.right_rbl)*(1+self.strap_offset.x/self.cell.width), -self.rbl[0] - (self.col_end_offset.y/self.cell.height)) + self.bitcell_array_inst.lr() diff --git a/compiler/modules/replica_column.py b/compiler/modules/replica_column.py index ad6e63dc..1fbe60fb 100644 --- a/compiler/modules/replica_column.py +++ b/compiler/modules/replica_column.py @@ -5,7 +5,7 @@ # import debug from bitcell_base_array import bitcell_base_array -from tech import cell_properties +from tech import cell_properties as props from sram_factory import factory from vector import vector from globals import OPTS @@ -30,11 +30,9 @@ class replica_column(bitcell_base_array): self.replica_bit = replica_bit # left, right, regular rows plus top/bottom dummy cells self.total_size = self.left_rbl + rows + self.right_rbl - try: - if not cell_properties.bitcell.end_caps: - self.total_size += 2 - except AttributeError: - self.total_size += 2 + + # For end caps + self.total_size += 2 self.column_offset = column_offset @@ -82,20 +80,17 @@ class replica_column(bitcell_base_array): self.dummy_cell = factory.create(module_type=OPTS.dummy_bitcell) self.add_mod(self.dummy_cell) try: - edge_module_type = ("col_cap" if cell_properties.bitcell.end_caps else "dummy") + edge_module_type = ("col_cap" if self.cell.end_caps else "dummy") except AttributeError: edge_module_type = "dummy" self.edge_cell = factory.create(module_type=edge_module_type + "_" + OPTS.bitcell) self.add_mod(self.edge_cell) + # Used for pin names only self.cell = factory.create(module_type=OPTS.bitcell) def create_instances(self): self.cell_inst = {} - try: - end_caps_enabled = cell_properties.bitcell.end_caps - except AttributeError: - end_caps_enabled = False for row in range(self.total_size): name="rbc_{0}".format(row) @@ -113,7 +108,7 @@ class replica_column(bitcell_base_array): elif (row == 0 or row == self.total_size - 1): self.cell_inst[row]=self.add_inst(name=name, mod=self.edge_cell) - if end_caps_enabled: + if self.cell.end_caps: self.connect_inst(self.get_bitcell_pins_col_cap(row, 0)) else: self.connect_inst(self.get_bitcell_pins(row, 0)) @@ -131,13 +126,13 @@ class replica_column(bitcell_base_array): # column that needs to be flipped. dir_y = False xoffset = 0 - if cell_properties.bitcell.mirror.y and self.column_offset % 2: + if self.replica_cell.mirror.y and self.column_offset % 2: dir_y = True xoffset = self.replica_cell.width for row in range(self.total_size): # name = "bit_r{0}_{1}".format(row, "rbl") - dir_x = cell_properties.bitcell.mirror.x and (row + rbl_offset) % 2 + dir_x = self.replica_cell.mirror.x and (row + rbl_offset) % 2 offset = vector(xoffset, self.cell.height * (row + (row + rbl_offset) % 2)) @@ -169,12 +164,7 @@ class replica_column(bitcell_base_array): width=bl_pin.width(), height=self.height) - try: - end_caps_enabled = cell_properties.bitcell.end_caps - except AttributeError: - end_caps_enabled = False - - if end_caps_enabled: + if self.cell.end_caps: row_range_max = self.total_size - 1 row_range_min = 1 else: diff --git a/compiler/modules/sense_amp_array.py b/compiler/modules/sense_amp_array.py index ce4e6911..d3ab94a5 100644 --- a/compiler/modules/sense_amp_array.py +++ b/compiler/modules/sense_amp_array.py @@ -10,7 +10,6 @@ from vector import vector from sram_factory import factory import debug from globals import OPTS -from tech import cell_properties class sense_amp_array(design.design): @@ -92,7 +91,6 @@ class sense_amp_array(design.design): def add_modules(self): self.amp = factory.create(module_type="sense_amp") - self.add_mod(self.amp) # This is just used for measurements, @@ -122,7 +120,7 @@ class sense_amp_array(design.design): self.offsets.append(i * self.bitcell.width) for i, xoffset in enumerate(self.offsets[0:self.num_cols:self.words_per_row]): - if cell_properties.bitcell.mirror.y and (i * self.words_per_row + self.column_offset) % 2: + if self.bitcell.mirror.y and (i * self.words_per_row + self.column_offset) % 2: mirror = "MY" xoffset = xoffset + self.amp_spacing else: @@ -134,7 +132,7 @@ class sense_amp_array(design.design): # place spare sense amps (will share the same enable as regular sense amps) for i, xoffset in enumerate(self.offsets[self.num_cols:]): index = self.word_size + i - if cell_properties.bitcell.mirror.y and (index + self.column_offset) % 2: + if self.bitcell.mirror.y and (index + self.column_offset) % 2: mirror = "MY" xoffset = xoffset + self.amp_width else: diff --git a/compiler/modules/write_driver_array.py b/compiler/modules/write_driver_array.py index aa0a4e29..afd21de5 100644 --- a/compiler/modules/write_driver_array.py +++ b/compiler/modules/write_driver_array.py @@ -12,7 +12,6 @@ from tech import drc from sram_factory import factory from vector import vector from globals import OPTS -from tech import cell_properties class write_driver_array(design.design): @@ -161,7 +160,7 @@ class write_driver_array(design.design): self.offsets.append(i * self.driver_spacing) for i, xoffset in enumerate(self.offsets[0:self.columns:self.words_per_row]): - if cell_properties.bitcell.mirror.y and (i * self.words_per_row + self.column_offset) % 2: + if self.bitcell.mirror.y and (i * self.words_per_row + self.column_offset) % 2: mirror = "MY" xoffset = xoffset + self.driver.width else: @@ -174,7 +173,7 @@ class write_driver_array(design.design): for i, xoffset in enumerate(self.offsets[self.columns:]): index = self.word_size + i - if cell_properties.bitcell.mirror.y and (index + self.column_offset) % 2: + if self.bitcell.mirror.y and (index + self.column_offset) % 2: mirror = "MY" xoffset = xoffset + self.driver.width else: diff --git a/technology/freepdk45/tech/tech.py b/technology/freepdk45/tech/tech.py index 46b7c2a5..436d2ff4 100644 --- a/technology/freepdk45/tech/tech.py +++ b/technology/freepdk45/tech/tech.py @@ -31,11 +31,8 @@ tech_modules = module_type() # Custom cell properties ################################################### cell_properties = cell_properties() -cell_properties.bitcell.mirror.x = True -cell_properties.bitcell.mirror.y = False cell_properties.bitcell_power_pin_directions = ("V", "V") - ################################################### # Custom cell properties ################################################### diff --git a/technology/scn4m_subm/tech/tech.py b/technology/scn4m_subm/tech/tech.py index e6a54e6e..6591fbbc 100644 --- a/technology/scn4m_subm/tech/tech.py +++ b/technology/scn4m_subm/tech/tech.py @@ -30,9 +30,6 @@ tech_modules = module_type() # Custom cell properties ################################################### cell_properties = cell_properties() -cell_properties.bitcell.mirror.x = True -cell_properties.bitcell.mirror.y = False - ################################################### # Custom cell properties