From acfec369d614f61220415a8e93e879aa6a48608f Mon Sep 17 00:00:00 2001 From: mrg Date: Wed, 28 Oct 2020 09:54:15 -0700 Subject: [PATCH] Add ptx cell properties --- compiler/base/custom_cell_properties.py | 26 ++++++++++++++++++++++- compiler/base/custom_layer_properties.py | 24 ++++++--------------- compiler/bitcells/bitcell.py | 2 -- compiler/modules/wordline_buffer_array.py | 2 +- compiler/modules/wordline_driver_array.py | 2 +- compiler/pgates/column_mux.py | 8 +++---- compiler/pgates/pgate.py | 6 +++--- compiler/pgates/pinv.py | 5 +++-- compiler/pgates/pinv_dec.py | 9 ++++---- compiler/pgates/pnand2.py | 7 +++--- compiler/pgates/pnand3.py | 6 +++--- compiler/pgates/pnand4.py | 6 +++--- compiler/pgates/pnor2.py | 6 +++--- compiler/pgates/precharge.py | 5 +++-- compiler/pgates/ptx.py | 9 ++++---- compiler/pgates/wordline_driver.py | 3 ++- 16 files changed, 71 insertions(+), 55 deletions(-) diff --git a/compiler/base/custom_cell_properties.py b/compiler/base/custom_cell_properties.py index 8e338548..43c84206 100644 --- a/compiler/base/custom_cell_properties.py +++ b/compiler/base/custom_cell_properties.py @@ -36,6 +36,17 @@ class _mirror_axis: self.y = y +class _ptx: + def __init__(self, model_is_subckt, bin_spice_models): + self.model_is_subckt = model_is_subckt + self.bin_spice_models = bin_spice_models + + +class _pgate: + def __init__(self, add_implants): + self.add_implants = add_implants + + class _bitcell: def __init__(self, mirror, cell_s8_6t, cell_6t, cell_1rw1r, cell_1w1r): self.mirror = mirror @@ -128,7 +139,12 @@ class cell_properties(): self.names = {} 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"], @@ -157,6 +173,14 @@ class cell_properties(): def bitcell(self): return self._bitcell + @property + def ptx(self): + return self._ptx + + @property + def pgate(self): + return self._pgate + @property def dff(self): return self._dff diff --git a/compiler/base/custom_layer_properties.py b/compiler/base/custom_layer_properties.py index c2dcae88..8faa2968 100644 --- a/compiler/base/custom_layer_properties.py +++ b/compiler/base/custom_layer_properties.py @@ -111,21 +111,17 @@ class _replica_column: self.even_rows = even_rows -class _wordline_buffer_array: +class _wordline_driver: def __init__(self, vertical_supply): # wordline_buffer_array # vertical vdd/gnd (sky130) - self.vertical_supply = vertical_supply - - -class _wordline_driver_array: - def __init__(self, - vertical_supply): # wordline_driver_array # vertical vdd/gnd (sky130) + # wordline_driver + # vertical vdd/gnd (sky130) self.vertical_supply = vertical_supply - + class layer_properties(): """ @@ -161,9 +157,7 @@ class layer_properties(): self._replica_column = _replica_column(even_rows=False) - self._wordline_buffer_array = _wordline_buffer_array(vertical_supply=False) - - self._wordline_driver_array = _wordline_driver_array(vertical_supply=False) + self._wordline_driver = _wordline_driver(vertical_supply=False) @property def bank(self): @@ -194,10 +188,6 @@ class layer_properties(): return self._replica_column @property - def wordline_buffer_array(self): - return self._wordline_buffer_array - - @property - def wordline_driver_array(self): - return self._wordline_driver_array + def wordline_driver(self): + return self._wordline_driver diff --git a/compiler/bitcells/bitcell.py b/compiler/bitcells/bitcell.py index 7f0acc4b..5a987ca4 100644 --- a/compiler/bitcells/bitcell.py +++ b/compiler/bitcells/bitcell.py @@ -46,8 +46,6 @@ class bitcell(bitcell_base.bitcell_base): self.add_pin_types(self.type_list) self.nets_match = self.do_nets_exist(self.storage_nets) - #debug.check(OPTS.tech_name != "sky130", "sky130 does not yet support single port cells") - def get_all_wl_names(self): """ Creates a list of all wordline pin names """ row_pins = [props.bitcell.cell_6t.pin.wl] diff --git a/compiler/modules/wordline_buffer_array.py b/compiler/modules/wordline_buffer_array.py index 6f728497..3b83b5eb 100644 --- a/compiler/modules/wordline_buffer_array.py +++ b/compiler/modules/wordline_buffer_array.py @@ -71,7 +71,7 @@ class wordline_buffer_array(design.design): Add a pin for each row of vdd/gnd which are must-connects next level up. """ - if layer_props.wordline_buffer_array.vertical_supply: + if layer_props.wordline_driver.vertical_supply: for name in ["vdd", "gnd"]: supply_pins = self.wld_inst[0].get_pins(name) for pin in supply_pins: diff --git a/compiler/modules/wordline_driver_array.py b/compiler/modules/wordline_driver_array.py index 5d93758a..c8d22260 100644 --- a/compiler/modules/wordline_driver_array.py +++ b/compiler/modules/wordline_driver_array.py @@ -72,7 +72,7 @@ class wordline_driver_array(design.design): Add a pin for each row of vdd/gnd which are must-connects next level up. """ - if layer_props.wordline_buffer_array.vertical_supply: + if layer_props.wordline_driver.vertical_supply: for name in ["vdd", "gnd"]: supply_pins = self.wld_inst[0].get_pins(name) for pin in supply_pins: diff --git a/compiler/pgates/column_mux.py b/compiler/pgates/column_mux.py index 20616115..18092b4d 100644 --- a/compiler/pgates/column_mux.py +++ b/compiler/pgates/column_mux.py @@ -10,7 +10,7 @@ import debug from tech import drc, layer from vector import vector from sram_factory import factory -from globals import OPTS +from tech import cell_properties as cell_props class column_mux(pgate.pgate): @@ -124,8 +124,8 @@ class column_mux(pgate.pgate): + vector(0, self.nmos.active_height + max(self.active_space, self.poly_space)) self.nmos_upper.place(nmos_upper_position) - if OPTS.tech_name == "sky130": - self.add_implants() + if cell_props.pgate.add_implants: + self.extend_implants() def connect_poly(self): """ Connect the poly gate of the two pass transistors """ @@ -198,7 +198,7 @@ class column_mux(pgate.pgate): self.add_path(self.col_mux_stack[2], [br_pin.bc(), mid1, mid2, nmos_lower_d_pin.center()]) - def add_implants(self): + def extend_implants(self): """ Add top-to-bottom implants for adjacency issues in s8. """ diff --git a/compiler/pgates/pgate.py b/compiler/pgates/pgate.py index 082ef7b8..468f367e 100644 --- a/compiler/pgates/pgate.py +++ b/compiler/pgates/pgate.py @@ -13,8 +13,8 @@ from bisect import bisect_left from tech import layer, drc from vector import vector from globals import OPTS - -if(OPTS.tech_name == "sky130"): +from tech import cell_properties as cell_props +if cell_props.ptx.bin_spice_models: from tech import nmos_bins, pmos_bins @@ -192,7 +192,7 @@ class pgate(design.design): width=self.width + 2 * self.well_extend_active, height=pwell_height) - if OPTS.tech_name == "sky130": + if cell_props.pgate.add_implants: self.extend_implants() def add_nwell_contact(self, pmos, pmos_pos): diff --git a/compiler/pgates/pinv.py b/compiler/pgates/pinv.py index eca2d22c..2546f833 100644 --- a/compiler/pgates/pinv.py +++ b/compiler/pgates/pinv.py @@ -17,6 +17,7 @@ from utils import round_to_grid import logical_effort from sram_factory import factory from errors import drc_error +from tech import cell_properties as cell_props class pinv(pgate.pgate): @@ -87,7 +88,7 @@ class pinv(pgate.pgate): self.tx_mults = 1 self.nmos_width = self.nmos_size * drc("minwidth_tx") self.pmos_width = self.pmos_size * drc("minwidth_tx") - if OPTS.tech_name == "sky130": + if cell_props.ptx.bin_spice_models: (self.nmos_width, self.tx_mults) = pgate.pgate.best_bin("nmos", self.nmos_width) (self.pmos_width, self.tx_mults) = pgate.pgate.best_bin("pmos", self.pmos_width) return @@ -132,7 +133,7 @@ class pinv(pgate.pgate): # Determine the number of mults for each to fit width # into available space - if OPTS.tech_name != "sky130": + if not cell_props.ptx.bin_spice_models: self.nmos_width = self.nmos_size * drc("minwidth_tx") self.pmos_width = self.pmos_size * drc("minwidth_tx") nmos_required_mults = max(int(ceil(self.nmos_width / nmos_height_available)), 1) diff --git a/compiler/pgates/pinv_dec.py b/compiler/pgates/pinv_dec.py index 028fe954..04e33fdd 100644 --- a/compiler/pgates/pinv_dec.py +++ b/compiler/pgates/pinv_dec.py @@ -12,6 +12,7 @@ from tech import drc, parameter, layer from vector import vector from globals import OPTS from sram_factory import factory +from tech import cell_properties as cell_props class pinv_dec(pinv.pinv): @@ -50,7 +51,7 @@ class pinv_dec(pinv.pinv): self.tx_mults = 1 self.nmos_width = self.nmos_size * drc("minwidth_tx") self.pmos_width = self.pmos_size * drc("minwidth_tx") - if OPTS.tech_name == "sky130": + if self.bin_spice_models: self.nmos_width = self.nearest_bin("nmos", self.nmos_width) self.pmos_width = self.nearest_bin("pmos", self.pmos_width) @@ -140,10 +141,10 @@ class pinv_dec(pinv.pinv): nmos_drain_pos = self.nmos_inst.get_pin("D").center() self.output_pos = vector(0.5 * (pmos_drain_pos.x + nmos_drain_pos.x), nmos_drain_pos.y) - if OPTS.tech_name == "sky130": - self.add_implants() + if cell_props.pgate.add_implants: + self.extend_implants() - def add_implants(self): + def extend_implants(self): """ Add top-to-bottom implants for adjacency issues in s8. """ diff --git a/compiler/pgates/pnand2.py b/compiler/pgates/pnand2.py index c1295a1b..b2dead7e 100644 --- a/compiler/pgates/pnand2.py +++ b/compiler/pgates/pnand2.py @@ -8,11 +8,11 @@ import pgate import debug from tech import drc, parameter, spice -from globals import OPTS from vector import vector import logical_effort from sram_factory import factory import contact +from tech import cell_properties as cell_props class pnand2(pgate.pgate): @@ -38,7 +38,7 @@ class pnand2(pgate.pgate): debug.check(size == 1, "Size 1 pnand2 is only supported now.") self.tx_mults = 1 - if OPTS.tech_name == "sky130": + if cell_props.ptx.bin_spice_models: self.nmos_width = self.nearest_bin("nmos", self.nmos_width) self.pmos_width = self.nearest_bin("pmos", self.pmos_width) @@ -212,9 +212,8 @@ class pnand2(pgate.pgate): "B", position="center") - if OPTS.tech_name == "sky130": + if cell_props.pgate.add_implants: self.add_enclosure([apin, bpin], "npc", drc("npc_enclose_poly")) - def route_output(self): """ Route the Z output """ diff --git a/compiler/pgates/pnand3.py b/compiler/pgates/pnand3.py index db5a1f28..de7e3e68 100644 --- a/compiler/pgates/pnand3.py +++ b/compiler/pgates/pnand3.py @@ -11,8 +11,8 @@ from tech import drc, parameter, spice from vector import vector import logical_effort from sram_factory import factory -from globals import OPTS import contact +from tech import cell_properties as cell_props class pnand3(pgate.pgate): @@ -41,7 +41,7 @@ class pnand3(pgate.pgate): "Size 1 pnand3 is only supported now.") self.tx_mults = 1 - if OPTS.tech_name == "sky130": + if cell_props.ptx.bin_spice_models: self.nmos_width = self.nearest_bin("nmos", self.nmos_width) self.pmos_width = self.nearest_bin("pmos", self.pmos_width) @@ -246,7 +246,7 @@ class pnand3(pgate.pgate): "C", position="right") - if OPTS.tech_name == "sky130": + if cell_props.pgate.add_implants: self.add_enclosure([apin, bpin, cpin], "npc", drc("npc_enclose_poly")) def route_output(self): diff --git a/compiler/pgates/pnand4.py b/compiler/pgates/pnand4.py index 5a812799..a71f2f52 100644 --- a/compiler/pgates/pnand4.py +++ b/compiler/pgates/pnand4.py @@ -11,8 +11,8 @@ from tech import drc, parameter, spice from vector import vector import logical_effort from sram_factory import factory -from globals import OPTS import contact +from tech import cell_properties as cell_props class pnand4(pgate.pgate): @@ -41,7 +41,7 @@ class pnand4(pgate.pgate): "Size 1 pnand4 is only supported now.") self.tx_mults = 1 - if OPTS.tech_name == "sky130": + if cell_props.ptx.bin_spice_models: self.nmos_width = self.nearest_bin("nmos", self.nmos_width) self.pmos_width = self.nearest_bin("pmos", self.pmos_width) @@ -268,7 +268,7 @@ class pnand4(pgate.pgate): "D", position="right") - if OPTS.tech_name == "sky130": + if cell_props.pgate.add_implants: self.add_enclosure([apin, bpin, cpin, dpin], "npc", drc("npc_enclose_poly")) def route_output(self): diff --git a/compiler/pgates/pnor2.py b/compiler/pgates/pnor2.py index b3d4d5ee..6a5679b0 100644 --- a/compiler/pgates/pnor2.py +++ b/compiler/pgates/pnor2.py @@ -7,10 +7,10 @@ # import pgate import debug -from globals import OPTS from tech import drc, parameter, spice from vector import vector from sram_factory import factory +from tech import cell_properties as cell_props class pnor2(pgate.pgate): @@ -36,7 +36,7 @@ class pnor2(pgate.pgate): debug.check(size==1, "Size 1 pnor2 is only supported now.") self.tx_mults = 1 - if OPTS.tech_name == "sky130": + if self.bin_spice_models: self.nmos_width = self.nearest_bin("nmos", self.nmos_width) self.pmos_width = self.nearest_bin("pmos", self.pmos_width) @@ -210,7 +210,7 @@ class pnor2(pgate.pgate): self.output_yoffset = self.inputA_yoffset + self.m1_nonpref_pitch - if OPTS.tech_name == "sky130": + if cell_props.pgate.add_implants: self.add_enclosure([apin, bpin], "npc", drc("npc_enclose_poly")) def route_output(self): diff --git a/compiler/pgates/precharge.py b/compiler/pgates/precharge.py index 4ae48167..feb9eca6 100644 --- a/compiler/pgates/precharge.py +++ b/compiler/pgates/precharge.py @@ -13,6 +13,7 @@ from tech import parameter, drc from vector import vector from globals import OPTS from sram_factory import factory +from tech import cell_properties as cell_props class precharge(design.design): @@ -79,7 +80,7 @@ class precharge(design.design): """ Initializes the upper and lower pmos """ - if(OPTS.tech_name == "sky130"): + if cell_props.ptx.bin_spice_models: self.ptx_width = pgate.nearest_bin("pmos", self.ptx_width) self.pmos = factory.create(module_type="ptx", width=self.ptx_width, @@ -300,4 +301,4 @@ class precharge(design.design): self.add_path(self.bitline_layer, [left_pos, right_pos], width=pmos_pin.height()) - \ No newline at end of file + diff --git a/compiler/pgates/ptx.py b/compiler/pgates/ptx.py index 67368ce9..e445cbcd 100644 --- a/compiler/pgates/ptx.py +++ b/compiler/pgates/ptx.py @@ -14,6 +14,7 @@ import contact import logical_effort from globals import OPTS from pgate import pgate +from tech import cell_properties as cell_props class ptx(design.design): @@ -129,9 +130,8 @@ class ptx(design.design): # be decided in the layout later. area_sd = 2.5 * self.poly_width * self.tx_width perimeter_sd = 2 * self.poly_width + 2 * self.tx_width - if OPTS.tech_name == "sky130": - # sky130 simulation cannot use the mult parameter in simulation - (self.tx_width, self.mults) = pgate.best_bin(self.tx_type, self.tx_width) + if cell_props.ptx.model_is_subckt: + # sky130 main_str = "X{{0}} {{1}} {0} m={1} w={2} l={3} ".format(spice[self.tx_type], self.mults, self.tx_width, @@ -150,12 +150,13 @@ class ptx(design.design): self.spice_device = main_str + area_str self.spice.append("\n* spice ptx " + self.spice_device) - if OPTS.tech_name == "sky130" and OPTS.lvs_exe and OPTS.lvs_exe[0] == "calibre": + if cell_props.ptx.model_is_subckt and OPTS.lvs_exe and OPTS.lvs_exe[0] == "calibre": # sky130 requires mult parameter too # self.lvs_device = "X{{0}} {{1}} {0} m={1} w={2} l={3} mult={1}".format(spice[self.tx_type], # self.mults, # self.tx_width, # drc("minwidth_poly")) + # TEMP FIX: Use old device names if using Calibre. self.lvs_device = "M{{0}} {{1}} {0} m={1} w={2} l={3} mult={1}".format("nshort" if self.tx_type == "nmos" else "pshort", self.mults, self.tx_width, diff --git a/compiler/pgates/wordline_driver.py b/compiler/pgates/wordline_driver.py index 6abf7b20..458f19f3 100644 --- a/compiler/pgates/wordline_driver.py +++ b/compiler/pgates/wordline_driver.py @@ -11,6 +11,7 @@ import design from sram_factory import factory from globals import OPTS from tech import layer +from tech import layer_properties as layer_props class wordline_driver(design.design): @@ -104,7 +105,7 @@ class wordline_driver(design.design): def route_supply_rails(self): """ Add vdd/gnd rails to the top, (middle), and bottom. """ - if OPTS.tech_name == "sky130": + if layer_props.wordline_driver.vertical_supply: for name in ["vdd", "gnd"]: for inst in [self.nand_inst, self.driver_inst]: self.copy_layout_pin(inst, name)