mirror of https://github.com/VLSIDA/OpenRAM.git
Consolidate metal pitch rules to new design class
This commit is contained in:
parent
2e5d60ae87
commit
94db2052dd
|
|
@ -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"))
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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"])
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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 = {}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue