Merge branch 'dev' into s8_single_port

This commit is contained in:
jcirimel 2020-11-03 03:45:34 -08:00
commit d69ca2b1ed
58 changed files with 594 additions and 447 deletions

View File

@ -51,8 +51,8 @@ class contact(hierarchy_design.hierarchy_design):
# Non-preferred directions # Non-preferred directions
if directions == "nonpref": if directions == "nonpref":
first_dir = "H" if self.get_preferred_direction(layer_stack[0])=="V" else "V" first_dir = "H" if tech.preferred_directions[layer_stack[0]]=="V" else "V"
second_dir = "H" if self.get_preferred_direction(layer_stack[2])=="V" else "V" second_dir = "H" if tech.preferred_directions[layer_stack[2]]=="V" else "V"
self.directions = (first_dir, second_dir) self.directions = (first_dir, second_dir)
# Preferred directions # Preferred directions
elif directions == "pref": elif directions == "pref":

View File

@ -7,13 +7,15 @@
# #
from globals import OPTS from globals import OPTS
class _pins: class _pins:
def __init__(self, pin_dict): def __init__(self, pin_dict):
# make the pins elements of the class to allow "." access. # make the pins elements of the class to allow "." access.
# For example: props.bitcell.cell_6t.pin.bl = "foobar" # For example: props.bitcell.cell_6t.pin.bl = "foobar"
for k,v in pin_dict.items(): for k, v in pin_dict.items():
self.__dict__[k] = v self.__dict__[k] = v
class _cell: class _cell:
def __init__(self, pin_dict): def __init__(self, pin_dict):
pin_dict.update(self._default_power_pins()) pin_dict.update(self._default_power_pins())
@ -24,13 +26,27 @@ class _cell:
return self._pins return self._pins
def _default_power_pins(self): def _default_power_pins(self):
return { 'vdd' : 'vdd', 'gnd' : 'gnd' } return {'vdd': 'vdd',
'gnd': 'gnd'}
class _mirror_axis: class _mirror_axis:
def __init__(self, x, y): def __init__(self, x, y):
self.x = x self.x = x
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
@ -42,27 +58,27 @@ class _bitcell:
def _default(): def _default():
axis = _mirror_axis(True, False) axis = _mirror_axis(True, False)
cell_s8_6t = _cell({'bl' : 'bl', cell_s8_6t = _cell({'bl': 'bl',
'br' : 'br', 'br': 'br',
'wl': 'wl'}) 'wl': 'wl'})
cell_6t = _cell({'bl' : 'bl', cell_6t = _cell({'bl': 'bl',
'br' : 'br', 'br': 'br',
'wl' : 'wl'}) 'wl': 'wl'})
cell_1rw1r = _cell({'bl0' : 'bl0', cell_1rw1r = _cell({'bl0': 'bl0',
'br0' : 'br0', 'br0': 'br0',
'bl1' : 'bl1', 'bl1': 'bl1',
'br1' : 'br1', 'br1': 'br1',
'wl0' : 'wl0', 'wl0': 'wl0',
'wl1' : 'wl1'}) 'wl1': 'wl1'})
cell_1w1r = _cell({'bl0' : 'bl0', cell_1w1r = _cell({'bl0': 'bl0',
'br0' : 'br0', 'br0': 'br0',
'bl1' : 'bl1', 'bl1': 'bl1',
'br1' : 'br1', 'br1': 'br1',
'wl0' : 'wl0', 'wl0': 'wl0',
'wl1' : 'wl1'}) 'wl1': 'wl1'})
return _bitcell(cell_s8_6t=cell_s8_6t, return _bitcell(cell_s8_6t=cell_s8_6t,
cell_6t=cell_6t, cell_6t=cell_6t,
@ -94,21 +110,25 @@ class _dff:
self.custom_type_list = custom_type_list self.custom_type_list = custom_type_list
self.clk_pin = clk_pin self.clk_pin = clk_pin
class _dff_buff: class _dff_buff:
def __init__(self, use_custom_ports, custom_buff_ports, add_body_contacts): def __init__(self, use_custom_ports, custom_buff_ports, add_body_contacts):
self.use_custom_ports = use_custom_ports self.use_custom_ports = use_custom_ports
self.buf_ports = custom_buff_ports self.buf_ports = custom_buff_ports
self.add_body_contacts = add_body_contacts self.add_body_contacts = add_body_contacts
class _dff_buff_array: class _dff_buff_array:
def __init__(self, use_custom_ports, add_body_contacts): def __init__(self, use_custom_ports, add_body_contacts):
self.use_custom_ports = use_custom_ports self.use_custom_ports = use_custom_ports
self.add_body_contacts = add_body_contacts self.add_body_contacts = add_body_contacts
class _bitcell_array: class _bitcell_array:
def __init__(self, use_custom_cell_arrangement): def __init__(self, use_custom_cell_arrangement):
self.use_custom_cell_arrangement = use_custom_cell_arrangement self.use_custom_cell_arrangement = use_custom_cell_arrangement
class cell_properties(): class cell_properties():
""" """
This contains meta information about the custom designed cells. For This contains meta information about the custom designed cells. For
@ -119,35 +139,48 @@ class cell_properties():
self.names = {} self.names = {}
self._bitcell = _bitcell._default() self._bitcell = _bitcell._default()
self._dff = _dff(use_custom_ports = False,
custom_port_list = ["D", "Q", "clk", "vdd", "gnd"],
custom_type_list = ["INPUT", "OUTPUT", "INPUT", "POWER", "GROUND"],
clk_pin= "clk")
self._dff_buff = _dff_buff(use_custom_ports = False,
custom_buff_ports = ["D", "qint", "clk", "vdd", "gnd"],
add_body_contacts = False)
self._dff_buff_array = _dff_buff_array(use_custom_ports = False, self._ptx = _ptx(model_is_subckt=False,
add_body_contacts = 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"],
clk_pin="clk")
self._dff_buff = _dff_buff(use_custom_ports=False,
custom_buff_ports=["D", "qint", "clk", "vdd", "gnd"],
add_body_contacts=False)
self._dff_buff_array = _dff_buff_array(use_custom_ports=False,
add_body_contacts=False)
self._write_driver = _cell({'din': 'din', self._write_driver = _cell({'din': 'din',
'bl' : 'bl', 'bl': 'bl',
'br' : 'br', 'br': 'br',
'en' : 'en'}) 'en': 'en'})
self._sense_amp = _cell({'bl' : 'bl', self._sense_amp = _cell({'bl': 'bl',
'br' : 'br', 'br': 'br',
'dout' : 'dout', 'dout': 'dout',
'en' : 'en'}) 'en': 'en'})
self._bitcell_array = _bitcell_array(use_custom_cell_arrangement = []) self._bitcell_array = _bitcell_array(use_custom_cell_arrangement=[])
@property @property
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

@ -0,0 +1,193 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2020 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
class _bank:
def __init__(self, stack, pitch):
# bank
# column address route: stack, pitch
# m1_stack, m2_pitch (default)
# m2_stack, m3_pitch (sky130)
self.stack = stack
self.pitch = pitch
class _hierarchical_decoder:
def __init__(self,
bus_layer,
bus_directions,
input_layer,
output_layer,
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 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
# m1, nonpref, m1_pitch, 1`.5*m1_space, m2, li, li_pitch (sky130)
#
# vertical vdd/gnd
# special jogging
self.bus_layer = bus_layer
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
class _column_mux_array:
def __init__(self,
select_layer,
select_pitch,
bitline_layer):
# column_mux_array
# sel_layer, sel_pitch, bitline_layer
# m1, m2_pitch, m2
# m3, m3_pitch, m1 (sky130)
self.select_layer = select_layer
self.select_pitch= select_pitch
self.bitline_layer = bitline_layer
class _port_address:
def __init__(self,
supply_offset):
# port_adress
# special supply offset
self.supply_offset = supply_offset
class _port_data:
def __init__(self,
channel_route_bitlines,
enable_layer):
# port_data
# connect bitlines instead of chanel route
# sense_amp_array
# en_layer
# m1
# m3 (sky130)
# precharge_array
# en_bar_layer
# m1
# m3 (sky130)
self.channel_route_bitlines = channel_route_bitlines
self.enable_layer = enable_layer
class _replica_column:
def __init__(self,
even_rows):
# replica_column
# even row check (sky130)
self.even_rows = even_rows
class _wordline_driver:
def __init__(self,
vertical_supply):
# wordline_buffer_array
# vertical vdd/gnd (sky130)
# wordline_driver_array
# vertical vdd/gnd (sky130)
# wordline_driver
# vertical vdd/gnd (sky130)
self.vertical_supply = vertical_supply
class layer_properties():
"""
This contains meta information about the module routing layers. These
can be overriden in the tech.py file.
"""
def __init__(self):
self._bank = _bank(stack="m1_stack",
pitch="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=True,
enable_layer="m1")
self._replica_column = _replica_column(even_rows=False)
self._wordline_driver = _wordline_driver(vertical_supply=False)
@property
def bank(self):
return self._bank
@property
def column_mux_array(self):
return self._column_mux_array
@property
def hierarchical_decoder(self):
return self._hierarchical_decoder
@property
def hierarchical_predecode(self):
return self._hierarchical_predecode
@property
def port_address(self):
return self._port_address
@property
def port_data(self):
return self._port_data
@property
def replica_column(self):
return self._replica_column
@property
def wordline_driver(self):
return self._wordline_driver

View File

@ -8,6 +8,7 @@
from hierarchy_design import hierarchy_design from hierarchy_design import hierarchy_design
from utils import round_to_grid from utils import round_to_grid
import contact import contact
from tech import preferred_directions
from globals import OPTS from globals import OPTS
import re import re
@ -18,21 +19,110 @@ class design(hierarchy_design):
some DRC/layer constants and analytical models for other modules to reuse. some DRC/layer constants and analytical models for other modules to reuse.
""" """
def __init__(self, name): def __init__(self, name):
super().__init__(name) super().__init__(name)
self.setup_drc_constants()
self.setup_layer_constants()
self.setup_multiport_constants()
self.setup_multiport_constants()
def check_pins(self): def check_pins(self):
for pin_name in self.pins: for pin_name in self.pins:
pins = self.get_pins(pin_name) pins = self.get_pins(pin_name)
for pin in pins: for pin in pins:
print(pin_name, pin) print(pin_name, pin)
@classmethod
def setup_drc_constants(design):
"""
These are some DRC constants used in many places
in the compiler.
"""
# Make some local rules for convenience
from tech import drc
for rule in drc.keys():
# Single layer width rules
match = re.search(r"minwidth_(.*)", rule)
if match:
if match.group(1) == "active_contact":
setattr(design, "contact_width", drc(match.group(0)))
else:
setattr(design, match.group(1) + "_width", drc(match.group(0)))
# Single layer area rules
match = re.search(r"minarea_(.*)", rule)
if match:
setattr(design, match.group(0), drc(match.group(0)))
# Single layer spacing rules
match = re.search(r"(.*)_to_(.*)", rule)
if match and match.group(1) == match.group(2):
setattr(design, match.group(1) + "_space", drc(match.group(0)))
elif match and match.group(1) != match.group(2):
if match.group(2) == "poly_active":
setattr(design, match.group(1) + "_to_contact",
drc(match.group(0)))
else:
setattr(design, match.group(0), drc(match.group(0)))
match = re.search(r"(.*)_enclose_(.*)", rule)
if match:
setattr(design, match.group(0), drc(match.group(0)))
match = re.search(r"(.*)_extend_(.*)", rule)
if match:
setattr(design, match.group(0), drc(match.group(0)))
# Create the maximum well extend active that gets used
# by cells to extend the wells for interaction with other cells
from tech import layer
design.well_extend_active = 0
if "nwell" in layer:
design.well_extend_active = max(design.well_extend_active, design.nwell_extend_active)
if "pwell" in layer:
design.well_extend_active = max(design.well_extend_active, design.pwell_extend_active)
# The active offset is due to the well extension
if "pwell" in layer:
design.pwell_enclose_active = drc("pwell_enclose_active")
else:
design.pwell_enclose_active = 0
if "nwell" in layer:
design.nwell_enclose_active = drc("nwell_enclose_active")
else:
design.nwell_enclose_active = 0
# Use the max of either so that the poly gates will align properly
design.well_enclose_active = max(design.pwell_enclose_active,
design.nwell_enclose_active,
design.active_space)
def setup_layer_constants(self): # These are for debugging previous manual rules
if False:
print("poly_width", design.poly_width)
print("poly_space", design.poly_space)
print("m1_width", design.m1_width)
print("m1_space", design.m1_space)
print("m2_width", design.m2_width)
print("m2_space", design.m2_space)
print("m3_width", design.m3_width)
print("m3_space", design.m3_space)
print("m4_width", design.m4_width)
print("m4_space", design.m4_space)
print("active_width", design.active_width)
print("active_space", design.active_space)
print("contact_width", design.contact_width)
print("poly_to_active", design.poly_to_active)
print("poly_extend_active", design.poly_extend_active)
print("poly_to_contact", design.poly_to_contact)
print("active_contact_to_gate", design.active_contact_to_gate)
print("poly_contact_to_gate", design.poly_contact_to_gate)
print("well_enclose_active", design.well_enclose_active)
print("implant_enclose_active", design.implant_enclose_active)
print("implant_space", design.implant_space)
import sys
sys.exit(1)
@classmethod
def setup_layer_constants(design):
""" """
These are some layer constants used These are some layer constants used
in many places in the compiler. in many places in the compiler.
@ -46,7 +136,7 @@ class design(hierarchy_design):
# Set the stack as a local helper # Set the stack as a local helper
try: try:
layer_stack = getattr(tech, key) layer_stack = getattr(tech, key)
setattr(self, key, layer_stack) setattr(design, key, layer_stack)
except AttributeError: except AttributeError:
pass pass
@ -55,14 +145,14 @@ class design(hierarchy_design):
continue continue
# Add the pitch # Add the pitch
setattr(self, setattr(design,
"{}_pitch".format(layer), "{}_pitch".format(layer),
self.compute_pitch(layer, True)) design.compute_pitch(layer, True))
# Add the non-preferrd pitch (which has vias in the "wrong" way) # Add the non-preferrd pitch (which has vias in the "wrong" way)
setattr(self, setattr(design,
"{}_nonpref_pitch".format(layer), "{}_nonpref_pitch".format(layer),
self.compute_pitch(layer, False)) design.compute_pitch(layer, False))
if False: if False:
from tech import preferred_directions from tech import preferred_directions
@ -73,17 +163,18 @@ class design(hierarchy_design):
continue continue
try: try:
print("{0} width {1} space {2}".format(name, print("{0} width {1} space {2}".format(name,
getattr(self, "{}_width".format(name)), getattr(design, "{}_width".format(name)),
getattr(self, "{}_space".format(name)))) getattr(design, "{}_space".format(name))))
print("pitch {0} nonpref {1}".format(getattr(self, "{}_pitch".format(name)), print("pitch {0} nonpref {1}".format(getattr(design, "{}_pitch".format(name)),
getattr(self, "{}_nonpref_pitch".format(name)))) getattr(design, "{}_nonpref_pitch".format(name))))
except AttributeError: except AttributeError:
pass pass
import sys import sys
sys.exit(1) sys.exit(1)
def compute_pitch(self, layer, preferred=True): @staticmethod
def compute_pitch(layer, preferred=True):
""" """
This is the preferred direction pitch This is the preferred direction pitch
@ -95,13 +186,18 @@ class design(hierarchy_design):
for stack in layer_stacks: for stack in layer_stacks:
# Compute the pitch with both vias above and below (if they exist) # Compute the pitch with both vias above and below (if they exist)
if stack[0] == layer: if stack[0] == layer:
pitches.append(self.compute_layer_pitch(stack, preferred)) pitches.append(design.compute_layer_pitch(stack, preferred))
if stack[2] == layer: if stack[2] == layer:
pitches.append(self.compute_layer_pitch(stack[::-1], True)) pitches.append(design.compute_layer_pitch(stack[::-1], True))
return max(pitches) return max(pitches)
def compute_layer_pitch(self, layer_stack, preferred): @staticmethod
def get_preferred_direction(layer):
return preferred_directions[layer]
@staticmethod
def compute_layer_pitch(layer_stack, preferred):
(layer1, via, layer2) = layer_stack (layer1, via, layer2) = layer_stack
try: try:
@ -113,112 +209,24 @@ class design(hierarchy_design):
contact1 = getattr(contact, layer2 + "_via") contact1 = getattr(contact, layer2 + "_via")
if preferred: if preferred:
if self.get_preferred_direction(layer1) == "V": if preferred_directions[layer1] == "V":
contact_width = contact1.first_layer_width contact_width = contact1.first_layer_width
else: else:
contact_width = contact1.first_layer_height contact_width = contact1.first_layer_height
else: else:
if self.get_preferred_direction(layer1) == "V": if preferred_directions[layer1] == "V":
contact_width = contact1.first_layer_height contact_width = contact1.first_layer_height
else: else:
contact_width = contact1.first_layer_width contact_width = contact1.first_layer_width
layer_space = getattr(self, layer1 + "_space") layer_space = getattr(design, layer1 + "_space")
#print(layer_stack) #print(layer_stack)
#print(contact1) #print(contact1)
pitch = contact_width + layer_space pitch = contact_width + layer_space
return round_to_grid(pitch) return round_to_grid(pitch)
def setup_drc_constants(self):
"""
These are some DRC constants used in many places
in the compiler.
"""
# Make some local rules for convenience
from tech import drc
for rule in drc.keys():
# Single layer width rules
match = re.search(r"minwidth_(.*)", rule)
if match:
if match.group(1) == "active_contact":
setattr(self, "contact_width", drc(match.group(0)))
else:
setattr(self, match.group(1) + "_width", drc(match.group(0)))
# Single layer area rules
match = re.search(r"minarea_(.*)", rule)
if match:
setattr(self, match.group(0), drc(match.group(0)))
# Single layer spacing rules
match = re.search(r"(.*)_to_(.*)", rule)
if match and match.group(1) == match.group(2):
setattr(self, match.group(1) + "_space", drc(match.group(0)))
elif match and match.group(1) != match.group(2):
if match.group(2) == "poly_active":
setattr(self, match.group(1) + "_to_contact",
drc(match.group(0)))
else:
setattr(self, match.group(0), drc(match.group(0)))
match = re.search(r"(.*)_enclose_(.*)", rule)
if match:
setattr(self, match.group(0), drc(match.group(0)))
match = re.search(r"(.*)_extend_(.*)", rule)
if match:
setattr(self, match.group(0), drc(match.group(0)))
# Create the maximum well extend active that gets used
# by cells to extend the wells for interaction with other cells
from tech import layer
self.well_extend_active = 0
if "nwell" in layer:
self.well_extend_active = max(self.well_extend_active, self.nwell_extend_active)
if "pwell" in layer:
self.well_extend_active = max(self.well_extend_active, self.pwell_extend_active)
# The active offset is due to the well extension
if "pwell" in layer:
self.pwell_enclose_active = drc("pwell_enclose_active")
else:
self.pwell_enclose_active = 0
if "nwell" in layer:
self.nwell_enclose_active = drc("nwell_enclose_active")
else:
self.nwell_enclose_active = 0
# Use the max of either so that the poly gates will align properly
self.well_enclose_active = max(self.pwell_enclose_active,
self.nwell_enclose_active,
self.active_space)
# These are for debugging previous manual rules
if False:
print("poly_width", self.poly_width)
print("poly_space", self.poly_space)
print("m1_width", self.m1_width)
print("m1_space", self.m1_space)
print("m2_width", self.m2_width)
print("m2_space", self.m2_space)
print("m3_width", self.m3_width)
print("m3_space", self.m3_space)
print("m4_width", self.m4_width)
print("m4_space", self.m4_space)
print("active_width", self.active_width)
print("active_space", self.active_space)
print("contact_width", self.contact_width)
print("poly_to_active", self.poly_to_active)
print("poly_extend_active", self.poly_extend_active)
print("poly_to_contact", self.poly_to_contact)
print("active_contact_to_gate", self.active_contact_to_gate)
print("poly_contact_to_gate", self.poly_contact_to_gate)
print("well_enclose_active", self.well_enclose_active)
print("implant_enclose_active", self.implant_enclose_active)
print("implant_space", self.implant_space)
import sys
sys.exit(1)
def setup_multiport_constants(self): def setup_multiport_constants(self):
""" """
These are contants and lists that aid multiport design. These are contants and lists that aid multiport design.
@ -266,3 +274,6 @@ class design(hierarchy_design):
total_module_power += inst.mod.analytical_power(corner, load) total_module_power += inst.mod.analytical_power(corner, load)
return total_module_power return total_module_power
design.setup_drc_constants()
design.setup_layer_constants()

View File

@ -13,7 +13,6 @@ from tech import drc, GDS
from tech import layer as techlayer from tech import layer as techlayer
from tech import layer_indices from tech import layer_indices
from tech import layer_stacks from tech import layer_stacks
from tech import preferred_directions
import os import os
from globals import OPTS from globals import OPTS
from vector import vector from vector import vector
@ -537,10 +536,6 @@ class layout():
position_list=coordinates, position_list=coordinates,
widen_short_wires=widen_short_wires) widen_short_wires=widen_short_wires)
def get_preferred_direction(self, layer):
""" Return the preferred routing directions """
return preferred_directions[layer]
def add_via(self, layers, offset, size=[1, 1], directions=None, implant_type=None, well_type=None): def add_via(self, layers, offset, size=[1, 1], directions=None, implant_type=None, well_type=None):
""" Add a three layer via structure. """ """ Add a three layer via structure. """
from sram_factory import factory from sram_factory import factory

View File

@ -10,7 +10,7 @@ import utils
from tech import GDS, layer from tech import GDS, layer
from tech import cell_properties as props from tech import cell_properties as props
import bitcell_base import bitcell_base
from globals import OPTS
class bitcell(bitcell_base.bitcell_base): class bitcell(bitcell_base.bitcell_base):
""" """
@ -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

@ -2,7 +2,7 @@ word_size = 32
num_words = 128 num_words = 128
tech_name = "scn4m_subm" tech_name = "scn4m_subm"
nominal_corners_only = False nominal_corner_only = False
process_corners = ["TT"] process_corners = ["TT"]
supply_voltages = [5.0] supply_voltages = [5.0]
temperatures = [25] temperatures = [25]

View File

@ -6,7 +6,7 @@ num_r_ports = 1
num_w_ports = 0 num_w_ports = 0
tech_name = "scn4m_subm" tech_name = "scn4m_subm"
nominal_corners_only = False nominal_corner_only = False
process_corners = ["TT"] process_corners = ["TT"]
supply_voltages = [5.0] supply_voltages = [5.0]
temperatures = [25] temperatures = [25]

View File

@ -0,0 +1,21 @@
word_size = 4
num_words = 16
write_size = 2
num_rw_ports = 1
num_r_ports = 0
num_w_ports = 1
tech_name = "scn4m_subm"
nominal_corner_only = False
process_corners = ["TT"]
supply_voltages = [5.0]
temperatures = [25]
route_supplies = False
check_lvsdrc = True
output_path = "temp"
output_name = "sram_1rw_1r_{0}_{1}_{2}".format(word_size,
num_words,
tech_name)

View File

@ -7,7 +7,7 @@ num_r_ports = 0
num_w_ports = 0 num_w_ports = 0
tech_name = "scn4m_subm" tech_name = "scn4m_subm"
nominal_corners_only = False nominal_corner_only = False
process_corners = ["TT"] process_corners = ["TT"]
supply_voltages = [5.0] supply_voltages = [5.0]
temperatures = [25] temperatures = [25]

View File

@ -6,7 +6,7 @@ num_r_ports = 1
num_w_ports = 1 num_w_ports = 1
tech_name = "scn4m_subm" tech_name = "scn4m_subm"
nominal_corners_only = False nominal_corner_only = False
process_corners = ["TT"] process_corners = ["TT"]
supply_voltages = [5.0] supply_voltages = [5.0]
temperatures = [25] temperatures = [25]

View File

@ -0,0 +1,21 @@
word_size = 2
num_words = 16
num_rw_ports = 2
num_r_ports = 0
num_w_ports = 0
tech_name = "scn4m_subm"
nominal_corner_only = False
process_corners = ["TT"]
supply_voltages = [5.0]
temperatures = [25]
route_supplies = False
check_lvsdrc = True
output_path = "temp"
output_name = "sram_1w_1r_{0}_{1}_{2}".format(word_size,
num_words,
tech_name)

View File

@ -2,14 +2,14 @@ word_size = 2
num_words = 16 num_words = 16
tech_name = "freepdk45" tech_name = "freepdk45"
nominal_corners_only = False nominal_corner_only = False
process_corners = ["TT"] process_corners = ["TT"]
supply_voltages = [1.0] supply_voltages = [1.0]
temperatures = [25] temperatures = [25]
route_supplies = False route_supplies = False
check_lvsdrc = True check_lvsdrc = True
# nominal_corners_only = True # nominal_corner_only = True
load_scales = [0.5, 1, 4] load_scales = [0.5, 1, 4]
slew_scales = [0.5, 1] slew_scales = [0.5, 1]

View File

@ -2,7 +2,7 @@ word_size = 2
num_words = 16 num_words = 16
tech_name = "scn4m_subm" tech_name = "scn4m_subm"
nominal_corners_only = False nominal_corner_only = False
process_corners = ["TT"] process_corners = ["TT"]
supply_voltages = [5.0] supply_voltages = [5.0]
temperatures = [25] temperatures = [25]

View File

@ -2,7 +2,7 @@ word_size = 64
num_words = 1024 num_words = 1024
tech_name = "scn4m_subm" tech_name = "scn4m_subm"
nominal_corners_only = False nominal_corner_only = False
process_corners = ["TT"] process_corners = ["TT"]
supply_voltages = [ 5.0 ] supply_voltages = [ 5.0 ]
temperatures = [ 25 ] temperatures = [ 25 ]

View File

@ -2,7 +2,7 @@ word_size = 16
num_words = 256 num_words = 256
tech_name = "scn4m_subm" tech_name = "scn4m_subm"
nominal_corners_only = False nominal_corner_only = False
process_corners = ["TT"] process_corners = ["TT"]
supply_voltages = [5.0] supply_voltages = [5.0]
temperatures = [25] temperatures = [25]

View File

@ -9,7 +9,7 @@ num_r_ports = 1
num_w_ports = 0 num_w_ports = 0
tech_name = "freepdk45" tech_name = "freepdk45"
nominal_corners_only = True nominal_corner_only = True
route_supplies = False route_supplies = False
check_lvsdrc = False check_lvsdrc = False

View File

@ -9,7 +9,7 @@ num_r_ports = 1
num_w_ports = 0 num_w_ports = 0
tech_name = "scn4m_subm" tech_name = "scn4m_subm"
nominal_corners_only = True nominal_corner_only = True
route_supplies = False route_supplies = False
check_lvsdrc = False check_lvsdrc = False

View File

@ -7,7 +7,7 @@ num_r_ports = 1
num_w_ports = 0 num_w_ports = 0
tech_name = "scn4m_subm" tech_name = "scn4m_subm"
nominal_corners_only = True nominal_corner_only = True
route_supplies = True route_supplies = True
check_lvsdrc = True check_lvsdrc = True

View File

@ -7,7 +7,7 @@ num_r_ports = 1
num_w_ports = 0 num_w_ports = 0
tech_name = "scn4m_subm" tech_name = "scn4m_subm"
nominal_corners_only = True nominal_corner_only = True
route_supplies = True route_supplies = True
check_lvsdrc = True check_lvsdrc = True

View File

@ -9,7 +9,7 @@ num_r_ports = 1
num_w_ports = 0 num_w_ports = 0
tech_name = "scn4m_subm" tech_name = "scn4m_subm"
nominal_corners_only = True nominal_corner_only = True
route_supplies = False route_supplies = False
check_lvsdrc = False check_lvsdrc = False

View File

@ -7,7 +7,7 @@ num_r_ports = 1
num_w_ports = 0 num_w_ports = 0
tech_name = "scn4m_subm" tech_name = "scn4m_subm"
nominal_corners_only = True nominal_corner_only = True
route_supplies = True route_supplies = True
check_lvsdrc = True check_lvsdrc = True

View File

@ -9,7 +9,7 @@ num_r_ports = 1
num_w_ports = 0 num_w_ports = 0
tech_name = "scn4m_subm" tech_name = "scn4m_subm"
nominal_corners_only = True nominal_corner_only = True
route_supplies = False route_supplies = False
check_lvsdrc = False check_lvsdrc = False

View File

@ -9,7 +9,7 @@ num_r_ports = 1
num_w_ports = 0 num_w_ports = 0
tech_name = "sky130" tech_name = "sky130"
nominal_corners_only = True nominal_corner_only = True
route_supplies = True route_supplies = True
check_lvsdrc = True check_lvsdrc = True

View File

@ -9,7 +9,7 @@ num_r_ports = 1
num_w_ports = 0 num_w_ports = 0
tech_name = "sky130" tech_name = "sky130"
nominal_corners_only = True nominal_corner_only = True
route_supplies = True route_supplies = True
check_lvsdrc = True check_lvsdrc = True

View File

@ -9,7 +9,7 @@ num_r_ports = 1
num_w_ports = 0 num_w_ports = 0
tech_name = "sky130" tech_name = "sky130"
nominal_corners_only = True nominal_corner_only = True
route_supplies = True route_supplies = True
check_lvsdrc = True check_lvsdrc = True

View File

@ -1,19 +0,0 @@
word_size = 2
num_words = 16
tech_name = "scn4m_subm"
process_corners = ["TT"]
supply_voltages = [5.0]
temperatures = [25]
#netlist_only = True
route_supplies = True
check_lvsdrc = True
output_name = "sram_{0}_{1}_{2}".format(word_size,
num_words,
tech_name)
drc_name = "magic"
lvs_name = "netgen"
pex_name = "magic"

View File

@ -1,19 +0,0 @@
word_size = 8
num_words = 128
tech_name = "scn4m_subm"
process_corners = ["TT"]
supply_voltages = [5.0]
temperatures = [25]
route_supplies = True
check_lvsdrc = True
netlist_only = True
output_name = "sram_{0}_{1}_{2}".format(word_size,
num_words,
tech_name)
drc_name = "magic"
lvs_name = "netgen"
pex_name = "magic"

View File

@ -1,18 +0,0 @@
word_size = 16
num_words = 256
tech_name = "scn4m_subm"
process_corners = ["TT"]
supply_voltages = [5.0]
temperatures = [25]
route_supplies = True
check_lvsdrc = True
netlist_only = True
output_name = "sram_{0}_{1}_{2}".format(word_size,
num_words,
tech_name)
drc_name = "magic"
lvs_name = "netgen"
pex_name = "magic"

View File

@ -1,18 +0,0 @@
word_size = 32
num_words = 128
tech_name = "scn4m_subm"
process_corners = ["TT"]
supply_voltages = [5.0]
temperatures = [25]
route_supplies = True
check_lvsdrc = True
netlist_only = True
output_name = "sram_{0}_{1}_{2}".format(word_size,
num_words,
tech_name)
drc_name = "magic"
lvs_name = "netgen"
pex_name = "magic"

View File

@ -1,19 +0,0 @@
word_size = 64
num_words = 128
tech_name = "scn4m_subm"
process_corners = ["TT"]
supply_voltages = [5.0]
temperatures = [25]
route_supplies = True
check_lvsdrc = True
output_path = "/home/jesse/thesis/outputs/run5"
output_name = "sram_{0}_{1}_{2}".format(word_size,
num_words,
tech_name)
drc_name = "magic"
lvs_name = "netgen"
pex_name = "magic"

View File

@ -1,31 +0,0 @@
word_size = 16
num_words = 16
num_rw_ports = 1
num_r_ports = 1
num_w_ports = 0
tech_name = "sky130"
accuracy_requirement = 0.05
magic_exe = ("magic", "magic")
nominal_corners_only = False
process_corners = ["TT"]
supply_voltages = [5.0]
temperatures = [25]
netlist_only = False
route_supplies = "grid"
check_lvsdrc = False
#replica_bitcell_array = "/home/jesse/openram/technology/sky130/modules/replica_bitcell_array.py"
output_path = "sram_" + str(accuracy_requirement)
output_name = "sram_{0}_{1}_{2}_{3}".format(word_size,
num_words,
tech_name,
accuracy_requirement
)
write_size=8

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 = getattr(self, layer_props.bank.stack)
stack = self.m2_stack pitch = getattr(self, 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

@ -85,8 +85,8 @@ class control_logic(design.design):
def add_modules(self): def add_modules(self):
""" Add all the required modules """ """ Add all the required modules """
dff = factory.create(module_type="dff_buf") self.dff = factory.create(module_type="dff_buf")
dff_height = dff.height dff_height = self.dff.height
self.ctrl_dff_array = factory.create(module_type="dff_buf_array", self.ctrl_dff_array = factory.create(module_type="dff_buf_array",
rows=self.num_control_signals, rows=self.num_control_signals,
@ -119,7 +119,7 @@ class control_logic(design.design):
# We will use the maximum since this same value is used to size the wl_en # We will use the maximum since this same value is used to size the wl_en
# and the p_en_bar drivers # and the p_en_bar drivers
max_fanout = max(self.num_rows, self.num_cols) # max_fanout = max(self.num_rows, self.num_cols)
# wl_en drives every row in the bank # wl_en drives every row in the bank
self.wl_en_driver = factory.create(module_type="pdriver", self.wl_en_driver = factory.create(module_type="pdriver",
@ -162,7 +162,7 @@ class control_logic(design.design):
self.delay_chain=factory.create(module_type="delay_chain", self.delay_chain=factory.create(module_type="delay_chain",
fanout_list = OPTS.delay_chain_stages * [ OPTS.delay_chain_fanout_per_stage ]) fanout_list = OPTS.delay_chain_stages * [ OPTS.delay_chain_fanout_per_stage ])
self.add_mod(self.delay_chain) self.add_mod(self.delay_chain)
def get_dynamic_delay_chain_size(self, previous_stages, previous_fanout): def get_dynamic_delay_chain_size(self, previous_stages, previous_fanout):
"""Determine the size of the delay chain used for the Sense Amp Enable using path delays""" """Determine the size of the delay chain used for the Sense Amp Enable using path delays"""
from math import ceil from math import ceil
@ -721,10 +721,8 @@ class control_logic(design.design):
def route_supply(self): def route_supply(self):
""" Add vdd and gnd to the instance cells """ """ Add vdd and gnd to the instance cells """
if OPTS.tech_name == "sky130": supply_layer = self.dff.get_pin("vdd").layer
supply_layer = "li"
else:
supply_layer = "m1"
max_row_x_loc = max([inst.rx() for inst in self.row_end_inst]) max_row_x_loc = max([inst.rx() for inst in self.row_end_inst])
for inst in self.row_end_inst: for inst in self.row_end_inst:
pins = inst.get_pins("vdd") pins = inst.get_pins("vdd")

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_predecode.input_layer
self.output_layer = "li" self.output_layer = layer_props.hierarchical_predecode.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_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

@ -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_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 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)
@ -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,9 +212,8 @@ 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

@ -5,13 +5,12 @@
# (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 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):
@ -37,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 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)
@ -211,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,
@ -300,4 +301,4 @@ class precharge(design.design):
self.add_path(self.bitline_layer, self.add_path(self.bitline_layer,
[left_pos, right_pos], [left_pos, right_pos],
width=pmos_pin.height()) width=pmos_pin.height())

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)

View File

@ -552,7 +552,7 @@ class pin_group:
Add the enclosure shape to the given cell. Add the enclosure shape to the given cell.
""" """
for enclosure in self.enclosures: for enclosure in self.enclosures:
debug.info(2, "Adding enclosure {0} {1}".format(self.name, debug.info(4, "Adding enclosure {0} {1}".format(self.name,
enclosure)) enclosure))
cell.add_rect(layer=enclosure.layer, cell.add_rect(layer=enclosure.layer,
offset=enclosure.ll(), offset=enclosure.ll(),
@ -612,7 +612,7 @@ class pin_group:
blockage_set = set() blockage_set = set()
for pin in self.pins: for pin in self.pins:
debug.info(2, " Converting {0}".format(pin)) debug.info(4, " Converting {0}".format(pin))
# Determine which tracks the pin overlaps # Determine which tracks the pin overlaps
(sufficient, insufficient) = self.router.convert_pin_to_tracks(self.name, (sufficient, insufficient) = self.router.convert_pin_to_tracks(self.name,
pin) pin)
@ -628,15 +628,15 @@ class pin_group:
# Remember, this excludes the pin blockages already # Remember, this excludes the pin blockages already
shared_set = pin_set & self.router.blocked_grids shared_set = pin_set & self.router.blocked_grids
if len(shared_set) > 0: if len(shared_set) > 0:
debug.info(2, "Removing pins {}".format(shared_set)) debug.info(4, "Removing pins {}".format(shared_set))
pin_set.difference_update(shared_set) pin_set.difference_update(shared_set)
shared_set = partial_set & self.router.blocked_grids shared_set = partial_set & self.router.blocked_grids
if len(shared_set) > 0: if len(shared_set) > 0:
debug.info(2, "Removing pins {}".format(shared_set)) debug.info(4, "Removing pins {}".format(shared_set))
partial_set.difference_update(shared_set) partial_set.difference_update(shared_set)
shared_set = blockage_set & self.router.blocked_grids shared_set = blockage_set & self.router.blocked_grids
if len(shared_set) > 0: if len(shared_set) > 0:
debug.info(2, "Removing blocks {}".format(shared_set)) debug.info(4, "Removing blocks {}".format(shared_set))
blockage_set.difference_update(shared_set) blockage_set.difference_update(shared_set)
# At least one of the groups must have some valid tracks # At least one of the groups must have some valid tracks
@ -666,5 +666,5 @@ class pin_group:
# Remember the secondary grids for removing adjacent pins # Remember the secondary grids for removing adjacent pins
self.secondary_grids = partial_set self.secondary_grids = partial_set
debug.info(2, " pins {}".format(self.grids)) debug.info(4, " pins {}".format(self.grids))
debug.info(2, " secondary {}".format(self.secondary_grids)) debug.info(4, " secondary {}".format(self.secondary_grids))

View File

@ -301,7 +301,6 @@ class router(router_tech):
adj_grids)) adj_grids))
self.remove_adjacent_grid(pg1, pg2, adj_grids) self.remove_adjacent_grid(pg1, pg2, adj_grids)
debug.info(1, "Removed {} adjacent grids.".format(removed_grids)) debug.info(1, "Removed {} adjacent grids.".format(removed_grids))
def remove_adjacent_grid(self, pg1, pg2, adj_grids): def remove_adjacent_grid(self, pg1, pg2, adj_grids):
@ -539,7 +538,7 @@ class router(router_tech):
sufficient_list.update([full_overlap]) sufficient_list.update([full_overlap])
if partial_overlap: if partial_overlap:
insufficient_list.update([partial_overlap]) insufficient_list.update([partial_overlap])
debug.info(2, debug.info(3,
"Converting [ {0} , {1} ] full={2}".format(x, "Converting [ {0} , {1} ] full={2}".format(x,
y, y,
full_overlap)) full_overlap))
@ -632,26 +631,26 @@ class router(router_tech):
pin.layer) pin.layer)
overlap_length = pin.overlap_length(track_pin) overlap_length = pin.overlap_length(track_pin)
debug.info(2,"Check overlap: {0} {1} . {2} = {3}".format(coord, debug.info(4,"Check overlap: {0} {1} . {2} = {3}".format(coord,
pin.rect, pin.rect,
track_pin, track_pin,
overlap_length)) overlap_length))
inflated_overlap_length = inflated_pin.overlap_length(track_pin) inflated_overlap_length = inflated_pin.overlap_length(track_pin)
debug.info(2,"Check overlap: {0} {1} . {2} = {3}".format(coord, debug.info(4,"Check overlap: {0} {1} . {2} = {3}".format(coord,
inflated_pin.rect, inflated_pin.rect,
track_pin, track_pin,
inflated_overlap_length)) inflated_overlap_length))
# If it overlaps with the pin, it is sufficient # If it overlaps with the pin, it is sufficient
if overlap_length == math.inf or overlap_length > 0: if overlap_length == math.inf or overlap_length > 0:
debug.info(2," Overlap: {0} >? {1}".format(overlap_length, 0)) debug.info(4," Overlap: {0} >? {1}".format(overlap_length, 0))
return (coord, None) return (coord, None)
# If it overlaps with the inflated pin, it is partial # If it overlaps with the inflated pin, it is partial
elif inflated_overlap_length == math.inf or inflated_overlap_length > 0: elif inflated_overlap_length == math.inf or inflated_overlap_length > 0:
debug.info(2," Partial overlap: {0} >? {1}".format(inflated_overlap_length, 0)) debug.info(4," Partial overlap: {0} >? {1}".format(inflated_overlap_length, 0))
return (None, coord) return (None, coord)
else: else:
debug.info(2, " No overlap: {0} {1}".format(overlap_length, 0)) debug.info(4, " No overlap: {0} {1}".format(overlap_length, 0))
return (None, None) return (None, None)
def convert_track_to_pin(self, track): def convert_track_to_pin(self, track):
@ -846,7 +845,7 @@ class router(router_tech):
"Pin component index too large.") "Pin component index too large.")
pin_in_tracks = self.pin_groups[pin_name][index].grids pin_in_tracks = self.pin_groups[pin_name][index].grids
debug.info(2,"Set source: " + str(pin_name) + " " + str(pin_in_tracks)) debug.info(3,"Set source: " + str(pin_name) + " " + str(pin_in_tracks))
self.rg.add_source(pin_in_tracks) self.rg.add_source(pin_in_tracks)
def add_path_target(self, paths): def add_path_target(self, paths):
@ -914,7 +913,7 @@ class router(router_tech):
""" """
path = self.prepare_path(path) path = self.prepare_path(path)
debug.info(2, "Adding route: {}".format(str(path))) debug.info(4, "Adding route: {}".format(str(path)))
# If it is only a square, add an enclosure to the track # If it is only a square, add an enclosure to the track
if len(path) == 1: if len(path) == 1:
self.add_single_enclosure(path[0][0]) self.add_single_enclosure(path[0][0])
@ -1007,8 +1006,7 @@ class router(router_tech):
# returns the path in tracks # returns the path in tracks
(path, cost) = self.rg.route(detour_scale) (path, cost) = self.rg.route(detour_scale)
if path: if path:
debug.info(1, "Found path: cost={0} ".format(cost)) debug.info(2, "Found path: cost={0} {1}".format(cost, str(path)))
debug.info(1, str(path))
self.paths.append(path) self.paths.append(path)
self.add_route(path) self.add_route(path)

