Add ptx cell properties

This commit is contained in:
mrg 2020-10-28 09:54:15 -07:00
parent 25495f3d94
commit acfec369d6
16 changed files with 71 additions and 55 deletions

View File

@ -36,6 +36,17 @@ class _mirror_axis:
self.y = y 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: class _bitcell:
def __init__(self, mirror, cell_s8_6t, cell_6t, cell_1rw1r, cell_1w1r): def __init__(self, mirror, cell_s8_6t, cell_6t, cell_1rw1r, cell_1w1r):
self.mirror = mirror self.mirror = mirror
@ -129,6 +140,11 @@ class cell_properties():
self._bitcell = _bitcell._default() 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, self._dff = _dff(use_custom_ports=False,
custom_port_list=["D", "Q", "clk", "vdd", "gnd"], custom_port_list=["D", "Q", "clk", "vdd", "gnd"],
custom_type_list=["INPUT", "OUTPUT", "INPUT", "POWER", "GROUND"], custom_type_list=["INPUT", "OUTPUT", "INPUT", "POWER", "GROUND"],
@ -157,6 +173,14 @@ class cell_properties():
def bitcell(self): def bitcell(self):
return self._bitcell return self._bitcell
@property
def ptx(self):
return self._ptx
@property
def pgate(self):
return self._pgate
@property @property
def dff(self): def dff(self):
return self._dff return self._dff

View File

@ -111,19 +111,15 @@ class _replica_column:
self.even_rows = even_rows self.even_rows = even_rows
class _wordline_buffer_array: class _wordline_driver:
def __init__(self, def __init__(self,
vertical_supply): vertical_supply):
# wordline_buffer_array # wordline_buffer_array
# vertical vdd/gnd (sky130) # vertical vdd/gnd (sky130)
self.vertical_supply = vertical_supply
class _wordline_driver_array:
def __init__(self,
vertical_supply):
# wordline_driver_array # wordline_driver_array
# vertical vdd/gnd (sky130) # vertical vdd/gnd (sky130)
# wordline_driver
# vertical vdd/gnd (sky130)
self.vertical_supply = vertical_supply self.vertical_supply = vertical_supply
@ -161,9 +157,7 @@ class layer_properties():
self._replica_column = _replica_column(even_rows=False) self._replica_column = _replica_column(even_rows=False)
self._wordline_buffer_array = _wordline_buffer_array(vertical_supply=False) self._wordline_driver = _wordline_driver(vertical_supply=False)
self._wordline_driver_array = _wordline_driver_array(vertical_supply=False)
@property @property
def bank(self): def bank(self):
@ -194,10 +188,6 @@ class layer_properties():
return self._replica_column return self._replica_column
@property @property
def wordline_buffer_array(self): def wordline_driver(self):
return self._wordline_buffer_array return self._wordline_driver
@property
def wordline_driver_array(self):
return self._wordline_driver_array

View File

@ -46,8 +46,6 @@ class bitcell(bitcell_base.bitcell_base):
self.add_pin_types(self.type_list) self.add_pin_types(self.type_list)
self.nets_match = self.do_nets_exist(self.storage_nets) 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): def get_all_wl_names(self):
""" Creates a list of all wordline pin names """ """ Creates a list of all wordline pin names """
row_pins = [props.bitcell.cell_6t.pin.wl] row_pins = [props.bitcell.cell_6t.pin.wl]

View File

@ -71,7 +71,7 @@ class wordline_buffer_array(design.design):
Add a pin for each row of vdd/gnd which Add a pin for each row of vdd/gnd which
are must-connects next level up. 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"]: for name in ["vdd", "gnd"]:
supply_pins = self.wld_inst[0].get_pins(name) supply_pins = self.wld_inst[0].get_pins(name)
for pin in supply_pins: for pin in supply_pins:

View File

@ -72,7 +72,7 @@ class wordline_driver_array(design.design):
Add a pin for each row of vdd/gnd which Add a pin for each row of vdd/gnd which
are must-connects next level up. 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"]: for name in ["vdd", "gnd"]:
supply_pins = self.wld_inst[0].get_pins(name) supply_pins = self.wld_inst[0].get_pins(name)
for pin in supply_pins: for pin in supply_pins:

View File

@ -10,7 +10,7 @@ import debug
from tech import drc, layer from tech import drc, layer
from vector import vector from vector import vector
from sram_factory import factory from sram_factory import factory
from globals import OPTS from tech import cell_properties as cell_props
class column_mux(pgate.pgate): 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)) + vector(0, self.nmos.active_height + max(self.active_space, self.poly_space))
self.nmos_upper.place(nmos_upper_position) self.nmos_upper.place(nmos_upper_position)
if OPTS.tech_name == "sky130": if cell_props.pgate.add_implants:
self.add_implants() self.extend_implants()
def connect_poly(self): def connect_poly(self):
""" Connect the poly gate of the two pass transistors """ """ 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], self.add_path(self.col_mux_stack[2],
[br_pin.bc(), mid1, mid2, nmos_lower_d_pin.center()]) [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. Add top-to-bottom implants for adjacency issues in s8.
""" """

View File

@ -13,8 +13,8 @@ from bisect import bisect_left
from tech import layer, drc from tech import layer, drc
from vector import vector from vector import vector
from globals import OPTS from globals import OPTS
from tech import cell_properties as cell_props
if(OPTS.tech_name == "sky130"): if cell_props.ptx.bin_spice_models:
from tech import nmos_bins, pmos_bins from tech import nmos_bins, pmos_bins
@ -192,7 +192,7 @@ class pgate(design.design):
width=self.width + 2 * self.well_extend_active, width=self.width + 2 * self.well_extend_active,
height=pwell_height) height=pwell_height)
if OPTS.tech_name == "sky130": if cell_props.pgate.add_implants:
self.extend_implants() self.extend_implants()
def add_nwell_contact(self, pmos, pmos_pos): def add_nwell_contact(self, pmos, pmos_pos):

View File

@ -17,6 +17,7 @@ from utils import round_to_grid
import logical_effort import logical_effort
from sram_factory import factory from sram_factory import factory
from errors import drc_error from errors import drc_error
from tech import cell_properties as cell_props
class pinv(pgate.pgate): class pinv(pgate.pgate):
@ -87,7 +88,7 @@ class pinv(pgate.pgate):
self.tx_mults = 1 self.tx_mults = 1
self.nmos_width = self.nmos_size * drc("minwidth_tx") self.nmos_width = self.nmos_size * drc("minwidth_tx")
self.pmos_width = self.pmos_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.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) (self.pmos_width, self.tx_mults) = pgate.pgate.best_bin("pmos", self.pmos_width)
return return
@ -132,7 +133,7 @@ class pinv(pgate.pgate):
# Determine the number of mults for each to fit width # Determine the number of mults for each to fit width
# into available space # 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.nmos_width = self.nmos_size * drc("minwidth_tx")
self.pmos_width = self.pmos_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) nmos_required_mults = max(int(ceil(self.nmos_width / nmos_height_available)), 1)

View File

@ -12,6 +12,7 @@ from tech import drc, parameter, layer
from vector import vector from vector import vector
from globals import OPTS from globals import OPTS
from sram_factory import factory from sram_factory import factory
from tech import cell_properties as cell_props
class pinv_dec(pinv.pinv): class pinv_dec(pinv.pinv):
@ -50,7 +51,7 @@ class pinv_dec(pinv.pinv):
self.tx_mults = 1 self.tx_mults = 1
self.nmos_width = self.nmos_size * drc("minwidth_tx") self.nmos_width = self.nmos_size * drc("minwidth_tx")
self.pmos_width = self.pmos_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.nmos_width = self.nearest_bin("nmos", self.nmos_width)
self.pmos_width = self.nearest_bin("pmos", self.pmos_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() 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) self.output_pos = vector(0.5 * (pmos_drain_pos.x + nmos_drain_pos.x), nmos_drain_pos.y)
if OPTS.tech_name == "sky130": if cell_props.pgate.add_implants:
self.add_implants() self.extend_implants()
def add_implants(self): def extend_implants(self):
""" """
Add top-to-bottom implants for adjacency issues in s8. Add top-to-bottom implants for adjacency issues in s8.
""" """

View File

@ -8,11 +8,11 @@
import pgate import pgate
import debug import debug
from tech import drc, parameter, spice from tech import drc, parameter, spice
from globals import OPTS
from vector import vector from vector import vector
import logical_effort import logical_effort
from sram_factory import factory from sram_factory import factory
import contact import contact
from tech import cell_properties as cell_props
class pnand2(pgate.pgate): class pnand2(pgate.pgate):
@ -38,7 +38,7 @@ class pnand2(pgate.pgate):
debug.check(size == 1, "Size 1 pnand2 is only supported now.") debug.check(size == 1, "Size 1 pnand2 is only supported now.")
self.tx_mults = 1 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.nmos_width = self.nearest_bin("nmos", self.nmos_width)
self.pmos_width = self.nearest_bin("pmos", self.pmos_width) self.pmos_width = self.nearest_bin("pmos", self.pmos_width)
@ -212,10 +212,9 @@ class pnand2(pgate.pgate):
"B", "B",
position="center") position="center")
if OPTS.tech_name == "sky130": if cell_props.pgate.add_implants:
self.add_enclosure([apin, bpin], "npc", drc("npc_enclose_poly")) self.add_enclosure([apin, bpin], "npc", drc("npc_enclose_poly"))
def route_output(self): def route_output(self):
""" Route the Z output """ """ Route the Z output """

View File

@ -11,8 +11,8 @@ from tech import drc, parameter, spice
from vector import vector from vector import vector
import logical_effort import logical_effort
from sram_factory import factory from sram_factory import factory
from globals import OPTS
import contact import contact
from tech import cell_properties as cell_props
class pnand3(pgate.pgate): class pnand3(pgate.pgate):
@ -41,7 +41,7 @@ class pnand3(pgate.pgate):
"Size 1 pnand3 is only supported now.") "Size 1 pnand3 is only supported now.")
self.tx_mults = 1 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.nmos_width = self.nearest_bin("nmos", self.nmos_width)
self.pmos_width = self.nearest_bin("pmos", self.pmos_width) self.pmos_width = self.nearest_bin("pmos", self.pmos_width)
@ -246,7 +246,7 @@ class pnand3(pgate.pgate):
"C", "C",
position="right") position="right")
if OPTS.tech_name == "sky130": if cell_props.pgate.add_implants:
self.add_enclosure([apin, bpin, cpin], "npc", drc("npc_enclose_poly")) self.add_enclosure([apin, bpin, cpin], "npc", drc("npc_enclose_poly"))
def route_output(self): def route_output(self):

View File

@ -11,8 +11,8 @@ from tech import drc, parameter, spice
from vector import vector from vector import vector
import logical_effort import logical_effort
from sram_factory import factory from sram_factory import factory
from globals import OPTS
import contact import contact
from tech import cell_properties as cell_props
class pnand4(pgate.pgate): class pnand4(pgate.pgate):
@ -41,7 +41,7 @@ class pnand4(pgate.pgate):
"Size 1 pnand4 is only supported now.") "Size 1 pnand4 is only supported now.")
self.tx_mults = 1 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.nmos_width = self.nearest_bin("nmos", self.nmos_width)
self.pmos_width = self.nearest_bin("pmos", self.pmos_width) self.pmos_width = self.nearest_bin("pmos", self.pmos_width)
@ -268,7 +268,7 @@ class pnand4(pgate.pgate):
"D", "D",
position="right") 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")) self.add_enclosure([apin, bpin, cpin, dpin], "npc", drc("npc_enclose_poly"))
def route_output(self): def route_output(self):

View File

@ -7,10 +7,10 @@
# #
import pgate import pgate
import debug import debug
from globals import OPTS
from tech import drc, parameter, spice from tech import drc, parameter, spice
from vector import vector from vector import vector
from sram_factory import factory from sram_factory import factory
from tech import cell_properties as cell_props
class pnor2(pgate.pgate): class pnor2(pgate.pgate):
@ -36,7 +36,7 @@ class pnor2(pgate.pgate):
debug.check(size==1, "Size 1 pnor2 is only supported now.") debug.check(size==1, "Size 1 pnor2 is only supported now.")
self.tx_mults = 1 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.nmos_width = self.nearest_bin("nmos", self.nmos_width)
self.pmos_width = self.nearest_bin("pmos", self.pmos_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 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")) self.add_enclosure([apin, bpin], "npc", drc("npc_enclose_poly"))
def route_output(self): def route_output(self):

View File

@ -13,6 +13,7 @@ from tech import parameter, drc
from vector import vector from vector import vector
from globals import OPTS from globals import OPTS
from sram_factory import factory from sram_factory import factory
from tech import cell_properties as cell_props
class precharge(design.design): class precharge(design.design):
@ -79,7 +80,7 @@ class precharge(design.design):
""" """
Initializes the upper and lower pmos 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.ptx_width = pgate.nearest_bin("pmos", self.ptx_width)
self.pmos = factory.create(module_type="ptx", self.pmos = factory.create(module_type="ptx",
width=self.ptx_width, width=self.ptx_width,

View File

@ -14,6 +14,7 @@ import contact
import logical_effort import logical_effort
from globals import OPTS from globals import OPTS
from pgate import pgate from pgate import pgate
from tech import cell_properties as cell_props
class ptx(design.design): class ptx(design.design):
@ -129,9 +130,8 @@ class ptx(design.design):
# be decided in the layout later. # be decided in the layout later.
area_sd = 2.5 * self.poly_width * self.tx_width area_sd = 2.5 * self.poly_width * self.tx_width
perimeter_sd = 2 * self.poly_width + 2 * self.tx_width perimeter_sd = 2 * self.poly_width + 2 * self.tx_width
if OPTS.tech_name == "sky130": if cell_props.ptx.model_is_subckt:
# sky130 simulation cannot use the mult parameter in simulation # sky130
(self.tx_width, self.mults) = pgate.best_bin(self.tx_type, self.tx_width)
main_str = "X{{0}} {{1}} {0} m={1} w={2} l={3} ".format(spice[self.tx_type], main_str = "X{{0}} {{1}} {0} m={1} w={2} l={3} ".format(spice[self.tx_type],
self.mults, self.mults,
self.tx_width, self.tx_width,
@ -150,12 +150,13 @@ class ptx(design.design):
self.spice_device = main_str + area_str self.spice_device = main_str + area_str
self.spice.append("\n* spice ptx " + self.spice_device) 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 # 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.lvs_device = "X{{0}} {{1}} {0} m={1} w={2} l={3} mult={1}".format(spice[self.tx_type],
# self.mults, # self.mults,
# self.tx_width, # self.tx_width,
# drc("minwidth_poly")) # 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.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.mults,
self.tx_width, self.tx_width,

View File

@ -11,6 +11,7 @@ import design
from sram_factory import factory from sram_factory import factory
from globals import OPTS from globals import OPTS
from tech import layer from tech import layer
from tech import layer_properties as layer_props
class wordline_driver(design.design): class wordline_driver(design.design):
@ -104,7 +105,7 @@ class wordline_driver(design.design):
def route_supply_rails(self): def route_supply_rails(self):
""" Add vdd/gnd rails to the top, (middle), and bottom. """ """ 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 name in ["vdd", "gnd"]:
for inst in [self.nand_inst, self.driver_inst]: for inst in [self.nand_inst, self.driver_inst]:
self.copy_layout_pin(inst, name) self.copy_layout_pin(inst, name)