Consolidate metal pitch rules to new design class

This commit is contained in:
Matt Guthaus 2018-07-09 15:42:46 -07:00
parent 2e5d60ae87
commit 94db2052dd
10 changed files with 7 additions and 65 deletions

View File

@ -1,11 +1,11 @@
import design
import hierarchy_design
import debug
import utils
from tech import drc
from vector import vector
class contact(design.design):
class contact(hierarchy_design.hierarchy_design):
"""
Object for a contact shape with its conductor enclosures.
Creates a contact array minimum active or poly enclosure and metal1 enclosure.
@ -31,7 +31,7 @@ class contact(design.design):
dimensions[0],
dimensions[1])
design.design.__init__(self, name)
hierarchy_design.hierarchy_design.__init__(self, name)
debug.info(4, "create contact object {0}".format(name))
self.layer_stack = layer_stack
@ -167,4 +167,5 @@ active = contact(layer_stack=("active", "contact", "poly"))
poly = contact(layer_stack=("poly", "contact", "metal1"))
m1m2 = contact(layer_stack=("metal1", "via1", "metal2"))
m2m3 = contact(layer_stack=("metal2", "via2", "metal3"))
#m3m4 = contact(layer_stack=("metal3", "via3", "metal4"))

View File

@ -7,7 +7,7 @@ import os
from globals import OPTS
class design(hierarchy_spice.spice, hierarchy_layout.layout):
class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
"""
Design Class for all modules to inherit the base features.
Class consisting of a set of modules and instances of these modules
@ -23,7 +23,6 @@ class design(hierarchy_spice.spice, hierarchy_layout.layout):
hierarchy_layout.layout.__init__(self, name)
hierarchy_spice.spice.__init__(self, name)
self.setup_drc_constants()
# Check if the name already exists, if so, give an error
# because each reference must be a unique name.
@ -38,8 +37,8 @@ class design(hierarchy_spice.spice, hierarchy_layout.layout):
'sram',
'hierarchical_predecode2x4',
'hierarchical_predecode3x8']
if name not in design.name_map:
design.name_map.append(name)
if name not in hierarchy_design.name_map:
hierarchy_design.name_map.append(name)
else:
for ok_names in ok_list:
if ok_names in self.__class__.__name__:
@ -47,27 +46,6 @@ class design(hierarchy_spice.spice, hierarchy_layout.layout):
else:
debug.error("Duplicate layout reference name {0} of class {1}. GDS2 requires names be unique.".format(name,self.__class__),-1)
def setup_drc_constants(self):
""" These are some DRC constants used in many places in the compiler."""
from tech import drc
self.well_width = drc["minwidth_well"]
self.poly_width = drc["minwidth_poly"]
self.poly_space = drc["poly_to_poly"]
self.m1_width = drc["minwidth_metal1"]
self.m1_space = drc["metal1_to_metal1"]
self.m2_width = drc["minwidth_metal2"]
self.m2_space = drc["metal2_to_metal2"]
self.m3_width = drc["minwidth_metal3"]
self.m3_space = drc["metal3_to_metal3"]
self.active_width = drc["minwidth_active"]
self.contact_width = drc["minwidth_contact"]
self.poly_to_active = drc["poly_to_active"]
self.poly_extend_active = drc["poly_extend_active"]
self.contact_to_gate = drc["contact_to_gate"]
self.well_enclose_active = drc["well_enclosure_active"]
self.implant_enclose_active = drc["implant_enclosure_active"]
self.implant_space = drc["implant_to_implant"]
def get_layout_pins(self,inst):
""" Return a map of pin locations of the instance offset """
@ -125,9 +103,3 @@ class design(hierarchy_spice.spice, hierarchy_layout.layout):
text+=str(i)+",\n"
return text
def analytical_power(self, proc, vdd, temp, load):
""" Get total power of a module """
total_module_power = self.return_power()
for inst in self.insts:
total_module_power += inst.mod.analytical_power(proc, vdd, temp, load)
return total_module_power

View File

@ -161,10 +161,6 @@ class bank(design.design):
else:
self.num_col_addr_lines = 0
# M1/M2 routing pitch is based on contacted pitch
self.m1_pitch = contact.m1m2.height + max(self.m1_space,self.m2_space)
self.m2_pitch = contact.m2m3.height + max(self.m2_space,self.m3_space)
# The width of this bus is needed to place other modules (e.g. decoder)
# A width on each side too
self.central_bus_width = self.m2_pitch * self.num_control_lines + 2*self.m2_width

View File

@ -56,10 +56,6 @@ class bank_select(design.design):
def calculate_module_offsets(self):
# M1/M2 routing pitch is based on contacted pitch
self.m1_pitch = contact.m1m2.height + max(self.m1_space,self.m2_space)
self.m2_pitch = contact.m2m3.height + max(self.m2_space,self.m3_space)
self.xoffset_nand = self.inv4x.width + 2*self.m2_pitch + drc["pwell_to_nwell"]
self.xoffset_nor = self.inv4x.width + 2*self.m2_pitch + drc["pwell_to_nwell"]
self.xoffset_inv = max(self.xoffset_nand + self.nand2.width, self.xoffset_nor + self.nor2.width)

View File

@ -86,10 +86,6 @@ class control_logic(design.design):
# These aren't for instantiating, but we use them to get the dimensions
#self.poly_contact_offset = vector(0.5*contact.poly.width,0.5*contact.poly.height)
# M1/M2 routing pitch is based on contacted pitch
self.m1_pitch = max(contact.m1m2.width,contact.m1m2.height) + max(drc["metal1_to_metal1"],drc["metal2_to_metal2"])
self.m2_pitch = max(contact.m2m3.width,contact.m2m3.height) + max(drc["metal2_to_metal2"],drc["metal3_to_metal3"])
# Have the cell gap leave enough room to route an M2 wire.
# Some cells may have pwell/nwell spacing problems too when the wells are different heights.
#self.cell_gap = max(self.m2_pitch,drc["pwell_to_nwell"])

View File

@ -90,9 +90,6 @@ class hierarchical_decoder(design.design):
debug.error("Invalid number of inputs for hierarchical decoder",-1)
def setup_layout_constants(self):
self.m1_pitch = contact.m1m2.height + max(self.m1_space,self.m2_space)
self.m2_pitch = contact.m2m3.height + max(self.m2_space,self.m3_space)
self.predec_groups = [] # This array is a 2D array.
# Distributing vertical rails to different groups. One group belongs to one pre-decoder.

View File

@ -50,10 +50,6 @@ class hierarchical_predecode(design.design):
debug.error("Invalid number of predecode inputs.",-1)
def setup_constraints(self):
# use a conservative douple spacing just to get rid of annoying via DRCs
self.m1_pitch = max(contact.m1m2.width,contact.m1m2.height) + max(self.m1_space, self.m2_space)
self.m2_pitch = max(contact.m2m3.width,contact.m2m3.height) + max(self.m2_space,self.m3_space)
# The rail offsets are indexed by the label
self.rails = {}

View File

@ -53,11 +53,6 @@ class replica_bitline(design.design):
# These aren't for instantiating, but we use them to get the dimensions
self.poly_contact_offset = vector(0.5*contact.poly.width,0.5*contact.poly.height)
# M1/M2 routing pitch is based on contacted pitch
self.m1_pitch = max(contact.m1m2.width,contact.m1m2.height) + max(self.m1_space,self.m2_space)
self.m2_pitch = max(contact.m2m3.width,contact.m2m3.height) + max(self.m2_space,self.m3_space)
# Quadrant 1: Replica bitline and such are not rotated, but they must be placed far enough
# away from the delay chain/inverter with space for three M2 tracks
self.bitcell_offset = vector(0,self.replica_bitcell.height)

View File

@ -57,7 +57,6 @@ class single_level_column_mux_array(design.design):
def setup_layout_constants(self):
self.column_addr_size = num_of_inputs = int(self.words_per_row / 2)
self.width = self.columns * self.mux.width
self.m1_pitch = contact.m1m2.width + max(drc["metal1_to_metal1"],drc["metal2_to_metal2"])
# one set of metal1 routes for select signals and a pair to interconnect the mux outputs bl/br
# one extra route pitch is to space from the sense amp
self.route_height = (self.words_per_row + 3)*self.m1_pitch

View File

@ -48,12 +48,6 @@ class sram(design.design):
design.design.__init__(self, name)
# M1/M2 routing pitch is based on contacted pitch of the biggest layer
self.m1_pitch = max(contact.m1m2.width,contact.m1m2.height) + max(self.m1_space,self.m2_space)
self.m2_pitch = max(contact.m2m3.width,contact.m2m3.height) + max(self.m2_space,self.m3_space)
self.m3_pitch = max(contact.m2m3.width,contact.m2m3.height) + max(self.m2_space,self.m3_space)
self.control_size = 6
self.bank_to_bus_distance = 5*self.m3_width