Add initial custom layer properties.

This commit is contained in:
mrg 2020-10-27 15:11:04 -07:00
parent 5bff641c0a
commit 611a4155b9
13 changed files with 142 additions and 101 deletions

View File

@ -5,9 +5,8 @@
# (acting for and on behalf of Oklahoma State University) # (acting for and on behalf of Oklahoma State University)
# All rights reserved. # All rights reserved.
# #
from design import design
class _bank: class _bank:
def __init__(self, stack, pitch): def __init__(self, stack, pitch):
# bank # bank
@ -17,25 +16,36 @@ class _bank:
self.stack = stack self.stack = stack
self.pitch = pitch self.pitch = pitch
class _hierarchical_decoder: class _hierarchical_decoder:
def __init__(self, def __init__(self,
bus_layer, bus_layer,
bus_directions, bus_directions,
bus_pitch,
bus_space,
input_layer, input_layer,
output_layer, output_layer,
output_layer_pitch,
vertical_supply): vertical_supply):
# hierarchical_decoder # hierarchical_decoder
# bus_layer, bus_directions, bus_pitch, bus_space, input_layer, output_layer, output_layer_pitch # bus_layer, bus_directions, bus_pitch, bus_space, input_layer, output_layer, output_layer_pitch
# m2, pref, m2_pitch, m2_space, m1, m3, m3_pitch # m2, pref, m2_pitch, m2_space, m1, m3, m3_pitch
# m1, nonpref, m1_pitch, m2_space, m2, li, li_pitch (sky130) # m1, nonpref, m1_pitch, m2_space, m2, li, li_pitch (sky130)
# #
# vertical vdd/gnd # vertical vdd/gnd
# special jog # special jogging
self.bus_layer = bus_layer
self.bus_directions = bus_directions
self.input_layer = input_layer
self.output_layer = output_layer
self.vertical_supply = vertical_supply
class _hierarchical_predecode:
def __init__(self,
bus_layer,
bus_directions,
bus_space_factor,
input_layer,
output_layer,
vertical_supply):
# hierarchical_predecode # hierarchical_predecode
# bus_layer, bus_directions, bus_pitch, bus_space, input_layer, output_layer, output_layer_pitch # bus_layer, bus_directions, bus_pitch, bus_space, input_layer, output_layer, output_layer_pitch
# m2, pref, m2_pitch, m2_space, m1, m1, m1_pitch # m2, pref, m2_pitch, m2_space, m1, m1, m1_pitch
@ -44,9 +54,8 @@ class _hierarchical_decoder:
# vertical vdd/gnd # vertical vdd/gnd
# special jogging # special jogging
self.bus_layer = bus_layer self.bus_layer = bus_layer
self.bus_directinos = bus_directions self.bus_directions = bus_directions
self.bus_pitch = bus_pitch self.bus_space_factor = bus_space_factor
self.bus_sapce = bus_space
self.input_layer = input_layer self.input_layer = input_layer
self.output_layer = output_layer self.output_layer = output_layer
self.vertical_supply = vertical_supply self.vertical_supply = vertical_supply
@ -76,6 +85,7 @@ class _port_address:
class _port_data: class _port_data:
def __init__(self, def __init__(self,
channel_route_bitlines,
enable_layer): enable_layer):
# port_data # port_data
# connect bitlines instead of chanel route # connect bitlines instead of chanel route
@ -89,6 +99,7 @@ class _port_data:
# en_bar_layer # en_bar_layer
# m1 # m1
# m3 (sky130) # m3 (sky130)
self.channel_route_bitlines = channel_route_bitlines
self.enable_layer = enable_layer self.enable_layer = enable_layer
@ -98,7 +109,7 @@ class _replica_column:
# replica_column # replica_column
# even row check (sky130) # even row check (sky130)
self.even_rows = even_rows self.even_rows = even_rows
class _wordline_buffer_array: class _wordline_buffer_array:
def __init__(self, def __init__(self,
@ -122,10 +133,37 @@ class layer_properties():
can be overriden in the tech.py file. can be overriden in the tech.py file.
""" """
def __init__(self): def __init__(self):
self.names = {}
self._bank = _bank(stack="m1_stack",
pitch="m2_pitch")
self._bank = _bank(stack=design.m1_stack, self._hierarchical_decoder = _hierarchical_decoder(bus_layer="m2",
pitch=design.m2_pitch) bus_directions="pref",
input_layer="m1",
output_layer="m3",
vertical_supply=False)
self._hierarchical_predecode = _hierarchical_predecode(bus_layer="m2",
bus_directions="pref",
bus_space_factor=1,
input_layer="m1",
output_layer="m1",
vertical_supply=False)
self._column_mux_array = _column_mux_array(select_layer="m1",
select_pitch="m2_pitch",
bitline_layer="m2")
self._port_address = _port_address(supply_offset=False)
self._port_data = _port_data(channel_route_bitlines=False,
enable_layer="m1")
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)
@property @property
def bank(self): def bank(self):
@ -137,8 +175,12 @@ class layer_properties():
@property @property
def hierarchical_decoder(self): def hierarchical_decoder(self):
return self._hierarcical_decoder return self._hierarchical_decoder
@property
def hierarchical_predecode(self):
return self._hierarchical_predecode
@property @property
def port_address(self): def port_address(self):
return self._port_address return self._port_address

View File

@ -9,9 +9,10 @@ import debug
import design import design
from sram_factory import factory from sram_factory import factory
from math import log, ceil, floor from math import log, ceil, floor
from tech import drc, layer from tech import drc
from vector import vector from vector import vector
from globals import OPTS from globals import OPTS
from tech import layer_properties as layer_props
class bank(design.design): class bank(design.design):
@ -906,18 +907,13 @@ class bank(design.design):
offset=mid2) offset=mid2)
self.add_path(bitcell_wl_pin.layer, [mid2, bitcell_wl_pos]) self.add_path(bitcell_wl_pin.layer, [mid2, bitcell_wl_pos])
def route_column_address_lines(self, port): def route_column_address_lines(self, port):
""" Connecting the select lines of column mux to the address bus """ """ Connecting the select lines of column mux to the address bus """
if not self.col_addr_size>0: if not self.col_addr_size>0:
return return
if OPTS.tech_name == "sky130": stack = layer_props.bank.stack
stack = self.m2_stack pitch = layer_props.bank.pitch
pitch = self.m3_pitch
else:
stack = self.m1_stack
pitch = self.m2_pitch
if self.col_addr_size == 1: if self.col_addr_size == 1:

