Remove some flake8 errors/warnings.

This commit is contained in:
mrg 2019-10-02 23:26:02 +00:00
parent b0dcfb5b2d
commit d583695959
10 changed files with 199 additions and 174 deletions

View File

@ -7,37 +7,42 @@
# #
import hierarchy_design import hierarchy_design
import debug import debug
import utils from tech import drc, layer
from tech import drc,layer
from vector import vector from vector import vector
class contact(hierarchy_design.hierarchy_design): class contact(hierarchy_design.hierarchy_design):
""" """
Object for a contact shape with its conductor enclosures. Object for a contact shape with its conductor enclosures. Creates
Creates a contact array minimum active or poly enclosure and metal1 enclosure. a contact array minimum active or poly enclosure and metal1
This class has enclosure on two or four sides of the contact. enclosure. This class has enclosure on two or four sides of the
The direction specifies whether the first and second layer have asymmetric extension in the H or V direction. contact. The direction specifies whether the first and second
layer have asymmetric extension in the H or V direction.
The well/implant_type is an option to add a select/implant layer
enclosing the contact. This is necessary to import layouts into
Magic which requires the select to be in the same GDS hierarchy as
the contact.
The well/implant_type is an option to add a select/implant layer enclosing the contact. This is
necessary to import layouts into Magic which requires the select to be in the same GDS
hierarchy as the contact.
""" """
def __init__(self, layer_stack, dimensions=(1,1), directions=("V","V"), implant_type=None, well_type=None, name=""): def __init__(self, layer_stack, dimensions=(1, 1), directions=("V", "V"),
# This will ignore the name parameter since we can guarantee a unique name here implant_type=None, well_type=None, name=""):
# This will ignore the name parameter since
# we can guarantee a unique name here
hierarchy_design.hierarchy_design.__init__(self, name) hierarchy_design.hierarchy_design.__init__(self, name)
debug.info(4, "create contact object {0}".format(name)) debug.info(4, "create contact object {0}".format(name))
self.add_comment("layers: {0}".format(layer_stack)) self.add_comment("layers: {0}".format(layer_stack))
self.add_comment("dimensions: {0}".format(dimensions)) self.add_comment("dimensions: {0}".format(dimensions))
if implant_type or well_type: if implant_type or well_type:
self.add_comment("implant type: {0}\nwell_type: {1}".format(implant_type,well_type)) self.add_comment("implant type: {}\n".format(implant_type))
self.add_comment("well_type: {}\n".format(well_type))
self.layer_stack = layer_stack self.layer_stack = layer_stack
self.dimensions = dimensions self.dimensions = dimensions
self.directions = directions self.directions = directions
self.offset = vector(0,0) self.offset = vector(0, 0)
self.implant_type = implant_type self.implant_type = implant_type
self.well_type = well_type self.well_type = well_type
# Module does not have pins, but has empty pin list. # Module does not have pins, but has empty pin list.
@ -59,7 +64,7 @@ class contact(hierarchy_design.hierarchy_design):
if self.implant_type and self.well_type: if self.implant_type and self.well_type:
self.create_implant_well_enclosures() self.create_implant_well_enclosures()
elif self.implant_type or self.well_type: elif self.implant_type or self.well_type:
debug.error(-1,"Must define both implant and well type or none at all.") debug.error(-1, "Must define both implant and well type or none at all.")
def setup_layers(self): def setup_layers(self):
""" Locally assign the layer names. """ """ Locally assign the layer names. """
@ -67,10 +72,11 @@ class contact(hierarchy_design.hierarchy_design):
(first_layer, via_layer, second_layer) = self.layer_stack (first_layer, via_layer, second_layer) = self.layer_stack
self.first_layer_name = first_layer self.first_layer_name = first_layer
self.via_layer_name = via_layer self.via_layer_name = via_layer
# Some technologies have a separate active contact from the poly contact # Some technologies have a separate active
# contact from the poly contact
# We will use contact for DRC, but active_contact for output # We will use contact for DRC, but active_contact for output
if first_layer=="active" or second_layer=="active": if first_layer == "active" or second_layer == "active":
self.via_layer_name_expanded = "active_"+via_layer self.via_layer_name_expanded = "active_" + via_layer
else: else:
self.via_layer_name_expanded = via_layer self.via_layer_name_expanded = via_layer
self.second_layer_name = second_layer self.second_layer_name = second_layer
@ -97,19 +103,19 @@ class contact(hierarchy_design.hierarchy_design):
second_layer_enclosure = drc("{0}_enclosure_{1}".format(self.second_layer_name, self.via_layer_name)) second_layer_enclosure = drc("{0}_enclosure_{1}".format(self.second_layer_name, self.via_layer_name))
second_layer_extend = drc("{0}_extend_{1}".format(self.second_layer_name, self.via_layer_name)) second_layer_extend = drc("{0}_extend_{1}".format(self.second_layer_name, self.via_layer_name))
# In some technologies, the minimum width may be larger
# In some technologies, the minimum width may be larger than the overlap requirement around the via, so # than the overlap requirement around the via, so
# check this for each dimension. # check this for each dimension.
if self.directions[0] == "V": if self.directions[0] == "V":
self.first_layer_horizontal_enclosure = max(first_layer_enclosure, self.first_layer_horizontal_enclosure = max(first_layer_enclosure,
(first_layer_minwidth - self.contact_array_width)/2) (first_layer_minwidth - self.contact_array_width) / 2)
self.first_layer_vertical_enclosure = max(first_layer_extend, self.first_layer_vertical_enclosure = max(first_layer_extend,
(first_layer_minwidth - self.contact_array_height)/2) (first_layer_minwidth - self.contact_array_height) / 2)
elif self.directions[0] == "H": elif self.directions[0] == "H":
self.first_layer_horizontal_enclosure = max(first_layer_extend, self.first_layer_horizontal_enclosure = max(first_layer_extend,
(first_layer_minwidth - self.contact_array_width)/2) (first_layer_minwidth - self.contact_array_width) / 2)
self.first_layer_vertical_enclosure = max(first_layer_enclosure, self.first_layer_vertical_enclosure = max(first_layer_enclosure,
(first_layer_minwidth - self.contact_array_height)/2) (first_layer_minwidth - self.contact_array_height) / 2)
else: else:
debug.error("Invalid first layer direction.", -1) debug.error("Invalid first layer direction.", -1)
@ -117,23 +123,23 @@ class contact(hierarchy_design.hierarchy_design):
# check this for each dimension. # check this for each dimension.
if self.directions[1] == "V": if self.directions[1] == "V":
self.second_layer_horizontal_enclosure = max(second_layer_enclosure, self.second_layer_horizontal_enclosure = max(second_layer_enclosure,
(second_layer_minwidth - self.contact_array_width)/2) (second_layer_minwidth - self.contact_array_width) / 2)
self.second_layer_vertical_enclosure = max(second_layer_extend, self.second_layer_vertical_enclosure = max(second_layer_extend,
(second_layer_minwidth - self.contact_array_height)/2) (second_layer_minwidth - self.contact_array_height) / 2)
elif self.directions[1] == "H": elif self.directions[1] == "H":
self.second_layer_horizontal_enclosure = max(second_layer_extend, self.second_layer_horizontal_enclosure = max(second_layer_extend,
(second_layer_minwidth - self.contact_array_height)/2) (second_layer_minwidth - self.contact_array_height) / 2)
self.second_layer_vertical_enclosure = max(second_layer_enclosure, self.second_layer_vertical_enclosure = max(second_layer_enclosure,
(second_layer_minwidth - self.contact_array_width)/2) (second_layer_minwidth - self.contact_array_width) / 2)
else: else:
debug.error("Invalid second layer direction.", -1) debug.error("Invalid second layer direction.", -1)
def create_contact_array(self): def create_contact_array(self):
""" Create the contact array at the origin""" """ Create the contact array at the origin"""
# offset for the via array # offset for the via array
self.via_layer_position =vector(max(self.first_layer_horizontal_enclosure,self.second_layer_horizontal_enclosure), self.via_layer_position = vector(
max(self.first_layer_vertical_enclosure,self.second_layer_vertical_enclosure)) max(self.first_layer_horizontal_enclosure, self.second_layer_horizontal_enclosure),
max(self.first_layer_vertical_enclosure, self.second_layer_vertical_enclosure))
for i in range(self.dimensions[1]): for i in range(self.dimensions[1]):
offset = self.via_layer_position + vector(0, self.contact_pitch * i) offset = self.via_layer_position + vector(0, self.contact_pitch * i)
@ -142,15 +148,16 @@ class contact(hierarchy_design.hierarchy_design):
offset=offset, offset=offset,
width=self.contact_width, width=self.contact_width,
height=self.contact_width) height=self.contact_width)
offset = offset + vector(self.contact_pitch,0) offset = offset + vector(self.contact_pitch, 0)
def create_first_layer_enclosure(self): def create_first_layer_enclosure(self):
# this is if the first and second layers are different # this is if the first and second layers are different
self.first_layer_position = vector(max(self.second_layer_horizontal_enclosure - self.first_layer_horizontal_enclosure,0), self.first_layer_position = vector(
max(self.second_layer_vertical_enclosure - self.first_layer_vertical_enclosure,0)) max(self.second_layer_horizontal_enclosure - self.first_layer_horizontal_enclosure, 0),
max(self.second_layer_vertical_enclosure - self.first_layer_vertical_enclosure, 0))
self.first_layer_width = self.contact_array_width + 2*self.first_layer_horizontal_enclosure self.first_layer_width = self.contact_array_width + 2 * self.first_layer_horizontal_enclosure
self.first_layer_height = self.contact_array_height + 2*self.first_layer_vertical_enclosure self.first_layer_height = self.contact_array_height + 2 * self.first_layer_vertical_enclosure
self.add_rect(layer=self.first_layer_name, self.add_rect(layer=self.first_layer_name,
offset=self.first_layer_position, offset=self.first_layer_position,
width=self.first_layer_width, width=self.first_layer_width,
@ -158,27 +165,28 @@ class contact(hierarchy_design.hierarchy_design):
def create_second_layer_enclosure(self): def create_second_layer_enclosure(self):
# this is if the first and second layers are different # this is if the first and second layers are different
self.second_layer_position = vector(max(self.first_layer_horizontal_enclosure - self.second_layer_horizontal_enclosure,0), self.second_layer_position = vector(
max(self.first_layer_vertical_enclosure - self.second_layer_vertical_enclosure,0)) max(self.first_layer_horizontal_enclosure - self.second_layer_horizontal_enclosure, 0),
max(self.first_layer_vertical_enclosure - self.second_layer_vertical_enclosure, 0))
self.second_layer_width = self.contact_array_width + 2*self.second_layer_horizontal_enclosure self.second_layer_width = self.contact_array_width + 2 * self.second_layer_horizontal_enclosure
self.second_layer_height = self.contact_array_height + 2*self.second_layer_vertical_enclosure self.second_layer_height = self.contact_array_height + 2 * self.second_layer_vertical_enclosure
self.add_rect(layer=self.second_layer_name, self.add_rect(layer=self.second_layer_name,
offset=self.second_layer_position, offset=self.second_layer_position,
width=self.second_layer_width, width=self.second_layer_width,
height=self.second_layer_height) height=self.second_layer_height)
def create_implant_well_enclosures(self): def create_implant_well_enclosures(self):
implant_position = self.first_layer_position - [drc("implant_enclosure_active")]*2 implant_position = self.first_layer_position - [drc("implant_enclosure_active")] * 2
implant_width = self.first_layer_width + 2*drc("implant_enclosure_active") implant_width = self.first_layer_width + 2 * drc("implant_enclosure_active")
implant_height = self.first_layer_height + 2*drc("implant_enclosure_active") implant_height = self.first_layer_height + 2 * drc("implant_enclosure_active")
self.add_rect(layer="{}implant".format(self.implant_type), self.add_rect(layer="{}implant".format(self.implant_type),
offset=implant_position, offset=implant_position,
width=implant_width, width=implant_width,
height=implant_height) height=implant_height)
well_position = self.first_layer_position - [drc("well_enclosure_active")]*2 well_position = self.first_layer_position - [drc("well_enclosure_active")] * 2
well_width = self.first_layer_width + 2*drc("well_enclosure_active") well_width = self.first_layer_width + 2 * drc("well_enclosure_active")
well_height = self.first_layer_height + 2*drc("well_enclosure_active") well_height = self.first_layer_height + 2 * drc("well_enclosure_active")
self.add_rect(layer="{}well".format(self.well_type), self.add_rect(layer="{}well".format(self.well_type),
offset=well_position, offset=well_position,
width=well_width, width=well_width,
@ -188,16 +196,30 @@ class contact(hierarchy_design.hierarchy_design):
""" Get total power of a module """ """ Get total power of a module """
return self.return_power() return self.return_power()
from sram_factory import factory from sram_factory import factory
# This is not instantiated and used for calculations only. # This is not instantiated and used for calculations only.
# These are static 1x1 contacts to reuse in all the design modules. # These are static 1x1 contacts to reuse in all the design modules.
well = factory.create(module_type="contact", layer_stack=("active", "contact", "metal1"), directions=("H","V")) well = factory.create(module_type="contact",
active = factory.create(module_type="contact", layer_stack=("active", "contact", "metal1"), directions=("H","V")) layer_stack=("active", "contact", "metal1"),
poly = factory.create(module_type="contact", layer_stack=("poly", "contact", "metal1"), directions=("V","H")) directions=("H", "V"))
m1m2 = factory.create(module_type="contact", layer_stack=("metal1", "via1", "metal2"), directions=("H","V")) active = factory.create(module_type="contact",
m2m3 = factory.create(module_type="contact", layer_stack=("metal2", "via2", "metal3"), directions=("V","H")) layer_stack=("active", "contact", "metal1"),
directions=("H", "V"))
poly = factory.create(module_type="contact",
layer_stack=("poly", "contact", "metal1"),
directions=("V", "H"))
m1m2 = factory.create(module_type="contact",
layer_stack=("metal1", "via1", "metal2"),
directions=("H", "V"))
m2m3 = factory.create(module_type="contact",
layer_stack=("metal2", "via2", "metal3"),
directions=("V", "H"))
if "metal4" in layer.keys(): if "metal4" in layer.keys():
m3m4 = factory.create(module_type="contact", layer_stack=("metal3", "via3", "metal4"), directions=("H","V")) m3m4 = factory.create(module_type="contact",
layer_stack=("metal3", "via3", "metal4"),
directions=("H", "V"))
else: else:
m3m4 = None m3m4 = None

View File

@ -6,6 +6,7 @@
# All rights reserved. # All rights reserved.
# #
class delay_data(): class delay_data():
""" """
This is the delay class to represent the delay information This is the delay class to represent the delay information
@ -20,13 +21,13 @@ class delay_data():
def __str__(self): def __str__(self):
""" override print function output """ """ override print function output """
return "Delay Data: Delay "+str(self.delay)+", Slew "+str(self.slew)+"" return "Delta Data: Delay {} Slew {}".format(self.delay, self.slew)
def __add__(self, other): def __add__(self, other):
""" """
Override - function (left), for delay_data: a+b != b+a Override - function (left), for delay_data: a+b != b+a
""" """
assert isinstance(other,delay_data) assert isinstance(other, delay_data)
return delay_data(other.delay + self.delay, return delay_data(other.delay + self.delay,
other.slew) other.slew)
@ -34,7 +35,7 @@ class delay_data():
""" """
Override - function (right), for delay_data: a+b != b+a Override - function (right), for delay_data: a+b != b+a
""" """
assert isinstance(other,delay_data) assert isinstance(other, delay_data)
return delay_data(other.delay + self.delay, return delay_data(other.delay + self.delay,
self.slew) self.slew)

View File

@ -7,12 +7,9 @@
# #
from hierarchy_design import hierarchy_design from hierarchy_design import hierarchy_design
import contact import contact
import globals
import verify
import debug
import os
from globals import OPTS from globals import OPTS
class design(hierarchy_design): class design(hierarchy_design):
""" """
This is the same as the hierarchy_design class except it contains This is the same as the hierarchy_design class except it contains
@ -21,22 +18,22 @@ class design(hierarchy_design):
""" """
def __init__(self, name): def __init__(self, name):
hierarchy_design.__init__(self,name) hierarchy_design.__init__(self, name)
self.setup_drc_constants() self.setup_drc_constants()
self.setup_multiport_constants() self.setup_multiport_constants()
from tech import layer from tech import layer
self.m1_pitch = max(contact.m1m2.width,contact.m1m2.height) + max(self.m1_space, self.m2_space) 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.m2_pitch = max(contact.m2m3.width, contact.m2m3.height) + max(self.m2_space, self.m3_space)
if "metal4" in layer: if "metal4" in layer:
self.m3_pitch = max(contact.m3m4.width,contact.m3m4.height) + max(self.m3_space, self.m4_space) self.m3_pitch = max(contact.m3m4.width, contact.m3m4.height) + max(self.m3_space, self.m4_space)
else: else:
self.m3_pitch = self.m2_pitch self.m3_pitch = self.m2_pitch
def setup_drc_constants(self): def setup_drc_constants(self):
""" These are some DRC constants used in many places in the compiler.""" """ These are some DRC constants used in many places in the compiler."""
from tech import drc,layer from tech import drc, layer
self.well_width = drc("minwidth_well") self.well_width = drc("minwidth_well")
self.poly_width = drc("minwidth_poly") self.poly_width = drc("minwidth_poly")
self.poly_space = drc("poly_to_poly") self.poly_space = drc("poly_to_poly")

View File

@ -15,6 +15,7 @@ import math
from globals import OPTS from globals import OPTS
from utils import round_to_grid from utils import round_to_grid
class geometry: class geometry:
""" """
A specific path, shape, or text geometry. Base class for shared A specific path, shape, or text geometry. Base class for shared
@ -27,11 +28,11 @@ class geometry:
def __str__(self): def __str__(self):
""" override print function output """ """ override print function output """
debug.error("__str__ must be overridden by all geometry types.",1) debug.error("__str__ must be overridden by all geometry types.", 1)
def __repr__(self): def __repr__(self):
""" override print function output """ """ override print function output """
debug.error("__repr__ must be overridden by all geometry types.",1) debug.error("__repr__ must be overridden by all geometry types.", 1)
# def translate_coords(self, coords, mirr, angle, xyShift): # def translate_coords(self, coords, mirr, angle, xyShift):
# """Calculate coordinates after flip, rotate, and shift""" # """Calculate coordinates after flip, rotate, and shift"""
@ -46,50 +47,52 @@ class geometry:
"""Calculate coordinates after flip, rotate, and shift""" """Calculate coordinates after flip, rotate, and shift"""
coordinate = [] coordinate = []
for item in coords: for item in coords:
x = item[0]*math.cos(angle) - item[1]*mirr*math.sin(angle) + offset[0] x = item[0] * math.cos(angle) - item[1] * mirr * math.sin(angle) + offset[0]
y = item[0]*math.sin(angle) + item[1]*mirr*math.cos(angle) + offset[1] y = item[0] * math.sin(angle) + item[1] * mirr * math.cos(angle) + offset[1]
coordinate += [[x, y]] coordinate += [[x, y]]
return coordinate return coordinate
def normalize(self): def normalize(self):
""" Re-find the LL and UR points after a transform """ """ Re-find the LL and UR points after a transform """
(first,second)=self.boundary (first, second) = self.boundary
ll = vector(min(first[0],second[0]),min(first[1],second[1])).snap_to_grid() ll = vector(min(first[0], second[0]),
ur = vector(max(first[0],second[0]),max(first[1],second[1])).snap_to_grid() min(first[1], second[1])).snap_to_grid()
self.boundary=[ll,ur] ur = vector(max(first[0], second[0]),
max(first[1], second[1])).snap_to_grid()
self.boundary = [ll, ur]
def update_boundary(self): def update_boundary(self):
""" Update the boundary with a new placement. """ """ Update the boundary with a new placement. """
self.compute_boundary(self.offset,self.mirror,self.rotate) self.compute_boundary(self.offset, self.mirror, self.rotate)
def compute_boundary(self,offset=vector(0,0),mirror="",rotate=0): def compute_boundary(self, offset=vector(0, 0), mirror="", rotate=0):
""" Transform with offset, mirror and rotation to get the absolute pin location. """ Transform with offset, mirror and rotation to get the absolute pin location.
We must then re-find the ll and ur. The master is the cell instance. """ We must then re-find the ll and ur. The master is the cell instance. """
if OPTS.netlist_only: if OPTS.netlist_only:
return return
(ll,ur) = [vector(0,0),vector(self.width,self.height)] (ll, ur) = [vector(0, 0), vector(self.width, self.height)]
if mirror=="MX": if mirror == "MX":
ll=ll.scale(1,-1) ll = ll.scale(1, -1)
ur=ur.scale(1,-1) ur = ur.scale(1, -1)
elif mirror=="MY": elif mirror == "MY":
ll=ll.scale(-1,1) ll = ll.scale(-1, 1)
ur=ur.scale(-1,1) ur = ur.scale(-1, 1)
elif mirror=="XY": elif mirror == "XY":
ll=ll.scale(-1,-1) ll = ll.scale(-1, -1)
ur=ur.scale(-1,-1) ur = ur.scale(-1, -1)
if rotate==90: if rotate == 90:
ll=ll.rotate_scale(-1,1) ll = ll.rotate_scale(-1, 1)
ur=ur.rotate_scale(-1,1) ur = ur.rotate_scale(-1, 1)
elif rotate==180: elif rotate == 180:
ll=ll.scale(-1,-1) ll = ll.scale(-1, -1)
ur=ur.scale(-1,-1) ur = ur.scale(-1, -1)
elif rotate==270: elif rotate == 270:
ll=ll.rotate_scale(1,-1) ll = ll.rotate_scale(1, -1)
ur=ur.rotate_scale(1,-1) ur = ur.rotate_scale(1, -1)
self.boundary=[offset+ll,offset+ur] self.boundary = [offset + ll, offset + ur]
self.normalize() self.normalize()
def ll(self): def ll(self):
@ -108,7 +111,6 @@ class geometry:
""" Return the upper left corner """ """ Return the upper left corner """
return vector(self.boundary[0].x, self.boundary[1].y) return vector(self.boundary[0].x, self.boundary[1].y)
def uy(self): def uy(self):
""" Return the upper edge """ """ Return the upper edge """
return self.boundary[1].y return self.boundary[1].y
@ -127,11 +129,11 @@ class geometry:
def cx(self): def cx(self):
""" Return the center x """ """ Return the center x """
return 0.5*(self.boundary[0].x + self.boundary[1].x) return 0.5 * (self.boundary[0].x + self.boundary[1].x)
def cy(self): def cy(self):
""" Return the center y """ """ Return the center y """
return 0.5*(self.boundary[0].y + self.boundary[1].y) return 0.5 * (self.boundary[0].y + self.boundary[1].y)
class instance(geometry): class instance(geometry):
@ -139,10 +141,11 @@ class instance(geometry):
An instance of an instance/module with a specified location and An instance of an instance/module with a specified location and
rotation rotation
""" """
def __init__(self, name, mod, offset=[0,0], mirror="R0", rotate=0): def __init__(self, name, mod, offset=[0, 0], mirror="R0", rotate=0):
"""Initializes an instance to represent a module""" """Initializes an instance to represent a module"""
geometry.__init__(self) geometry.__init__(self)
debug.check(mirror not in ["R90","R180","R270"], "Please use rotation and not mirroring during instantiation.") debug.check(mirror not in ["R90", "R180", "R270"],
"Please use rotation and not mirroring during instantiation.")
self.name = name self.name = name
self.mod = mod self.mod = mod
@ -154,13 +157,13 @@ class instance(geometry):
self.width = 0 self.width = 0
self.height = 0 self.height = 0
else: else:
if mirror in ["R90","R270"] or rotate in [90,270]: if mirror in ["R90", "R270"] or rotate in [90, 270]:
self.width = round_to_grid(mod.height) self.width = round_to_grid(mod.height)
self.height = round_to_grid(mod.width) self.height = round_to_grid(mod.width)
else: else:
self.width = round_to_grid(mod.width) self.width = round_to_grid(mod.width)
self.height = round_to_grid(mod.height) self.height = round_to_grid(mod.height)
self.compute_boundary(offset,mirror,rotate) self.compute_boundary(offset, mirror, rotate)
debug.info(4, "creating instance: " + self.name) debug.info(4, "creating instance: " + self.name)
@ -169,18 +172,18 @@ class instance(geometry):
Apply the transform of the instance placement to give absolute blockages.""" Apply the transform of the instance placement to give absolute blockages."""
angle = math.radians(float(self.rotate)) angle = math.radians(float(self.rotate))
mirr = 1 mirr = 1
if self.mirror=="R90": if self.mirror == "R90":
angle += math.radians(90.0) angle += math.radians(90.0)
elif self.mirror=="R180": elif self.mirror == "R180":
angle += math.radians(180.0) angle += math.radians(180.0)
elif self.mirror=="R270": elif self.mirror == "R270":
angle += math.radians(270.0) angle += math.radians(270.0)
elif self.mirror=="MX": elif self.mirror == "MX":
mirr = -1 mirr = -1
elif self.mirror=="MY": elif self.mirror == "MY":
mirr = -1 mirr = -1
angle += math.radians(180.0) angle += math.radians(180.0)
elif self.mirror=="XY": elif self.mirror == "XY":
mirr = 1 mirr = 1
angle += math.radians(180.0) angle += math.radians(180.0)
@ -226,7 +229,7 @@ class instance(geometry):
this instance location. Index will return one of several pins.""" this instance location. Index will return one of several pins."""
import copy import copy
if index==-1: if index == -1:
pin = copy.deepcopy(self.mod.get_pin(name)) pin = copy.deepcopy(self.mod.get_pin(name))
pin.transform(self.offset,self.mirror,self.rotate) pin.transform(self.offset,self.mirror,self.rotate)
return pin return pin
@ -339,6 +342,7 @@ class label(geometry):
""" override print function output """ """ override print function output """
return "( label: " + self.text + " @" + str(self.offset) + " layer=" + str(self.layerNumber) + " )" return "( label: " + self.text + " @" + str(self.offset) + " layer=" + str(self.layerNumber) + " )"
class rectangle(geometry): class rectangle(geometry):
"""Represents a rectangular shape""" """Represents a rectangular shape"""
@ -351,16 +355,17 @@ class rectangle(geometry):
self.size = vector(width, height).snap_to_grid() self.size = vector(width, height).snap_to_grid()
self.width = round_to_grid(self.size.x) self.width = round_to_grid(self.size.x)
self.height = round_to_grid(self.size.y) self.height = round_to_grid(self.size.y)
self.compute_boundary(offset,"",0) self.compute_boundary(offset, "", 0)
debug.info(4, "creating rectangle (" + str(self.layerNumber) + "): " debug.info(4, "creating rectangle (" + str(self.layerNumber) + "): "
+ str(self.width) + "x" + str(self.height) + " @ " + str(self.offset)) + str(self.width) + "x" + str(self.height) + " @ " + str(self.offset))
def get_blockages(self, layer): def get_blockages(self, layer):
""" Returns a list of one rectangle if it is on this layer""" """ Returns a list of one rectangle if it is on this layer"""
if self.layerNumber == layer: if self.layerNumber == layer:
return [[self.offset, vector(self.offset.x+self.width,self.offset.y+self.height)]] return [[self.offset,
vector(self.offset.x + self.width,
self.offset.y + self.height)]]
else: else:
return [] return []

View File

@ -94,7 +94,7 @@ def info(lev, str):
frm = inspect.stack()[1] frm = inspect.stack()[1]
mod = inspect.getmodule(frm[0]) mod = inspect.getmodule(frm[0])
# classname = frm.f_globals['__name__'] # classname = frm.f_globals['__name__']
if mod.__name__ == None: if mod.__name__ is None:
class_name = "" class_name = ""
else: else:
class_name = mod.__name__ class_name = mod.__name__

View File

@ -13,10 +13,7 @@ created without re-running the entire process. Right now, it assumes the nominal
corner, but should probably be extended. corner, but should probably be extended.
""" """
import sys,os import sys
import datetime
import re
import importlib
from globals import * from globals import *
(OPTS, args) = parse_args() (OPTS, args) = parse_args()

View File

@ -16,34 +16,32 @@ a LEF (.lef) file for preliminary P&R (real one should be from layout)
a Liberty (.lib) file for timing analysis/optimization a Liberty (.lib) file for timing analysis/optimization
""" """
import sys,os import sys
import datetime import datetime
import re import globals as g
import importlib
from globals import *
(OPTS, args) = parse_args() (OPTS, args) = g.parse_args()
# Check that we are left with a single configuration file as argument. # Check that we are left with a single configuration file as argument.
if len(args) != 1: if len(args) != 1:
print(USAGE) print(g.USAGE)
sys.exit(2) sys.exit(2)
# These depend on arguments, so don't load them until now. # These depend on arguments, so don't load them until now.
import debug import debug
init_openram(config_file=args[0], is_unit_test=False) g.init_openram(config_file=args[0], is_unit_test=False)
# Only print banner here so it's not in unit tests # Only print banner here so it's not in unit tests
print_banner() g.print_banner()
# Keep track of running stats # Keep track of running stats
start_time = datetime.datetime.now() start_time = datetime.datetime.now()
print_time("Start",start_time) g.print_time("Start", start_time)
# Output info about this run # Output info about this run
report_status() g.report_status()
from sram_config import sram_config from sram_config import sram_config
@ -54,15 +52,16 @@ c = sram_config(word_size=OPTS.word_size,
write_size=OPTS.write_size) write_size=OPTS.write_size)
debug.print_raw("Words per row: {}".format(c.words_per_row)) debug.print_raw("Words per row: {}".format(c.words_per_row))
#from parser import * output_extensions = ["sp", "v", "lib", "py", "html", "log"]
output_extensions = ["sp","v","lib","py","html","log"]
# Only output lef/gds if back-end # Only output lef/gds if back-end
if not OPTS.netlist_only: if not OPTS.netlist_only:
output_extensions.extend(["lef","gds"]) output_extensions.extend(["lef", "gds"])
output_files = ["{0}{1}.{2}".format(OPTS.output_path,OPTS.output_name,x) for x in output_extensions] output_files = ["{0}{1}.{2}".format(OPTS.output_path,
OPTS.output_name, x)
for x in output_extensions]
debug.print_raw("Output files are: ") debug.print_raw("Output files are: ")
for path in output_files: for path in output_files:
debug.print_raw(path) debug.print_raw(path)
@ -74,7 +73,7 @@ s = sram(sram_config=c,
s.save() s.save()
# Delete temp files etc. # Delete temp files etc.
end_openram() g.end_openram()
print_time("End",datetime.datetime.now(), start_time) g.print_time("End", datetime.datetime.now(), start_time)

View File

@ -8,11 +8,11 @@
import optparse import optparse
import getpass import getpass
import os import os
#import sram_config
class options(optparse.Values): class options(optparse.Values):
""" """
Class for holding all of the OpenRAM options. All of these options can be over-riden in a configuration file Class for holding all of the OpenRAM options. All
of these options can be over-riden in a configuration file
that is the sole required command-line positional argument for openram.py. that is the sole required command-line positional argument for openram.py.
""" """
@ -39,15 +39,16 @@ class options(optparse.Values):
process_corners = "" process_corners = ""
# Size parameters must be specified by user in config file. # Size parameters must be specified by user in config file.
#num_words = 0 # num_words = 0
#word_size = 0 # word_size = 0
# You can manually specify banks, but it is better to auto-detect it. # You can manually specify banks, but it is better to auto-detect it.
num_banks = 1 num_banks = 1
################### ###################
# Optimization options # Optimization options
################### ###################
rbl_delay_percentage = 0.5 #Approximate percentage of delay compared to bitlines # Approximate percentage of delay compared to bitlines
rbl_delay_percentage = 0.5
# Allow manual adjustment of the delay chain over automatic # Allow manual adjustment of the delay chain over automatic
use_tech_delay_chain_size = False use_tech_delay_chain_size = False
@ -65,7 +66,8 @@ class options(optparse.Values):
openram_temp = os.path.abspath(os.environ.get("OPENRAM_TMP")) openram_temp = os.path.abspath(os.environ.get("OPENRAM_TMP"))
except: except:
# Else use a unique temporary directory # Else use a unique temporary directory
openram_temp = "/tmp/openram_{0}_{1}_temp/".format(getpass.getuser(),os.getpid()) openram_temp = "/tmp/openram_{0}_{1}_temp/".format(getpass.getuser(),
os.getpid())
# This is the verbosity level to control debug information. 0 is none, 1 # This is the verbosity level to control debug information. 0 is none, 1
# is minimal, etc. # is minimal, etc.
debug_level = 0 debug_level = 0
@ -100,7 +102,8 @@ class options(optparse.Values):
drc_name = "" drc_name = ""
lvs_name = "" lvs_name = ""
pex_name = "" pex_name = ""
# The DRC/LVS/PEX executable being used which is derived from the user PATH. # The DRC/LVS/PEX executable being used
# which is derived from the user PATH.
drc_exe = None drc_exe = None
lvs_exe = None lvs_exe = None
pex_exe = None pex_exe = None
@ -113,15 +116,14 @@ class options(optparse.Values):
output_path = "." output_path = "."
# Define the output file base name # Define the output file base name
output_name = "" output_name = ""
# Use analytical delay models by default rather than (slow) characterization # Use analytical delay models by default
# rather than (slow) characterization
analytical_delay = True analytical_delay = True
# Purge the temp directory after a successful run (doesn't purge on errors, anyhow) # Purge the temp directory after a successful
# run (doesn't purge on errors, anyhow)
purge_temp = True purge_temp = True
###################
# These are the default modules that can be over-riden # These are the default modules that can be over-riden
###################
bank_select = "bank_select" bank_select = "bank_select"
bitcell_array = "bitcell_array" bitcell_array = "bitcell_array"
bitcell = "bitcell" bitcell = "bitcell"

View File

@ -5,9 +5,9 @@
# (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 debug
from globals import OPTS from globals import OPTS
class sram_factory: class sram_factory:
""" """
This is a factory pattern to create modules for usage in an SRAM. This is a factory pattern to create modules for usage in an SRAM.
@ -34,8 +34,8 @@ class sram_factory:
def create(self, module_type, **kwargs): def create(self, module_type, **kwargs):
""" """
A generic function to create a module with a given module_type. The args A generic function to create a module with a given module_type.
are passed directly to the module constructor. The args are passed directly to the module constructor.
""" """
# if name!="": # if name!="":
# # This is a special case where the name and type don't match # # This is a special case where the name and type don't match
@ -58,28 +58,30 @@ class sram_factory:
self.objects[module_type] = [] self.objects[module_type] = []
# Either retreive a previous object or create a new one # Either retreive a previous object or create a new one
#print("new",kwargs)
for obj in self.objects[module_type]: for obj in self.objects[module_type]:
(obj_kwargs, obj_item) = obj (obj_kwargs, obj_item) = obj
# Must have the same dictionary exactly (conservative) # Must have the same dictionary exactly (conservative)
if obj_kwargs == kwargs: if obj_kwargs == kwargs:
#debug.info(0, "Existing module: type={0} name={1} kwargs={2}".format(module_type, obj_item.name, str(kwargs)))
return obj_item return obj_item
#else:
# print("obj",obj_kwargs)
# Use the default name if there are default arguments # Use the default name if there are default arguments
# This is especially for library cells so that the spice and gds files can be found. # This is especially for library cells so that the
if len(kwargs)>0: # spice and gds files can be found.
if len(kwargs) > 0:
# Create a unique name and increment the index # Create a unique name and increment the index
module_name = "{0}_{1}".format(module_type, self.module_indices[module_type]) module_name = "{0}_{1}".format(module_type,
self.module_indices[module_type])
self.module_indices[module_type] += 1 self.module_indices[module_type] += 1
else: else:
module_name = module_type module_name = module_type
#debug.info(0, "New module: type={0} name={1} kwargs={2}".format(module_type,module_name,str(kwargs))) # type_str = "type={}".format(module_type)
obj = mod(name=module_name,**kwargs) # name_str = "name={}".format(module_name)
self.objects[module_type].append((kwargs,obj)) # kwargs_str = "kwargs={}".format(str(kwargs))
# import debug
# debug.info(0, "New module:" + type_str + name_str + kwargs_str)
obj = mod(name=module_name, **kwargs)
self.objects[module_type].append((kwargs, obj))
return obj return obj
def get_mods(self, module_type): def get_mods(self, module_type):
@ -90,11 +92,11 @@ class sram_factory:
module_type = getattr(OPTS, module_type) module_type = getattr(OPTS, module_type)
try: try:
mod_tuples = self.objects[module_type] mod_tuples = self.objects[module_type]
mods = [mod for kwargs,mod in mod_tuples] mods = [mod for kwargs, mod in mod_tuples]
except KeyError: except KeyError:
mods = [] mods = []
return mods return mods
# Make a factory # Make a factory
factory = sram_factory() factory = sram_factory()

View File

@ -9,8 +9,8 @@
import pstats import pstats
p = pstats.Stats("profile.dat") p = pstats.Stats("profile.dat")
p.strip_dirs() p.strip_dirs()
#p.sort_stats("cumulative") # p.sort_stats("cumulative")
p.sort_stats("tottime") p.sort_stats("tottime")
#p.print_stats(50) # p.print_stats(50)
p.print_stats() p.print_stats()