View File

@ -2,7 +2,7 @@
04_pbitcell_test.py 04_pbitcell_test.py
04_precharge_pbitcell_test.py 04_precharge_pbitcell_test.py
04_replica_pbitcell_test.py 04_replica_pbitcell_test.py
04_single_level_column_mux_pbitcell_test.py 04_column_mux_pbitcell_test.py
05_bitcell_1rw_1r_array_test.py 05_bitcell_1rw_1r_array_test.py
05_bitcell_array_test.py 05_bitcell_array_test.py
05_dummy_array_test.py 05_dummy_array_test.py
@ -14,7 +14,7 @@
06_hierarchical_predecode3x8_pbitcell_test.py 06_hierarchical_predecode3x8_pbitcell_test.py
06_hierarchical_predecode3x8_test.py 06_hierarchical_predecode3x8_test.py
06_hierarchical_predecode4x16_test.py 06_hierarchical_predecode4x16_test.py
07_single_level_column_mux_array_pbitcell_test.py 07_column_mux_array_pbitcell_test.py
08_wordline_driver_array_pbitcell_test.py 08_wordline_driver_array_pbitcell_test.py
08_wordline_driver_array_test.py 08_wordline_driver_array_test.py
09_sense_amp_array_test_pbitcell.py 09_sense_amp_array_test_pbitcell.py

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
################################################### ###################################################