View File

@ -11,7 +11,8 @@ from tech import layer, preferred_directions
from vector import vector from vector import vector
from sram_factory import factory from sram_factory import factory
from globals import OPTS from globals import OPTS
from tech import cell_properties from tech import cell_properties as cell_props
from tech import layer_properties as layer_props
class column_mux_array(design.design): class column_mux_array(design.design):
@ -33,14 +34,18 @@ class column_mux_array(design.design):
self.bitcell_br = bitcell_br self.bitcell_br = bitcell_br
self.column_offset = column_offset self.column_offset = column_offset
if OPTS.tech_name == "sky130": self.sel_layer = layer_props.column_mux_array.select_layer
self.sel_layer = "m3" self.sel_pitch = getattr(self, layer_props.column_mux_array.select_pitch)
self.sel_pitch = self.m3_pitch self.bitline_layer = layer_props.column_mux_array.bitline_layer
self.bitline_layer = "m1"
else: # if OPTS.tech_name == "sky130":
self.sel_layer = "m1" # self.sel_layer = "m3"
self.sel_pitch = self.m2_pitch # self.sel_pitch = self.m3_pitch
self.bitline_layer = "m2" # self.bitline_layer = "m1"
# else:
# self.sel_layer = "m1"
# self.sel_pitch = self.m2_pitch
# self.bitline_layer = "m2"
if preferred_directions[self.sel_layer] == "V": if preferred_directions[self.sel_layer] == "V":
self.via_directions = ("H", "H") self.via_directions = ("H", "H")
@ -123,7 +128,7 @@ class column_mux_array(design.design):
# For every column, add a pass gate # For every column, add a pass gate
for col_num, xoffset in enumerate(self.offsets[0:self.columns]): for col_num, xoffset in enumerate(self.offsets[0:self.columns]):
if cell_properties.bitcell.mirror.y and (col_num + self.column_offset) % 2: if cell_props.bitcell.mirror.y and (col_num + self.column_offset) % 2:
mirror = "MY" mirror = "MY"
xoffset = xoffset + self.mux.width xoffset = xoffset + self.mux.width
else: else:

View File

@ -11,6 +11,7 @@ import math
from sram_factory import factory from sram_factory import factory
from vector import vector from vector import vector
from globals import OPTS from globals import OPTS
from tech import layer_properties as layer_props
class hierarchical_decoder(design.design): class hierarchical_decoder(design.design):
@ -181,25 +182,15 @@ class hierarchical_decoder(design.design):
# Inputs to cells are on input layer # Inputs to cells are on input layer
# Outputs from cells are on output layer # Outputs from cells are on output layer
if OPTS.tech_name == "sky130":
self.bus_layer = "m1"
self.bus_directions = "nonpref"
self.bus_pitch = self.m1_pitch
self.bus_space = self.m2_space
self.input_layer = "m2"
self.output_layer = "li"
self.output_layer_pitch = self.li_pitch
else:
self.bus_layer = "m2"
self.bus_directions = "pref"
self.bus_pitch = self.m2_pitch
self.bus_space = self.m2_space
# These two layers being the same requires a special jog
# to ensure to conflicts with the output layers
self.input_layer = "m1"
self.output_layer = "m3"
self.output_layer_pitch = self.m3_pitch
self.bus_layer = layer_props.hierarchical_decoder.bus_layer
self.bus_directions = layer_props.hierarchical_decoder.bus_directions
self.bus_pitch = getattr(self, self.bus_layer + "_pitch")
self.bus_space = getattr(self, self.bus_layer + "_space")
self.input_layer = layer_props.hierarchical_decoder.input_layer
self.output_layer = layer_props.hierarchical_decoder.output_layer
self.output_layer_pitch = getattr(self, self.output_layer + "_pitch")
# Two extra pitches between modules on left and right # Two extra pitches between modules on left and right
self.internal_routing_width = self.total_number_of_predecoder_outputs * self.bus_pitch + self.bus_pitch self.internal_routing_width = self.total_number_of_predecoder_outputs * self.bus_pitch + self.bus_pitch
self.row_decoder_height = self.and2.height * self.num_outputs self.row_decoder_height = self.and2.height * self.num_outputs
@ -606,7 +597,7 @@ class hierarchical_decoder(design.design):
must-connects next level up. must-connects next level up.
""" """
if OPTS.tech_name == "sky130": if layer_props.hierarchical_decoder.vertical_supply:
for n in ["vdd", "gnd"]: for n in ["vdd", "gnd"]:
pins = self.and_inst[0].get_pins(n) pins = self.and_inst[0].get_pins(n)
for pin in pins: for pin in pins:
@ -678,9 +669,9 @@ class hierarchical_decoder(design.design):
mid_point2 = vector(x_offset, y_offset) mid_point2 = vector(x_offset, y_offset)
rail_pos = vector(self.predecode_bus[rail_name].cx(), mid_point2.y) rail_pos = vector(self.predecode_bus[rail_name].cx(), mid_point2.y)
self.add_path(self.output_layer, [pin_pos, mid_point1, mid_point2, rail_pos]) self.add_path(self.output_layer, [pin_pos, mid_point1, mid_point2, rail_pos])
if OPTS.tech_name == "sky130": if layer_props.hierarchical_decoder.vertical_supply:
above_rail = vector(self.predecode_bus[rail_name].cx(), mid_point2.y + (self.cell_height/2)) above_rail = vector(self.predecode_bus[rail_name].cx(), mid_point2.y + (self.cell_height / 2))
self.add_path(self.bus_layer, [rail_pos, above_rail], width = self.li_width + self.m1_enclose_mcon * 2) self.add_path(self.bus_layer, [rail_pos, above_rail], width=self.li_width + self.m1_enclose_mcon * 2)
# pin_pos = pin.center() # pin_pos = pin.center()
# rail_pos = vector(self.predecode_bus[rail_name].cx(), pin_pos.y) # rail_pos = vector(self.predecode_bus[rail_name].cx(), pin_pos.y)

View File

@ -11,6 +11,7 @@ import math
from vector import vector from vector import vector
from sram_factory import factory from sram_factory import factory
from globals import OPTS from globals import OPTS
from tech import layer_properties as layer_props
class hierarchical_predecode(design.design): class hierarchical_predecode(design.design):
@ -83,24 +84,15 @@ class hierarchical_predecode(design.design):
# Inputs to cells are on input layer # Inputs to cells are on input layer
# Outputs from cells are on output layer # Outputs from cells are on output layer
if OPTS.tech_name == "sky130":
self.bus_layer = "m1" self.bus_layer = layer_props.hierarchical_predecode.bus_layer
self.bus_directions = "nonpref" self.bus_directions = layer_props.hierarchical_predecode.bus_directions
self.bus_pitch = self.m1_pitch self.bus_pitch = getattr(self, self.bus_layer + "_pitch")
self.bus_space = 1.5 * self.m1_space self.bus_space = layer_props.hierarchical_predecode.bus_space_factor * getattr(self, self.bus_layer + "_space")
self.input_layer = "m2" self.input_layer = layer_props.hierarchical_decoder.input_layer
self.output_layer = "li" self.output_layer = layer_props.hierarchical_decoder.output_layer
self.output_layer_pitch = self.li_pitch self.output_layer_pitch = getattr(self, self.output_layer + "_pitch")
else:
self.bus_layer = "m2"
self.bus_directions = "pref"
self.bus_pitch = self.m2_pitch
self.bus_space = self.m2_space
# This requires a special jog to ensure to conflicts with the output layers
self.input_layer = "m1"
self.output_layer = "m1"
self.output_layer_pitch = self.m1_pitch
self.height = self.number_of_outputs * self.and_mod.height self.height = self.number_of_outputs * self.and_mod.height
# x offset for input inverters # x offset for input inverters
@ -276,9 +268,9 @@ class hierarchical_predecode(design.design):
height=via.mod.second_layer_height, height=via.mod.second_layer_height,
width=via.mod.second_layer_width) width=via.mod.second_layer_width)
if OPTS.tech_name == "sky130": if layer_props.hierarchical_predecode.vertical_supply:
below_rail = vector(self.decode_rails[out_pin].cx(), y_offset - (self.cell_height/2)) below_rail = vector(self.decode_rails[out_pin].cx(), y_offset - (self.cell_height / 2))
self.add_path(self.bus_layer, [rail_pos, below_rail], width = self.li_width + self.m1_enclose_mcon * 2) self.add_path(self.bus_layer, [rail_pos, below_rail], width=self.li_width + self.m1_enclose_mcon * 2)
def route_and_to_rails(self): def route_and_to_rails(self):
# This 2D array defines the connection mapping # This 2D array defines the connection mapping
@ -319,8 +311,8 @@ class hierarchical_predecode(design.design):
def route_vdd_gnd(self): def route_vdd_gnd(self):
""" Add a pin for each row of vdd/gnd which are must-connects next level up. """ """ Add a pin for each row of vdd/gnd which are must-connects next level up. """
# In sky130, we use hand-made decoder cells with vertical power # We may ahve vertical power supply rails
if OPTS.tech_name == "sky130" and not self.column_decoder: if layer_props.hierarchical_predecode.vertical_supply and not self.column_decoder:
for n in ["vdd", "gnd"]: for n in ["vdd", "gnd"]:
# This makes a wire from top to bottom for both inv and and gates # This makes a wire from top to bottom for both inv and and gates
for i in [self.inv_inst, self.and_inst]: for i in [self.inv_inst, self.and_inst]:

View File

@ -10,6 +10,7 @@ from sram_factory import factory
from vector import vector from vector import vector
from tech import layer from tech import layer
from globals import OPTS from globals import OPTS
from tech import layer_properties as layer_props
class port_address(design.design): class port_address(design.design):
@ -80,7 +81,7 @@ class port_address(design.design):
self.copy_power_pins(inst, "gnd") self.copy_power_pins(inst, "gnd")
for rbl_vdd_pin in self.rbl_driver_inst.get_pins("vdd"): for rbl_vdd_pin in self.rbl_driver_inst.get_pins("vdd"):
if OPTS.tech_name == "sky130": if layer_props.port_address.supply_offset:
self.add_power_pin("vdd", rbl_vdd_pin.center()) self.add_power_pin("vdd", rbl_vdd_pin.center())
else: else:
self.add_power_pin("vdd", rbl_vdd_pin.lc()) self.add_power_pin("vdd", rbl_vdd_pin.lc())

View File

@ -11,6 +11,7 @@ from sram_factory import factory
from collections import namedtuple from collections import namedtuple
from vector import vector from vector import vector
from globals import OPTS from globals import OPTS
from tech import layer_properties as layer_props
class port_data(design.design): class port_data(design.design):
@ -580,20 +581,20 @@ class port_data(design.design):
inst1_start_bit=self.num_cols + off, inst1_start_bit=self.num_cols + off,
inst2_start_bit=self.word_size) inst2_start_bit=self.word_size)
# This could be a channel route, but in some techs the bitlines elif layer_props.port_data.channel_route_bitlines:
# are too close together.
elif OPTS.tech_name == "sky130":
self.connect_bitlines(inst1=inst1,
inst1_bls_template=inst1_bls_templ,
inst2=inst2,
num_bits=self.word_size,
inst1_start_bit=start_bit)
else:
self.channel_route_bitlines(inst1=inst1, self.channel_route_bitlines(inst1=inst1,
inst1_bls_template=inst1_bls_templ, inst1_bls_template=inst1_bls_templ,
inst2=inst2, inst2=inst2,
num_bits=self.word_size + self.num_spare_cols, num_bits=self.word_size + self.num_spare_cols,
inst1_start_bit=start_bit) inst1_start_bit=start_bit)
# This could be a channel route, but in some techs the bitlines
# are too close together.
else:
self.connect_bitlines(inst1=inst1,
inst1_bls_template=inst1_bls_templ,
inst2=inst2,
num_bits=self.word_size,
inst1_start_bit=start_bit)
def route_write_driver_to_column_mux_or_precharge_array(self, port): def route_write_driver_to_column_mux_or_precharge_array(self, port):
""" Routing of BL and BR between sense_amp and column mux or precharge array """ """ Routing of BL and BR between sense_amp and column mux or precharge array """
@ -640,17 +641,16 @@ class port_data(design.design):
# This could be a channel route, but in some techs the bitlines # This could be a channel route, but in some techs the bitlines
# are too close together. # are too close together.
elif OPTS.tech_name == "sky130": elif layer_props.port_data.channel_route_bitlines:
self.channel_route_bitlines(inst1=inst1, inst2=inst2,
num_bits=self.word_size + self.num_spare_cols,
inst1_bls_template=inst1_bls_templ,
inst1_start_bit=start_bit)
else:
self.connect_bitlines(inst1=inst1, inst2=inst2, self.connect_bitlines(inst1=inst1, inst2=inst2,
num_bits=self.word_size, num_bits=self.word_size,
inst1_bls_template=inst1_bls_templ, inst1_bls_template=inst1_bls_templ,
inst1_start_bit=start_bit) inst1_start_bit=start_bit)
else:
self.channel_route_bitlines(inst1=inst1, inst2=inst2,
num_bits=self.word_size+self.num_spare_cols,
inst1_bls_template=inst1_bls_templ,
inst1_start_bit=start_bit)
def route_write_driver_to_sense_amp(self, port): def route_write_driver_to_sense_amp(self, port):
""" Routing of BL and BR between write driver and sense amp """ """ Routing of BL and BR between write driver and sense amp """

View File

@ -9,6 +9,7 @@ from tech import cell_properties
from sram_factory import factory from sram_factory import factory
from vector import vector from vector import vector
from globals import OPTS from globals import OPTS
from tech import layer_properties as layer_props
class replica_column(bitcell_base_array): class replica_column(bitcell_base_array):
@ -41,7 +42,7 @@ class replica_column(bitcell_base_array):
"Replica bit cannot be the dummy row.") "Replica bit cannot be the dummy row.")
debug.check(replica_bit <= self.left_rbl or replica_bit >= self.total_size - self.right_rbl - 1, debug.check(replica_bit <= self.left_rbl or replica_bit >= self.total_size - self.right_rbl - 1,
"Replica bit cannot be in the regular array.") "Replica bit cannot be in the regular array.")
if OPTS.tech_name == "sky130": if layer_props.replica_column.even_rows:
debug.check(rows % 2 == 0 and (self.left_rbl + 1) % 2 == 0, debug.check(rows % 2 == 0 and (self.left_rbl + 1) % 2 == 0,
"sky130 currently requires rows to be even and to start with X mirroring" "sky130 currently requires rows to be even and to start with X mirroring"
+ " (left_rbl must be odd) for LVS.") + " (left_rbl must be odd) for LVS.")

View File

@ -7,10 +7,11 @@
# #
import debug import debug
import design import design
from tech import drc, layer from tech import layer
from vector import vector from vector import vector
from sram_factory import factory from sram_factory import factory
from globals import OPTS from globals import OPTS
from tech import layer_properties as layer_props
class wordline_buffer_array(design.design): class wordline_buffer_array(design.design):
@ -70,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 OPTS.tech_name == "sky130": if layer_props.wordline_buffer_array.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

@ -11,6 +11,7 @@ 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 globals import OPTS
from tech import layer_properties as layer_props
class wordline_driver_array(design.design): class wordline_driver_array(design.design):
@ -71,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 OPTS.tech_name == "sky130": if layer_props.wordline_buffer_array.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

@ -5,7 +5,6 @@
# (acting for and on behalf of Oklahoma State University) # (acting for and on behalf of Oklahoma State University)
# All rights reserved. # All rights reserved.
# #
import contact
import pgate import pgate
import debug import debug
from globals import OPTS from globals import OPTS

View File

@ -9,6 +9,7 @@ import os
from design_rules import * from design_rules import *
from module_type import * from module_type import *
from custom_cell_properties import cell_properties from custom_cell_properties import cell_properties
from custom_layer_properties import layer_properties
""" """
File containing the process technology parameters for FreePDK 45nm. File containing the process technology parameters for FreePDK 45nm.
@ -34,6 +35,11 @@ cell_properties.bitcell.mirror.x = True
cell_properties.bitcell.mirror.y = False cell_properties.bitcell.mirror.y = False
cell_properties.bitcell_power_pin_directions = ("V", "V") cell_properties.bitcell_power_pin_directions = ("V", "V")
###################################################
# Custom cell properties
###################################################
layer_properties = layer_properties()
################################################### ###################################################
# GDS file info # GDS file info
################################################### ###################################################

View File

@ -9,6 +9,7 @@ import os
from design_rules import * from design_rules import *
from module_type import * from module_type import *
from custom_cell_properties import cell_properties from custom_cell_properties import cell_properties
from custom_layer_properties import layer_properties
""" """
File containing the process technology parameters for SCMOS 4m, 0.35um File containing the process technology parameters for SCMOS 4m, 0.35um
@ -32,6 +33,11 @@ cell_properties = cell_properties()
cell_properties.bitcell.mirror.x = True cell_properties.bitcell.mirror.x = True
cell_properties.bitcell.mirror.y = False cell_properties.bitcell.mirror.y = False
###################################################
# Custom cell properties
###################################################
layer_properties = layer_properties()
################################################### ###################################################
# GDS file info # GDS file info
################################################### ###################################################