mirror of https://github.com/VLSIDA/OpenRAM.git
Cleanup and rename vias.
This commit is contained in:
parent
3147b99ce0
commit
79391b84da
|
|
@ -36,6 +36,7 @@ class contact(hierarchy_design.hierarchy_design):
|
|||
|
||||
hierarchy_design.hierarchy_design.__init__(self, name)
|
||||
debug.info(4, "create contact object {0}".format(name))
|
||||
|
||||
self.add_comment("layers: {0}".format(layer_stack))
|
||||
self.add_comment("dimensions: {0}".format(dimensions))
|
||||
if implant_type or well_type:
|
||||
|
|
@ -243,14 +244,19 @@ class contact(hierarchy_design.hierarchy_design):
|
|||
""" Get total power of a module """
|
||||
return self.return_power()
|
||||
|
||||
|
||||
|
||||
# Set up a static for each layer to be used for measurements
|
||||
for layer_stack in tech.layer_stacks:
|
||||
(layer1, via, layer2) = layer_stack
|
||||
cont = factory.create(module_type="contact",
|
||||
layer_stack=layer_stack)
|
||||
module = sys.modules[__name__]
|
||||
# Create the contact as just the concat of the layer names
|
||||
setattr(module, layer1 + layer2, cont)
|
||||
# Also create a contact that is just the first layer
|
||||
if layer1 == "poly" or layer1 == "active":
|
||||
setattr(module, layer1 + "_contact", cont)
|
||||
else:
|
||||
setattr(module, layer1 + "_via", cont)
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -61,8 +61,12 @@ class design(hierarchy_design):
|
|||
"""
|
||||
(layer1, via, layer2) = layer_stack
|
||||
|
||||
contact1 = getattr(contact, layer1 + layer2)
|
||||
if layer1 == "poly" or layer1 == "active":
|
||||
contact1 = getattr(contact, layer1 + "_contact")
|
||||
else:
|
||||
contact1 = getattr(contact, layer1 + "_via")
|
||||
max_contact = max(contact1.width, contact1.height)
|
||||
|
||||
layer1_space = getattr(self, layer1 + "_space")
|
||||
layer2_space = getattr(self, layer2 + "_space")
|
||||
pitch = max_contact + max(layer1_space, layer2_space)
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@
|
|||
#
|
||||
import debug
|
||||
import utils
|
||||
from tech import GDS, layer
|
||||
from tech import GDS, layer, parameter
|
||||
from tech import cell_properties
|
||||
import bitcell_base
|
||||
|
||||
|
||||
|
|
@ -19,7 +20,14 @@ class bitcell(bitcell_base.bitcell_base):
|
|||
library.
|
||||
"""
|
||||
|
||||
pin_names = ["bl", "br", "wl", "vdd", "gnd"]
|
||||
# If we have a split WL bitcell, if not be backwards
|
||||
# compatible in the tech file
|
||||
|
||||
if cell_properties.bitcell.split_wl:
|
||||
pin_names = ["bl", "br", "wl0", "wl1", "vdd", "gnd"]
|
||||
else:
|
||||
pin_names = ["bl", "br", "wl", "vdd", "gnd"]
|
||||
|
||||
storage_nets = ['Q', 'Qbar']
|
||||
type_list = ["OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"]
|
||||
(width, height) = utils.get_libcell_size("cell_6t",
|
||||
|
|
@ -40,7 +48,10 @@ class bitcell(bitcell_base.bitcell_base):
|
|||
|
||||
def get_all_wl_names(self):
|
||||
""" Creates a list of all wordline pin names """
|
||||
row_pins = ["wl"]
|
||||
if cell_properties.bitcell.split_wl:
|
||||
row_pins = ["wl0", "wl1"]
|
||||
else:
|
||||
row_pins = ["wl"]
|
||||
return row_pins
|
||||
|
||||
def get_all_bitline_names(self):
|
||||
|
|
|
|||
|
|
@ -6,22 +6,24 @@
|
|||
# All rights reserved.
|
||||
#
|
||||
|
||||
class _MirrorAxis:
|
||||
class _mirror_axis:
|
||||
def __init__(self, x, y):
|
||||
self.x = x
|
||||
self.y = y
|
||||
|
||||
class _Bitcell:
|
||||
def __init__(self, mirror):
|
||||
class _bitcell:
|
||||
def __init__(self, mirror, split_wl):
|
||||
self.mirror = mirror
|
||||
self.split_wl = split_wl
|
||||
|
||||
class CellProperties():
|
||||
class cell_properties():
|
||||
"""
|
||||
TODO
|
||||
"""
|
||||
def __init__(self):
|
||||
self.names = {}
|
||||
self._bitcell = _Bitcell(_MirrorAxis(True, False))
|
||||
self._bitcell = _bitcell(mirror = _mirror_axis(True, False),
|
||||
split_wl = False)
|
||||
|
||||
@property
|
||||
def bitcell(self):
|
||||
|
|
@ -212,20 +212,20 @@ class pbitcell(bitcell_base.bitcell_base):
|
|||
|
||||
# y-offset for the access transistor's gate contact
|
||||
self.gate_contact_yoffset = max_contact_extension + self.m2_space \
|
||||
+ 0.5 * max(contact.polym1.height, contact.m1m2.height)
|
||||
+ 0.5 * max(contact.poly_contact.height, contact.m1_via.height)
|
||||
|
||||
# y-position of access transistors
|
||||
self.port_ypos = self.m1_space + 0.5 * contact.m1m2.height + self.gate_contact_yoffset
|
||||
self.port_ypos = self.m1_space + 0.5 * contact.m1_via.height + self.gate_contact_yoffset
|
||||
|
||||
# y-position of inverter nmos
|
||||
self.inverter_nmos_ypos = self.port_ypos
|
||||
|
||||
# spacing between ports (same for read/write and write ports)
|
||||
self.bitline_offset = -0.5 * self.readwrite_nmos.active_width \
|
||||
+ 0.5 * contact.m1m2.height \
|
||||
+ 0.5 * contact.m1_via.height \
|
||||
+ self.m2_space + self.m2_width
|
||||
m2_constraint = self.bitline_offset + self.m2_space \
|
||||
+ 0.5 * contact.m1m2.height \
|
||||
+ 0.5 * contact.m1_via.height \
|
||||
- 0.5 * self.readwrite_nmos.active_width
|
||||
self.write_port_spacing = max(self.active_space,
|
||||
self.m1_space,
|
||||
|
|
@ -233,7 +233,7 @@ class pbitcell(bitcell_base.bitcell_base):
|
|||
self.read_port_spacing = self.bitline_offset + self.m2_space
|
||||
|
||||
# spacing between cross coupled inverters
|
||||
self.inverter_to_inverter_spacing = contact.polym1.width + self.m1_space
|
||||
self.inverter_to_inverter_spacing = contact.poly_contact.width + self.m1_space
|
||||
|
||||
# calculations related to inverter connections
|
||||
inverter_pmos_contact_extension = 0.5 * \
|
||||
|
|
@ -242,19 +242,19 @@ class pbitcell(bitcell_base.bitcell_base):
|
|||
(self.inverter_nmos.active_contact.height - self.inverter_nmos.active_height)
|
||||
self.inverter_gap = max(self.poly_to_active,
|
||||
self.m1_space + inverter_nmos_contact_extension) \
|
||||
+ self.poly_to_contact + 2 * contact.polym1.width \
|
||||
+ self.poly_to_contact + 2 * contact.poly_contact.width \
|
||||
+ self.m1_space + inverter_pmos_contact_extension
|
||||
self.cross_couple_lower_ypos = self.inverter_nmos_ypos \
|
||||
+ self.inverter_nmos.active_height \
|
||||
+ max(self.poly_to_active,
|
||||
self.m1_space + inverter_nmos_contact_extension) \
|
||||
+ 0.5 * contact.polym1.width
|
||||
+ 0.5 * contact.poly_contact.width
|
||||
self.cross_couple_upper_ypos = self.inverter_nmos_ypos \
|
||||
+ self.inverter_nmos.active_height \
|
||||
+ max(self.poly_to_active,
|
||||
self.m1_space + inverter_nmos_contact_extension) \
|
||||
+ self.poly_to_contact \
|
||||
+ 1.5 * contact.polym1.width
|
||||
+ 1.5 * contact.poly_contact.width
|
||||
|
||||
# spacing between wordlines (and gnd)
|
||||
self.m1_offset = -0.5 * self.m1_width
|
||||
|
|
@ -290,7 +290,7 @@ class pbitcell(bitcell_base.bitcell_base):
|
|||
(self.write_nmos.active_width + self.write_port_spacing) \
|
||||
- self.num_r_ports * \
|
||||
(self.read_port_width + self.read_port_spacing) \
|
||||
- self.bitline_offset - 0.5 * contact.m1m2.width
|
||||
- self.bitline_offset - 0.5 * contact.m1_via.width
|
||||
|
||||
self.width = -2 * self.leftmost_xpos
|
||||
self.height = self.topmost_ypos - self.botmost_ypos
|
||||
|
|
@ -375,14 +375,14 @@ class pbitcell(bitcell_base.bitcell_base):
|
|||
# add contacts to connect gate poly to drain/source
|
||||
# metal1 (to connect Q to Q_bar)
|
||||
contact_offset_left = vector(self.inverter_nmos_left.get_pin("D").rc().x \
|
||||
+ 0.5 * contact.polym1.height,
|
||||
+ 0.5 * contact.poly_contact.height,
|
||||
self.cross_couple_upper_ypos)
|
||||
self.add_via_center(layers=self.poly_stack,
|
||||
offset=contact_offset_left)
|
||||
|
||||
|
||||
contact_offset_right = vector(self.inverter_nmos_right.get_pin("S").lc().x \
|
||||
- 0.5*contact.polym1.height,
|
||||
- 0.5*contact.poly_contact.height,
|
||||
self.cross_couple_lower_ypos)
|
||||
self.add_via_center(layers=self.poly_stack,
|
||||
offset=contact_offset_right)
|
||||
|
|
@ -824,7 +824,7 @@ class pbitcell(bitcell_base.bitcell_base):
|
|||
offset=port_contact_offest)
|
||||
|
||||
self.add_path("m2",
|
||||
[port_contact_offest, bl_offset], width=contact.m1m2.height)
|
||||
[port_contact_offest, bl_offset], width=contact.m1_via.height)
|
||||
|
||||
for k in range(self.total_ports):
|
||||
port_contact_offest = right_port_transistors[k].get_pin("D").center()
|
||||
|
|
@ -836,7 +836,7 @@ class pbitcell(bitcell_base.bitcell_base):
|
|||
offset=port_contact_offest)
|
||||
|
||||
self.add_path("m2",
|
||||
[port_contact_offest, br_offset], width=contact.m1m2.height)
|
||||
[port_contact_offest, br_offset], width=contact.m1_via.height)
|
||||
|
||||
def route_supply(self):
|
||||
""" Route inverter nmos and read-access nmos to gnd. Route inverter pmos to vdd. """
|
||||
|
|
@ -853,9 +853,9 @@ class pbitcell(bitcell_base.bitcell_base):
|
|||
offset=position)
|
||||
|
||||
if position.x > 0:
|
||||
contact_correct = 0.5 * contact.m1m2.height
|
||||
contact_correct = 0.5 * contact.m1_via.height
|
||||
else:
|
||||
contact_correct = -0.5 * contact.m1m2.height
|
||||
contact_correct = -0.5 * contact.m1_via.height
|
||||
supply_offset = vector(position.x + contact_correct,
|
||||
self.gnd_position.y)
|
||||
self.add_via_center(layers=self.m1_stack,
|
||||
|
|
@ -921,13 +921,13 @@ class pbitcell(bitcell_base.bitcell_base):
|
|||
"""
|
||||
# add poly to metal1 contacts for gates of the inverters
|
||||
left_storage_contact = vector(self.inverter_nmos_left.get_pin("G").lc().x \
|
||||
- self.poly_to_contact - 0.5*contact.polym1.width,
|
||||
- self.poly_to_contact - 0.5*contact.poly_contact.width,
|
||||
self.cross_couple_upper_ypos)
|
||||
self.add_via_center(layers=self.poly_stack,
|
||||
offset=left_storage_contact)
|
||||
|
||||
right_storage_contact = vector(self.inverter_nmos_right.get_pin("G").rc().x \
|
||||
+ self.poly_to_contact + 0.5*contact.polym1.width,
|
||||
+ self.poly_to_contact + 0.5*contact.poly_contact.width,
|
||||
self.cross_couple_upper_ypos)
|
||||
self.add_via_center(layers=self.poly_stack,
|
||||
offset=right_storage_contact)
|
||||
|
|
|
|||
|
|
@ -256,7 +256,7 @@ class bank_select(design.design):
|
|||
|
||||
|
||||
# Connect the logic B input to bank_sel/bank_sel_bar
|
||||
logic_pos = logic_inst.get_pin("B").lc() - vector(0.5*contact.m1m2.height,0)
|
||||
logic_pos = logic_inst.get_pin("B").lc() - vector(0.5*contact.m1_via.height,0)
|
||||
input_pos = vector(xoffset_bank_signal, logic_pos.y)
|
||||
self.add_path("m2",[logic_pos, input_pos])
|
||||
self.add_via_center(layers=self.m1_stack,
|
||||
|
|
|
|||
|
|
@ -5,14 +5,11 @@
|
|||
# (acting for and on behalf of Oklahoma State University)
|
||||
# All rights reserved.
|
||||
#
|
||||
import debug
|
||||
import design
|
||||
from base_array import bitcell_base_array
|
||||
from bitcell_base_array import bitcell_base_array
|
||||
from tech import drc, spice
|
||||
from vector import vector
|
||||
from globals import OPTS
|
||||
from sram_factory import factory
|
||||
import logical_effort
|
||||
|
||||
|
||||
class bitcell_array(bitcell_base_array):
|
||||
"""
|
||||
|
|
@ -29,7 +26,7 @@ class bitcell_array(bitcell_base_array):
|
|||
|
||||
# We don't offset this because we need to align
|
||||
# the replica bitcell in the control logic
|
||||
#self.offset_all_coordinates()
|
||||
# self.offset_all_coordinates()
|
||||
|
||||
|
||||
def create_netlist(self):
|
||||
|
|
@ -48,13 +45,11 @@ class bitcell_array(bitcell_base_array):
|
|||
|
||||
self.DRC_LVS()
|
||||
|
||||
|
||||
def add_modules(self):
|
||||
""" Add the modules used in this design """
|
||||
self.cell = factory.create(module_type="bitcell")
|
||||
self.add_mod(self.cell)
|
||||
|
||||
|
||||
def create_instances(self):
|
||||
""" Create the module instances used in this design """
|
||||
self.cell_inst = {}
|
||||
|
|
@ -65,7 +60,6 @@ class bitcell_array(bitcell_base_array):
|
|||
mod=self.cell)
|
||||
self.connect_inst(self.get_bitcell_pins(col, row))
|
||||
|
||||
|
||||
def analytical_power(self, corner, load):
|
||||
"""Power of Bitcell array and bitline in nW."""
|
||||
from tech import drc, parameter
|
||||
|
|
@ -77,10 +71,10 @@ class bitcell_array(bitcell_base_array):
|
|||
freq = spice["default_event_frequency"]
|
||||
bitline_dynamic = self.calc_dynamic_power(corner, cell_load, freq, swing=bl_swing)
|
||||
|
||||
#Calculate the bitcell power which currently only includes leakage
|
||||
# Calculate the bitcell power which currently only includes leakage
|
||||
cell_power = self.cell.analytical_power(corner, load)
|
||||
|
||||
#Leakage power grows with entire array and bitlines.
|
||||
# Leakage power grows with entire array and bitlines.
|
||||
total_power = self.return_power(cell_power.dynamic + bitline_dynamic * self.column_size,
|
||||
cell_power.leakage * self.column_size * self.row_size)
|
||||
return total_power
|
||||
|
|
|
|||
|
|
@ -178,7 +178,7 @@ class hierarchical_predecode(design.design):
|
|||
# route one signal next to each vdd/gnd rail since this is
|
||||
# typically where the p/n devices are and there are no
|
||||
# pins in the nand gates.
|
||||
y_offset = (num+self.number_of_inputs) * self.inv.height + contact.m1m2.width + self.m1_space
|
||||
y_offset = (num+self.number_of_inputs) * self.inv.height + contact.m1_via.width + self.m1_space
|
||||
in_pin = "in_{}".format(num)
|
||||
a_pin = "A_{}".format(num)
|
||||
in_pos = vector(self.input_rails[in_pin].x,y_offset)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
# All rights reserved.
|
||||
#
|
||||
|
||||
class ModuleType():
|
||||
class module_type():
|
||||
"""
|
||||
This is a class that maps cell names to python classes implementing them.
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -810,7 +810,7 @@ class multibank(design.design):
|
|||
self.add_wire(("m3","via2","m2"),[in_pin, rail_pos, rail_pos - vector(0,self.m2_pitch)])
|
||||
# Bring it up to M2 for M2/M3 routing
|
||||
self.add_via(layers=self.m1_stack,
|
||||
offset=in_pin + contact.m1m2.offset,
|
||||
offset=in_pin + contact.m1_via.offset,
|
||||
rotate=90)
|
||||
self.add_via(layers=self.m2_stack,
|
||||
offset=in_pin + self.m2m3_via_offset,
|
||||
|
|
@ -823,7 +823,7 @@ class multibank(design.design):
|
|||
rail_pos = vector(self.rail_1_x_offsets[rail], in_pin.y)
|
||||
self.add_wire(("m3","via2","m2"),[in_pin, rail_pos, rail_pos - vector(0,self.m2_pitch)])
|
||||
self.add_via(layers=self.m1_stack,
|
||||
offset=in_pin + contact.m1m2.offset,
|
||||
offset=in_pin + contact.m1_via.offset,
|
||||
rotate=90)
|
||||
self.add_via(layers=self.m2_stack,
|
||||
offset=in_pin + self.m2m3_via_offset,
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ class wordline_driver(design.design):
|
|||
up_or_down = self.m2_space if row % 2 else -self.m2_space
|
||||
input_offset = vector(0, b_pos.y + up_or_down)
|
||||
base_offset = vector(clk_offset.x, input_offset.y)
|
||||
contact_offset = vector(0.5 * self.m2_width + self.m2_space + 0.5 * contact.m1m2.width, 0)
|
||||
contact_offset = vector(0.5 * self.m2_width + self.m2_space + 0.5 * contact.m1_via.width, 0)
|
||||
mid_via_offset = base_offset + contact_offset
|
||||
|
||||
# must under the clk line in M1
|
||||
|
|
@ -191,7 +191,7 @@ class wordline_driver(design.design):
|
|||
|
||||
# now connect to the nand2 B
|
||||
self.add_path("m2", [mid_via_offset, b_pos])
|
||||
contact_offset = b_pos - vector(0.5 * contact.m1m2.height, 0)
|
||||
contact_offset = b_pos - vector(0.5 * contact.m1_via.height, 0)
|
||||
self.add_via_center(layers=self.m1_stack,
|
||||
offset=contact_offset,
|
||||
directions=("H", "H"))
|
||||
|
|
|
|||
|
|
@ -87,16 +87,16 @@ class pgate(design.design):
|
|||
left_gate_offset = vector(nmos_gate_pin.lx(), ypos)
|
||||
|
||||
# Center is completely symmetric.
|
||||
contact_width = contact.polym1.width
|
||||
contact_m1_width = contact.polym1.second_layer_width
|
||||
contact_m1_height = contact.polym1.second_layer_height
|
||||
contact_width = contact.poly_contact.width
|
||||
contact_m1_width = contact.poly_contact.second_layer_width
|
||||
contact_m1_height = contact.poly_contact.second_layer_height
|
||||
|
||||
if position == "center":
|
||||
contact_offset = left_gate_offset \
|
||||
+ vector(0.5 * self.poly_width, 0)
|
||||
elif position == "farleft":
|
||||
contact_offset = left_gate_offset \
|
||||
- vector(0.5 * contact.polym1.width, 0)
|
||||
- vector(0.5 * contact.poly_contact.width, 0)
|
||||
elif position == "left":
|
||||
contact_offset = left_gate_offset \
|
||||
- vector(0.5 * contact_width - 0.5 * self.poly_width, 0)
|
||||
|
|
@ -120,7 +120,7 @@ class pgate(design.design):
|
|||
+ left_gate_offset.scale(0.5, 0)
|
||||
self.add_rect_center(layer="poly",
|
||||
offset=mid_point,
|
||||
height=contact.polym1.first_layer_width,
|
||||
height=contact.poly_contact.first_layer_width,
|
||||
width=left_gate_offset.x - contact_offset.x)
|
||||
|
||||
def extend_wells(self, middle_position):
|
||||
|
|
|
|||
|
|
@ -89,14 +89,15 @@ class pinv(pgate.pgate):
|
|||
# Assume we need 3 metal 1 pitches (2 power rails, one
|
||||
# between the tx for the drain)
|
||||
# plus the tx height
|
||||
nmos = factory.create(module_type="ptx", tx_type="nmos")
|
||||
nmos = factory.create(module_type="ptx",
|
||||
tx_type="nmos")
|
||||
pmos = factory.create(module_type="ptx",
|
||||
width=drc("minwidth_tx"),
|
||||
tx_type="pmos")
|
||||
tx_height = nmos.poly_height + pmos.poly_height
|
||||
# rotated m1 pitch or poly to active spacing
|
||||
min_channel = max(contact.polym1.width + self.m1_space,
|
||||
contact.polym1.width + 2 * self.poly_to_active)
|
||||
min_channel = max(contact.poly_contact.width + self.m1_space,
|
||||
contact.poly_contact.width + 2 * self.poly_to_active)
|
||||
|
||||
# This is the extra space needed to ensure DRC rules
|
||||
# to the active contacts
|
||||
|
|
|
|||
|
|
@ -85,10 +85,10 @@ class pnand2(pgate.pgate):
|
|||
""" Pre-compute some handy layout parameters. """
|
||||
|
||||
# metal spacing to allow contacts on any layer
|
||||
self.input_spacing = max(self.poly_space + contact.polym1.first_layer_width,
|
||||
self.m1_space + contact.m1m2.first_layer_width,
|
||||
self.m2_space + contact.m2m3.first_layer_width,
|
||||
self.m3_space + contact.m2m3.second_layer_width)
|
||||
self.input_spacing = max(self.poly_space + contact.poly_contact.first_layer_width,
|
||||
self.m1_space + contact.m1_via.first_layer_width,
|
||||
self.m2_space + contact.m2_via.first_layer_width,
|
||||
self.m3_space + contact.m2_via.second_layer_width)
|
||||
|
||||
|
||||
# Compute the other pmos2 location,
|
||||
|
|
@ -98,7 +98,7 @@ class pnand2(pgate.pgate):
|
|||
|
||||
# Two PMOS devices and a well contact. Separation between each.
|
||||
# Enclosure space on the sides.
|
||||
self.well_width = 2 * self.pmos.active_width + contact.activem1.width \
|
||||
self.well_width = 2 * self.pmos.active_width + contact.active_contact.width \
|
||||
+ 2 * self.active_space \
|
||||
+ 2 * self.nwell_enclose_active
|
||||
|
||||
|
|
@ -245,8 +245,8 @@ class pnand2(pgate.pgate):
|
|||
self.add_layout_pin_rect_center(text="Z",
|
||||
layer="m1",
|
||||
offset=out_offset,
|
||||
width=contact.m1m2.first_layer_height,
|
||||
height=contact.m1m2.first_layer_width)
|
||||
width=contact.m1_via.first_layer_height,
|
||||
height=contact.m1_via.first_layer_width)
|
||||
|
||||
def analytical_power(self, corner, load):
|
||||
"""Returns dynamic and leakage power. Results in nW"""
|
||||
|
|
|
|||
|
|
@ -202,10 +202,10 @@ class pnand3(pgate.pgate):
|
|||
# wire space or wire and one contact space
|
||||
metal_spacing = max(self.m1_space + self.m1_width,
|
||||
self.m2_space + self.m2_width,
|
||||
self.m1_space + 0.5 *contact.polym1.width + 0.5 * self.m1_width)
|
||||
self.m1_space + 0.5 *contact.poly_contact.width + 0.5 * self.m1_width)
|
||||
|
||||
active_spacing = max(self.m1_space,
|
||||
0.5 * contact.polym1.first_layer_width + self.poly_to_active)
|
||||
0.5 * contact.poly_contact.first_layer_width + self.poly_to_active)
|
||||
inputC_yoffset = self.nmos3_pos.y + self.nmos.active_height + active_spacing
|
||||
self.route_input_gate(self.pmos3_inst,
|
||||
self.nmos3_inst,
|
||||
|
|
@ -256,8 +256,8 @@ class pnand3(pgate.pgate):
|
|||
self.add_layout_pin_rect_center(text="Z",
|
||||
layer="m1",
|
||||
offset=mid_offset,
|
||||
width=contact.m1m2.first_layer_width,
|
||||
height=contact.m1m2.first_layer_height)
|
||||
width=contact.m1_via.first_layer_width,
|
||||
height=contact.m1_via.first_layer_height)
|
||||
|
||||
def analytical_power(self, corner, load):
|
||||
"""Returns dynamic and leakage power. Results in nW"""
|
||||
|
|
|
|||
|
|
@ -84,10 +84,10 @@ class pnor2(pgate.pgate):
|
|||
""" Pre-compute some handy layout parameters. """
|
||||
|
||||
# metal spacing to allow contacts on any layer
|
||||
self.input_spacing = max(self.poly_space + contact.polym1.first_layer_width,
|
||||
self.m1_space + contact.m1m2.first_layer_width,
|
||||
self.m2_space + contact.m2m3.first_layer_width,
|
||||
self.m3_space + contact.m2m3.second_layer_width)
|
||||
self.input_spacing = max(self.poly_space + contact.poly_contact.first_layer_width,
|
||||
self.m1_space + contact.m1_via.first_layer_width,
|
||||
self.m2_space + contact.m2_via.first_layer_width,
|
||||
self.m3_space + contact.m2_via.second_layer_width)
|
||||
|
||||
# Compute the other pmos2 location, but determining
|
||||
# offset to overlap the source and drain pins
|
||||
|
|
@ -234,8 +234,8 @@ class pnor2(pgate.pgate):
|
|||
self.add_layout_pin_rect_center(text="Z",
|
||||
layer="m1",
|
||||
offset=mid3_offset,
|
||||
width=contact.m1m2.first_layer_height,
|
||||
height=contact.m1m2.first_layer_width)
|
||||
width=contact.m1_via.first_layer_height,
|
||||
height=contact.m1_via.first_layer_width)
|
||||
|
||||
def analytical_power(self, corner, load):
|
||||
"""Returns dynamic and leakage power. Results in nW"""
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ class precharge(design.design):
|
|||
self.lower_pmos_inst.place(self.lower_pmos_position)
|
||||
|
||||
# adds the upper pmos(s) to layout
|
||||
ydiff = self.pmos.height + 2 * self.m1_space + contact.polym1.width
|
||||
ydiff = self.pmos.height + 2 * self.m1_space + contact.poly_contact.width
|
||||
self.upper_pmos1_pos = self.lower_pmos_position + vector(0, ydiff)
|
||||
self.upper_pmos1_inst.place(self.upper_pmos1_pos)
|
||||
|
||||
|
|
@ -175,7 +175,7 @@ class precharge(design.design):
|
|||
|
||||
# adds the contact from active to metal1
|
||||
well_contact_pos = self.upper_pmos1_inst.get_pin("D").center().scale(1, 0) \
|
||||
+ vector(0, self.upper_pmos1_inst.uy() + contact.activem1.height / 2 \
|
||||
+ vector(0, self.upper_pmos1_inst.uy() + contact.active_contact.height / 2 \
|
||||
+ self.nwell_extend_active)
|
||||
self.add_via_center(layers=self.active_stack,
|
||||
offset=well_contact_pos,
|
||||
|
|
@ -183,7 +183,7 @@ class precharge(design.design):
|
|||
well_type="n")
|
||||
|
||||
# leave an extra pitch for the height
|
||||
self.height = well_contact_pos.y + contact.activem1.height + self.m1_pitch
|
||||
self.height = well_contact_pos.y + contact.active_contact.height + self.m1_pitch
|
||||
|
||||
# nwell should span the whole design since it is pmos only
|
||||
self.add_rect(layer="nwell",
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ class ptristate_inv(pgate.pgate):
|
|||
# Height is an input parameter, so it is not recomputed.
|
||||
|
||||
# Make sure we can put a well above and below
|
||||
self.top_bottom_space = max(contact.activem1.width, contact.activem1.height)
|
||||
self.top_bottom_space = max(contact.active_contact.width, contact.active_contact.height)
|
||||
|
||||
def add_ptx(self):
|
||||
""" Create the PMOS and NMOS transistors. """
|
||||
|
|
@ -135,8 +135,8 @@ class ptristate_inv(pgate.pgate):
|
|||
"""
|
||||
|
||||
pmos_yoff = self.height - self.pmos.active_height \
|
||||
- self.top_bottom_space - 0.5 * contact.activem1.height
|
||||
nmos_yoff = self.top_bottom_space + 0.5 * contact.activem1.height
|
||||
- self.top_bottom_space - 0.5 * contact.active_contact.height
|
||||
nmos_yoff = self.top_bottom_space + 0.5 * contact.active_contact.height
|
||||
|
||||
# Tristate transistors
|
||||
pmos1_pos = vector(self.pmos.active_offset.x, pmos_yoff)
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ from globals import OPTS, print_time
|
|||
|
||||
from sram_base import sram_base
|
||||
from bank import bank
|
||||
from contact import m2m3
|
||||
from contact import m2_via
|
||||
from dff_buf_array import dff_buf_array
|
||||
from dff_array import dff_array
|
||||
|
||||
|
|
@ -280,7 +280,7 @@ class sram_1bank(sram_base):
|
|||
mid_pos = vector(clk_steiner_pos.x, data_dff_clk_pos.y)
|
||||
# In some designs, the steiner via will be too close to the mid_pos via
|
||||
# so make the wire as wide as the contacts
|
||||
self.add_path("m2",[mid_pos, clk_steiner_pos], width=max(m2m3.width,m2m3.height))
|
||||
self.add_path("m2",[mid_pos, clk_steiner_pos], width=max(m2_via.width,m2_via.height))
|
||||
self.add_wire(("m3","via2","m2"),[data_dff_clk_pos, mid_pos, clk_steiner_pos])
|
||||
|
||||
if self.write_size:
|
||||
|
|
@ -289,7 +289,7 @@ class sram_1bank(sram_base):
|
|||
mid_pos = vector(clk_steiner_pos.x, wmask_dff_clk_pos.y)
|
||||
# In some designs, the steiner via will be too close to the mid_pos via
|
||||
# so make the wire as wide as the contacts
|
||||
self.add_path("m2", [mid_pos, clk_steiner_pos], width=max(m2m3.width, m2m3.height))
|
||||
self.add_path("m2", [mid_pos, clk_steiner_pos], width=max(m2_via.width, m2_via.height))
|
||||
self.add_wire(("m3", "via2", "m2"), [wmask_dff_clk_pos, mid_pos, clk_steiner_pos])
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
import os
|
||||
from design_rules import *
|
||||
from module_type import *
|
||||
from custom_cell_properties import CellProperties
|
||||
from custom_cell_properties import cell_properties
|
||||
|
||||
"""
|
||||
File containing the process technology parameters for FreePDK 45nm.
|
||||
|
|
@ -23,15 +23,16 @@ File containing the process technology parameters for FreePDK 45nm.
|
|||
# Using tech_modules['cellname'] you can override each class by providing a custom
|
||||
# implementation in '$OPENRAM_TECHDIR/modules/'
|
||||
# For example: tech_modules['contact'] = 'contact_freepdk45'
|
||||
tech_modules = ModuleType()
|
||||
tech_modules = module_type()
|
||||
|
||||
###################################################
|
||||
# Custom cell properties
|
||||
###################################################
|
||||
cell_properties = CellProperties()
|
||||
cell_properties = cell_properties()
|
||||
cell_properties.bitcell.mirror.x = True
|
||||
cell_properties.bitcell.mirror.y = False
|
||||
|
||||
|
||||
###################################################
|
||||
# GDS file info
|
||||
###################################################
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
import os
|
||||
from design_rules import *
|
||||
from module_type import *
|
||||
from custom_cell_properties import CellProperties
|
||||
from custom_cell_properties import cell_properties
|
||||
|
||||
"""
|
||||
File containing the process technology parameters for SCMOS 4m, 0.35um
|
||||
|
|
@ -23,12 +23,12 @@ File containing the process technology parameters for SCMOS 4m, 0.35um
|
|||
# Using tech_modules['cellname'] you can override each class by providing a custom
|
||||
# implementation in '$OPENRAM_TECHDIR/modules/'
|
||||
# For example: tech_modules['contact'] = 'contact_scn4m'
|
||||
tech_modules = ModuleType()
|
||||
tech_modules = module_type()
|
||||
|
||||
###################################################
|
||||
# Custom cell properties
|
||||
###################################################
|
||||
cell_properties = CellProperties()
|
||||
cell_properties = cell_properties()
|
||||
cell_properties.bitcell.mirror.x = True
|
||||
cell_properties.bitcell.mirror.y = False
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue