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

View File

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

View File

@ -11,7 +11,8 @@ from tech import layer, preferred_directions
from vector import vector
from sram_factory import factory
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):
@ -33,14 +34,18 @@ class column_mux_array(design.design):
self.bitcell_br = bitcell_br
self.column_offset = column_offset
if OPTS.tech_name == "sky130":
self.sel_layer = "m3"
self.sel_pitch = self.m3_pitch
self.bitline_layer = "m1"
else:
self.sel_layer = "m1"
self.sel_pitch = self.m2_pitch
self.bitline_layer = "m2"
self.sel_layer = layer_props.column_mux_array.select_layer
self.sel_pitch = getattr(self, layer_props.column_mux_array.select_pitch)
self.bitline_layer = layer_props.column_mux_array.bitline_layer
# if OPTS.tech_name == "sky130":
# self.sel_layer = "m3"
# self.sel_pitch = self.m3_pitch
# 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":
self.via_directions = ("H", "H")
@ -123,7 +128,7 @@ class column_mux_array(design.design):
# For every column, add a pass gate
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"
xoffset = xoffset + self.mux.width
else:

View File

@ -11,6 +11,7 @@ import math
from sram_factory import factory
from vector import vector
from globals import OPTS
from tech import layer_properties as layer_props
class hierarchical_decoder(design.design):
@ -181,25 +182,15 @@ class hierarchical_decoder(design.design):
# Inputs to cells are on input 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
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
@ -606,7 +597,7 @@ class hierarchical_decoder(design.design):
must-connects next level up.
"""
if OPTS.tech_name == "sky130":
if layer_props.hierarchical_decoder.vertical_supply:
for n in ["vdd", "gnd"]:
pins = self.and_inst[0].get_pins(n)
for pin in pins:
@ -678,9 +669,9 @@ class hierarchical_decoder(design.design):
mid_point2 = vector(x_offset, y_offset)
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])
if OPTS.tech_name == "sky130":
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)
if layer_props.hierarchical_decoder.vertical_supply:
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)
# pin_pos = pin.center()
# 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 sram_factory import factory
from globals import OPTS
from tech import layer_properties as layer_props
class hierarchical_predecode(design.design):
@ -83,24 +84,15 @@ class hierarchical_predecode(design.design):
# Inputs to cells are on input 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 = 1.5 * self.m1_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
# 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.bus_layer = layer_props.hierarchical_predecode.bus_layer
self.bus_directions = layer_props.hierarchical_predecode.bus_directions
self.bus_pitch = getattr(self, self.bus_layer + "_pitch")
self.bus_space = layer_props.hierarchical_predecode.bus_space_factor * 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")
self.height = self.number_of_outputs * self.and_mod.height
# x offset for input inverters
@ -276,9 +268,9 @@ class hierarchical_predecode(design.design):
height=via.mod.second_layer_height,
width=via.mod.second_layer_width)
if OPTS.tech_name == "sky130":
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)
if layer_props.hierarchical_predecode.vertical_supply:
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)
def route_and_to_rails(self):
# This 2D array defines the connection mapping
@ -319,8 +311,8 @@ class hierarchical_predecode(design.design):
def route_vdd_gnd(self):
""" 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
if OPTS.tech_name == "sky130" and not self.column_decoder:
# We may ahve vertical power supply rails
if layer_props.hierarchical_predecode.vertical_supply and not self.column_decoder:
for n in ["vdd", "gnd"]:
# This makes a wire from top to bottom for both inv and and gates
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 tech import layer
from globals import OPTS
from tech import layer_properties as layer_props
class port_address(design.design):
@ -80,7 +81,7 @@ class port_address(design.design):
self.copy_power_pins(inst, "gnd")
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())
else:
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 vector import vector
from globals import OPTS
from tech import layer_properties as layer_props
class port_data(design.design):
@ -580,20 +581,20 @@ class port_data(design.design):
inst1_start_bit=self.num_cols + off,
inst2_start_bit=self.word_size)
# This could be a channel route, but in some techs the 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:
elif layer_props.port_data.channel_route_bitlines:
self.channel_route_bitlines(inst1=inst1,
inst1_bls_template=inst1_bls_templ,
inst2=inst2,
num_bits=self.word_size + self.num_spare_cols,
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):
""" 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
# 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,
num_bits=self.word_size,
inst1_bls_template=inst1_bls_templ,
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):
""" 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 vector import vector
from globals import OPTS
from tech import layer_properties as layer_props
class replica_column(bitcell_base_array):
@ -41,7 +42,7 @@ class replica_column(bitcell_base_array):
"Replica bit cannot be the dummy row.")
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.")
if OPTS.tech_name == "sky130":
if layer_props.replica_column.even_rows:
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"
+ " (left_rbl must be odd) for LVS.")

View File

@ -7,10 +7,11 @@
#
import debug
import design
from tech import drc, layer
from tech import layer
from vector import vector
from sram_factory import factory
from globals import OPTS
from tech import layer_properties as layer_props
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
are must-connects next level up.
"""
if OPTS.tech_name == "sky130":
if layer_props.wordline_buffer_array.vertical_supply:
for name in ["vdd", "gnd"]:
supply_pins = self.wld_inst[0].get_pins(name)
for pin in supply_pins:

View File

@ -11,6 +11,7 @@ from tech import drc, layer
from vector import vector
from sram_factory import factory
from globals import OPTS
from tech import layer_properties as layer_props
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
are must-connects next level up.
"""
if OPTS.tech_name == "sky130":
if layer_props.wordline_buffer_array.vertical_supply:
for name in ["vdd", "gnd"]:
supply_pins = self.wld_inst[0].get_pins(name)
for pin in supply_pins:

View File

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

View File

@ -9,6 +9,7 @@ import os
from design_rules import *
from module_type import *
from custom_cell_properties import cell_properties
from custom_layer_properties import layer_properties
"""
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_power_pin_directions = ("V", "V")
###################################################
# Custom cell properties
###################################################
layer_properties = layer_properties()
###################################################
# GDS file info
###################################################

View File

@ -9,6 +9,7 @@ import os
from design_rules import *
from module_type import *
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
@ -32,6 +33,11 @@ cell_properties = cell_properties()
cell_properties.bitcell.mirror.x = True
cell_properties.bitcell.mirror.y = False
###################################################
# Custom cell properties
###################################################
layer_properties = layer_properties()
###################################################
# GDS file info
###################################################