diff --git a/compiler/base/custom_layer_properties.py b/compiler/base/custom_layer_properties.py index f1d35e71..c2dcae88 100644 --- a/compiler/base/custom_layer_properties.py +++ b/compiler/base/custom_layer_properties.py @@ -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 diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index a1c6c251..335ee2b2 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -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: diff --git a/compiler/modules/column_mux_array.py b/compiler/modules/column_mux_array.py index 87e750cf..61c71672 100644 --- a/compiler/modules/column_mux_array.py +++ b/compiler/modules/column_mux_array.py @@ -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: diff --git a/compiler/modules/hierarchical_decoder.py b/compiler/modules/hierarchical_decoder.py index f022a048..a5a63fc8 100644 --- a/compiler/modules/hierarchical_decoder.py +++ b/compiler/modules/hierarchical_decoder.py @@ -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) diff --git a/compiler/modules/hierarchical_predecode.py b/compiler/modules/hierarchical_predecode.py index f5bff640..fff2de4b 100644 --- a/compiler/modules/hierarchical_predecode.py +++ b/compiler/modules/hierarchical_predecode.py @@ -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]: diff --git a/compiler/modules/port_address.py b/compiler/modules/port_address.py index e416eb43..14d0b833 100644 --- a/compiler/modules/port_address.py +++ b/compiler/modules/port_address.py @@ -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()) diff --git a/compiler/modules/port_data.py b/compiler/modules/port_data.py index c013bc4a..636f4b44 100644 --- a/compiler/modules/port_data.py +++ b/compiler/modules/port_data.py @@ -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 """ diff --git a/compiler/modules/replica_column.py b/compiler/modules/replica_column.py index d7e36fce..0ce472c3 100644 --- a/compiler/modules/replica_column.py +++ b/compiler/modules/replica_column.py @@ -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.") diff --git a/compiler/modules/wordline_buffer_array.py b/compiler/modules/wordline_buffer_array.py index 45f3ef33..6f728497 100644 --- a/compiler/modules/wordline_buffer_array.py +++ b/compiler/modules/wordline_buffer_array.py @@ -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: diff --git a/compiler/modules/wordline_driver_array.py b/compiler/modules/wordline_driver_array.py index c334404e..5d93758a 100644 --- a/compiler/modules/wordline_driver_array.py +++ b/compiler/modules/wordline_driver_array.py @@ -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: diff --git a/compiler/pgates/pnor2.py b/compiler/pgates/pnor2.py index 331a0745..b3d4d5ee 100644 --- a/compiler/pgates/pnor2.py +++ b/compiler/pgates/pnor2.py @@ -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 diff --git a/technology/freepdk45/tech/tech.py b/technology/freepdk45/tech/tech.py index abe09e34..7aeb3e21 100644 --- a/technology/freepdk45/tech/tech.py +++ b/technology/freepdk45/tech/tech.py @@ -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 ################################################### diff --git a/technology/scn4m_subm/tech/tech.py b/technology/scn4m_subm/tech/tech.py index 41801566..f9a99a86 100644 --- a/technology/scn4m_subm/tech/tech.py +++ b/technology/scn4m_subm/tech/tech.py @@ -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 ###################################################