mirror of https://github.com/VLSIDA/OpenRAM.git
Clean up and generalize layer rules.
Convert metalN to mN. Generalize helper constants in modules for space, width, enclose, etc. Use layer stacks whever possible. Try to remove drc() calls in liu of helper constants.
This commit is contained in:
parent
a79d03fef4
commit
ed28b4983b
|
|
@ -104,11 +104,11 @@ class contact(hierarchy_design.hierarchy_design):
|
||||||
# The enclosure rule applies to symmetric enclosure component.
|
# The enclosure rule applies to symmetric enclosure component.
|
||||||
|
|
||||||
first_layer_minwidth = drc("minwidth_{0}".format(self.first_layer_name))
|
first_layer_minwidth = drc("minwidth_{0}".format(self.first_layer_name))
|
||||||
first_layer_enclosure = drc("{0}_enclosure_{1}".format(self.first_layer_name, self.via_layer_name))
|
first_layer_enclosure = drc("{0}_enclose_{1}".format(self.first_layer_name, self.via_layer_name))
|
||||||
first_layer_extend = drc("{0}_extend_{1}".format(self.first_layer_name, self.via_layer_name))
|
first_layer_extend = drc("{0}_extend_{1}".format(self.first_layer_name, self.via_layer_name))
|
||||||
|
|
||||||
second_layer_minwidth = drc("minwidth_{0}".format(self.second_layer_name))
|
second_layer_minwidth = drc("minwidth_{0}".format(self.second_layer_name))
|
||||||
second_layer_enclosure = drc("{0}_enclosure_{1}".format(self.second_layer_name, self.via_layer_name))
|
second_layer_enclosure = drc("{0}_enclose_{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
|
||||||
|
|
@ -204,16 +204,16 @@ class contact(hierarchy_design.hierarchy_design):
|
||||||
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_enclose_active")] * 2
|
||||||
implant_width = self.first_layer_width + 2 * drc("implant_enclosure_active")
|
implant_width = self.first_layer_width + 2 * drc("implant_enclose_active")
|
||||||
implant_height = self.first_layer_height + 2 * drc("implant_enclosure_active")
|
implant_height = self.first_layer_height + 2 * drc("implant_enclose_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_enclose_active")] * 2
|
||||||
well_width = self.first_layer_width + 2 * drc("well_enclosure_active")
|
well_width = self.first_layer_width + 2 * drc("well_enclose_active")
|
||||||
well_height = self.first_layer_height + 2 * drc("well_enclosure_active")
|
well_height = self.first_layer_height + 2 * drc("well_enclose_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,
|
||||||
|
|
@ -250,7 +250,7 @@ m1m2 = factory.create(module_type="contact",
|
||||||
m2m3 = factory.create(module_type="contact",
|
m2m3 = factory.create(module_type="contact",
|
||||||
layer_stack=m2_stack,
|
layer_stack=m2_stack,
|
||||||
directions=("V", "H"))
|
directions=("V", "H"))
|
||||||
if "metal4" in layer.keys():
|
if "m4" in layer.keys():
|
||||||
m3m4 = factory.create(module_type="contact",
|
m3m4 = factory.create(module_type="contact",
|
||||||
layer_stack=m3_stack,
|
layer_stack=m3_stack,
|
||||||
directions=("H", "V"))
|
directions=("H", "V"))
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
from hierarchy_design import hierarchy_design
|
from hierarchy_design import hierarchy_design
|
||||||
import contact
|
import contact
|
||||||
from globals import OPTS
|
from globals import OPTS
|
||||||
|
import re
|
||||||
|
|
||||||
class design(hierarchy_design):
|
class design(hierarchy_design):
|
||||||
"""
|
"""
|
||||||
|
|
@ -32,7 +32,7 @@ class design(hierarchy_design):
|
||||||
|
|
||||||
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 tech.layer:
|
if "m4" in tech.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
|
||||||
|
|
@ -46,36 +46,62 @@ class design(hierarchy_design):
|
||||||
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.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")
|
|
||||||
if "metal4" in layer:
|
|
||||||
self.m4_width = drc("minwidth_metal4")
|
|
||||||
self.m4_space = drc("metal4_to_metal4")
|
|
||||||
self.active_width = drc("minwidth_active")
|
|
||||||
self.active_space = drc("active_to_body_active")
|
|
||||||
if "contact" in layer:
|
|
||||||
self.contact_width = drc("minwidth_contact")
|
|
||||||
else:
|
|
||||||
self.contact_width = drc("minwidth_active_contact")
|
|
||||||
|
|
||||||
self.poly_to_active = drc("poly_to_active")
|
# Make some local rules for convenience
|
||||||
self.poly_extend_active = drc("poly_extend_active")
|
for rule in drc.keys():
|
||||||
if "contact" in layer:
|
# Single layer width rules
|
||||||
self.poly_to_contact = drc("poly_to_contact")
|
match = re.search(r"minwidth_(.*)", rule)
|
||||||
else:
|
if match:
|
||||||
self.poly_to_contact = drc("poly_to_active_contact")
|
if match.group(1)=="active_contact":
|
||||||
self.contact_to_gate = drc("contact_to_gate")
|
setattr(self, "contact_width", drc(match.group(0)))
|
||||||
self.well_enclose_active = drc("well_enclosure_active")
|
else:
|
||||||
self.implant_enclose_active = drc("implant_enclosure_active")
|
setattr(self, match.group(1)+"_width", drc(match.group(0)))
|
||||||
self.implant_space = drc("implant_to_implant")
|
|
||||||
|
# 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)))
|
||||||
|
|
||||||
|
# These are for debugging previous manual rules
|
||||||
|
# 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("contact_to_gate", self.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)
|
||||||
|
|
||||||
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.
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ class layout():
|
||||||
y_dir = 1
|
y_dir = 1
|
||||||
else:
|
else:
|
||||||
# we lose a rail after every 2 gates
|
# we lose a rail after every 2 gates
|
||||||
base_offset=vector(x_offset, (inv_num+1) * height - (inv_num%2)*drc["minwidth_metal1"])
|
base_offset=vector(x_offset, (inv_num+1) * height - (inv_num%2)*drc["minwidth_m1"])
|
||||||
y_dir = -1
|
y_dir = -1
|
||||||
|
|
||||||
return (base_offset,y_dir)
|
return (base_offset,y_dir)
|
||||||
|
|
@ -388,9 +388,9 @@ class layout():
|
||||||
|
|
||||||
def get_preferred_direction(self, layer):
|
def get_preferred_direction(self, layer):
|
||||||
""" Return the preferred routing directions """
|
""" Return the preferred routing directions """
|
||||||
if layer in ["metal1", "metal3", "metal5"]:
|
if layer in ["m1", "m3", "m5"]:
|
||||||
return "H"
|
return "H"
|
||||||
elif layer in ["active", "poly", "metal2", "metal4"]:
|
elif layer in ["active", "poly", "m2", "m4"]:
|
||||||
return "V"
|
return "V"
|
||||||
else:
|
else:
|
||||||
return "N"
|
return "N"
|
||||||
|
|
@ -682,12 +682,12 @@ class layout():
|
||||||
return line_positions
|
return line_positions
|
||||||
|
|
||||||
def connect_horizontal_bus(self, mapping, inst, bus_offsets,
|
def connect_horizontal_bus(self, mapping, inst, bus_offsets,
|
||||||
layer_stack=("metal1","via1","metal2")):
|
layer_stack=("m1", "via1", "m2")):
|
||||||
""" Horizontal version of connect_bus. """
|
""" Horizontal version of connect_bus. """
|
||||||
self.connect_bus(mapping, inst, bus_offsets, layer_stack, True)
|
self.connect_bus(mapping, inst, bus_offsets, layer_stack, True)
|
||||||
|
|
||||||
def connect_vertical_bus(self, mapping, inst, bus_offsets,
|
def connect_vertical_bus(self, mapping, inst, bus_offsets,
|
||||||
layer_stack=("metal1","via1","metal2")):
|
layer_stack=("m1", "via1", "m2")):
|
||||||
""" Vertical version of connect_bus. """
|
""" Vertical version of connect_bus. """
|
||||||
self.connect_bus(mapping, inst, bus_offsets, layer_stack, False)
|
self.connect_bus(mapping, inst, bus_offsets, layer_stack, False)
|
||||||
|
|
||||||
|
|
@ -734,15 +734,15 @@ class layout():
|
||||||
rotate=90)
|
rotate=90)
|
||||||
def get_layer_pitch(self, layer):
|
def get_layer_pitch(self, layer):
|
||||||
""" Return the track pitch on a given layer """
|
""" Return the track pitch on a given layer """
|
||||||
if layer=="metal1":
|
if layer=="m1":
|
||||||
return (self.m1_pitch,self.m1_pitch-self.m1_space,self.m1_space)
|
return (self.m1_pitch,self.m1_pitch-self.m1_space,self.m1_space)
|
||||||
elif layer=="metal2":
|
elif layer=="m2":
|
||||||
return (self.m2_pitch,self.m2_pitch-self.m2_space,self.m2_space)
|
return (self.m2_pitch,self.m2_pitch-self.m2_space,self.m2_space)
|
||||||
elif layer=="metal3":
|
elif layer=="m3":
|
||||||
return (self.m3_pitch,self.m3_pitch-self.m3_space,self.m3_space)
|
return (self.m3_pitch,self.m3_pitch-self.m3_space,self.m3_space)
|
||||||
elif layer=="metal4":
|
elif layer=="m4":
|
||||||
from tech import layer as tech_layer
|
from tech import layer as tech_layer
|
||||||
if "metal4" in tech_layer:
|
if "m4" in tech_layer:
|
||||||
return (self.m3_pitch,self.m3_pitch-self.m4_space,self.m4_space)
|
return (self.m3_pitch,self.m3_pitch-self.m4_space,self.m4_space)
|
||||||
else:
|
else:
|
||||||
return (self.m3_pitch,self.m3_pitch-self.m3_space,self.m3_space)
|
return (self.m3_pitch,self.m3_pitch-self.m3_space,self.m3_space)
|
||||||
|
|
@ -1006,16 +1006,16 @@ class layout():
|
||||||
"""
|
"""
|
||||||
pins=inst.get_pins(name)
|
pins=inst.get_pins(name)
|
||||||
for pin in pins:
|
for pin in pins:
|
||||||
if pin.layer=="metal3":
|
if pin.layer=="m3":
|
||||||
self.add_layout_pin(name, pin.layer, pin.ll(), pin.width(), pin.height())
|
self.add_layout_pin(name, pin.layer, pin.ll(), pin.width(), pin.height())
|
||||||
elif pin.layer=="metal1":
|
elif pin.layer=="m1":
|
||||||
self.add_power_pin(name, pin.center())
|
self.add_power_pin(name, pin.center())
|
||||||
else:
|
else:
|
||||||
debug.warning("{0} pins of {1} should be on metal3 or metal1 for supply router.".format(name,inst.name))
|
debug.warning("{0} pins of {1} should be on metal3 or metal1 for supply router.".format(name,inst.name))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def add_power_pin(self, name, loc, vertical=False, start_layer="metal1"):
|
def add_power_pin(self, name, loc, vertical=False, start_layer="m1"):
|
||||||
"""
|
"""
|
||||||
Add a single power pin from M3 down to M1 at the given center location.
|
Add a single power pin from M3 down to M1 at the given center location.
|
||||||
The starting layer is specified to determine which vias are needed.
|
The starting layer is specified to determine which vias are needed.
|
||||||
|
|
@ -1025,24 +1025,24 @@ class layout():
|
||||||
else:
|
else:
|
||||||
direction=("H","H")
|
direction=("H","H")
|
||||||
|
|
||||||
if start_layer=="metal1":
|
if start_layer=="m1":
|
||||||
self.add_via_center(layers=self.m1_stack,
|
self.add_via_center(layers=self.m1_stack,
|
||||||
offset=loc,
|
offset=loc,
|
||||||
directions=direction)
|
directions=direction)
|
||||||
|
|
||||||
|
|
||||||
if start_layer=="metal1" or start_layer=="metal2":
|
if start_layer=="m1" or start_layer=="m2":
|
||||||
via=self.add_via_center(layers=self.m2_stack,
|
via=self.add_via_center(layers=self.m2_stack,
|
||||||
offset=loc,
|
offset=loc,
|
||||||
directions=direction)
|
directions=direction)
|
||||||
|
|
||||||
if start_layer=="metal3":
|
if start_layer=="m3":
|
||||||
self.add_layout_pin_rect_center(text=name,
|
self.add_layout_pin_rect_center(text=name,
|
||||||
layer="metal3",
|
layer="m3",
|
||||||
offset=loc)
|
offset=loc)
|
||||||
else:
|
else:
|
||||||
self.add_layout_pin_rect_center(text=name,
|
self.add_layout_pin_rect_center(text=name,
|
||||||
layer="metal3",
|
layer="m3",
|
||||||
offset=loc,
|
offset=loc,
|
||||||
width=via.width,
|
width=via.width,
|
||||||
height=via.height)
|
height=via.height)
|
||||||
|
|
@ -1064,7 +1064,7 @@ class layout():
|
||||||
# LEFT vertical rails
|
# LEFT vertical rails
|
||||||
offset = ll + vector(-2*self.supply_rail_pitch, -2*self.supply_rail_pitch)
|
offset = ll + vector(-2*self.supply_rail_pitch, -2*self.supply_rail_pitch)
|
||||||
left_gnd_pin=self.add_layout_pin(text="gnd",
|
left_gnd_pin=self.add_layout_pin(text="gnd",
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=offset,
|
offset=offset,
|
||||||
width=self.supply_rail_width,
|
width=self.supply_rail_width,
|
||||||
height=height)
|
height=height)
|
||||||
|
|
@ -1072,7 +1072,7 @@ class layout():
|
||||||
|
|
||||||
offset = ll + vector(-1*self.supply_rail_pitch, -1*self.supply_rail_pitch)
|
offset = ll + vector(-1*self.supply_rail_pitch, -1*self.supply_rail_pitch)
|
||||||
left_vdd_pin=self.add_layout_pin(text="vdd",
|
left_vdd_pin=self.add_layout_pin(text="vdd",
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=offset,
|
offset=offset,
|
||||||
width=self.supply_rail_width,
|
width=self.supply_rail_width,
|
||||||
height=height)
|
height=height)
|
||||||
|
|
@ -1080,14 +1080,14 @@ class layout():
|
||||||
# RIGHT vertical rails
|
# RIGHT vertical rails
|
||||||
offset = vector(ur.x,ll.y) + vector(0,-2*self.supply_rail_pitch)
|
offset = vector(ur.x,ll.y) + vector(0,-2*self.supply_rail_pitch)
|
||||||
right_gnd_pin = self.add_layout_pin(text="gnd",
|
right_gnd_pin = self.add_layout_pin(text="gnd",
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=offset,
|
offset=offset,
|
||||||
width=self.supply_rail_width,
|
width=self.supply_rail_width,
|
||||||
height=height)
|
height=height)
|
||||||
|
|
||||||
offset = vector(ur.x,ll.y) + vector(self.supply_rail_pitch,-1*self.supply_rail_pitch)
|
offset = vector(ur.x,ll.y) + vector(self.supply_rail_pitch,-1*self.supply_rail_pitch)
|
||||||
right_vdd_pin=self.add_layout_pin(text="vdd",
|
right_vdd_pin=self.add_layout_pin(text="vdd",
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=offset,
|
offset=offset,
|
||||||
width=self.supply_rail_width,
|
width=self.supply_rail_width,
|
||||||
height=height)
|
height=height)
|
||||||
|
|
@ -1095,14 +1095,14 @@ class layout():
|
||||||
# BOTTOM horizontal rails
|
# BOTTOM horizontal rails
|
||||||
offset = ll + vector(-2*self.supply_rail_pitch, -2*self.supply_rail_pitch)
|
offset = ll + vector(-2*self.supply_rail_pitch, -2*self.supply_rail_pitch)
|
||||||
bottom_gnd_pin=self.add_layout_pin(text="gnd",
|
bottom_gnd_pin=self.add_layout_pin(text="gnd",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=offset,
|
offset=offset,
|
||||||
width=width,
|
width=width,
|
||||||
height=self.supply_rail_width)
|
height=self.supply_rail_width)
|
||||||
|
|
||||||
offset = ll + vector(-1*self.supply_rail_pitch, -1*self.supply_rail_pitch)
|
offset = ll + vector(-1*self.supply_rail_pitch, -1*self.supply_rail_pitch)
|
||||||
bottom_vdd_pin=self.add_layout_pin(text="vdd",
|
bottom_vdd_pin=self.add_layout_pin(text="vdd",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=offset,
|
offset=offset,
|
||||||
width=width,
|
width=width,
|
||||||
height=self.supply_rail_width)
|
height=self.supply_rail_width)
|
||||||
|
|
@ -1110,14 +1110,14 @@ class layout():
|
||||||
# TOP horizontal rails
|
# TOP horizontal rails
|
||||||
offset = vector(ll.x, ur.y) + vector(-2*self.supply_rail_pitch,0)
|
offset = vector(ll.x, ur.y) + vector(-2*self.supply_rail_pitch,0)
|
||||||
top_gnd_pin=self.add_layout_pin(text="gnd",
|
top_gnd_pin=self.add_layout_pin(text="gnd",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=offset,
|
offset=offset,
|
||||||
width=width,
|
width=width,
|
||||||
height=self.supply_rail_width)
|
height=self.supply_rail_width)
|
||||||
|
|
||||||
offset = vector(ll.x, ur.y) + vector(-1*self.supply_rail_pitch, self.supply_rail_pitch)
|
offset = vector(ll.x, ur.y) + vector(-1*self.supply_rail_pitch, self.supply_rail_pitch)
|
||||||
top_vdd_pin=self.add_layout_pin(text="vdd",
|
top_vdd_pin=self.add_layout_pin(text="vdd",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=offset,
|
offset=offset,
|
||||||
width=width,
|
width=width,
|
||||||
height=self.supply_rail_width)
|
height=self.supply_rail_width)
|
||||||
|
|
@ -1139,7 +1139,7 @@ class layout():
|
||||||
from sram_factory import factory
|
from sram_factory import factory
|
||||||
while True:
|
while True:
|
||||||
c=factory.create(module_type="contact",
|
c=factory.create(module_type="contact",
|
||||||
layer_stack=("metal1","via1","metal2"),
|
layer_stack=self.m1_stack,
|
||||||
dimensions=(self.supply_vias, self.supply_vias))
|
dimensions=(self.supply_vias, self.supply_vias))
|
||||||
if c.second_layer_width < self.supply_rail_width and c.second_layer_height < self.supply_rail_width:
|
if c.second_layer_width < self.supply_rail_width and c.second_layer_height < self.supply_rail_width:
|
||||||
self.supply_vias += 1
|
self.supply_vias += 1
|
||||||
|
|
|
||||||
|
|
@ -364,11 +364,11 @@ class pbitcell(bitcell_base.bitcell_base):
|
||||||
self.inverter_pmos_right.get_pin("G").bc()])
|
self.inverter_pmos_right.get_pin("G").bc()])
|
||||||
|
|
||||||
# connect output (drain/source) of inverters
|
# connect output (drain/source) of inverters
|
||||||
self.add_path("metal1",
|
self.add_path("m1",
|
||||||
[self.inverter_nmos_left.get_pin("D").uc(),
|
[self.inverter_nmos_left.get_pin("D").uc(),
|
||||||
self.inverter_pmos_left.get_pin("D").bc()],
|
self.inverter_pmos_left.get_pin("D").bc()],
|
||||||
width=contact.active.second_layer_width)
|
width=contact.active.second_layer_width)
|
||||||
self.add_path("metal1",
|
self.add_path("m1",
|
||||||
[self.inverter_nmos_right.get_pin("S").uc(),
|
[self.inverter_nmos_right.get_pin("S").uc(),
|
||||||
self.inverter_pmos_right.get_pin("S").bc()],
|
self.inverter_pmos_right.get_pin("S").bc()],
|
||||||
width=contact.active.second_layer_width)
|
width=contact.active.second_layer_width)
|
||||||
|
|
@ -404,7 +404,7 @@ class pbitcell(bitcell_base.bitcell_base):
|
||||||
# Add rails for vdd and gnd
|
# Add rails for vdd and gnd
|
||||||
gnd_ypos = self.m1_offset - self.total_ports * self.m1_pitch
|
gnd_ypos = self.m1_offset - self.total_ports * self.m1_pitch
|
||||||
self.gnd_position = vector(0, gnd_ypos)
|
self.gnd_position = vector(0, gnd_ypos)
|
||||||
self.add_rect_center(layer="metal1",
|
self.add_rect_center(layer="m1",
|
||||||
offset=self.gnd_position,
|
offset=self.gnd_position,
|
||||||
width=self.width)
|
width=self.width)
|
||||||
self.add_power_pin("gnd", vector(0, gnd_ypos))
|
self.add_power_pin("gnd", vector(0, gnd_ypos))
|
||||||
|
|
@ -416,7 +416,7 @@ class pbitcell(bitcell_base.bitcell_base):
|
||||||
+ self.inverter_pmos.active_height \
|
+ self.inverter_pmos.active_height \
|
||||||
+ self.vdd_offset
|
+ self.vdd_offset
|
||||||
self.vdd_position = vector(0, vdd_ypos)
|
self.vdd_position = vector(0, vdd_ypos)
|
||||||
self.add_rect_center(layer="metal1",
|
self.add_rect_center(layer="m1",
|
||||||
offset=self.vdd_position,
|
offset=self.vdd_position,
|
||||||
width=self.width)
|
width=self.width)
|
||||||
self.add_power_pin("vdd", vector(0, vdd_ypos))
|
self.add_power_pin("vdd", vector(0, vdd_ypos))
|
||||||
|
|
@ -489,7 +489,7 @@ class pbitcell(bitcell_base.bitcell_base):
|
||||||
rwwl_ypos = self.m1_offset - k * self.m1_pitch
|
rwwl_ypos = self.m1_offset - k * self.m1_pitch
|
||||||
self.rwwl_positions[k] = vector(0, rwwl_ypos)
|
self.rwwl_positions[k] = vector(0, rwwl_ypos)
|
||||||
self.add_layout_pin_rect_center(text=self.rw_wl_names[k],
|
self.add_layout_pin_rect_center(text=self.rw_wl_names[k],
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=self.rwwl_positions[k],
|
offset=self.rwwl_positions[k],
|
||||||
width=self.width)
|
width=self.width)
|
||||||
|
|
||||||
|
|
@ -499,7 +499,7 @@ class pbitcell(bitcell_base.bitcell_base):
|
||||||
+ 0.5 * self.m2_width
|
+ 0.5 * self.m2_width
|
||||||
self.rwbl_positions[k] = vector(rwbl_xpos, self.center_ypos)
|
self.rwbl_positions[k] = vector(rwbl_xpos, self.center_ypos)
|
||||||
self.add_layout_pin_rect_center(text=self.rw_bl_names[k],
|
self.add_layout_pin_rect_center(text=self.rw_bl_names[k],
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=self.rwbl_positions[k],
|
offset=self.rwbl_positions[k],
|
||||||
height=self.height)
|
height=self.height)
|
||||||
|
|
||||||
|
|
@ -509,7 +509,7 @@ class pbitcell(bitcell_base.bitcell_base):
|
||||||
- 0.5 * self.m2_width
|
- 0.5 * self.m2_width
|
||||||
self.rwbr_positions[k] = vector(rwbr_xpos, self.center_ypos)
|
self.rwbr_positions[k] = vector(rwbr_xpos, self.center_ypos)
|
||||||
self.add_layout_pin_rect_center(text=self.rw_br_names[k],
|
self.add_layout_pin_rect_center(text=self.rw_br_names[k],
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=self.rwbr_positions[k],
|
offset=self.rwbr_positions[k],
|
||||||
height=self.height)
|
height=self.height)
|
||||||
|
|
||||||
|
|
@ -586,7 +586,7 @@ class pbitcell(bitcell_base.bitcell_base):
|
||||||
- k * self.m1_pitch
|
- k * self.m1_pitch
|
||||||
self.wwl_positions[k] = vector(0, wwl_ypos)
|
self.wwl_positions[k] = vector(0, wwl_ypos)
|
||||||
self.add_layout_pin_rect_center(text=self.w_wl_names[k],
|
self.add_layout_pin_rect_center(text=self.w_wl_names[k],
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=self.wwl_positions[k],
|
offset=self.wwl_positions[k],
|
||||||
width=self.width)
|
width=self.width)
|
||||||
|
|
||||||
|
|
@ -596,7 +596,7 @@ class pbitcell(bitcell_base.bitcell_base):
|
||||||
+ 0.5 * self.m2_width
|
+ 0.5 * self.m2_width
|
||||||
self.wbl_positions[k] = vector(wbl_xpos, self.center_ypos)
|
self.wbl_positions[k] = vector(wbl_xpos, self.center_ypos)
|
||||||
self.add_layout_pin_rect_center(text=self.w_bl_names[k],
|
self.add_layout_pin_rect_center(text=self.w_bl_names[k],
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=self.wbl_positions[k],
|
offset=self.wbl_positions[k],
|
||||||
height=self.height)
|
height=self.height)
|
||||||
|
|
||||||
|
|
@ -606,7 +606,7 @@ class pbitcell(bitcell_base.bitcell_base):
|
||||||
- 0.5 * self.m2_width
|
- 0.5 * self.m2_width
|
||||||
self.wbr_positions[k] = vector(wbr_xpos, self.center_ypos)
|
self.wbr_positions[k] = vector(wbr_xpos, self.center_ypos)
|
||||||
self.add_layout_pin_rect_center(text=self.w_br_names[k],
|
self.add_layout_pin_rect_center(text=self.w_br_names[k],
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=self.wbr_positions[k],
|
offset=self.wbr_positions[k],
|
||||||
height=self.height)
|
height=self.height)
|
||||||
|
|
||||||
|
|
@ -713,7 +713,7 @@ class pbitcell(bitcell_base.bitcell_base):
|
||||||
- k * self.m1_pitch
|
- k * self.m1_pitch
|
||||||
self.rwl_positions[k] = vector(0, rwl_ypos)
|
self.rwl_positions[k] = vector(0, rwl_ypos)
|
||||||
self.add_layout_pin_rect_center(text=self.r_wl_names[k],
|
self.add_layout_pin_rect_center(text=self.r_wl_names[k],
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=self.rwl_positions[k],
|
offset=self.rwl_positions[k],
|
||||||
width=self.width)
|
width=self.width)
|
||||||
|
|
||||||
|
|
@ -723,7 +723,7 @@ class pbitcell(bitcell_base.bitcell_base):
|
||||||
+ 0.5 * self.m2_width
|
+ 0.5 * self.m2_width
|
||||||
self.rbl_positions[k] = vector(rbl_xpos, self.center_ypos)
|
self.rbl_positions[k] = vector(rbl_xpos, self.center_ypos)
|
||||||
self.add_layout_pin_rect_center(text=self.r_bl_names[k],
|
self.add_layout_pin_rect_center(text=self.r_bl_names[k],
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=self.rbl_positions[k],
|
offset=self.rbl_positions[k],
|
||||||
height=self.height)
|
height=self.height)
|
||||||
|
|
||||||
|
|
@ -733,7 +733,7 @@ class pbitcell(bitcell_base.bitcell_base):
|
||||||
- 0.5 * self.m2_width
|
- 0.5 * self.m2_width
|
||||||
self.rbr_positions[k] = vector(rbr_xpos, self.center_ypos)
|
self.rbr_positions[k] = vector(rbr_xpos, self.center_ypos)
|
||||||
self.add_layout_pin_rect_center(text=self.r_br_names[k],
|
self.add_layout_pin_rect_center(text=self.r_br_names[k],
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=self.rbr_positions[k],
|
offset=self.rbr_positions[k],
|
||||||
height=self.height)
|
height=self.height)
|
||||||
|
|
||||||
|
|
@ -775,7 +775,7 @@ class pbitcell(bitcell_base.bitcell_base):
|
||||||
offset=port_contact_offset)
|
offset=port_contact_offset)
|
||||||
|
|
||||||
self.add_path("poly", [gate_offset, port_contact_offset])
|
self.add_path("poly", [gate_offset, port_contact_offset])
|
||||||
self.add_path("metal1",
|
self.add_path("m1",
|
||||||
[port_contact_offset, wl_contact_offset])
|
[port_contact_offset, wl_contact_offset])
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
@ -789,7 +789,7 @@ class pbitcell(bitcell_base.bitcell_base):
|
||||||
directions=("H", "H"))
|
directions=("H", "H"))
|
||||||
|
|
||||||
self.add_path("poly", [gate_offset, port_contact_offset])
|
self.add_path("poly", [gate_offset, port_contact_offset])
|
||||||
self.add_path("metal2",
|
self.add_path("m2",
|
||||||
[port_contact_offset, wl_contact_offset])
|
[port_contact_offset, wl_contact_offset])
|
||||||
|
|
||||||
def route_bitlines(self):
|
def route_bitlines(self):
|
||||||
|
|
@ -827,7 +827,7 @@ class pbitcell(bitcell_base.bitcell_base):
|
||||||
self.add_via_center(layers=self.m1_stack,
|
self.add_via_center(layers=self.m1_stack,
|
||||||
offset=port_contact_offest)
|
offset=port_contact_offest)
|
||||||
|
|
||||||
self.add_path("metal2",
|
self.add_path("m2",
|
||||||
[port_contact_offest, bl_offset], width=contact.m1m2.height)
|
[port_contact_offest, bl_offset], width=contact.m1m2.height)
|
||||||
|
|
||||||
for k in range(self.total_ports):
|
for k in range(self.total_ports):
|
||||||
|
|
@ -839,7 +839,7 @@ class pbitcell(bitcell_base.bitcell_base):
|
||||||
self.add_via_center(layers=self.m1_stack,
|
self.add_via_center(layers=self.m1_stack,
|
||||||
offset=port_contact_offest)
|
offset=port_contact_offest)
|
||||||
|
|
||||||
self.add_path("metal2",
|
self.add_path("m2",
|
||||||
[port_contact_offest, br_offset], width=contact.m1m2.height)
|
[port_contact_offest, br_offset], width=contact.m1m2.height)
|
||||||
|
|
||||||
def route_supply(self):
|
def route_supply(self):
|
||||||
|
|
@ -866,17 +866,17 @@ class pbitcell(bitcell_base.bitcell_base):
|
||||||
offset=supply_offset,
|
offset=supply_offset,
|
||||||
directions=("H", "H"))
|
directions=("H", "H"))
|
||||||
|
|
||||||
self.add_path("metal2", [position, supply_offset])
|
self.add_path("m2", [position, supply_offset])
|
||||||
|
|
||||||
# route inverter pmos to vdd
|
# route inverter pmos to vdd
|
||||||
vdd_pos_left = vector(self.inverter_nmos_left.get_pin("S").uc().x,
|
vdd_pos_left = vector(self.inverter_nmos_left.get_pin("S").uc().x,
|
||||||
self.vdd_position.y)
|
self.vdd_position.y)
|
||||||
self.add_path("metal1",
|
self.add_path("m1",
|
||||||
[self.inverter_pmos_left.get_pin("S").uc(), vdd_pos_left])
|
[self.inverter_pmos_left.get_pin("S").uc(), vdd_pos_left])
|
||||||
|
|
||||||
vdd_pos_right = vector(self.inverter_nmos_right.get_pin("D").uc().x,
|
vdd_pos_right = vector(self.inverter_nmos_right.get_pin("D").uc().x,
|
||||||
self.vdd_position.y)
|
self.vdd_position.y)
|
||||||
self.add_path("metal1",
|
self.add_path("m1",
|
||||||
[self.inverter_pmos_right.get_pin("D").uc(), vdd_pos_right])
|
[self.inverter_pmos_right.get_pin("D").uc(), vdd_pos_right])
|
||||||
|
|
||||||
def route_readwrite_access(self):
|
def route_readwrite_access(self):
|
||||||
|
|
@ -889,14 +889,14 @@ class pbitcell(bitcell_base.bitcell_base):
|
||||||
self.cross_couple_lower_ypos)
|
self.cross_couple_lower_ypos)
|
||||||
Q_pos = vector(self.inverter_nmos_left.get_pin("D").lx(),
|
Q_pos = vector(self.inverter_nmos_left.get_pin("D").lx(),
|
||||||
self.cross_couple_lower_ypos)
|
self.cross_couple_lower_ypos)
|
||||||
self.add_path("metal1",
|
self.add_path("m1",
|
||||||
[self.readwrite_nmos_left[k].get_pin("D").uc(), mid, Q_pos])
|
[self.readwrite_nmos_left[k].get_pin("D").uc(), mid, Q_pos])
|
||||||
|
|
||||||
mid = vector(self.readwrite_nmos_right[k].get_pin("S").uc().x,
|
mid = vector(self.readwrite_nmos_right[k].get_pin("S").uc().x,
|
||||||
self.cross_couple_lower_ypos)
|
self.cross_couple_lower_ypos)
|
||||||
Q_bar_pos = vector(self.inverter_nmos_right.get_pin("S").rx(),
|
Q_bar_pos = vector(self.inverter_nmos_right.get_pin("S").rx(),
|
||||||
self.cross_couple_lower_ypos)
|
self.cross_couple_lower_ypos)
|
||||||
self.add_path("metal1",
|
self.add_path("m1",
|
||||||
[self.readwrite_nmos_right[k].get_pin("S").uc(), mid, Q_bar_pos])
|
[self.readwrite_nmos_right[k].get_pin("S").uc(), mid, Q_bar_pos])
|
||||||
|
|
||||||
def route_write_access(self):
|
def route_write_access(self):
|
||||||
|
|
@ -909,14 +909,14 @@ class pbitcell(bitcell_base.bitcell_base):
|
||||||
self.cross_couple_lower_ypos)
|
self.cross_couple_lower_ypos)
|
||||||
Q_pos = vector(self.inverter_nmos_left.get_pin("D").lx(),
|
Q_pos = vector(self.inverter_nmos_left.get_pin("D").lx(),
|
||||||
self.cross_couple_lower_ypos)
|
self.cross_couple_lower_ypos)
|
||||||
self.add_path("metal1",
|
self.add_path("m1",
|
||||||
[self.write_nmos_left[k].get_pin("D").uc(), mid, Q_pos])
|
[self.write_nmos_left[k].get_pin("D").uc(), mid, Q_pos])
|
||||||
|
|
||||||
mid = vector(self.write_nmos_right[k].get_pin("S").uc().x,
|
mid = vector(self.write_nmos_right[k].get_pin("S").uc().x,
|
||||||
self.cross_couple_lower_ypos)
|
self.cross_couple_lower_ypos)
|
||||||
Q_bar_pos = vector(self.inverter_nmos_right.get_pin("S").rx(),
|
Q_bar_pos = vector(self.inverter_nmos_right.get_pin("S").rx(),
|
||||||
self.cross_couple_lower_ypos)
|
self.cross_couple_lower_ypos)
|
||||||
self.add_path("metal1",
|
self.add_path("m1",
|
||||||
[self.write_nmos_right[k].get_pin("S").uc(), mid, Q_bar_pos])
|
[self.write_nmos_right[k].get_pin("S").uc(), mid, Q_bar_pos])
|
||||||
|
|
||||||
def route_read_access(self):
|
def route_read_access(self):
|
||||||
|
|
@ -960,7 +960,7 @@ class pbitcell(bitcell_base.bitcell_base):
|
||||||
|
|
||||||
mid = vector(self.read_access_nmos_left[k].get_pin("G").uc().x,
|
mid = vector(self.read_access_nmos_left[k].get_pin("G").uc().x,
|
||||||
self.cross_couple_upper_ypos)
|
self.cross_couple_upper_ypos)
|
||||||
self.add_path("metal1",
|
self.add_path("m1",
|
||||||
[port_contact_offset, mid, left_storage_contact])
|
[port_contact_offset, mid, left_storage_contact])
|
||||||
|
|
||||||
port_contact_offset = self.read_access_nmos_right[k].get_pin("G").uc() \
|
port_contact_offset = self.read_access_nmos_right[k].get_pin("G").uc() \
|
||||||
|
|
@ -975,7 +975,7 @@ class pbitcell(bitcell_base.bitcell_base):
|
||||||
|
|
||||||
mid = vector(self.read_access_nmos_right[k].get_pin("G").uc().x,
|
mid = vector(self.read_access_nmos_right[k].get_pin("G").uc().x,
|
||||||
self.cross_couple_upper_ypos)
|
self.cross_couple_upper_ypos)
|
||||||
self.add_path("metal1",
|
self.add_path("m1",
|
||||||
[port_contact_offset, mid, right_storage_contact])
|
[port_contact_offset, mid, right_storage_contact])
|
||||||
|
|
||||||
def extend_well(self):
|
def extend_well(self):
|
||||||
|
|
@ -1076,7 +1076,7 @@ class pbitcell(bitcell_base.bitcell_base):
|
||||||
"""
|
"""
|
||||||
Q_bar_pos = self.inverter_pmos_right.get_pin("S").center()
|
Q_bar_pos = self.inverter_pmos_right.get_pin("S").center()
|
||||||
vdd_pos = self.inverter_pmos_right.get_pin("D").center()
|
vdd_pos = self.inverter_pmos_right.get_pin("D").center()
|
||||||
self.add_path("metal1", [Q_bar_pos, vdd_pos])
|
self.add_path("m1", [Q_bar_pos, vdd_pos])
|
||||||
|
|
||||||
def get_storage_net_names(self):
|
def get_storage_net_names(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import debug
|
||||||
from drc_value import *
|
from drc_value import *
|
||||||
from drc_lut import *
|
from drc_lut import *
|
||||||
|
|
||||||
class design_rules():
|
class design_rules(dict):
|
||||||
"""
|
"""
|
||||||
This is a class that implements the design rules structures.
|
This is a class that implements the design rules structures.
|
||||||
"""
|
"""
|
||||||
|
|
@ -43,7 +43,9 @@ class design_rules():
|
||||||
else:
|
else:
|
||||||
debug.error("Must call complex DRC rule {} with arguments.".format(b),-1)
|
debug.error("Must call complex DRC rule {} with arguments.".format(b),-1)
|
||||||
|
|
||||||
|
def keys(self):
|
||||||
|
return self.rules.keys()
|
||||||
|
|
||||||
def add_layer(self, name, width, spacing, area=0):
|
def add_layer(self, name, width, spacing, area=0):
|
||||||
# Minimum width
|
# Minimum width
|
||||||
self.add("minwidth_{}".format(name), width)
|
self.add("minwidth_{}".format(name), width)
|
||||||
|
|
@ -53,7 +55,7 @@ class design_rules():
|
||||||
self.add("minarea_{}".format(name), area)
|
self.add("minarea_{}".format(name), area)
|
||||||
|
|
||||||
def add_enclosure(self, name, layer, enclosure, extension=None):
|
def add_enclosure(self, name, layer, enclosure, extension=None):
|
||||||
self.add("{0}_enclosure_{1}".format(name, layer), enclosure)
|
self.add("{0}_enclose_{1}".format(name, layer), enclosure)
|
||||||
# Reserved for asymmetric enclosures
|
# Reserved for asymmetric enclosures
|
||||||
if extension:
|
if extension:
|
||||||
self.add("{0}_extend_{1}".format(name, layer), extension)
|
self.add("{0}_extend_{1}".format(name, layer), extension)
|
||||||
|
|
|
||||||
|
|
@ -333,7 +333,7 @@ class bank(design.design):
|
||||||
self.col_addr_bus_width = self.m2_pitch*self.num_col_addr_lines
|
self.col_addr_bus_width = self.m2_pitch*self.num_col_addr_lines
|
||||||
|
|
||||||
# A space for wells or jogging m2
|
# A space for wells or jogging m2
|
||||||
self.m2_gap = max(2*drc("pwell_to_nwell") + drc("well_enclosure_active"),
|
self.m2_gap = max(2*drc("pwell_to_nwell") + drc("well_enclose_active"),
|
||||||
3*self.m2_pitch)
|
3*self.m2_pitch)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -605,7 +605,7 @@ class bank(design.design):
|
||||||
out_pos = self.bank_select_inst[port].get_pin(gated_bank_sel_signals[signal]).rc()
|
out_pos = self.bank_select_inst[port].get_pin(gated_bank_sel_signals[signal]).rc()
|
||||||
name = self.control_signals[port][signal]
|
name = self.control_signals[port][signal]
|
||||||
bus_pos = vector(self.bus_xoffset[port][name].x, out_pos.y)
|
bus_pos = vector(self.bus_xoffset[port][name].x, out_pos.y)
|
||||||
self.add_path("metal3",[out_pos, bus_pos])
|
self.add_path("m3",[out_pos, bus_pos])
|
||||||
self.add_via_center(layers=self.m2_stack,
|
self.add_via_center(layers=self.m2_stack,
|
||||||
offset=bus_pos)
|
offset=bus_pos)
|
||||||
self.add_via_center(layers=self.m1_stack,
|
self.add_via_center(layers=self.m1_stack,
|
||||||
|
|
@ -648,7 +648,7 @@ class bank(design.design):
|
||||||
control_bus_offset = vector(-self.m2_pitch * self.num_control_lines[0] - self.m2_pitch, self.min_y_offset)
|
control_bus_offset = vector(-self.m2_pitch * self.num_control_lines[0] - self.m2_pitch, self.min_y_offset)
|
||||||
# The control bus is routed up to two pitches below the bitcell array
|
# The control bus is routed up to two pitches below the bitcell array
|
||||||
control_bus_length = self.main_bitcell_array_bottom - self.min_y_offset - 2*self.m1_pitch
|
control_bus_length = self.main_bitcell_array_bottom - self.min_y_offset - 2*self.m1_pitch
|
||||||
self.bus_xoffset[0] = self.create_bus(layer="metal2",
|
self.bus_xoffset[0] = self.create_bus(layer="m2",
|
||||||
pitch=self.m2_pitch,
|
pitch=self.m2_pitch,
|
||||||
offset=control_bus_offset,
|
offset=control_bus_offset,
|
||||||
names=self.control_signals[0],
|
names=self.control_signals[0],
|
||||||
|
|
@ -663,7 +663,7 @@ class bank(design.design):
|
||||||
control_bus_offset = vector(self.bitcell_array_right + self.m2_pitch,
|
control_bus_offset = vector(self.bitcell_array_right + self.m2_pitch,
|
||||||
self.max_y_offset - control_bus_length)
|
self.max_y_offset - control_bus_length)
|
||||||
# The bus for the right port is reversed so that the rbl_wl is closest to the array
|
# The bus for the right port is reversed so that the rbl_wl is closest to the array
|
||||||
self.bus_xoffset[1] = self.create_bus(layer="metal2",
|
self.bus_xoffset[1] = self.create_bus(layer="m2",
|
||||||
pitch=self.m2_pitch,
|
pitch=self.m2_pitch,
|
||||||
offset=control_bus_offset,
|
offset=control_bus_offset,
|
||||||
names=list(reversed(self.control_signals[1])),
|
names=list(reversed(self.control_signals[1])),
|
||||||
|
|
@ -817,7 +817,7 @@ class bank(design.design):
|
||||||
bitcell_wl_pos = self.bitcell_array_inst.get_pin(self.wl_names[port]+"_{}".format(row)).lc()
|
bitcell_wl_pos = self.bitcell_array_inst.get_pin(self.wl_names[port]+"_{}".format(row)).lc()
|
||||||
mid1 = driver_wl_pos.scale(0,1) + vector(0.5*self.port_address_inst[port].rx() + 0.5*self.bitcell_array_inst.lx(),0)
|
mid1 = driver_wl_pos.scale(0,1) + vector(0.5*self.port_address_inst[port].rx() + 0.5*self.bitcell_array_inst.lx(),0)
|
||||||
mid2 = mid1.scale(1,0)+bitcell_wl_pos.scale(0.5,1)
|
mid2 = mid1.scale(1,0)+bitcell_wl_pos.scale(0.5,1)
|
||||||
self.add_path("metal1", [driver_wl_pos, mid1, mid2, bitcell_wl_pos])
|
self.add_path("m1", [driver_wl_pos, mid1, mid2, bitcell_wl_pos])
|
||||||
|
|
||||||
|
|
||||||
def route_port_address_right(self, port):
|
def route_port_address_right(self, port):
|
||||||
|
|
@ -829,7 +829,7 @@ class bank(design.design):
|
||||||
bitcell_wl_pos = self.bitcell_array_inst.get_pin(self.wl_names[port]+"_{}".format(row)).rc()
|
bitcell_wl_pos = self.bitcell_array_inst.get_pin(self.wl_names[port]+"_{}".format(row)).rc()
|
||||||
mid1 = driver_wl_pos.scale(0,1) + vector(0.5*self.port_address_inst[port].lx() + 0.5*self.bitcell_array_inst.rx(),0)
|
mid1 = driver_wl_pos.scale(0,1) + vector(0.5*self.port_address_inst[port].lx() + 0.5*self.bitcell_array_inst.rx(),0)
|
||||||
mid2 = mid1.scale(1,0)+bitcell_wl_pos.scale(0,1)
|
mid2 = mid1.scale(1,0)+bitcell_wl_pos.scale(0,1)
|
||||||
self.add_path("metal1", [driver_wl_pos, mid1, mid2, bitcell_wl_pos])
|
self.add_path("m1", [driver_wl_pos, mid1, 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 """
|
||||||
|
|
@ -878,7 +878,7 @@ class bank(design.design):
|
||||||
wl_name = "wl_{}".format(i)
|
wl_name = "wl_{}".format(i)
|
||||||
wl_pin = self.bitcell_array_inst.get_pin(wl_name)
|
wl_pin = self.bitcell_array_inst.get_pin(wl_name)
|
||||||
self.add_label(text=wl_name,
|
self.add_label(text=wl_name,
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=wl_pin.center())
|
offset=wl_pin.center())
|
||||||
|
|
||||||
# Add the bitline names
|
# Add the bitline names
|
||||||
|
|
@ -888,10 +888,10 @@ class bank(design.design):
|
||||||
bl_pin = self.bitcell_array_inst.get_pin(bl_name)
|
bl_pin = self.bitcell_array_inst.get_pin(bl_name)
|
||||||
br_pin = self.bitcell_array_inst.get_pin(br_name)
|
br_pin = self.bitcell_array_inst.get_pin(br_name)
|
||||||
self.add_label(text=bl_name,
|
self.add_label(text=bl_name,
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=bl_pin.center())
|
offset=bl_pin.center())
|
||||||
self.add_label(text=br_name,
|
self.add_label(text=br_name,
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=br_pin.center())
|
offset=br_pin.center())
|
||||||
|
|
||||||
# # Add the data output names to the sense amp output
|
# # Add the data output names to the sense amp output
|
||||||
|
|
@ -899,7 +899,7 @@ class bank(design.design):
|
||||||
# data_name = "data_{}".format(i)
|
# data_name = "data_{}".format(i)
|
||||||
# data_pin = self.sense_amp_array_inst.get_pin(data_name)
|
# data_pin = self.sense_amp_array_inst.get_pin(data_name)
|
||||||
# self.add_label(text="sa_out_{}".format(i),
|
# self.add_label(text="sa_out_{}".format(i),
|
||||||
# layer="metal2",
|
# layer="m2",
|
||||||
# offset=data_pin.center())
|
# offset=data_pin.center())
|
||||||
|
|
||||||
# Add labels on the decoder
|
# Add labels on the decoder
|
||||||
|
|
@ -909,7 +909,7 @@ class bank(design.design):
|
||||||
pin_name = "in_{}".format(i)
|
pin_name = "in_{}".format(i)
|
||||||
data_pin = self.wordline_driver_inst[port].get_pin(pin_name)
|
data_pin = self.wordline_driver_inst[port].get_pin(pin_name)
|
||||||
self.add_label(text=data_name,
|
self.add_label(text=data_name,
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=data_pin.center())
|
offset=data_pin.center())
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -941,7 +941,7 @@ class bank(design.design):
|
||||||
for (control_signal, pin_pos) in connection:
|
for (control_signal, pin_pos) in connection:
|
||||||
control_mid_pos = self.bus_xoffset[port][control_signal]
|
control_mid_pos = self.bus_xoffset[port][control_signal]
|
||||||
control_pos = vector(self.bus_xoffset[port][control_signal].x ,pin_pos.y)
|
control_pos = vector(self.bus_xoffset[port][control_signal].x ,pin_pos.y)
|
||||||
self.add_wire(("metal1","via1","metal2"), [control_mid_pos, control_pos, pin_pos])
|
self.add_wire(self.m1_stack, [control_mid_pos, control_pos, pin_pos])
|
||||||
self.add_via_center(layers=self.m1_stack,
|
self.add_via_center(layers=self.m1_stack,
|
||||||
offset=control_pos)
|
offset=control_pos)
|
||||||
|
|
||||||
|
|
@ -956,7 +956,7 @@ class bank(design.design):
|
||||||
mid_pos = pin_pos - vector(0,2*self.m2_gap) # to route down to the top of the bus
|
mid_pos = pin_pos - vector(0,2*self.m2_gap) # to route down to the top of the bus
|
||||||
control_x_offset = self.bus_xoffset[port][control_signal].x
|
control_x_offset = self.bus_xoffset[port][control_signal].x
|
||||||
control_pos = vector(control_x_offset, mid_pos.y)
|
control_pos = vector(control_x_offset, mid_pos.y)
|
||||||
self.add_wire(("metal1","via1","metal2"),[pin_pos, mid_pos, control_pos])
|
self.add_wire(self.m1_stack,[pin_pos, mid_pos, control_pos])
|
||||||
self.add_via_center(layers=self.m1_stack,
|
self.add_via_center(layers=self.m1_stack,
|
||||||
offset=control_pos)
|
offset=control_pos)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -208,18 +208,18 @@ class bank_select(design.design):
|
||||||
xoffset_bank_sel = bank_sel_inv_pin.lx()
|
xoffset_bank_sel = bank_sel_inv_pin.lx()
|
||||||
bank_sel_line_pos = vector(xoffset_bank_sel, 0)
|
bank_sel_line_pos = vector(xoffset_bank_sel, 0)
|
||||||
bank_sel_line_end = vector(xoffset_bank_sel, self.yoffset_maxpoint)
|
bank_sel_line_end = vector(xoffset_bank_sel, self.yoffset_maxpoint)
|
||||||
self.add_path("metal2", [bank_sel_line_pos, bank_sel_line_end])
|
self.add_path("m2", [bank_sel_line_pos, bank_sel_line_end])
|
||||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
self.add_via_center(layers=self.m1_stack,
|
||||||
offset=bank_sel_inv_pin.lc())
|
offset=bank_sel_inv_pin.lc())
|
||||||
|
|
||||||
# Route the pin to the left edge as well
|
# Route the pin to the left edge as well
|
||||||
bank_sel_pin_pos=vector(0, 0)
|
bank_sel_pin_pos=vector(0, 0)
|
||||||
bank_sel_pin_end=vector(bank_sel_line_pos.x, bank_sel_pin_pos.y)
|
bank_sel_pin_end=vector(bank_sel_line_pos.x, bank_sel_pin_pos.y)
|
||||||
self.add_layout_pin_segment_center(text="bank_sel",
|
self.add_layout_pin_segment_center(text="bank_sel",
|
||||||
layer="metal3",
|
layer="m3",
|
||||||
start=bank_sel_pin_pos,
|
start=bank_sel_pin_pos,
|
||||||
end=bank_sel_pin_end)
|
end=bank_sel_pin_end)
|
||||||
self.add_via_center(layers=("metal2","via2","metal3"),
|
self.add_via_center(layers=self.m2_stack,
|
||||||
offset=bank_sel_pin_end,
|
offset=bank_sel_pin_end,
|
||||||
directions=("H","H"))
|
directions=("H","H"))
|
||||||
|
|
||||||
|
|
@ -227,10 +227,10 @@ class bank_select(design.design):
|
||||||
bank_sel_bar_pin = self.bank_sel_inv.get_pin("Z")
|
bank_sel_bar_pin = self.bank_sel_inv.get_pin("Z")
|
||||||
xoffset_bank_sel_bar = bank_sel_bar_pin.rx()
|
xoffset_bank_sel_bar = bank_sel_bar_pin.rx()
|
||||||
self.add_label_pin(text="bank_sel_bar",
|
self.add_label_pin(text="bank_sel_bar",
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=vector(xoffset_bank_sel_bar, 0),
|
offset=vector(xoffset_bank_sel_bar, 0),
|
||||||
height=self.inv4x.height)
|
height=self.inv4x.height)
|
||||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
self.add_via_center(layers=self.m1_stack,
|
||||||
offset=bank_sel_bar_pin.rc())
|
offset=bank_sel_bar_pin.rc())
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -251,13 +251,13 @@ class bank_select(design.design):
|
||||||
out_position = logic_inst.get_pin("Z").rc() + vector(0.5*self.m1_width,0)
|
out_position = logic_inst.get_pin("Z").rc() + vector(0.5*self.m1_width,0)
|
||||||
in_position = inv_inst.get_pin("A").lc() + vector(0.5*self.m1_width,0)
|
in_position = inv_inst.get_pin("A").lc() + vector(0.5*self.m1_width,0)
|
||||||
post = inv_inst.get_pin("A").rc()
|
post = inv_inst.get_pin("A").rc()
|
||||||
self.add_path("metal1", [pre, out_position, in_position, post])
|
self.add_path("m1", [pre, out_position, in_position, post])
|
||||||
|
|
||||||
|
|
||||||
# Connect the logic B input to bank_sel/bank_sel_bar
|
# 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.m1m2.height,0)
|
||||||
input_pos = vector(xoffset_bank_signal, logic_pos.y)
|
input_pos = vector(xoffset_bank_signal, logic_pos.y)
|
||||||
self.add_path("metal2",[logic_pos, input_pos])
|
self.add_path("m2",[logic_pos, input_pos])
|
||||||
self.add_via_center(layers=self.m1_stack,
|
self.add_via_center(layers=self.m1_stack,
|
||||||
offset=logic_pos,
|
offset=logic_pos,
|
||||||
directions=("H","H"))
|
directions=("H","H"))
|
||||||
|
|
@ -273,7 +273,7 @@ class bank_select(design.design):
|
||||||
offset=logic_pos,
|
offset=logic_pos,
|
||||||
directions=("H","H"))
|
directions=("H","H"))
|
||||||
self.add_layout_pin_segment_center(text=input_name,
|
self.add_layout_pin_segment_center(text=input_name,
|
||||||
layer="metal3",
|
layer="m3",
|
||||||
start=input_pos,
|
start=input_pos,
|
||||||
end=logic_pos)
|
end=logic_pos)
|
||||||
|
|
||||||
|
|
@ -294,7 +294,7 @@ class bank_select(design.design):
|
||||||
for n in ["vdd", "gnd"]:
|
for n in ["vdd", "gnd"]:
|
||||||
supply_pin = self.inv_inst[num].get_pin(n)
|
supply_pin = self.inv_inst[num].get_pin(n)
|
||||||
supply_offset = supply_pin.ll().scale(0,1)
|
supply_offset = supply_pin.ll().scale(0,1)
|
||||||
self.add_rect(layer="metal1",
|
self.add_rect(layer="m1",
|
||||||
offset=supply_offset,
|
offset=supply_offset,
|
||||||
width=self.width)
|
width=self.width)
|
||||||
|
|
||||||
|
|
@ -308,20 +308,20 @@ class bank_select(design.design):
|
||||||
offset=pin_pos,
|
offset=pin_pos,
|
||||||
directions=("H","H"))
|
directions=("H","H"))
|
||||||
self.add_layout_pin_rect_center(text=n,
|
self.add_layout_pin_rect_center(text=n,
|
||||||
layer="metal3",
|
layer="m3",
|
||||||
offset=pin_pos)
|
offset=pin_pos)
|
||||||
|
|
||||||
# Add vdd/gnd supply rails
|
# Add vdd/gnd supply rails
|
||||||
gnd_pin = inv_inst.get_pin("gnd")
|
gnd_pin = inv_inst.get_pin("gnd")
|
||||||
left_gnd_pos = vector(0, gnd_pin.cy())
|
left_gnd_pos = vector(0, gnd_pin.cy())
|
||||||
self.add_layout_pin_segment_center(text="gnd",
|
self.add_layout_pin_segment_center(text="gnd",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
start=left_gnd_pos,
|
start=left_gnd_pos,
|
||||||
end=gnd_pin.rc())
|
end=gnd_pin.rc())
|
||||||
|
|
||||||
vdd_pin = inv_inst.get_pin("vdd")
|
vdd_pin = inv_inst.get_pin("vdd")
|
||||||
left_vdd_pos = vector(0, vdd_pin.cy())
|
left_vdd_pos = vector(0, vdd_pin.cy())
|
||||||
self.add_layout_pin_segment_center(text="vdd",
|
self.add_layout_pin_segment_center(text="vdd",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
start=left_vdd_pos,
|
start=left_vdd_pos,
|
||||||
end=vdd_pin.rc())
|
end=vdd_pin.rc())
|
||||||
|
|
|
||||||
|
|
@ -173,7 +173,7 @@ class bitcell_array(design.design):
|
||||||
width = 0
|
width = 0
|
||||||
else:
|
else:
|
||||||
width = self.width
|
width = self.width
|
||||||
wl_wire = self.generate_rc_net(int(self.column_size), width, drc("minwidth_metal1"))
|
wl_wire = self.generate_rc_net(int(self.column_size), width, drc("minwidth_m1"))
|
||||||
wl_wire.wire_c = 2*spice["min_tx_gate_c"] + wl_wire.wire_c # 2 access tx gate per cell
|
wl_wire.wire_c = 2*spice["min_tx_gate_c"] + wl_wire.wire_c # 2 access tx gate per cell
|
||||||
return wl_wire
|
return wl_wire
|
||||||
|
|
||||||
|
|
@ -183,7 +183,7 @@ class bitcell_array(design.design):
|
||||||
else:
|
else:
|
||||||
height = self.height
|
height = self.height
|
||||||
bl_pos = 0
|
bl_pos = 0
|
||||||
bl_wire = self.generate_rc_net(int(self.row_size-bl_pos), height, drc("minwidth_metal1"))
|
bl_wire = self.generate_rc_net(int(self.row_size-bl_pos), height, drc("minwidth_m1"))
|
||||||
bl_wire.wire_c =spice["min_tx_drain_c"] + bl_wire.wire_c # 1 access tx d/s per cell
|
bl_wire.wire_c =spice["min_tx_drain_c"] + bl_wire.wire_c # 1 access tx d/s per cell
|
||||||
return bl_wire
|
return bl_wire
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -371,7 +371,7 @@ class control_logic(design.design):
|
||||||
height = self.control_logic_center.y - self.m2_pitch
|
height = self.control_logic_center.y - self.m2_pitch
|
||||||
offset = vector(self.ctrl_dff_array.width,0)
|
offset = vector(self.ctrl_dff_array.width,0)
|
||||||
|
|
||||||
self.rail_offsets = self.create_vertical_bus("metal2", self.m2_pitch, offset, self.internal_bus_list, height)
|
self.rail_offsets = self.create_vertical_bus("m2", self.m2_pitch, offset, self.internal_bus_list, height)
|
||||||
|
|
||||||
|
|
||||||
def create_instances(self):
|
def create_instances(self):
|
||||||
|
|
@ -483,8 +483,8 @@ class control_logic(design.design):
|
||||||
vdd_ypos = self.p_en_bar_nand_inst.get_pin("vdd").by()
|
vdd_ypos = self.p_en_bar_nand_inst.get_pin("vdd").by()
|
||||||
in_pos = vector(self.rail_offsets["rbl_bl_delay"].x,vdd_ypos)
|
in_pos = vector(self.rail_offsets["rbl_bl_delay"].x,vdd_ypos)
|
||||||
mid1 = vector(out_pos.x,in_pos.y)
|
mid1 = vector(out_pos.x,in_pos.y)
|
||||||
self.add_wire(("metal1","via1","metal2"),[out_pos, mid1, in_pos])
|
self.add_wire(self.m1_stack,[out_pos, mid1, in_pos])
|
||||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
self.add_via_center(layers=self.m1_stack,
|
||||||
offset=in_pos)
|
offset=in_pos)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -509,10 +509,10 @@ class control_logic(design.design):
|
||||||
clk_pin = self.clk_buf_inst.get_pin("A")
|
clk_pin = self.clk_buf_inst.get_pin("A")
|
||||||
clk_pos = clk_pin.center()
|
clk_pos = clk_pin.center()
|
||||||
self.add_layout_pin_segment_center(text="clk",
|
self.add_layout_pin_segment_center(text="clk",
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
start=clk_pos,
|
start=clk_pos,
|
||||||
end=clk_pos.scale(1,0))
|
end=clk_pos.scale(1,0))
|
||||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
self.add_via_center(layers=self.m1_stack,
|
||||||
offset=clk_pos)
|
offset=clk_pos)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -521,9 +521,9 @@ class control_logic(design.design):
|
||||||
mid1 = vector(out_pos.x,2*self.m2_pitch)
|
mid1 = vector(out_pos.x,2*self.m2_pitch)
|
||||||
mid2 = vector(self.rail_offsets["clk_buf"].x, mid1.y)
|
mid2 = vector(self.rail_offsets["clk_buf"].x, mid1.y)
|
||||||
bus_pos = self.rail_offsets["clk_buf"]
|
bus_pos = self.rail_offsets["clk_buf"]
|
||||||
self.add_wire(("metal3","via2","metal2"),[out_pos, mid1, mid2, bus_pos])
|
self.add_wire(("m3","via2","m2"),[out_pos, mid1, mid2, bus_pos])
|
||||||
# The pin is on M1, so we need another via as well
|
# The pin is on M1, so we need another via as well
|
||||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
self.add_via_center(layers=self.m1_stack,
|
||||||
offset=self.clk_buf_inst.get_pin("Z").center())
|
offset=self.clk_buf_inst.get_pin("Z").center())
|
||||||
|
|
||||||
self.connect_output(self.clk_buf_inst, "Z", "clk_buf")
|
self.connect_output(self.clk_buf_inst, "Z", "clk_buf")
|
||||||
|
|
@ -552,21 +552,21 @@ class control_logic(design.design):
|
||||||
out_pos = self.clk_bar_inst.get_pin("Z").center()
|
out_pos = self.clk_bar_inst.get_pin("Z").center()
|
||||||
in_pos = self.gated_clk_bar_inst.get_pin("B").center()
|
in_pos = self.gated_clk_bar_inst.get_pin("B").center()
|
||||||
mid1 = vector(in_pos.x,out_pos.y)
|
mid1 = vector(in_pos.x,out_pos.y)
|
||||||
self.add_path("metal1",[out_pos, mid1, in_pos])
|
self.add_path("m1",[out_pos, mid1, in_pos])
|
||||||
|
|
||||||
# This is the second gate over, so it needs to be on M3
|
# This is the second gate over, so it needs to be on M3
|
||||||
clkbuf_map = zip(["A"], ["cs"])
|
clkbuf_map = zip(["A"], ["cs"])
|
||||||
self.connect_vertical_bus(clkbuf_map, self.gated_clk_bar_inst, self.rail_offsets, ("metal3", "via2", "metal2"))
|
self.connect_vertical_bus(clkbuf_map, self.gated_clk_bar_inst, self.rail_offsets, ("m3", "via2", "m2"))
|
||||||
# The pin is on M1, so we need another via as well
|
# The pin is on M1, so we need another via as well
|
||||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
self.add_via_center(layers=self.m1_stack,
|
||||||
offset=self.gated_clk_bar_inst.get_pin("A").center())
|
offset=self.gated_clk_bar_inst.get_pin("A").center())
|
||||||
|
|
||||||
|
|
||||||
# This is the second gate over, so it needs to be on M3
|
# This is the second gate over, so it needs to be on M3
|
||||||
clkbuf_map = zip(["Z"], ["gated_clk_bar"])
|
clkbuf_map = zip(["Z"], ["gated_clk_bar"])
|
||||||
self.connect_vertical_bus(clkbuf_map, self.gated_clk_bar_inst, self.rail_offsets, ("metal3", "via2", "metal2"))
|
self.connect_vertical_bus(clkbuf_map, self.gated_clk_bar_inst, self.rail_offsets, ("m3", "via2", "m2"))
|
||||||
# The pin is on M1, so we need another via as well
|
# The pin is on M1, so we need another via as well
|
||||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
self.add_via_center(layers=self.m1_stack,
|
||||||
offset=self.gated_clk_bar_inst.get_pin("Z").center())
|
offset=self.gated_clk_bar_inst.get_pin("Z").center())
|
||||||
|
|
||||||
def create_gated_clk_buf_row(self):
|
def create_gated_clk_buf_row(self):
|
||||||
|
|
@ -587,9 +587,9 @@ class control_logic(design.design):
|
||||||
|
|
||||||
|
|
||||||
clkbuf_map = zip(["Z"], ["gated_clk_buf"])
|
clkbuf_map = zip(["Z"], ["gated_clk_buf"])
|
||||||
self.connect_vertical_bus(clkbuf_map, self.gated_clk_buf_inst, self.rail_offsets, ("metal3", "via2", "metal2"))
|
self.connect_vertical_bus(clkbuf_map, self.gated_clk_buf_inst, self.rail_offsets, ("m3", "via2", "m2"))
|
||||||
# The pin is on M1, so we need another via as well
|
# The pin is on M1, so we need another via as well
|
||||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
self.add_via_center(layers=self.m1_stack,
|
||||||
offset=self.gated_clk_buf_inst.get_pin("Z").center())
|
offset=self.gated_clk_buf_inst.get_pin("Z").center())
|
||||||
|
|
||||||
def create_wlen_row(self):
|
def create_wlen_row(self):
|
||||||
|
|
@ -637,7 +637,7 @@ class control_logic(design.design):
|
||||||
out_pos = self.p_en_bar_nand_inst.get_pin("Z").rc()
|
out_pos = self.p_en_bar_nand_inst.get_pin("Z").rc()
|
||||||
in_pos = self.p_en_bar_driver_inst.get_pin("A").lc()
|
in_pos = self.p_en_bar_driver_inst.get_pin("A").lc()
|
||||||
mid1 = vector(out_pos.x,in_pos.y)
|
mid1 = vector(out_pos.x,in_pos.y)
|
||||||
self.add_wire(("metal1","via1","metal2"),[out_pos, mid1,in_pos])
|
self.add_wire(self.m1_stack,[out_pos, mid1,in_pos])
|
||||||
|
|
||||||
self.connect_output(self.p_en_bar_driver_inst, "Z", "p_en_bar")
|
self.connect_output(self.p_en_bar_driver_inst, "Z", "p_en_bar")
|
||||||
|
|
||||||
|
|
@ -694,9 +694,9 @@ class control_logic(design.design):
|
||||||
# Connect to rail
|
# Connect to rail
|
||||||
|
|
||||||
rbl_map = zip(["Z"], ["rbl_bl_delay_bar"])
|
rbl_map = zip(["Z"], ["rbl_bl_delay_bar"])
|
||||||
self.connect_vertical_bus(rbl_map, self.rbl_bl_delay_inv_inst, self.rail_offsets, ("metal3", "via2", "metal2"))
|
self.connect_vertical_bus(rbl_map, self.rbl_bl_delay_inv_inst, self.rail_offsets, ("m3", "via2", "m2"))
|
||||||
# The pin is on M1, so we need another via as well
|
# The pin is on M1, so we need another via as well
|
||||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
self.add_via_center(layers=self.m1_stack,
|
||||||
offset=self.rbl_bl_delay_inv_inst.get_pin("Z").center())
|
offset=self.rbl_bl_delay_inv_inst.get_pin("Z").center())
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -754,14 +754,14 @@ class control_logic(design.design):
|
||||||
dff_out_map = zip(["dout_bar_0", "dout_0"], ["cs", "cs_bar"])
|
dff_out_map = zip(["dout_bar_0", "dout_0"], ["cs", "cs_bar"])
|
||||||
else:
|
else:
|
||||||
dff_out_map = zip(["dout_bar_0"], ["cs"])
|
dff_out_map = zip(["dout_bar_0"], ["cs"])
|
||||||
self.connect_vertical_bus(dff_out_map, self.ctrl_dff_inst, self.rail_offsets, ("metal3", "via2", "metal2"))
|
self.connect_vertical_bus(dff_out_map, self.ctrl_dff_inst, self.rail_offsets, ("m3", "via2", "m2"))
|
||||||
|
|
||||||
# Connect the clock rail to the other clock rail
|
# Connect the clock rail to the other clock rail
|
||||||
in_pos = self.ctrl_dff_inst.get_pin("clk").uc()
|
in_pos = self.ctrl_dff_inst.get_pin("clk").uc()
|
||||||
mid_pos = in_pos + vector(0,2*self.m2_pitch)
|
mid_pos = in_pos + vector(0,2*self.m2_pitch)
|
||||||
rail_pos = vector(self.rail_offsets["clk_buf"].x, mid_pos.y)
|
rail_pos = vector(self.rail_offsets["clk_buf"].x, mid_pos.y)
|
||||||
self.add_wire(("metal1","via1","metal2"),[in_pos, mid_pos, rail_pos])
|
self.add_wire(self.m1_stack,[in_pos, mid_pos, rail_pos])
|
||||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
self.add_via_center(layers=self.m1_stack,
|
||||||
offset=rail_pos)
|
offset=rail_pos)
|
||||||
|
|
||||||
self.copy_layout_pin(self.ctrl_dff_inst, "din_0", "csb")
|
self.copy_layout_pin(self.ctrl_dff_inst, "din_0", "csb")
|
||||||
|
|
@ -786,7 +786,7 @@ class control_logic(design.design):
|
||||||
out_pin = inst.get_pin(pin_name)
|
out_pin = inst.get_pin(pin_name)
|
||||||
right_pos=out_pin.center() + vector(self.width-out_pin.cx(),0)
|
right_pos=out_pin.center() + vector(self.width-out_pin.cx(),0)
|
||||||
self.add_layout_pin_segment_center(text=out_name,
|
self.add_layout_pin_segment_center(text=out_name,
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
start=out_pin.center(),
|
start=out_pin.center(),
|
||||||
end=right_pos)
|
end=right_pos)
|
||||||
|
|
||||||
|
|
@ -799,19 +799,19 @@ class control_logic(design.design):
|
||||||
for inst in self.row_end_inst:
|
for inst in self.row_end_inst:
|
||||||
pins = inst.get_pins("vdd")
|
pins = inst.get_pins("vdd")
|
||||||
for pin in pins:
|
for pin in pins:
|
||||||
if pin.layer == "metal1":
|
if pin.layer == "m1":
|
||||||
row_loc = pin.rc()
|
row_loc = pin.rc()
|
||||||
pin_loc = vector(max_row_x_loc, pin.rc().y)
|
pin_loc = vector(max_row_x_loc, pin.rc().y)
|
||||||
self.add_power_pin("vdd", pin_loc)
|
self.add_power_pin("vdd", pin_loc)
|
||||||
self.add_path("metal1", [row_loc, pin_loc])
|
self.add_path("m1", [row_loc, pin_loc])
|
||||||
|
|
||||||
pins = inst.get_pins("gnd")
|
pins = inst.get_pins("gnd")
|
||||||
for pin in pins:
|
for pin in pins:
|
||||||
if pin.layer == "metal1":
|
if pin.layer == "m1":
|
||||||
row_loc = pin.rc()
|
row_loc = pin.rc()
|
||||||
pin_loc = vector(max_row_x_loc, pin.rc().y)
|
pin_loc = vector(max_row_x_loc, pin.rc().y)
|
||||||
self.add_power_pin("gnd", pin_loc)
|
self.add_power_pin("gnd", pin_loc)
|
||||||
self.add_path("metal1", [row_loc, pin_loc])
|
self.add_path("m1", [row_loc, pin_loc])
|
||||||
|
|
||||||
self.copy_layout_pin(self.delay_inst,"gnd")
|
self.copy_layout_pin(self.delay_inst,"gnd")
|
||||||
self.copy_layout_pin(self.delay_inst,"vdd")
|
self.copy_layout_pin(self.delay_inst,"vdd")
|
||||||
|
|
@ -828,14 +828,14 @@ class control_logic(design.design):
|
||||||
"""
|
"""
|
||||||
# pin=self.clk_inv1.get_pin("Z")
|
# pin=self.clk_inv1.get_pin("Z")
|
||||||
# self.add_label_pin(text="clk1_bar",
|
# self.add_label_pin(text="clk1_bar",
|
||||||
# layer="metal1",
|
# layer="m1",
|
||||||
# offset=pin.ll(),
|
# offset=pin.ll(),
|
||||||
# height=pin.height(),
|
# height=pin.height(),
|
||||||
# width=pin.width())
|
# width=pin.width())
|
||||||
|
|
||||||
# pin=self.clk_inv2.get_pin("Z")
|
# pin=self.clk_inv2.get_pin("Z")
|
||||||
# self.add_label_pin(text="clk2",
|
# self.add_label_pin(text="clk2",
|
||||||
# layer="metal1",
|
# layer="m1",
|
||||||
# offset=pin.ll(),
|
# offset=pin.ll(),
|
||||||
# height=pin.height(),
|
# height=pin.height(),
|
||||||
# width=pin.width())
|
# width=pin.width())
|
||||||
|
|
|
||||||
|
|
@ -132,11 +132,11 @@ class delay_chain(design.design):
|
||||||
pin1_pos = pin1.center()
|
pin1_pos = pin1.center()
|
||||||
pin2_pos = pin2.center()
|
pin2_pos = pin2.center()
|
||||||
if pin1_pos.y == pin2_pos.y:
|
if pin1_pos.y == pin2_pos.y:
|
||||||
self.add_path("metal2", [pin1_pos, pin2_pos])
|
self.add_path("m2", [pin1_pos, pin2_pos])
|
||||||
else:
|
else:
|
||||||
mid_point = vector(pin2_pos.x, 0.5*(pin1_pos.y+pin2_pos.y))
|
mid_point = vector(pin2_pos.x, 0.5*(pin1_pos.y+pin2_pos.y))
|
||||||
# Written this way to guarantee it goes right first if we are switching rows
|
# Written this way to guarantee it goes right first if we are switching rows
|
||||||
self.add_path("metal2", [pin1_pos, vector(pin1_pos.x,mid_point.y), mid_point, vector(mid_point.x,pin2_pos.y), pin2_pos])
|
self.add_path("m2", [pin1_pos, vector(pin1_pos.x,mid_point.y), mid_point, vector(mid_point.x,pin2_pos.y), pin2_pos])
|
||||||
|
|
||||||
def route_inverters(self):
|
def route_inverters(self):
|
||||||
""" Add metal routing for each of the fanout stages """
|
""" Add metal routing for each of the fanout stages """
|
||||||
|
|
@ -146,22 +146,22 @@ class delay_chain(design.design):
|
||||||
for load in self.load_inst_map[inv]:
|
for load in self.load_inst_map[inv]:
|
||||||
# Drop a via on each A pin
|
# Drop a via on each A pin
|
||||||
a_pin = load.get_pin("A")
|
a_pin = load.get_pin("A")
|
||||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
self.add_via_center(layers=self.m1_stack,
|
||||||
offset=a_pin.center())
|
offset=a_pin.center())
|
||||||
self.add_via_center(layers=("metal2","via2","metal3"),
|
self.add_via_center(layers=self.m2_stack,
|
||||||
offset=a_pin.center())
|
offset=a_pin.center())
|
||||||
|
|
||||||
# Route an M3 horizontal wire to the furthest
|
# Route an M3 horizontal wire to the furthest
|
||||||
z_pin = inv.get_pin("Z")
|
z_pin = inv.get_pin("Z")
|
||||||
a_pin = inv.get_pin("A")
|
a_pin = inv.get_pin("A")
|
||||||
a_max = self.rightest_load_inst[inv].get_pin("A")
|
a_max = self.rightest_load_inst[inv].get_pin("A")
|
||||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
self.add_via_center(layers=self.m1_stack,
|
||||||
offset=a_pin.center())
|
offset=a_pin.center())
|
||||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
self.add_via_center(layers=self.m1_stack,
|
||||||
offset=z_pin.center())
|
offset=z_pin.center())
|
||||||
self.add_via_center(layers=("metal2","via2","metal3"),
|
self.add_via_center(layers=self.m2_stack,
|
||||||
offset=z_pin.center())
|
offset=z_pin.center())
|
||||||
self.add_path("metal3",[z_pin.center(), a_max.center()])
|
self.add_path("m3",[z_pin.center(), a_max.center()])
|
||||||
|
|
||||||
|
|
||||||
# Route Z to the A of the next stage
|
# Route Z to the A of the next stage
|
||||||
|
|
@ -172,7 +172,7 @@ class delay_chain(design.design):
|
||||||
y_mid = (z_pin.cy() + next_a_pin.cy())/2
|
y_mid = (z_pin.cy() + next_a_pin.cy())/2
|
||||||
mid1_point = vector(z_pin.cx(), y_mid)
|
mid1_point = vector(z_pin.cx(), y_mid)
|
||||||
mid2_point = vector(next_a_pin.cx(), y_mid)
|
mid2_point = vector(next_a_pin.cx(), y_mid)
|
||||||
self.add_path("metal2",[z_pin.center(), mid1_point, mid2_point, next_a_pin.center()])
|
self.add_path("m2",[z_pin.center(), mid1_point, mid2_point, next_a_pin.center()])
|
||||||
|
|
||||||
|
|
||||||
def add_layout_pins(self):
|
def add_layout_pins(self):
|
||||||
|
|
@ -205,10 +205,10 @@ class delay_chain(design.design):
|
||||||
|
|
||||||
# input is A pin of first inverter
|
# input is A pin of first inverter
|
||||||
a_pin = self.driver_inst_list[0].get_pin("A")
|
a_pin = self.driver_inst_list[0].get_pin("A")
|
||||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
self.add_via_center(layers=self.m1_stack,
|
||||||
offset=a_pin.center())
|
offset=a_pin.center())
|
||||||
self.add_layout_pin(text="in",
|
self.add_layout_pin(text="in",
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=a_pin.ll().scale(1,0),
|
offset=a_pin.ll().scale(1,0),
|
||||||
height=a_pin.cy())
|
height=a_pin.cy())
|
||||||
|
|
||||||
|
|
@ -216,12 +216,12 @@ class delay_chain(design.design):
|
||||||
# output is A pin of last load inverter
|
# output is A pin of last load inverter
|
||||||
last_driver_inst = self.driver_inst_list[-1]
|
last_driver_inst = self.driver_inst_list[-1]
|
||||||
a_pin = self.rightest_load_inst[last_driver_inst].get_pin("A")
|
a_pin = self.rightest_load_inst[last_driver_inst].get_pin("A")
|
||||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
self.add_via_center(layers=self.m1_stack,
|
||||||
offset=a_pin.center())
|
offset=a_pin.center())
|
||||||
mid_point = vector(a_pin.cx()+3*self.m2_width,a_pin.cy())
|
mid_point = vector(a_pin.cx()+3*self.m2_width,a_pin.cy())
|
||||||
self.add_path("metal2",[a_pin.center(), mid_point, mid_point.scale(1,0)])
|
self.add_path("m2",[a_pin.center(), mid_point, mid_point.scale(1,0)])
|
||||||
self.add_layout_pin_segment_center(text="out",
|
self.add_layout_pin_segment_center(text="out",
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
start=mid_point,
|
start=mid_point,
|
||||||
end=mid_point.scale(1,0))
|
end=mid_point.scale(1,0))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -124,7 +124,7 @@ class dff_array(design.design):
|
||||||
for row in range(self.rows):
|
for row in range(self.rows):
|
||||||
for col in range(self.columns):
|
for col in range(self.columns):
|
||||||
din_pin = self.dff_insts[row,col].get_pin("D")
|
din_pin = self.dff_insts[row,col].get_pin("D")
|
||||||
debug.check(din_pin.layer=="metal2","DFF D pin not on metal2")
|
debug.check(din_pin.layer=="m2","DFF D pin not on metal2")
|
||||||
self.add_layout_pin(text=self.get_din_name(row,col),
|
self.add_layout_pin(text=self.get_din_name(row,col),
|
||||||
layer=din_pin.layer,
|
layer=din_pin.layer,
|
||||||
offset=din_pin.ll(),
|
offset=din_pin.ll(),
|
||||||
|
|
@ -132,7 +132,7 @@ class dff_array(design.design):
|
||||||
height=din_pin.height())
|
height=din_pin.height())
|
||||||
|
|
||||||
dout_pin = self.dff_insts[row,col].get_pin("Q")
|
dout_pin = self.dff_insts[row,col].get_pin("Q")
|
||||||
debug.check(dout_pin.layer=="metal2","DFF Q pin not on metal2")
|
debug.check(dout_pin.layer=="m2","DFF Q pin not on metal2")
|
||||||
self.add_layout_pin(text=self.get_dout_name(row,col),
|
self.add_layout_pin(text=self.get_dout_name(row,col),
|
||||||
layer=dout_pin.layer,
|
layer=dout_pin.layer,
|
||||||
offset=dout_pin.ll(),
|
offset=dout_pin.ll(),
|
||||||
|
|
@ -144,20 +144,20 @@ class dff_array(design.design):
|
||||||
# Create vertical spines to a single horizontal rail
|
# Create vertical spines to a single horizontal rail
|
||||||
clk_pin = self.dff_insts[0,0].get_pin("clk")
|
clk_pin = self.dff_insts[0,0].get_pin("clk")
|
||||||
clk_ypos = 2*self.m3_pitch+self.m3_width
|
clk_ypos = 2*self.m3_pitch+self.m3_width
|
||||||
debug.check(clk_pin.layer=="metal2","DFF clk pin not on metal2")
|
debug.check(clk_pin.layer=="m2","DFF clk pin not on metal2")
|
||||||
self.add_layout_pin_segment_center(text="clk",
|
self.add_layout_pin_segment_center(text="clk",
|
||||||
layer="metal3",
|
layer="m3",
|
||||||
start=vector(0,clk_ypos),
|
start=vector(0,clk_ypos),
|
||||||
end=vector(self.width,clk_ypos))
|
end=vector(self.width,clk_ypos))
|
||||||
for col in range(self.columns):
|
for col in range(self.columns):
|
||||||
clk_pin = self.dff_insts[0,col].get_pin("clk")
|
clk_pin = self.dff_insts[0,col].get_pin("clk")
|
||||||
# Make a vertical strip for each column
|
# Make a vertical strip for each column
|
||||||
self.add_rect(layer="metal2",
|
self.add_rect(layer="m2",
|
||||||
offset=clk_pin.ll().scale(1,0),
|
offset=clk_pin.ll().scale(1,0),
|
||||||
width=self.m2_width,
|
width=self.m2_width,
|
||||||
height=self.height)
|
height=self.height)
|
||||||
# Drop a via to the M3 pin
|
# Drop a via to the M3 pin
|
||||||
self.add_via_center(layers=("metal2","via2","metal3"),
|
self.add_via_center(layers=self.m2_stack,
|
||||||
offset=vector(clk_pin.cx(),clk_ypos))
|
offset=vector(clk_pin.cx(),clk_ypos))
|
||||||
|
|
||||||
def get_clk_cin(self):
|
def get_clk_cin(self):
|
||||||
|
|
|
||||||
|
|
@ -112,12 +112,12 @@ class dff_buf(design.design):
|
||||||
mid_x_offset = 0.5*(a1_pin.cx() + q_pin.cx())
|
mid_x_offset = 0.5*(a1_pin.cx() + q_pin.cx())
|
||||||
mid1 = vector(mid_x_offset, q_pin.cy())
|
mid1 = vector(mid_x_offset, q_pin.cy())
|
||||||
mid2 = vector(mid_x_offset, a1_pin.cy())
|
mid2 = vector(mid_x_offset, a1_pin.cy())
|
||||||
self.add_path("metal3", [q_pin.center(), mid1, mid2, a1_pin.center()])
|
self.add_path("m3", [q_pin.center(), mid1, mid2, a1_pin.center()])
|
||||||
self.add_via_center(layers=("metal2","via2","metal3"),
|
self.add_via_center(layers=self.m2_stack,
|
||||||
offset=q_pin.center())
|
offset=q_pin.center())
|
||||||
self.add_via_center(layers=("metal2","via2","metal3"),
|
self.add_via_center(layers=self.m2_stack,
|
||||||
offset=a1_pin.center())
|
offset=a1_pin.center())
|
||||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
self.add_via_center(layers=self.m1_stack,
|
||||||
offset=a1_pin.center())
|
offset=a1_pin.center())
|
||||||
|
|
||||||
# Route inv1 z to inv2 a
|
# Route inv1 z to inv2 a
|
||||||
|
|
@ -126,14 +126,14 @@ class dff_buf(design.design):
|
||||||
mid_x_offset = 0.5*(z1_pin.cx() + a2_pin.cx())
|
mid_x_offset = 0.5*(z1_pin.cx() + a2_pin.cx())
|
||||||
self.mid_qb_pos = vector(mid_x_offset, z1_pin.cy())
|
self.mid_qb_pos = vector(mid_x_offset, z1_pin.cy())
|
||||||
mid2 = vector(mid_x_offset, a2_pin.cy())
|
mid2 = vector(mid_x_offset, a2_pin.cy())
|
||||||
self.add_path("metal1", [z1_pin.center(), self.mid_qb_pos, mid2, a2_pin.center()])
|
self.add_path("m1", [z1_pin.center(), self.mid_qb_pos, mid2, a2_pin.center()])
|
||||||
|
|
||||||
def add_layout_pins(self):
|
def add_layout_pins(self):
|
||||||
|
|
||||||
# Continous vdd rail along with label.
|
# Continous vdd rail along with label.
|
||||||
vdd_pin=self.dff_inst.get_pin("vdd")
|
vdd_pin=self.dff_inst.get_pin("vdd")
|
||||||
self.add_layout_pin(text="vdd",
|
self.add_layout_pin(text="vdd",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=vdd_pin.ll(),
|
offset=vdd_pin.ll(),
|
||||||
width=self.width,
|
width=self.width,
|
||||||
height=vdd_pin.height())
|
height=vdd_pin.height())
|
||||||
|
|
@ -141,7 +141,7 @@ class dff_buf(design.design):
|
||||||
# Continous gnd rail along with label.
|
# Continous gnd rail along with label.
|
||||||
gnd_pin=self.dff_inst.get_pin("gnd")
|
gnd_pin=self.dff_inst.get_pin("gnd")
|
||||||
self.add_layout_pin(text="gnd",
|
self.add_layout_pin(text="gnd",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=gnd_pin.ll(),
|
offset=gnd_pin.ll(),
|
||||||
width=self.width,
|
width=self.width,
|
||||||
height=vdd_pin.height())
|
height=vdd_pin.height())
|
||||||
|
|
@ -164,18 +164,18 @@ class dff_buf(design.design):
|
||||||
mid_pos = dout_pin.center() + vector(self.m1_pitch,0)
|
mid_pos = dout_pin.center() + vector(self.m1_pitch,0)
|
||||||
q_pos = mid_pos - vector(0,self.m2_pitch)
|
q_pos = mid_pos - vector(0,self.m2_pitch)
|
||||||
self.add_layout_pin_rect_center(text="Q",
|
self.add_layout_pin_rect_center(text="Q",
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=q_pos)
|
offset=q_pos)
|
||||||
self.add_path("metal1", [dout_pin.center(), mid_pos, q_pos])
|
self.add_path("m1", [dout_pin.center(), mid_pos, q_pos])
|
||||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
self.add_via_center(layers=self.m1_stack,
|
||||||
offset=q_pos)
|
offset=q_pos)
|
||||||
|
|
||||||
qb_pos = self.mid_qb_pos + vector(0,self.m2_pitch)
|
qb_pos = self.mid_qb_pos + vector(0,self.m2_pitch)
|
||||||
self.add_layout_pin_rect_center(text="Qb",
|
self.add_layout_pin_rect_center(text="Qb",
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=qb_pos)
|
offset=qb_pos)
|
||||||
self.add_path("metal1", [self.mid_qb_pos, qb_pos])
|
self.add_path("m1", [self.mid_qb_pos, qb_pos])
|
||||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
self.add_via_center(layers=self.m1_stack,
|
||||||
offset=qb_pos)
|
offset=qb_pos)
|
||||||
|
|
||||||
def get_clk_cin(self):
|
def get_clk_cin(self):
|
||||||
|
|
|
||||||
|
|
@ -142,7 +142,7 @@ class dff_buf_array(design.design):
|
||||||
for row in range(self.rows):
|
for row in range(self.rows):
|
||||||
for col in range(self.columns):
|
for col in range(self.columns):
|
||||||
din_pin = self.dff_insts[row,col].get_pin("D")
|
din_pin = self.dff_insts[row,col].get_pin("D")
|
||||||
debug.check(din_pin.layer=="metal2","DFF D pin not on metal2")
|
debug.check(din_pin.layer=="m2","DFF D pin not on metal2")
|
||||||
self.add_layout_pin(text=self.get_din_name(row,col),
|
self.add_layout_pin(text=self.get_din_name(row,col),
|
||||||
layer=din_pin.layer,
|
layer=din_pin.layer,
|
||||||
offset=din_pin.ll(),
|
offset=din_pin.ll(),
|
||||||
|
|
@ -150,7 +150,7 @@ class dff_buf_array(design.design):
|
||||||
height=din_pin.height())
|
height=din_pin.height())
|
||||||
|
|
||||||
dout_pin = self.dff_insts[row,col].get_pin("Q")
|
dout_pin = self.dff_insts[row,col].get_pin("Q")
|
||||||
debug.check(dout_pin.layer=="metal2","DFF Q pin not on metal2")
|
debug.check(dout_pin.layer=="m2","DFF Q pin not on metal2")
|
||||||
self.add_layout_pin(text=self.get_dout_name(row,col),
|
self.add_layout_pin(text=self.get_dout_name(row,col),
|
||||||
layer=dout_pin.layer,
|
layer=dout_pin.layer,
|
||||||
offset=dout_pin.ll(),
|
offset=dout_pin.ll(),
|
||||||
|
|
@ -158,7 +158,7 @@ class dff_buf_array(design.design):
|
||||||
height=dout_pin.height())
|
height=dout_pin.height())
|
||||||
|
|
||||||
dout_bar_pin = self.dff_insts[row,col].get_pin("Qb")
|
dout_bar_pin = self.dff_insts[row,col].get_pin("Qb")
|
||||||
debug.check(dout_bar_pin.layer=="metal2","DFF Qb pin not on metal2")
|
debug.check(dout_bar_pin.layer=="m2","DFF Qb pin not on metal2")
|
||||||
self.add_layout_pin(text=self.get_dout_bar_name(row,col),
|
self.add_layout_pin(text=self.get_dout_bar_name(row,col),
|
||||||
layer=dout_bar_pin.layer,
|
layer=dout_bar_pin.layer,
|
||||||
offset=dout_bar_pin.ll(),
|
offset=dout_bar_pin.ll(),
|
||||||
|
|
@ -169,28 +169,28 @@ class dff_buf_array(design.design):
|
||||||
# Create vertical spines to a single horizontal rail
|
# Create vertical spines to a single horizontal rail
|
||||||
clk_pin = self.dff_insts[0,0].get_pin("clk")
|
clk_pin = self.dff_insts[0,0].get_pin("clk")
|
||||||
clk_ypos = 2*self.m3_pitch+self.m3_width
|
clk_ypos = 2*self.m3_pitch+self.m3_width
|
||||||
debug.check(clk_pin.layer=="metal2","DFF clk pin not on metal2")
|
debug.check(clk_pin.layer=="m2","DFF clk pin not on metal2")
|
||||||
if self.columns==1:
|
if self.columns==1:
|
||||||
self.add_layout_pin(text="clk",
|
self.add_layout_pin(text="clk",
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=clk_pin.ll().scale(1,0),
|
offset=clk_pin.ll().scale(1,0),
|
||||||
width=self.m2_width,
|
width=self.m2_width,
|
||||||
height=self.height)
|
height=self.height)
|
||||||
else:
|
else:
|
||||||
self.add_layout_pin_segment_center(text="clk",
|
self.add_layout_pin_segment_center(text="clk",
|
||||||
layer="metal3",
|
layer="m3",
|
||||||
start=vector(0,clk_ypos),
|
start=vector(0,clk_ypos),
|
||||||
end=vector(self.width,clk_ypos))
|
end=vector(self.width,clk_ypos))
|
||||||
for col in range(self.columns):
|
for col in range(self.columns):
|
||||||
clk_pin = self.dff_insts[0,col].get_pin("clk")
|
clk_pin = self.dff_insts[0,col].get_pin("clk")
|
||||||
|
|
||||||
# Make a vertical strip for each column
|
# Make a vertical strip for each column
|
||||||
self.add_rect(layer="metal2",
|
self.add_rect(layer="m2",
|
||||||
offset=clk_pin.ll().scale(1,0),
|
offset=clk_pin.ll().scale(1,0),
|
||||||
width=self.m2_width,
|
width=self.m2_width,
|
||||||
height=self.height)
|
height=self.height)
|
||||||
# Drop a via to the M3 pin
|
# Drop a via to the M3 pin
|
||||||
self.add_via_center(layers=("metal2","via2","metal3"),
|
self.add_via_center(layers=self.m2_stack,
|
||||||
offset=vector(clk_pin.cx(),clk_ypos))
|
offset=vector(clk_pin.cx(),clk_ypos))
|
||||||
|
|
||||||
def get_clk_cin(self):
|
def get_clk_cin(self):
|
||||||
|
|
|
||||||
|
|
@ -97,13 +97,13 @@ class dff_inv(design.design):
|
||||||
mid_x_offset = 0.5*(a1_pin.cx() + q_pin.cx())
|
mid_x_offset = 0.5*(a1_pin.cx() + q_pin.cx())
|
||||||
mid1 = vector(mid_x_offset, q_pin.cy())
|
mid1 = vector(mid_x_offset, q_pin.cy())
|
||||||
mid2 = vector(mid_x_offset, a1_pin.cy())
|
mid2 = vector(mid_x_offset, a1_pin.cy())
|
||||||
self.add_path("metal3",
|
self.add_path("m3",
|
||||||
[q_pin.center(), mid1, mid2, a1_pin.center()])
|
[q_pin.center(), mid1, mid2, a1_pin.center()])
|
||||||
self.add_via_center(layers=("metal2","via2","metal3"),
|
self.add_via_center(layers=self.m2_stack,
|
||||||
offset=q_pin.center())
|
offset=q_pin.center())
|
||||||
self.add_via_center(layers=("metal2","via2","metal3"),
|
self.add_via_center(layers=self.m2_stack,
|
||||||
offset=a1_pin.center())
|
offset=a1_pin.center())
|
||||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
self.add_via_center(layers=self.m1_stack,
|
||||||
offset=a1_pin.center())
|
offset=a1_pin.center())
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -112,7 +112,7 @@ class dff_inv(design.design):
|
||||||
# Continous vdd rail along with label.
|
# Continous vdd rail along with label.
|
||||||
vdd_pin=self.dff_inst.get_pin("vdd")
|
vdd_pin=self.dff_inst.get_pin("vdd")
|
||||||
self.add_layout_pin(text="vdd",
|
self.add_layout_pin(text="vdd",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=vdd_pin.ll(),
|
offset=vdd_pin.ll(),
|
||||||
width=self.width,
|
width=self.width,
|
||||||
height=vdd_pin.height())
|
height=vdd_pin.height())
|
||||||
|
|
@ -120,7 +120,7 @@ class dff_inv(design.design):
|
||||||
# Continous gnd rail along with label.
|
# Continous gnd rail along with label.
|
||||||
gnd_pin=self.dff_inst.get_pin("gnd")
|
gnd_pin=self.dff_inst.get_pin("gnd")
|
||||||
self.add_layout_pin(text="gnd",
|
self.add_layout_pin(text="gnd",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=gnd_pin.ll(),
|
offset=gnd_pin.ll(),
|
||||||
width=self.width,
|
width=self.width,
|
||||||
height=vdd_pin.height())
|
height=vdd_pin.height())
|
||||||
|
|
@ -146,9 +146,9 @@ class dff_inv(design.design):
|
||||||
|
|
||||||
dout_pin = self.inv1_inst.get_pin("Z")
|
dout_pin = self.inv1_inst.get_pin("Z")
|
||||||
self.add_layout_pin_rect_center(text="Qb",
|
self.add_layout_pin_rect_center(text="Qb",
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=dout_pin.center())
|
offset=dout_pin.center())
|
||||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
self.add_via_center(layers=self.m1_stack,
|
||||||
offset=dout_pin.center())
|
offset=dout_pin.center())
|
||||||
|
|
||||||
def get_clk_cin(self):
|
def get_clk_cin(self):
|
||||||
|
|
|
||||||
|
|
@ -140,7 +140,7 @@ class dff_inv_array(design.design):
|
||||||
for row in range(self.rows):
|
for row in range(self.rows):
|
||||||
for col in range(self.columns):
|
for col in range(self.columns):
|
||||||
din_pin = self.dff_insts[row,col].get_pin("D")
|
din_pin = self.dff_insts[row,col].get_pin("D")
|
||||||
debug.check(din_pin.layer=="metal2","DFF D pin not on metal2")
|
debug.check(din_pin.layer=="m2","DFF D pin not on metal2")
|
||||||
self.add_layout_pin(text=self.get_din_name(row,col),
|
self.add_layout_pin(text=self.get_din_name(row,col),
|
||||||
layer=din_pin.layer,
|
layer=din_pin.layer,
|
||||||
offset=din_pin.ll(),
|
offset=din_pin.ll(),
|
||||||
|
|
@ -148,7 +148,7 @@ class dff_inv_array(design.design):
|
||||||
height=din_pin.height())
|
height=din_pin.height())
|
||||||
|
|
||||||
dout_pin = self.dff_insts[row,col].get_pin("Q")
|
dout_pin = self.dff_insts[row,col].get_pin("Q")
|
||||||
debug.check(dout_pin.layer=="metal2","DFF Q pin not on metal2")
|
debug.check(dout_pin.layer=="m2","DFF Q pin not on metal2")
|
||||||
self.add_layout_pin(text=self.get_dout_name(row,col),
|
self.add_layout_pin(text=self.get_dout_name(row,col),
|
||||||
layer=dout_pin.layer,
|
layer=dout_pin.layer,
|
||||||
offset=dout_pin.ll(),
|
offset=dout_pin.ll(),
|
||||||
|
|
@ -156,7 +156,7 @@ class dff_inv_array(design.design):
|
||||||
height=dout_pin.height())
|
height=dout_pin.height())
|
||||||
|
|
||||||
dout_bar_pin = self.dff_insts[row,col].get_pin("Qb")
|
dout_bar_pin = self.dff_insts[row,col].get_pin("Qb")
|
||||||
debug.check(dout_bar_pin.layer=="metal2","DFF Qb pin not on metal2")
|
debug.check(dout_bar_pin.layer=="m2","DFF Qb pin not on metal2")
|
||||||
self.add_layout_pin(text=self.get_dout_bar_name(row,col),
|
self.add_layout_pin(text=self.get_dout_bar_name(row,col),
|
||||||
layer=dout_bar_pin.layer,
|
layer=dout_bar_pin.layer,
|
||||||
offset=dout_bar_pin.ll(),
|
offset=dout_bar_pin.ll(),
|
||||||
|
|
@ -167,27 +167,27 @@ class dff_inv_array(design.design):
|
||||||
# Create vertical spines to a single horizontal rail
|
# Create vertical spines to a single horizontal rail
|
||||||
clk_pin = self.dff_insts[0,0].get_pin("clk")
|
clk_pin = self.dff_insts[0,0].get_pin("clk")
|
||||||
clk_ypos = 2*self.m3_pitch+self.m3_width
|
clk_ypos = 2*self.m3_pitch+self.m3_width
|
||||||
debug.check(clk_pin.layer=="metal2","DFF clk pin not on metal2")
|
debug.check(clk_pin.layer=="m2","DFF clk pin not on metal2")
|
||||||
if self.columns==1:
|
if self.columns==1:
|
||||||
self.add_layout_pin(text="clk",
|
self.add_layout_pin(text="clk",
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=clk_pin.ll().scale(1,0),
|
offset=clk_pin.ll().scale(1,0),
|
||||||
width=self.m2_width,
|
width=self.m2_width,
|
||||||
height=self.height)
|
height=self.height)
|
||||||
else:
|
else:
|
||||||
self.add_layout_pin_segment_center(text="clk",
|
self.add_layout_pin_segment_center(text="clk",
|
||||||
layer="metal3",
|
layer="m3",
|
||||||
start=vector(0,clk_ypos),
|
start=vector(0,clk_ypos),
|
||||||
end=vector(self.width,clk_ypos))
|
end=vector(self.width,clk_ypos))
|
||||||
for col in range(self.columns):
|
for col in range(self.columns):
|
||||||
clk_pin = self.dff_insts[0,col].get_pin("clk")
|
clk_pin = self.dff_insts[0,col].get_pin("clk")
|
||||||
# Make a vertical strip for each column
|
# Make a vertical strip for each column
|
||||||
self.add_rect(layer="metal2",
|
self.add_rect(layer="m2",
|
||||||
offset=clk_pin.ll().scale(1,0),
|
offset=clk_pin.ll().scale(1,0),
|
||||||
width=self.m2_width,
|
width=self.m2_width,
|
||||||
height=self.height)
|
height=self.height)
|
||||||
# Drop a via to the M3 pin
|
# Drop a via to the M3 pin
|
||||||
self.add_via_center(layers=("metal2","via2","metal3"),
|
self.add_via_center(layers=self.m2_stack,
|
||||||
offset=vector(clk_pin.cx(),clk_ypos))
|
offset=vector(clk_pin.cx(),clk_ypos))
|
||||||
|
|
||||||
def get_clk_cin(self):
|
def get_clk_cin(self):
|
||||||
|
|
|
||||||
|
|
@ -122,7 +122,7 @@ class dummy_array(design.design):
|
||||||
for cell_column in column_list:
|
for cell_column in column_list:
|
||||||
bl_pin = self.cell_inst[0,col].get_pin(cell_column)
|
bl_pin = self.cell_inst[0,col].get_pin(cell_column)
|
||||||
self.add_layout_pin(text=cell_column+"_{0}".format(col),
|
self.add_layout_pin(text=cell_column+"_{0}".format(col),
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=bl_pin.ll(),
|
offset=bl_pin.ll(),
|
||||||
width=bl_pin.width(),
|
width=bl_pin.width(),
|
||||||
height=self.height)
|
height=self.height)
|
||||||
|
|
@ -131,7 +131,7 @@ class dummy_array(design.design):
|
||||||
for cell_row in row_list:
|
for cell_row in row_list:
|
||||||
wl_pin = self.cell_inst[row,0].get_pin(cell_row)
|
wl_pin = self.cell_inst[row,0].get_pin(cell_row)
|
||||||
self.add_layout_pin(text=cell_row+"_{0}".format(row),
|
self.add_layout_pin(text=cell_row+"_{0}".format(row),
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=wl_pin.ll(),
|
offset=wl_pin.ll(),
|
||||||
width=self.width,
|
width=self.width,
|
||||||
height=wl_pin.height())
|
height=wl_pin.height())
|
||||||
|
|
|
||||||
|
|
@ -173,7 +173,7 @@ class hierarchical_decoder(design.design):
|
||||||
input_offset=vector(min_x - self.input_routing_width,0)
|
input_offset=vector(min_x - self.input_routing_width,0)
|
||||||
|
|
||||||
input_bus_names = ["addr_{0}".format(i) for i in range(self.num_inputs)]
|
input_bus_names = ["addr_{0}".format(i) for i in range(self.num_inputs)]
|
||||||
self.input_rails = self.create_vertical_pin_bus(layer="metal2",
|
self.input_rails = self.create_vertical_pin_bus(layer="m2",
|
||||||
pitch=self.m2_pitch,
|
pitch=self.m2_pitch,
|
||||||
offset=input_offset,
|
offset=input_offset,
|
||||||
names=input_bus_names,
|
names=input_bus_names,
|
||||||
|
|
@ -225,7 +225,7 @@ class hierarchical_decoder(design.design):
|
||||||
offset=input_offset)
|
offset=input_offset)
|
||||||
self.add_via_center(layers=self.m2_stack,
|
self.add_via_center(layers=self.m2_stack,
|
||||||
offset=output_offset)
|
offset=output_offset)
|
||||||
self.add_path(("metal3"), [input_offset, output_offset])
|
self.add_path(("m3"), [input_offset, output_offset])
|
||||||
|
|
||||||
|
|
||||||
def add_pins(self):
|
def add_pins(self):
|
||||||
|
|
@ -467,11 +467,11 @@ class hierarchical_decoder(design.design):
|
||||||
# ensure the bend is in the middle
|
# ensure the bend is in the middle
|
||||||
mid1_pos = vector(0.5*(zr_pos.x+al_pos.x), zr_pos.y)
|
mid1_pos = vector(0.5*(zr_pos.x+al_pos.x), zr_pos.y)
|
||||||
mid2_pos = vector(0.5*(zr_pos.x+al_pos.x), al_pos.y)
|
mid2_pos = vector(0.5*(zr_pos.x+al_pos.x), al_pos.y)
|
||||||
self.add_path("metal1", [zr_pos, mid1_pos, mid2_pos, al_pos])
|
self.add_path("m1", [zr_pos, mid1_pos, mid2_pos, al_pos])
|
||||||
|
|
||||||
z_pin = self.inv_inst[row].get_pin("Z")
|
z_pin = self.inv_inst[row].get_pin("Z")
|
||||||
self.add_layout_pin(text="decode_{0}".format(row),
|
self.add_layout_pin(text="decode_{0}".format(row),
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=z_pin.ll(),
|
offset=z_pin.ll(),
|
||||||
width=z_pin.width(),
|
width=z_pin.width(),
|
||||||
height=z_pin.height())
|
height=z_pin.height())
|
||||||
|
|
@ -485,7 +485,7 @@ class hierarchical_decoder(design.design):
|
||||||
if (self.num_inputs >= 4):
|
if (self.num_inputs >= 4):
|
||||||
input_offset = vector(0.5*self.m2_width,0)
|
input_offset = vector(0.5*self.m2_width,0)
|
||||||
input_bus_names = ["predecode_{0}".format(i) for i in range(self.total_number_of_predecoder_outputs)]
|
input_bus_names = ["predecode_{0}".format(i) for i in range(self.total_number_of_predecoder_outputs)]
|
||||||
self.predecode_rails = self.create_vertical_pin_bus(layer="metal2",
|
self.predecode_rails = self.create_vertical_pin_bus(layer="m2",
|
||||||
pitch=self.m2_pitch,
|
pitch=self.m2_pitch,
|
||||||
offset=input_offset,
|
offset=input_offset,
|
||||||
names=input_bus_names,
|
names=input_bus_names,
|
||||||
|
|
@ -570,7 +570,7 @@ class hierarchical_decoder(design.design):
|
||||||
start = self.nand_inst[num].get_pin(pin_name).lc()
|
start = self.nand_inst[num].get_pin(pin_name).lc()
|
||||||
end = self.inv_inst[num].get_pin(pin_name).rc()
|
end = self.inv_inst[num].get_pin(pin_name).rc()
|
||||||
mid = (start+end).scale(0.5,0.5)
|
mid = (start+end).scale(0.5,0.5)
|
||||||
self.add_rect_center(layer="metal1",
|
self.add_rect_center(layer="m1",
|
||||||
offset=mid,
|
offset=mid,
|
||||||
width=end.x-start.x)
|
width=end.x-start.x)
|
||||||
|
|
||||||
|
|
@ -584,7 +584,7 @@ class hierarchical_decoder(design.design):
|
||||||
def route_predecode_rail(self, rail_name, pin):
|
def route_predecode_rail(self, rail_name, pin):
|
||||||
""" Connect the routing rail to the given metal1 pin """
|
""" Connect the routing rail to the given metal1 pin """
|
||||||
rail_pos = vector(self.predecode_rails[rail_name].x,pin.lc().y)
|
rail_pos = vector(self.predecode_rails[rail_name].x,pin.lc().y)
|
||||||
self.add_path("metal1", [rail_pos, pin.lc()])
|
self.add_path("m1", [rail_pos, pin.lc()])
|
||||||
self.add_via_center(layers=self.m1_stack,
|
self.add_via_center(layers=self.m1_stack,
|
||||||
offset=rail_pos)
|
offset=rail_pos)
|
||||||
|
|
||||||
|
|
@ -597,7 +597,7 @@ class hierarchical_decoder(design.design):
|
||||||
rail_pos = vector(self.predecode_rails[rail_name].x,mid_point.y)
|
rail_pos = vector(self.predecode_rails[rail_name].x,mid_point.y)
|
||||||
self.add_via_center(layers=self.m1_stack,
|
self.add_via_center(layers=self.m1_stack,
|
||||||
offset=pin.center())
|
offset=pin.center())
|
||||||
self.add_wire(("metal3","via2","metal2"), [rail_pos, mid_point, pin.uc()])
|
self.add_wire(("m3","via2","m2"), [rail_pos, mid_point, pin.uc()])
|
||||||
self.add_via_center(layers=self.m2_stack,
|
self.add_via_center(layers=self.m2_stack,
|
||||||
offset=rail_pos)
|
offset=rail_pos)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ class hierarchical_predecode(design.design):
|
||||||
""" Create all of the rails for the inputs and vdd/gnd/inputs_bar/inputs """
|
""" Create all of the rails for the inputs and vdd/gnd/inputs_bar/inputs """
|
||||||
input_names = ["in_{}".format(x) for x in range(self.number_of_inputs)]
|
input_names = ["in_{}".format(x) for x in range(self.number_of_inputs)]
|
||||||
offset = vector(0.5*self.m2_width,2*self.m1_width)
|
offset = vector(0.5*self.m2_width,2*self.m1_width)
|
||||||
self.input_rails = self.create_vertical_pin_bus(layer="metal2",
|
self.input_rails = self.create_vertical_pin_bus(layer="m2",
|
||||||
pitch=self.m2_pitch,
|
pitch=self.m2_pitch,
|
||||||
offset=offset,
|
offset=offset,
|
||||||
names=input_names,
|
names=input_names,
|
||||||
|
|
@ -83,7 +83,7 @@ class hierarchical_predecode(design.design):
|
||||||
non_invert_names = ["A_{}".format(x) for x in range(self.number_of_inputs)]
|
non_invert_names = ["A_{}".format(x) for x in range(self.number_of_inputs)]
|
||||||
decode_names = invert_names + non_invert_names
|
decode_names = invert_names + non_invert_names
|
||||||
offset = vector(self.x_off_inv_1 + self.inv.width + 2*self.m2_pitch, 2*self.m1_width)
|
offset = vector(self.x_off_inv_1 + self.inv.width + 2*self.m2_pitch, 2*self.m1_width)
|
||||||
self.decode_rails = self.create_vertical_bus(layer="metal2",
|
self.decode_rails = self.create_vertical_bus(layer="m2",
|
||||||
pitch=self.m2_pitch,
|
pitch=self.m2_pitch,
|
||||||
offset=offset,
|
offset=offset,
|
||||||
names=decode_names,
|
names=decode_names,
|
||||||
|
|
@ -183,7 +183,7 @@ class hierarchical_predecode(design.design):
|
||||||
a_pin = "A_{}".format(num)
|
a_pin = "A_{}".format(num)
|
||||||
in_pos = vector(self.input_rails[in_pin].x,y_offset)
|
in_pos = vector(self.input_rails[in_pin].x,y_offset)
|
||||||
a_pos = vector(self.decode_rails[a_pin].x,y_offset)
|
a_pos = vector(self.decode_rails[a_pin].x,y_offset)
|
||||||
self.add_path("metal1",[in_pos, a_pos])
|
self.add_path("m1",[in_pos, a_pos])
|
||||||
self.add_via_center(layers = self.m1_stack,
|
self.add_via_center(layers = self.m1_stack,
|
||||||
offset=[self.input_rails[in_pin].x, y_offset])
|
offset=[self.input_rails[in_pin].x, y_offset])
|
||||||
self.add_via_center(layers = self.m1_stack,
|
self.add_via_center(layers = self.m1_stack,
|
||||||
|
|
@ -201,11 +201,11 @@ class hierarchical_predecode(design.design):
|
||||||
# ensure the bend is in the middle
|
# ensure the bend is in the middle
|
||||||
mid1_pos = vector(0.5*(zr_pos.x+al_pos.x), zr_pos.y)
|
mid1_pos = vector(0.5*(zr_pos.x+al_pos.x), zr_pos.y)
|
||||||
mid2_pos = vector(0.5*(zr_pos.x+al_pos.x), al_pos.y)
|
mid2_pos = vector(0.5*(zr_pos.x+al_pos.x), al_pos.y)
|
||||||
self.add_path("metal1", [zr_pos, mid1_pos, mid2_pos, al_pos])
|
self.add_path("m1", [zr_pos, mid1_pos, mid2_pos, al_pos])
|
||||||
|
|
||||||
z_pin = self.inv_inst[num].get_pin("Z")
|
z_pin = self.inv_inst[num].get_pin("Z")
|
||||||
self.add_layout_pin(text="out_{}".format(num),
|
self.add_layout_pin(text="out_{}".format(num),
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=z_pin.ll(),
|
offset=z_pin.ll(),
|
||||||
height=z_pin.height(),
|
height=z_pin.height(),
|
||||||
width=z_pin.width())
|
width=z_pin.width())
|
||||||
|
|
@ -226,7 +226,7 @@ class hierarchical_predecode(design.design):
|
||||||
inv_out_pos = self.in_inst[inv_num].get_pin("Z").rc()
|
inv_out_pos = self.in_inst[inv_num].get_pin("Z").rc()
|
||||||
right_pos = inv_out_pos + vector(self.inv.width - self.inv.get_pin("Z").lx(),0)
|
right_pos = inv_out_pos + vector(self.inv.width - self.inv.get_pin("Z").lx(),0)
|
||||||
rail_pos = vector(self.decode_rails[out_pin].x,y_offset)
|
rail_pos = vector(self.decode_rails[out_pin].x,y_offset)
|
||||||
self.add_path("metal1", [inv_out_pos, right_pos, vector(right_pos.x, y_offset), rail_pos])
|
self.add_path("m1", [inv_out_pos, right_pos, vector(right_pos.x, y_offset), rail_pos])
|
||||||
self.add_via_center(layers = self.m1_stack,
|
self.add_via_center(layers = self.m1_stack,
|
||||||
offset=rail_pos)
|
offset=rail_pos)
|
||||||
|
|
||||||
|
|
@ -234,7 +234,7 @@ class hierarchical_predecode(design.design):
|
||||||
#route input
|
#route input
|
||||||
inv_in_pos = self.in_inst[inv_num].get_pin("A").lc()
|
inv_in_pos = self.in_inst[inv_num].get_pin("A").lc()
|
||||||
in_pos = vector(self.input_rails[in_pin].x,inv_in_pos.y)
|
in_pos = vector(self.input_rails[in_pin].x,inv_in_pos.y)
|
||||||
self.add_path("metal1", [in_pos, inv_in_pos])
|
self.add_path("m1", [in_pos, inv_in_pos])
|
||||||
self.add_via_center(layers=self.m1_stack,
|
self.add_via_center(layers=self.m1_stack,
|
||||||
offset=in_pos)
|
offset=in_pos)
|
||||||
|
|
||||||
|
|
@ -255,7 +255,7 @@ class hierarchical_predecode(design.design):
|
||||||
for rail_pin,gate_pin in zip(index_lst,gate_lst):
|
for rail_pin,gate_pin in zip(index_lst,gate_lst):
|
||||||
pin_pos = self.nand_inst[k].get_pin(gate_pin).lc()
|
pin_pos = self.nand_inst[k].get_pin(gate_pin).lc()
|
||||||
rail_pos = vector(self.decode_rails[rail_pin].x, pin_pos.y)
|
rail_pos = vector(self.decode_rails[rail_pin].x, pin_pos.y)
|
||||||
self.add_path("metal1", [rail_pos, pin_pos])
|
self.add_path("m1", [rail_pos, pin_pos])
|
||||||
self.add_via_center(layers=self.m1_stack,
|
self.add_via_center(layers=self.m1_stack,
|
||||||
offset=rail_pos)
|
offset=rail_pos)
|
||||||
|
|
||||||
|
|
@ -275,7 +275,7 @@ class hierarchical_predecode(design.design):
|
||||||
for n in ["vdd", "gnd"]:
|
for n in ["vdd", "gnd"]:
|
||||||
nand_pin = self.nand_inst[num].get_pin(n)
|
nand_pin = self.nand_inst[num].get_pin(n)
|
||||||
supply_offset = nand_pin.ll().scale(0,1)
|
supply_offset = nand_pin.ll().scale(0,1)
|
||||||
self.add_rect(layer="metal1",
|
self.add_rect(layer="m1",
|
||||||
offset=supply_offset,
|
offset=supply_offset,
|
||||||
width=self.inv_inst[num].rx())
|
width=self.inv_inst[num].rx())
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -160,7 +160,7 @@ class multibank(design.design):
|
||||||
self.central_bus_width = self.m2_pitch * self.num_control_lines + 2*self.m2_width
|
self.central_bus_width = self.m2_pitch * self.num_control_lines + 2*self.m2_width
|
||||||
|
|
||||||
# A space for wells or jogging m2
|
# A space for wells or jogging m2
|
||||||
self.m2_gap = max(2*drc("pwell_to_nwell"] + drc["well_enclosure_active"),
|
self.m2_gap = max(2*drc("pwell_to_nwell"] + drc["well_enclose_active"),
|
||||||
2*self.m2_pitch)
|
2*self.m2_pitch)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -451,7 +451,7 @@ class multibank(design.design):
|
||||||
# Connect the inverter output to the central bus
|
# Connect the inverter output to the central bus
|
||||||
out_pos = self.bank_select_inst.get_pin(gated_name).rc()
|
out_pos = self.bank_select_inst.get_pin(gated_name).rc()
|
||||||
bus_pos = vector(self.bus_xoffset[gated_name], out_pos.y)
|
bus_pos = vector(self.bus_xoffset[gated_name], out_pos.y)
|
||||||
self.add_path("metal3",[out_pos, bus_pos])
|
self.add_path("m3",[out_pos, bus_pos])
|
||||||
self.add_via_center(layers=self.m2_stack,
|
self.add_via_center(layers=self.m2_stack,
|
||||||
offset=bus_pos,
|
offset=bus_pos,
|
||||||
rotate=90)
|
rotate=90)
|
||||||
|
|
@ -512,7 +512,7 @@ class multibank(design.design):
|
||||||
# 2 pitches on the right for vias/jogs to access the inputs
|
# 2 pitches on the right for vias/jogs to access the inputs
|
||||||
control_bus_offset = vector(-self.m2_pitch * self.num_control_lines - self.m2_width, 0)
|
control_bus_offset = vector(-self.m2_pitch * self.num_control_lines - self.m2_width, 0)
|
||||||
control_bus_length = self.bitcell_array_inst.uy()
|
control_bus_length = self.bitcell_array_inst.uy()
|
||||||
self.bus_xoffset = self.create_vertical_bus(layer="metal2",
|
self.bus_xoffset = self.create_vertical_bus(layer="m2",
|
||||||
pitch=self.m2_pitch,
|
pitch=self.m2_pitch,
|
||||||
offset=control_bus_offset,
|
offset=control_bus_offset,
|
||||||
names=self.control_signals,
|
names=self.control_signals,
|
||||||
|
|
@ -530,9 +530,9 @@ class multibank(design.design):
|
||||||
bitcell_br = self.bitcell_array_inst.get_pin("br_{}".format(i)).uc()
|
bitcell_br = self.bitcell_array_inst.get_pin("br_{}".format(i)).uc()
|
||||||
|
|
||||||
yoffset = 0.5*(precharge_bl.y+bitcell_bl.y)
|
yoffset = 0.5*(precharge_bl.y+bitcell_bl.y)
|
||||||
self.add_path("metal2",[precharge_bl, vector(precharge_bl.x,yoffset),
|
self.add_path("m2",[precharge_bl, vector(precharge_bl.x,yoffset),
|
||||||
vector(bitcell_bl.x,yoffset), bitcell_bl])
|
vector(bitcell_bl.x,yoffset), bitcell_bl])
|
||||||
self.add_path("metal2",[precharge_br, vector(precharge_br.x,yoffset),
|
self.add_path("m2",[precharge_br, vector(precharge_br.x,yoffset),
|
||||||
vector(bitcell_br.x,yoffset), bitcell_br])
|
vector(bitcell_br.x,yoffset), bitcell_br])
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -550,9 +550,9 @@ class multibank(design.design):
|
||||||
bitcell_br = self.bitcell_array_inst.get_pin("br_{}".format(i)).bc()
|
bitcell_br = self.bitcell_array_inst.get_pin("br_{}".format(i)).bc()
|
||||||
|
|
||||||
yoffset = 0.5*(col_mux_bl.y+bitcell_bl.y)
|
yoffset = 0.5*(col_mux_bl.y+bitcell_bl.y)
|
||||||
self.add_path("metal2",[col_mux_bl, vector(col_mux_bl.x,yoffset),
|
self.add_path("m2",[col_mux_bl, vector(col_mux_bl.x,yoffset),
|
||||||
vector(bitcell_bl.x,yoffset), bitcell_bl])
|
vector(bitcell_bl.x,yoffset), bitcell_bl])
|
||||||
self.add_path("metal2",[col_mux_br, vector(col_mux_br.x,yoffset),
|
self.add_path("m2",[col_mux_br, vector(col_mux_br.x,yoffset),
|
||||||
vector(bitcell_br.x,yoffset), bitcell_br])
|
vector(bitcell_br.x,yoffset), bitcell_br])
|
||||||
|
|
||||||
def route_sense_amp_to_col_mux_or_bitcell_array(self):
|
def route_sense_amp_to_col_mux_or_bitcell_array(self):
|
||||||
|
|
@ -573,9 +573,9 @@ class multibank(design.design):
|
||||||
|
|
||||||
|
|
||||||
yoffset = 0.5*(sense_amp_bl.y+connect_bl.y)
|
yoffset = 0.5*(sense_amp_bl.y+connect_bl.y)
|
||||||
self.add_path("metal2",[sense_amp_bl, vector(sense_amp_bl.x,yoffset),
|
self.add_path("m2",[sense_amp_bl, vector(sense_amp_bl.x,yoffset),
|
||||||
vector(connect_bl.x,yoffset), connect_bl])
|
vector(connect_bl.x,yoffset), connect_bl])
|
||||||
self.add_path("metal2",[sense_amp_br, vector(sense_amp_br.x,yoffset),
|
self.add_path("m2",[sense_amp_br, vector(sense_amp_br.x,yoffset),
|
||||||
vector(connect_br.x,yoffset), connect_br])
|
vector(connect_br.x,yoffset), connect_br])
|
||||||
|
|
||||||
def route_sense_amp_to_trigate(self):
|
def route_sense_amp_to_trigate(self):
|
||||||
|
|
@ -590,7 +590,7 @@ class multibank(design.design):
|
||||||
offset=tri_gate_in)
|
offset=tri_gate_in)
|
||||||
self.add_via_center(layers=self.m2_stack,
|
self.add_via_center(layers=self.m2_stack,
|
||||||
offset=sa_data_out)
|
offset=sa_data_out)
|
||||||
self.add_path("metal3",[sa_data_out,tri_gate_in])
|
self.add_path("m3",[sa_data_out,tri_gate_in])
|
||||||
|
|
||||||
def route_sense_amp_out(self):
|
def route_sense_amp_out(self):
|
||||||
""" Add pins for the sense amp output """
|
""" Add pins for the sense amp output """
|
||||||
|
|
@ -644,14 +644,14 @@ class multibank(design.design):
|
||||||
driver_in_pos = self.wordline_driver_inst.get_pin("in_{}".format(i)).lc()
|
driver_in_pos = self.wordline_driver_inst.get_pin("in_{}".format(i)).lc()
|
||||||
mid1 = decoder_out_pos.scale(0.5,1)+driver_in_pos.scale(0.5,0)
|
mid1 = decoder_out_pos.scale(0.5,1)+driver_in_pos.scale(0.5,0)
|
||||||
mid2 = decoder_out_pos.scale(0.5,0)+driver_in_pos.scale(0.5,1)
|
mid2 = decoder_out_pos.scale(0.5,0)+driver_in_pos.scale(0.5,1)
|
||||||
self.add_path("metal1", [decoder_out_pos, mid1, mid2, driver_in_pos])
|
self.add_path("m1", [decoder_out_pos, mid1, mid2, driver_in_pos])
|
||||||
|
|
||||||
# The mid guarantees we exit the input cell to the right.
|
# The mid guarantees we exit the input cell to the right.
|
||||||
driver_wl_pos = self.wordline_driver_inst.get_pin("wl_{}".format(i)).rc()
|
driver_wl_pos = self.wordline_driver_inst.get_pin("wl_{}".format(i)).rc()
|
||||||
bitcell_wl_pos = self.bitcell_array_inst.get_pin("wl_{}".format(i)).lc()
|
bitcell_wl_pos = self.bitcell_array_inst.get_pin("wl_{}".format(i)).lc()
|
||||||
mid1 = driver_wl_pos.scale(0.5,1)+bitcell_wl_pos.scale(0.5,0)
|
mid1 = driver_wl_pos.scale(0.5,1)+bitcell_wl_pos.scale(0.5,0)
|
||||||
mid2 = driver_wl_pos.scale(0.5,0)+bitcell_wl_pos.scale(0.5,1)
|
mid2 = driver_wl_pos.scale(0.5,0)+bitcell_wl_pos.scale(0.5,1)
|
||||||
self.add_path("metal1", [driver_wl_pos, mid1, mid2, bitcell_wl_pos])
|
self.add_path("m1", [driver_wl_pos, mid1, mid2, bitcell_wl_pos])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -698,8 +698,8 @@ class multibank(design.design):
|
||||||
else:
|
else:
|
||||||
mid1_pos = vector(decode_out_pos.x + delta_offset + (self.num_col_addr_lines-i)*self.m2_pitch,decode_out_pos.y)
|
mid1_pos = vector(decode_out_pos.x + delta_offset + (self.num_col_addr_lines-i)*self.m2_pitch,decode_out_pos.y)
|
||||||
mid2_pos = vector(mid1_pos.x,mux_addr_pos.y)
|
mid2_pos = vector(mid1_pos.x,mux_addr_pos.y)
|
||||||
#self.add_wire(("metal1","via1","metal2"),[decode_out_pos, mid1_pos, mid2_pos, mux_addr_pos])
|
#self.add_wire(self.m1_stack,[decode_out_pos, mid1_pos, mid2_pos, mux_addr_pos])
|
||||||
self.add_path("metal1",[decode_out_pos, mid1_pos, mid2_pos, mux_addr_pos])
|
self.add_path("m1",[decode_out_pos, mid1_pos, mid2_pos, mux_addr_pos])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -715,7 +715,7 @@ class multibank(design.design):
|
||||||
wl_name = "wl_{}".format(i)
|
wl_name = "wl_{}".format(i)
|
||||||
wl_pin = self.bitcell_array_inst.get_pin(wl_name)
|
wl_pin = self.bitcell_array_inst.get_pin(wl_name)
|
||||||
self.add_label(text=wl_name,
|
self.add_label(text=wl_name,
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=wl_pin.center())
|
offset=wl_pin.center())
|
||||||
|
|
||||||
# Add the bitline names
|
# Add the bitline names
|
||||||
|
|
@ -725,10 +725,10 @@ class multibank(design.design):
|
||||||
bl_pin = self.bitcell_array_inst.get_pin(bl_name)
|
bl_pin = self.bitcell_array_inst.get_pin(bl_name)
|
||||||
br_pin = self.bitcell_array_inst.get_pin(br_name)
|
br_pin = self.bitcell_array_inst.get_pin(br_name)
|
||||||
self.add_label(text=bl_name,
|
self.add_label(text=bl_name,
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=bl_pin.center())
|
offset=bl_pin.center())
|
||||||
self.add_label(text=br_name,
|
self.add_label(text=br_name,
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=br_pin.center())
|
offset=br_pin.center())
|
||||||
|
|
||||||
# # Add the data output names to the sense amp output
|
# # Add the data output names to the sense amp output
|
||||||
|
|
@ -736,7 +736,7 @@ class multibank(design.design):
|
||||||
# data_name = "data_{}".format(i)
|
# data_name = "data_{}".format(i)
|
||||||
# data_pin = self.sense_amp_array_inst.get_pin(data_name)
|
# data_pin = self.sense_amp_array_inst.get_pin(data_name)
|
||||||
# self.add_label(text="sa_out_{}".format(i),
|
# self.add_label(text="sa_out_{}".format(i),
|
||||||
# layer="metal2",
|
# layer="m2",
|
||||||
# offset=data_pin.center())
|
# offset=data_pin.center())
|
||||||
|
|
||||||
# Add labels on the decoder
|
# Add labels on the decoder
|
||||||
|
|
@ -745,7 +745,7 @@ class multibank(design.design):
|
||||||
pin_name = "in_{}".format(i)
|
pin_name = "in_{}".format(i)
|
||||||
data_pin = self.wordline_driver_inst.get_pin(pin_name)
|
data_pin = self.wordline_driver_inst.get_pin(pin_name)
|
||||||
self.add_label(text=data_name,
|
self.add_label(text=data_name,
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=data_pin.center())
|
offset=data_pin.center())
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -765,7 +765,7 @@ class multibank(design.design):
|
||||||
|
|
||||||
for (control_signal, pin_pos) in connection:
|
for (control_signal, pin_pos) in connection:
|
||||||
control_pos = vector(self.bus_xoffset[control_signal].x ,pin_pos.y)
|
control_pos = vector(self.bus_xoffset[control_signal].x ,pin_pos.y)
|
||||||
self.add_path("metal1", [control_pos, pin_pos])
|
self.add_path("m1", [control_pos, pin_pos])
|
||||||
self.add_via_center(layers=self.m1_stack,
|
self.add_via_center(layers=self.m1_stack,
|
||||||
offset=control_pos,
|
offset=control_pos,
|
||||||
rotate=90)
|
rotate=90)
|
||||||
|
|
@ -776,7 +776,7 @@ class multibank(design.design):
|
||||||
mid_pos = pin_pos + vector(0,self.m1_pitch)
|
mid_pos = pin_pos + vector(0,self.m1_pitch)
|
||||||
control_x_offset = self.bus_xoffset[control_signal].x
|
control_x_offset = self.bus_xoffset[control_signal].x
|
||||||
control_pos = vector(control_x_offset + self.m1_width, mid_pos.y)
|
control_pos = vector(control_x_offset + self.m1_width, mid_pos.y)
|
||||||
self.add_wire(("metal1","via1","metal2"),[pin_pos, mid_pos, control_pos])
|
self.add_wire(self.m1_stack,[pin_pos, mid_pos, control_pos])
|
||||||
control_via_pos = vector(control_x_offset, mid_pos.y)
|
control_via_pos = vector(control_x_offset, mid_pos.y)
|
||||||
self.add_via_center(layers=self.m1_stack,
|
self.add_via_center(layers=self.m1_stack,
|
||||||
offset=control_via_pos,
|
offset=control_via_pos,
|
||||||
|
|
@ -791,13 +791,13 @@ class multibank(design.design):
|
||||||
if self.num_banks > 1:
|
if self.num_banks > 1:
|
||||||
# it's not an input pin if we have multiple banks
|
# it's not an input pin if we have multiple banks
|
||||||
self.add_label_pin(text=ctrl,
|
self.add_label_pin(text=ctrl,
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=vector(x_offset, self.min_y_offset),
|
offset=vector(x_offset, self.min_y_offset),
|
||||||
width=self.m2_width,
|
width=self.m2_width,
|
||||||
height=self.max_y_offset-self.min_y_offset)
|
height=self.max_y_offset-self.min_y_offset)
|
||||||
else:
|
else:
|
||||||
self.add_layout_pin(text=ctrl,
|
self.add_layout_pin(text=ctrl,
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=vector(x_offset, self.min_y_offset),
|
offset=vector(x_offset, self.min_y_offset),
|
||||||
width=self.m2_width,
|
width=self.m2_width,
|
||||||
height=self.max_y_offset-self.min_y_offset)
|
height=self.max_y_offset-self.min_y_offset)
|
||||||
|
|
@ -807,12 +807,12 @@ class multibank(design.design):
|
||||||
""" Helper routine to connect an unrotated/mirrored oriented instance to the rails """
|
""" Helper routine to connect an unrotated/mirrored oriented instance to the rails """
|
||||||
in_pin = inst.get_pin(pin).lc()
|
in_pin = inst.get_pin(pin).lc()
|
||||||
rail_pos = vector(self.rail_1_x_offsets[rail], in_pin.y)
|
rail_pos = vector(self.rail_1_x_offsets[rail], in_pin.y)
|
||||||
self.add_wire(("metal3","via2","metal2"),[in_pin, rail_pos, rail_pos - vector(0,self.m2_pitch)])
|
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
|
# Bring it up to M2 for M2/M3 routing
|
||||||
self.add_via(layers=("metal1","via1","metal2"),
|
self.add_via(layers=self.m1_stack,
|
||||||
offset=in_pin + contact.m1m2.offset,
|
offset=in_pin + contact.m1m2.offset,
|
||||||
rotate=90)
|
rotate=90)
|
||||||
self.add_via(layers=("metal2","via2","metal3"),
|
self.add_via(layers=self.m2_stack,
|
||||||
offset=in_pin + self.m2m3_via_offset,
|
offset=in_pin + self.m2m3_via_offset,
|
||||||
rotate=90)
|
rotate=90)
|
||||||
|
|
||||||
|
|
@ -821,10 +821,10 @@ class multibank(design.design):
|
||||||
""" Helper routine to connect an unrotated/mirrored oriented instance to the rails """
|
""" Helper routine to connect an unrotated/mirrored oriented instance to the rails """
|
||||||
in_pin = inst.get_pin(pin).rc()
|
in_pin = inst.get_pin(pin).rc()
|
||||||
rail_pos = vector(self.rail_1_x_offsets[rail], in_pin.y)
|
rail_pos = vector(self.rail_1_x_offsets[rail], in_pin.y)
|
||||||
self.add_wire(("metal3","via2","metal2"),[in_pin, rail_pos, rail_pos - vector(0,self.m2_pitch)])
|
self.add_wire(("m3","via2","m2"),[in_pin, rail_pos, rail_pos - vector(0,self.m2_pitch)])
|
||||||
self.add_via(layers=("metal1","via1","metal2"),
|
self.add_via(layers=self.m1_stack,
|
||||||
offset=in_pin + contact.m1m2.offset,
|
offset=in_pin + contact.m1m2.offset,
|
||||||
rotate=90)
|
rotate=90)
|
||||||
self.add_via(layers=("metal2","via2","metal3"),
|
self.add_via(layers=self.m2_stack,
|
||||||
offset=in_pin + self.m2m3_via_offset,
|
offset=in_pin + self.m2m3_via_offset,
|
||||||
rotate=90)
|
rotate=90)
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,7 @@ class port_address(design.design):
|
||||||
driver_in_pos = self.wordline_driver_inst.get_pin("in_{}".format(row)).lc()
|
driver_in_pos = self.wordline_driver_inst.get_pin("in_{}".format(row)).lc()
|
||||||
mid1 = decoder_out_pos.scale(0.5,1)+driver_in_pos.scale(0.5,0)
|
mid1 = decoder_out_pos.scale(0.5,1)+driver_in_pos.scale(0.5,0)
|
||||||
mid2 = decoder_out_pos.scale(0.5,0)+driver_in_pos.scale(0.5,1)
|
mid2 = decoder_out_pos.scale(0.5,0)+driver_in_pos.scale(0.5,1)
|
||||||
self.add_path("metal1", [decoder_out_pos, mid1, mid2, driver_in_pos])
|
self.add_path("m1", [decoder_out_pos, mid1, mid2, driver_in_pos])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -149,7 +149,7 @@ class port_address(design.design):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# A space for wells or jogging m2
|
# A space for wells or jogging m2
|
||||||
self.m2_gap = max(2*drc("pwell_to_nwell") + drc("well_enclosure_active"),
|
self.m2_gap = max(2*drc("pwell_to_nwell") + drc("well_enclose_active"),
|
||||||
3*self.m2_pitch)
|
3*self.m2_pitch)
|
||||||
|
|
||||||
row_decoder_offset = vector(0,0)
|
row_decoder_offset = vector(0,0)
|
||||||
|
|
|
||||||
|
|
@ -212,7 +212,7 @@ class port_data(design.design):
|
||||||
|
|
||||||
|
|
||||||
# A space for wells or jogging m2 between modules
|
# A space for wells or jogging m2 between modules
|
||||||
self.m2_gap = max(2*drc("pwell_to_nwell") + drc("well_enclosure_active"),
|
self.m2_gap = max(2*drc("pwell_to_nwell") + drc("well_enclose_active"),
|
||||||
3*self.m2_pitch)
|
3*self.m2_pitch)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -479,7 +479,7 @@ class port_data(design.design):
|
||||||
offset=end_pos)
|
offset=end_pos)
|
||||||
|
|
||||||
# Route between write mask AND array and write driver array
|
# Route between write mask AND array and write driver array
|
||||||
self.add_wire(("metal1","via1","metal2"), [beg_pos, middle_pos, end_pos])
|
self.add_wire(self.m1_stack, [beg_pos, middle_pos, end_pos])
|
||||||
|
|
||||||
|
|
||||||
def route_column_mux_to_precharge_array(self, port):
|
def route_column_mux_to_precharge_array(self, port):
|
||||||
|
|
@ -655,9 +655,9 @@ class port_data(design.design):
|
||||||
top_br = top_inst.get_pin(top_br_name.format(col+top_start_bit)).bc()
|
top_br = top_inst.get_pin(top_br_name.format(col+top_start_bit)).bc()
|
||||||
|
|
||||||
yoffset = 0.5*(top_bl.y+bottom_bl.y)
|
yoffset = 0.5*(top_bl.y+bottom_bl.y)
|
||||||
self.add_path("metal2",[bottom_bl, vector(bottom_bl.x,yoffset),
|
self.add_path("m2",[bottom_bl, vector(bottom_bl.x,yoffset),
|
||||||
vector(top_bl.x,yoffset), top_bl])
|
vector(top_bl.x,yoffset), top_bl])
|
||||||
self.add_path("metal2",[bottom_br, vector(bottom_br.x,yoffset),
|
self.add_path("m2",[bottom_br, vector(bottom_br.x,yoffset),
|
||||||
vector(top_br.x,yoffset), top_br])
|
vector(top_br.x,yoffset), top_br])
|
||||||
|
|
||||||
def graph_exclude_precharge(self):
|
def graph_exclude_precharge(self):
|
||||||
|
|
|
||||||
|
|
@ -68,10 +68,10 @@ class precharge_array(design.design):
|
||||||
def add_layout_pins(self):
|
def add_layout_pins(self):
|
||||||
|
|
||||||
self.add_layout_pin(text="en_bar",
|
self.add_layout_pin(text="en_bar",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=self.pc_cell.get_pin("en_bar").ll(),
|
offset=self.pc_cell.get_pin("en_bar").ll(),
|
||||||
width=self.width,
|
width=self.width,
|
||||||
height=drc("minwidth_metal1"))
|
height=drc("minwidth_m1"))
|
||||||
|
|
||||||
for inst in self.local_insts:
|
for inst in self.local_insts:
|
||||||
self.copy_layout_pin(inst, "vdd")
|
self.copy_layout_pin(inst, "vdd")
|
||||||
|
|
@ -80,15 +80,15 @@ class precharge_array(design.design):
|
||||||
inst = self.local_insts[i]
|
inst = self.local_insts[i]
|
||||||
bl_pin = inst.get_pin("bl")
|
bl_pin = inst.get_pin("bl")
|
||||||
self.add_layout_pin(text="bl_{0}".format(i),
|
self.add_layout_pin(text="bl_{0}".format(i),
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=bl_pin.ll(),
|
offset=bl_pin.ll(),
|
||||||
width=drc("minwidth_metal2"),
|
width=drc("minwidth_m2"),
|
||||||
height=bl_pin.height())
|
height=bl_pin.height())
|
||||||
br_pin = inst.get_pin("br")
|
br_pin = inst.get_pin("br")
|
||||||
self.add_layout_pin(text="br_{0}".format(i),
|
self.add_layout_pin(text="br_{0}".format(i),
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=br_pin.ll(),
|
offset=br_pin.ll(),
|
||||||
width=drc("minwidth_metal2"),
|
width=drc("minwidth_m2"),
|
||||||
height=bl_pin.height())
|
height=bl_pin.height())
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -399,7 +399,7 @@ class replica_bitcell_array(design.design):
|
||||||
else:
|
else:
|
||||||
height = self.height
|
height = self.height
|
||||||
bl_pos = 0
|
bl_pos = 0
|
||||||
bl_wire = self.generate_rc_net(int(self.row_size-bl_pos), height, drc("minwidth_metal1"))
|
bl_wire = self.generate_rc_net(int(self.row_size-bl_pos), height, drc("minwidth_m1"))
|
||||||
bl_wire.wire_c =spice["min_tx_drain_c"] + bl_wire.wire_c # 1 access tx d/s per cell
|
bl_wire.wire_c =spice["min_tx_drain_c"] + bl_wire.wire_c # 1 access tx d/s per cell
|
||||||
return bl_wire
|
return bl_wire
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -116,7 +116,7 @@ class replica_column(design.design):
|
||||||
for bl_name in self.cell.get_all_bitline_names():
|
for bl_name in self.cell.get_all_bitline_names():
|
||||||
bl_pin = self.cell_inst[0].get_pin(bl_name)
|
bl_pin = self.cell_inst[0].get_pin(bl_name)
|
||||||
self.add_layout_pin(text=bl_name,
|
self.add_layout_pin(text=bl_name,
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=bl_pin.ll(),
|
offset=bl_pin.ll(),
|
||||||
width=bl_pin.width(),
|
width=bl_pin.width(),
|
||||||
height=self.height)
|
height=self.height)
|
||||||
|
|
@ -125,7 +125,7 @@ class replica_column(design.design):
|
||||||
for wl_name in self.cell.get_all_wl_names():
|
for wl_name in self.cell.get_all_wl_names():
|
||||||
wl_pin = self.cell_inst[row].get_pin(wl_name)
|
wl_pin = self.cell_inst[row].get_pin(wl_name)
|
||||||
self.add_layout_pin(text="{0}_{1}".format(wl_name,row),
|
self.add_layout_pin(text="{0}_{1}".format(wl_name,row),
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=wl_pin.ll().scale(0,1),
|
offset=wl_pin.ll().scale(0,1),
|
||||||
width=self.width,
|
width=self.width,
|
||||||
height=wl_pin.height())
|
height=wl_pin.height())
|
||||||
|
|
|
||||||
|
|
@ -102,13 +102,13 @@ class sense_amp_array(design.design):
|
||||||
self.add_via_center(layers=self.m2_stack,
|
self.add_via_center(layers=self.m2_stack,
|
||||||
offset=gnd_pos)
|
offset=gnd_pos)
|
||||||
self.add_layout_pin_rect_center(text="gnd",
|
self.add_layout_pin_rect_center(text="gnd",
|
||||||
layer="metal3",
|
layer="m3",
|
||||||
offset=gnd_pos)
|
offset=gnd_pos)
|
||||||
vdd_pos = inst.get_pin("vdd").center()
|
vdd_pos = inst.get_pin("vdd").center()
|
||||||
self.add_via_center(layers=self.m2_stack,
|
self.add_via_center(layers=self.m2_stack,
|
||||||
offset=vdd_pos)
|
offset=vdd_pos)
|
||||||
self.add_layout_pin_rect_center(text="vdd",
|
self.add_layout_pin_rect_center(text="vdd",
|
||||||
layer="metal3",
|
layer="m3",
|
||||||
offset=vdd_pos)
|
offset=vdd_pos)
|
||||||
|
|
||||||
bl_pin = inst.get_pin("bl")
|
bl_pin = inst.get_pin("bl")
|
||||||
|
|
@ -116,18 +116,18 @@ class sense_amp_array(design.design):
|
||||||
dout_pin = inst.get_pin("dout")
|
dout_pin = inst.get_pin("dout")
|
||||||
|
|
||||||
self.add_layout_pin(text="bl_{0}".format(i),
|
self.add_layout_pin(text="bl_{0}".format(i),
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=bl_pin.ll(),
|
offset=bl_pin.ll(),
|
||||||
width=bl_pin.width(),
|
width=bl_pin.width(),
|
||||||
height=bl_pin.height())
|
height=bl_pin.height())
|
||||||
self.add_layout_pin(text="br_{0}".format(i),
|
self.add_layout_pin(text="br_{0}".format(i),
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=br_pin.ll(),
|
offset=br_pin.ll(),
|
||||||
width=br_pin.width(),
|
width=br_pin.width(),
|
||||||
height=br_pin.height())
|
height=br_pin.height())
|
||||||
|
|
||||||
self.add_layout_pin(text="data_{0}".format(i),
|
self.add_layout_pin(text="data_{0}".format(i),
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=dout_pin.ll(),
|
offset=dout_pin.ll(),
|
||||||
width=dout_pin.width(),
|
width=dout_pin.width(),
|
||||||
height=dout_pin.height())
|
height=dout_pin.height())
|
||||||
|
|
@ -137,10 +137,10 @@ class sense_amp_array(design.design):
|
||||||
# add sclk rail across entire array
|
# add sclk rail across entire array
|
||||||
sclk_offset = self.amp.get_pin("en").ll().scale(0,1)
|
sclk_offset = self.amp.get_pin("en").ll().scale(0,1)
|
||||||
self.add_layout_pin(text="en",
|
self.add_layout_pin(text="en",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=sclk_offset,
|
offset=sclk_offset,
|
||||||
width=self.width,
|
width=self.width,
|
||||||
height=drc("minwidth_metal1"))
|
height=drc("minwidth_m1"))
|
||||||
|
|
||||||
def input_load(self):
|
def input_load(self):
|
||||||
return self.amp.input_load()
|
return self.amp.input_load()
|
||||||
|
|
|
||||||
|
|
@ -113,13 +113,13 @@ class single_level_column_mux_array(design.design):
|
||||||
mux_inst = self.mux_inst[col_num]
|
mux_inst = self.mux_inst[col_num]
|
||||||
offset = mux_inst.get_pin("bl").ll()
|
offset = mux_inst.get_pin("bl").ll()
|
||||||
self.add_layout_pin(text="bl_{}".format(col_num),
|
self.add_layout_pin(text="bl_{}".format(col_num),
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=offset,
|
offset=offset,
|
||||||
height=self.height-offset.y)
|
height=self.height-offset.y)
|
||||||
|
|
||||||
offset = mux_inst.get_pin("br").ll()
|
offset = mux_inst.get_pin("br").ll()
|
||||||
self.add_layout_pin(text="br_{}".format(col_num),
|
self.add_layout_pin(text="br_{}".format(col_num),
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=offset,
|
offset=offset,
|
||||||
height=self.height-offset.y)
|
height=self.height-offset.y)
|
||||||
|
|
||||||
|
|
@ -137,7 +137,7 @@ class single_level_column_mux_array(design.design):
|
||||||
for j in range(self.words_per_row):
|
for j in range(self.words_per_row):
|
||||||
offset = vector(0, self.route_height + (j-self.words_per_row)*self.m1_pitch)
|
offset = vector(0, self.route_height + (j-self.words_per_row)*self.m1_pitch)
|
||||||
self.add_layout_pin(text="sel_{}".format(j),
|
self.add_layout_pin(text="sel_{}".format(j),
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=offset,
|
offset=offset,
|
||||||
width=self.mux.width * self.columns)
|
width=self.mux.width * self.columns)
|
||||||
|
|
||||||
|
|
@ -155,7 +155,7 @@ class single_level_column_mux_array(design.design):
|
||||||
# use the y offset from the sel pin and the x offset from the gate
|
# use the y offset from the sel pin and the x offset from the gate
|
||||||
offset = vector(gate_offset.x,self.get_pin("sel_{}".format(sel_index)).cy())
|
offset = vector(gate_offset.x,self.get_pin("sel_{}".format(sel_index)).cy())
|
||||||
# Add the poly contact with a shift to account for the rotation
|
# Add the poly contact with a shift to account for the rotation
|
||||||
self.add_via_center(layers=("metal1", "contact", "poly"),
|
self.add_via_center(layers=("m1", "contact", "poly"),
|
||||||
offset=offset)
|
offset=offset)
|
||||||
self.add_path("poly", [offset, gate_offset])
|
self.add_path("poly", [offset, gate_offset])
|
||||||
|
|
||||||
|
|
@ -176,16 +176,16 @@ class single_level_column_mux_array(design.design):
|
||||||
# These will be located below the select lines. Yes, these are M2 width
|
# These will be located below the select lines. Yes, these are M2 width
|
||||||
# to ensure vias are enclosed and M1 min width rules.
|
# to ensure vias are enclosed and M1 min width rules.
|
||||||
width = self.m2_width + self.mux.width * (self.words_per_row - 1)
|
width = self.m2_width + self.mux.width * (self.words_per_row - 1)
|
||||||
self.add_path("metal1", [bl_out_offset, bl_out_offset+vector(width,0)])
|
self.add_path("m1", [bl_out_offset, bl_out_offset+vector(width,0)])
|
||||||
self.add_path("metal1", [br_out_offset, br_out_offset+vector(width,0)])
|
self.add_path("m1", [br_out_offset, br_out_offset+vector(width,0)])
|
||||||
|
|
||||||
# Extend the bitline output rails and gnd downward on the first bit of each n-way mux
|
# Extend the bitline output rails and gnd downward on the first bit of each n-way mux
|
||||||
self.add_layout_pin_segment_center(text="bl_out_{}".format(int(j/self.words_per_row)),
|
self.add_layout_pin_segment_center(text="bl_out_{}".format(int(j/self.words_per_row)),
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
start=bl_out_offset,
|
start=bl_out_offset,
|
||||||
end=bl_out_offset_end)
|
end=bl_out_offset_end)
|
||||||
self.add_layout_pin_segment_center(text="br_out_{}".format(int(j/self.words_per_row)),
|
self.add_layout_pin_segment_center(text="br_out_{}".format(int(j/self.words_per_row)),
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
start=br_out_offset,
|
start=br_out_offset,
|
||||||
end=br_out_offset_end)
|
end=br_out_offset_end)
|
||||||
|
|
||||||
|
|
@ -200,8 +200,8 @@ class single_level_column_mux_array(design.design):
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
||||||
self.add_path("metal2", [ bl_out_offset, bl_out_offset_end])
|
self.add_path("m2", [ bl_out_offset, bl_out_offset_end])
|
||||||
self.add_path("metal2", [ br_out_offset, br_out_offset_end])
|
self.add_path("m2", [ br_out_offset, br_out_offset_end])
|
||||||
|
|
||||||
# This via is on the right of the wire
|
# This via is on the right of the wire
|
||||||
self.add_via_center(layers=self.m1_stack,
|
self.add_via_center(layers=self.m1_stack,
|
||||||
|
|
|
||||||
|
|
@ -83,14 +83,14 @@ class tri_gate_array(design.design):
|
||||||
|
|
||||||
in_pin = self.tri_inst[i].get_pin("in")
|
in_pin = self.tri_inst[i].get_pin("in")
|
||||||
self.add_layout_pin(text="in_{0}".format(index),
|
self.add_layout_pin(text="in_{0}".format(index),
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=in_pin.ll(),
|
offset=in_pin.ll(),
|
||||||
width=in_pin.width(),
|
width=in_pin.width(),
|
||||||
height=in_pin.height())
|
height=in_pin.height())
|
||||||
|
|
||||||
out_pin = self.tri_inst[i].get_pin("out")
|
out_pin = self.tri_inst[i].get_pin("out")
|
||||||
self.add_layout_pin(text="out_{0}".format(index),
|
self.add_layout_pin(text="out_{0}".format(index),
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=out_pin.ll(),
|
offset=out_pin.ll(),
|
||||||
width=out_pin.width(),
|
width=out_pin.width(),
|
||||||
height=out_pin.height())
|
height=out_pin.height())
|
||||||
|
|
@ -103,21 +103,21 @@ class tri_gate_array(design.design):
|
||||||
self.add_via_center(layers=self.m2_stack,
|
self.add_via_center(layers=self.m2_stack,
|
||||||
offset=pin_pos)
|
offset=pin_pos)
|
||||||
self.add_layout_pin_rect_center(text=n,
|
self.add_layout_pin_rect_center(text=n,
|
||||||
layer="metal3",
|
layer="m3",
|
||||||
offset=pin_pos)
|
offset=pin_pos)
|
||||||
|
|
||||||
|
|
||||||
width = self.tri.width * self.columns - (self.words_per_row - 1) * self.tri.width
|
width = self.tri.width * self.columns - (self.words_per_row - 1) * self.tri.width
|
||||||
en_pin = self.tri_inst[0].get_pin("en")
|
en_pin = self.tri_inst[0].get_pin("en")
|
||||||
self.add_layout_pin(text="en",
|
self.add_layout_pin(text="en",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=en_pin.ll().scale(0, 1),
|
offset=en_pin.ll().scale(0, 1),
|
||||||
width=width,
|
width=width,
|
||||||
height=drc("minwidth_metal1"))
|
height=drc("minwidth_m1"))
|
||||||
|
|
||||||
enbar_pin = self.tri_inst[0].get_pin("en_bar")
|
enbar_pin = self.tri_inst[0].get_pin("en_bar")
|
||||||
self.add_layout_pin(text="en_bar",
|
self.add_layout_pin(text="en_bar",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=enbar_pin.ll().scale(0, 1),
|
offset=enbar_pin.ll().scale(0, 1),
|
||||||
width=width,
|
width=width,
|
||||||
height=drc("minwidth_metal1"))
|
height=drc("minwidth_m1"))
|
||||||
|
|
@ -142,7 +142,7 @@ class wordline_driver(design.design):
|
||||||
# Wordline enable connection
|
# Wordline enable connection
|
||||||
en_offset = [self.m1_width + 2 * self.m1_space, 0]
|
en_offset = [self.m1_width + 2 * self.m1_space, 0]
|
||||||
en_pin = self.add_layout_pin(text="en",
|
en_pin = self.add_layout_pin(text="en",
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=en_offset,
|
offset=en_offset,
|
||||||
width=self.m2_width,
|
width=self.m2_width,
|
||||||
height=self.height)
|
height=self.height)
|
||||||
|
|
@ -155,7 +155,7 @@ class wordline_driver(design.design):
|
||||||
a_pin = nand_inst.get_pin("A")
|
a_pin = nand_inst.get_pin("A")
|
||||||
a_pos = a_pin.lc()
|
a_pos = a_pin.lc()
|
||||||
clk_offset = vector(en_pin.bc().x, a_pos.y)
|
clk_offset = vector(en_pin.bc().x, a_pos.y)
|
||||||
self.add_segment_center(layer="metal1",
|
self.add_segment_center(layer="m1",
|
||||||
start=clk_offset,
|
start=clk_offset,
|
||||||
end=a_pos)
|
end=a_pos)
|
||||||
self.add_via_center(layers=self.m1_stack,
|
self.add_via_center(layers=self.m1_stack,
|
||||||
|
|
@ -167,7 +167,7 @@ class wordline_driver(design.design):
|
||||||
# ensure the bend is in the middle
|
# ensure the bend is in the middle
|
||||||
mid1_pos = vector(0.5*(zr_pos.x+al_pos.x), zr_pos.y)
|
mid1_pos = vector(0.5*(zr_pos.x+al_pos.x), zr_pos.y)
|
||||||
mid2_pos = vector(0.5*(zr_pos.x+al_pos.x), al_pos.y)
|
mid2_pos = vector(0.5*(zr_pos.x+al_pos.x), al_pos.y)
|
||||||
self.add_path("metal1", [zr_pos, mid1_pos, mid2_pos, al_pos])
|
self.add_path("m1", [zr_pos, mid1_pos, mid2_pos, al_pos])
|
||||||
|
|
||||||
# connect the decoder input pin to nand2 B
|
# connect the decoder input pin to nand2 B
|
||||||
b_pin = nand_inst.get_pin("B")
|
b_pin = nand_inst.get_pin("B")
|
||||||
|
|
@ -182,7 +182,7 @@ class wordline_driver(design.design):
|
||||||
|
|
||||||
# must under the clk line in M1
|
# must under the clk line in M1
|
||||||
self.add_layout_pin_segment_center(text="in_{0}".format(row),
|
self.add_layout_pin_segment_center(text="in_{0}".format(row),
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
start=input_offset,
|
start=input_offset,
|
||||||
end=mid_via_offset)
|
end=mid_via_offset)
|
||||||
self.add_via_center(layers=self.m1_stack,
|
self.add_via_center(layers=self.m1_stack,
|
||||||
|
|
@ -190,7 +190,7 @@ class wordline_driver(design.design):
|
||||||
directions=("V", "V"))
|
directions=("V", "V"))
|
||||||
|
|
||||||
# now connect to the nand2 B
|
# now connect to the nand2 B
|
||||||
self.add_path("metal2", [mid_via_offset, b_pos])
|
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.m1m2.height, 0)
|
||||||
self.add_via_center(layers=self.m1_stack,
|
self.add_via_center(layers=self.m1_stack,
|
||||||
offset=contact_offset,
|
offset=contact_offset,
|
||||||
|
|
@ -199,7 +199,7 @@ class wordline_driver(design.design):
|
||||||
# output each WL on the right
|
# output each WL on the right
|
||||||
wl_offset = inv2_inst.get_pin("Z").rc()
|
wl_offset = inv2_inst.get_pin("Z").rc()
|
||||||
self.add_layout_pin_segment_center(text="wl_{0}".format(row),
|
self.add_layout_pin_segment_center(text="wl_{0}".format(row),
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
start=wl_offset,
|
start=wl_offset,
|
||||||
end=wl_offset - vector(self.m1_width, 0))
|
end=wl_offset - vector(self.m1_width, 0))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -120,20 +120,20 @@ class write_driver_array(design.design):
|
||||||
for i in range(self.word_size):
|
for i in range(self.word_size):
|
||||||
din_pin = self.driver_insts[i].get_pin("din")
|
din_pin = self.driver_insts[i].get_pin("din")
|
||||||
self.add_layout_pin(text="data_{0}".format(i),
|
self.add_layout_pin(text="data_{0}".format(i),
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=din_pin.ll(),
|
offset=din_pin.ll(),
|
||||||
width=din_pin.width(),
|
width=din_pin.width(),
|
||||||
height=din_pin.height())
|
height=din_pin.height())
|
||||||
bl_pin = self.driver_insts[i].get_pin("bl")
|
bl_pin = self.driver_insts[i].get_pin("bl")
|
||||||
self.add_layout_pin(text="bl_{0}".format(i),
|
self.add_layout_pin(text="bl_{0}".format(i),
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=bl_pin.ll(),
|
offset=bl_pin.ll(),
|
||||||
width=bl_pin.width(),
|
width=bl_pin.width(),
|
||||||
height=bl_pin.height())
|
height=bl_pin.height())
|
||||||
|
|
||||||
br_pin = self.driver_insts[i].get_pin("br")
|
br_pin = self.driver_insts[i].get_pin("br")
|
||||||
self.add_layout_pin(text="br_{0}".format(i),
|
self.add_layout_pin(text="br_{0}".format(i),
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=br_pin.ll(),
|
offset=br_pin.ll(),
|
||||||
width=br_pin.width(),
|
width=br_pin.width(),
|
||||||
height=br_pin.height())
|
height=br_pin.height())
|
||||||
|
|
@ -146,7 +146,7 @@ class write_driver_array(design.design):
|
||||||
self.add_via_center(layers=self.m2_stack,
|
self.add_via_center(layers=self.m2_stack,
|
||||||
offset=pin_pos)
|
offset=pin_pos)
|
||||||
self.add_layout_pin_rect_center(text=n,
|
self.add_layout_pin_rect_center(text=n,
|
||||||
layer="metal3",
|
layer="m3",
|
||||||
offset=pin_pos)
|
offset=pin_pos)
|
||||||
if self.write_size:
|
if self.write_size:
|
||||||
for bit in range(self.num_wmasks):
|
for bit in range(self.num_wmasks):
|
||||||
|
|
@ -165,7 +165,7 @@ class write_driver_array(design.design):
|
||||||
height=en_pin.height())
|
height=en_pin.height())
|
||||||
else:
|
else:
|
||||||
self.add_layout_pin(text="en",
|
self.add_layout_pin(text="en",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=self.driver_insts[0].get_pin("en").ll().scale(0,1),
|
offset=self.driver_insts[0].get_pin("en").ll().scale(0,1),
|
||||||
width=self.width)
|
width=self.width)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -114,7 +114,7 @@ class write_mask_and_array(design.design):
|
||||||
# Extend metal3 to edge of AND array in multiport
|
# Extend metal3 to edge of AND array in multiport
|
||||||
en_to_edge = self.and2.width - beg_en_pin.cx()
|
en_to_edge = self.and2.width - beg_en_pin.cx()
|
||||||
self.add_layout_pin(text="en",
|
self.add_layout_pin(text="en",
|
||||||
layer="metal3",
|
layer="m3",
|
||||||
offset=beg_en_pin.bc(),
|
offset=beg_en_pin.bc(),
|
||||||
width=end_en_pin.cx() - beg_en_pin.cx() + en_to_edge)
|
width=end_en_pin.cx() - beg_en_pin.cx() + en_to_edge)
|
||||||
self.add_via_center(layers=self.m1_stack,
|
self.add_via_center(layers=self.m1_stack,
|
||||||
|
|
@ -123,7 +123,7 @@ class write_mask_and_array(design.design):
|
||||||
offset=vector(end_en_pin.cx() + en_to_edge, end_en_pin.cy()))
|
offset=vector(end_en_pin.cx() + en_to_edge, end_en_pin.cy()))
|
||||||
else:
|
else:
|
||||||
self.add_layout_pin(text="en",
|
self.add_layout_pin(text="en",
|
||||||
layer="metal3",
|
layer="m3",
|
||||||
offset=beg_en_pin.bc(),
|
offset=beg_en_pin.bc(),
|
||||||
width=end_en_pin.cx() - beg_en_pin.cx())
|
width=end_en_pin.cx() - beg_en_pin.cx())
|
||||||
|
|
||||||
|
|
@ -146,7 +146,7 @@ class write_mask_and_array(design.design):
|
||||||
for n in ["gnd","vdd"]:
|
for n in ["gnd","vdd"]:
|
||||||
pin = self.and2_insts[i].get_pin(n)
|
pin = self.and2_insts[i].get_pin(n)
|
||||||
next_pin = self.and2_insts[i+1].get_pin(n)
|
next_pin = self.and2_insts[i+1].get_pin(n)
|
||||||
self.add_path("metal1",[pin.center(),next_pin.center()])
|
self.add_path("m1",[pin.center(),next_pin.center()])
|
||||||
|
|
||||||
def get_cin(self):
|
def get_cin(self):
|
||||||
"""Get the relative capacitance of all the input connections in the bank"""
|
"""Get the relative capacitance of all the input connections in the bank"""
|
||||||
|
|
|
||||||
|
|
@ -76,14 +76,14 @@ class pand2(pgate.pgate):
|
||||||
a2_pin = self.inv_inst.get_pin("A")
|
a2_pin = self.inv_inst.get_pin("A")
|
||||||
mid1_point = vector(0.5 * (z1_pin.cx() + a2_pin.cx()), z1_pin.cy())
|
mid1_point = vector(0.5 * (z1_pin.cx() + a2_pin.cx()), z1_pin.cy())
|
||||||
mid2_point = vector(mid1_point, a2_pin.cy())
|
mid2_point = vector(mid1_point, a2_pin.cy())
|
||||||
self.add_path("metal1",
|
self.add_path("m1",
|
||||||
[z1_pin.center(), mid1_point, mid2_point, a2_pin.center()])
|
[z1_pin.center(), mid1_point, mid2_point, a2_pin.center()])
|
||||||
|
|
||||||
def add_layout_pins(self):
|
def add_layout_pins(self):
|
||||||
# Continous vdd rail along with label.
|
# Continous vdd rail along with label.
|
||||||
vdd_pin = self.inv_inst.get_pin("vdd")
|
vdd_pin = self.inv_inst.get_pin("vdd")
|
||||||
self.add_layout_pin(text="vdd",
|
self.add_layout_pin(text="vdd",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=vdd_pin.ll().scale(0, 1),
|
offset=vdd_pin.ll().scale(0, 1),
|
||||||
width=self.width,
|
width=self.width,
|
||||||
height=vdd_pin.height())
|
height=vdd_pin.height())
|
||||||
|
|
@ -91,7 +91,7 @@ class pand2(pgate.pgate):
|
||||||
# Continous gnd rail along with label.
|
# Continous gnd rail along with label.
|
||||||
gnd_pin = self.inv_inst.get_pin("gnd")
|
gnd_pin = self.inv_inst.get_pin("gnd")
|
||||||
self.add_layout_pin(text="gnd",
|
self.add_layout_pin(text="gnd",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=gnd_pin.ll().scale(0, 1),
|
offset=gnd_pin.ll().scale(0, 1),
|
||||||
width=self.width,
|
width=self.width,
|
||||||
height=vdd_pin.height())
|
height=vdd_pin.height())
|
||||||
|
|
|
||||||
|
|
@ -76,14 +76,14 @@ class pand3(pgate.pgate):
|
||||||
a2_pin = self.inv_inst.get_pin("A")
|
a2_pin = self.inv_inst.get_pin("A")
|
||||||
mid1_point = vector(0.5 * (z1_pin.cx()+a2_pin.cx()), z1_pin.cy())
|
mid1_point = vector(0.5 * (z1_pin.cx()+a2_pin.cx()), z1_pin.cy())
|
||||||
mid2_point = vector(mid1_point, a2_pin.cy())
|
mid2_point = vector(mid1_point, a2_pin.cy())
|
||||||
self.add_path("metal1",
|
self.add_path("m1",
|
||||||
[z1_pin.center(), mid1_point, mid2_point, a2_pin.center()])
|
[z1_pin.center(), mid1_point, mid2_point, a2_pin.center()])
|
||||||
|
|
||||||
def add_layout_pins(self):
|
def add_layout_pins(self):
|
||||||
# Continous vdd rail along with label.
|
# Continous vdd rail along with label.
|
||||||
vdd_pin = self.inv_inst.get_pin("vdd")
|
vdd_pin = self.inv_inst.get_pin("vdd")
|
||||||
self.add_layout_pin(text="vdd",
|
self.add_layout_pin(text="vdd",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=vdd_pin.ll().scale(0, 1),
|
offset=vdd_pin.ll().scale(0, 1),
|
||||||
width=self.width,
|
width=self.width,
|
||||||
height=vdd_pin.height())
|
height=vdd_pin.height())
|
||||||
|
|
@ -91,7 +91,7 @@ class pand3(pgate.pgate):
|
||||||
# Continous gnd rail along with label.
|
# Continous gnd rail along with label.
|
||||||
gnd_pin = self.inv_inst.get_pin("gnd")
|
gnd_pin = self.inv_inst.get_pin("gnd")
|
||||||
self.add_layout_pin(text="gnd",
|
self.add_layout_pin(text="gnd",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=gnd_pin.ll().scale(0, 1),
|
offset=gnd_pin.ll().scale(0, 1),
|
||||||
width=self.width,
|
width=self.width,
|
||||||
height=vdd_pin.height())
|
height=vdd_pin.height())
|
||||||
|
|
|
||||||
|
|
@ -78,13 +78,13 @@ class pbuf(pgate.pgate):
|
||||||
z1_pin = self.inv1_inst.get_pin("Z")
|
z1_pin = self.inv1_inst.get_pin("Z")
|
||||||
a2_pin = self.inv2_inst.get_pin("A")
|
a2_pin = self.inv2_inst.get_pin("A")
|
||||||
mid_point = vector(z1_pin.cx(), a2_pin.cy())
|
mid_point = vector(z1_pin.cx(), a2_pin.cy())
|
||||||
self.add_path("metal1", [z1_pin.center(), mid_point, a2_pin.center()])
|
self.add_path("m1", [z1_pin.center(), mid_point, a2_pin.center()])
|
||||||
|
|
||||||
def add_layout_pins(self):
|
def add_layout_pins(self):
|
||||||
# Continous vdd rail along with label.
|
# Continous vdd rail along with label.
|
||||||
vdd_pin = self.inv1_inst.get_pin("vdd")
|
vdd_pin = self.inv1_inst.get_pin("vdd")
|
||||||
self.add_layout_pin(text="vdd",
|
self.add_layout_pin(text="vdd",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=vdd_pin.ll().scale(0, 1),
|
offset=vdd_pin.ll().scale(0, 1),
|
||||||
width=self.width,
|
width=self.width,
|
||||||
height=vdd_pin.height())
|
height=vdd_pin.height())
|
||||||
|
|
@ -92,7 +92,7 @@ class pbuf(pgate.pgate):
|
||||||
# Continous gnd rail along with label.
|
# Continous gnd rail along with label.
|
||||||
gnd_pin = self.inv1_inst.get_pin("gnd")
|
gnd_pin = self.inv1_inst.get_pin("gnd")
|
||||||
self.add_layout_pin(text="gnd",
|
self.add_layout_pin(text="gnd",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=gnd_pin.ll().scale(0, 1),
|
offset=gnd_pin.ll().scale(0, 1),
|
||||||
width=self.width,
|
width=self.width,
|
||||||
height=vdd_pin.height())
|
height=vdd_pin.height())
|
||||||
|
|
|
||||||
|
|
@ -140,7 +140,7 @@ class pdriver(pgate.pgate):
|
||||||
z_inst_list.append(self.inv_inst_list[x].get_pin("Z"))
|
z_inst_list.append(self.inv_inst_list[x].get_pin("Z"))
|
||||||
a_inst_list.append(self.inv_inst_list[x + 1].get_pin("A"))
|
a_inst_list.append(self.inv_inst_list[x + 1].get_pin("A"))
|
||||||
mid_point = vector(z_inst_list[x].cx(), a_inst_list[x].cy())
|
mid_point = vector(z_inst_list[x].cx(), a_inst_list[x].cy())
|
||||||
self.add_path("metal1",
|
self.add_path("m1",
|
||||||
[z_inst_list[x].center(), mid_point,
|
[z_inst_list[x].center(), mid_point,
|
||||||
a_inst_list[x].center()])
|
a_inst_list[x].center()])
|
||||||
|
|
||||||
|
|
@ -148,7 +148,7 @@ class pdriver(pgate.pgate):
|
||||||
# Continous vdd rail along with label.
|
# Continous vdd rail along with label.
|
||||||
vdd_pin = self.inv_inst_list[0].get_pin("vdd")
|
vdd_pin = self.inv_inst_list[0].get_pin("vdd")
|
||||||
self.add_layout_pin(text="vdd",
|
self.add_layout_pin(text="vdd",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=vdd_pin.ll().scale(0, 1),
|
offset=vdd_pin.ll().scale(0, 1),
|
||||||
width=self.width,
|
width=self.width,
|
||||||
height=vdd_pin.height())
|
height=vdd_pin.height())
|
||||||
|
|
@ -156,7 +156,7 @@ class pdriver(pgate.pgate):
|
||||||
# Continous gnd rail along with label.
|
# Continous gnd rail along with label.
|
||||||
gnd_pin = self.inv_inst_list[0].get_pin("gnd")
|
gnd_pin = self.inv_inst_list[0].get_pin("gnd")
|
||||||
self.add_layout_pin(text="gnd",
|
self.add_layout_pin(text="gnd",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=gnd_pin.ll().scale(0, 1),
|
offset=gnd_pin.ll().scale(0, 1),
|
||||||
width=self.width,
|
width=self.width,
|
||||||
height=vdd_pin.height())
|
height=vdd_pin.height())
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ class pgate(design.design):
|
||||||
debug.error("Invalid supply name.", -1)
|
debug.error("Invalid supply name.", -1)
|
||||||
|
|
||||||
if abs(height) > 0:
|
if abs(height) > 0:
|
||||||
self.add_rect(layer="metal1",
|
self.add_rect(layer="m1",
|
||||||
offset=source_pin.ll(),
|
offset=source_pin.ll(),
|
||||||
height=height,
|
height=height,
|
||||||
width=source_pin.width())
|
width=source_pin.width())
|
||||||
|
|
@ -120,7 +120,7 @@ class pgate(design.design):
|
||||||
directions=directions)
|
directions=directions)
|
||||||
|
|
||||||
self.add_layout_pin_rect_center(text=name,
|
self.add_layout_pin_rect_center(text=name,
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=contact_offset,
|
offset=contact_offset,
|
||||||
width=contact_m1_width,
|
width=contact_m1_width,
|
||||||
height=contact_m1_height)
|
height=contact_m1_height)
|
||||||
|
|
@ -172,7 +172,7 @@ class pgate(design.design):
|
||||||
|
|
||||||
# To the right a spacing away from the pmos right active edge
|
# To the right a spacing away from the pmos right active edge
|
||||||
contact_xoffset = pmos_pos.x + pmos.active_width \
|
contact_xoffset = pmos_pos.x + pmos.active_width \
|
||||||
+ drc("active_to_body_active")
|
+ self.active_space
|
||||||
|
|
||||||
# Must be at least an well enclosure of active down
|
# Must be at least an well enclosure of active down
|
||||||
# from the top of the well
|
# from the top of the well
|
||||||
|
|
@ -189,7 +189,7 @@ class pgate(design.design):
|
||||||
directions=("H", "V"),
|
directions=("H", "V"),
|
||||||
implant_type="n",
|
implant_type="n",
|
||||||
well_type="n")
|
well_type="n")
|
||||||
self.add_rect_center(layer="metal1",
|
self.add_rect_center(layer="m1",
|
||||||
offset=contact_offset + vector(0, 0.5 * (self.height-contact_offset.y)),
|
offset=contact_offset + vector(0, 0.5 * (self.height-contact_offset.y)),
|
||||||
width=self.nwell_contact.mod.second_layer_width,
|
width=self.nwell_contact.mod.second_layer_width,
|
||||||
height=self.height - contact_offset.y)
|
height=self.height - contact_offset.y)
|
||||||
|
|
@ -227,7 +227,7 @@ class pgate(design.design):
|
||||||
|
|
||||||
# To the right a spacing away from the nmos right active edge
|
# To the right a spacing away from the nmos right active edge
|
||||||
contact_xoffset = nmos_pos.x + nmos.active_width \
|
contact_xoffset = nmos_pos.x + nmos.active_width \
|
||||||
+ drc("active_to_body_active")
|
+ self.active_space
|
||||||
# Must be at least an well enclosure of active up
|
# Must be at least an well enclosure of active up
|
||||||
# from the bottom of the well
|
# from the bottom of the well
|
||||||
contact_yoffset = max(nmos_pos.y,
|
contact_yoffset = max(nmos_pos.y,
|
||||||
|
|
@ -243,7 +243,7 @@ class pgate(design.design):
|
||||||
directions=("H", "V"),
|
directions=("H", "V"),
|
||||||
implant_type="p",
|
implant_type="p",
|
||||||
well_type="p")
|
well_type="p")
|
||||||
self.add_rect_center(layer="metal1",
|
self.add_rect_center(layer="m1",
|
||||||
offset=contact_offset.scale(1,0.5),
|
offset=contact_offset.scale(1,0.5),
|
||||||
width=self.pwell_contact.mod.second_layer_width,
|
width=self.pwell_contact.mod.second_layer_width,
|
||||||
height=contact_offset.y)
|
height=contact_offset.y)
|
||||||
|
|
|
||||||
|
|
@ -96,14 +96,14 @@ class pinv(pgate.pgate):
|
||||||
tx_height = nmos.poly_height + pmos.poly_height
|
tx_height = nmos.poly_height + pmos.poly_height
|
||||||
# rotated m1 pitch or poly to active spacing
|
# rotated m1 pitch or poly to active spacing
|
||||||
min_channel = max(contact.poly.width + self.m1_space,
|
min_channel = max(contact.poly.width + self.m1_space,
|
||||||
contact.poly.width + 2 * drc("poly_to_active"))
|
contact.poly.width + 2 * self.poly_to_active)
|
||||||
|
|
||||||
# This is the extra space needed to ensure DRC rules
|
# This is the extra space needed to ensure DRC rules
|
||||||
# to the active contacts
|
# to the active contacts
|
||||||
extra_contact_space = max(-nmos.get_pin("D").by(), 0)
|
extra_contact_space = max(-nmos.get_pin("D").by(), 0)
|
||||||
# This is a poly-to-poly of a flipped cell
|
# This is a poly-to-poly of a flipped cell
|
||||||
self.top_bottom_space = max(0.5*self.m1_width + self.m1_space + extra_contact_space,
|
self.top_bottom_space = max(0.5*self.m1_width + self.m1_space + extra_contact_space,
|
||||||
drc("poly_extend_active"), self.poly_space)
|
self.poly_extend_active, self.poly_space)
|
||||||
total_height = tx_height + min_channel + 2 * self.top_bottom_space
|
total_height = tx_height + min_channel + 2 * self.top_bottom_space
|
||||||
debug.check(self.height > total_height,
|
debug.check(self.height > total_height,
|
||||||
"Cell height {0} too small for simple min height {1}.".format(self.height,
|
"Cell height {0} too small for simple min height {1}.".format(self.height,
|
||||||
|
|
@ -153,7 +153,7 @@ class pinv(pgate.pgate):
|
||||||
# the well width is determined the multi-finger PMOS device width plus
|
# the well width is determined the multi-finger PMOS device width plus
|
||||||
# the well contact width and half well enclosure on both sides
|
# the well contact width and half well enclosure on both sides
|
||||||
self.well_width = self.pmos.active_width + self.pmos.active_contact.width \
|
self.well_width = self.pmos.active_width + self.pmos.active_contact.width \
|
||||||
+ drc("active_to_body_active") + 2*drc("well_enclosure_active")
|
+ self.active_space + 2*self.well_enclose_active
|
||||||
self.width = self.well_width
|
self.width = self.well_width
|
||||||
# Height is an input parameter, so it is not recomputed.
|
# Height is an input parameter, so it is not recomputed.
|
||||||
|
|
||||||
|
|
@ -178,12 +178,12 @@ class pinv(pgate.pgate):
|
||||||
def route_supply_rails(self):
|
def route_supply_rails(self):
|
||||||
""" Add vdd/gnd rails to the top and bottom. """
|
""" Add vdd/gnd rails to the top and bottom. """
|
||||||
self.add_layout_pin_rect_center(text="gnd",
|
self.add_layout_pin_rect_center(text="gnd",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=vector(0.5 * self.width, 0),
|
offset=vector(0.5 * self.width, 0),
|
||||||
width=self.width)
|
width=self.width)
|
||||||
|
|
||||||
self.add_layout_pin_rect_center(text="vdd",
|
self.add_layout_pin_rect_center(text="vdd",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=vector(0.5 * self.width, self.height),
|
offset=vector(0.5 * self.width, self.height),
|
||||||
width=self.width)
|
width=self.width)
|
||||||
|
|
||||||
|
|
@ -238,7 +238,7 @@ class pinv(pgate.pgate):
|
||||||
# Pick point at right most of NMOS and connect down to PMOS
|
# Pick point at right most of NMOS and connect down to PMOS
|
||||||
nmos_drain_pos = nmos_drain_pin.bc()
|
nmos_drain_pos = nmos_drain_pin.bc()
|
||||||
pmos_drain_pos = vector(nmos_drain_pos.x, pmos_drain_pin.uc().y)
|
pmos_drain_pos = vector(nmos_drain_pos.x, pmos_drain_pin.uc().y)
|
||||||
self.add_path("metal1", [nmos_drain_pos, pmos_drain_pos])
|
self.add_path("m1", [nmos_drain_pos, pmos_drain_pos])
|
||||||
|
|
||||||
# Remember the mid for the output
|
# Remember the mid for the output
|
||||||
mid_drain_offset = vector(nmos_drain_pos.x, self.output_pos.y)
|
mid_drain_offset = vector(nmos_drain_pos.x, self.output_pos.y)
|
||||||
|
|
@ -247,13 +247,13 @@ class pinv(pgate.pgate):
|
||||||
# This extends the output to the edge of the cell
|
# This extends the output to the edge of the cell
|
||||||
output_offset = mid_drain_offset.scale(0, 1) + vector(self.width, 0)
|
output_offset = mid_drain_offset.scale(0, 1) + vector(self.width, 0)
|
||||||
self.add_layout_pin_segment_center(text="Z",
|
self.add_layout_pin_segment_center(text="Z",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
start=mid_drain_offset,
|
start=mid_drain_offset,
|
||||||
end=output_offset)
|
end=output_offset)
|
||||||
else:
|
else:
|
||||||
# This leaves the output as an internal pin (min sized)
|
# This leaves the output as an internal pin (min sized)
|
||||||
self.add_layout_pin_rect_center(text="Z",
|
self.add_layout_pin_rect_center(text="Z",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=mid_drain_offset \
|
offset=mid_drain_offset \
|
||||||
+ vector(0.5 * self.m1_width, 0))
|
+ vector(0.5 * self.m1_width, 0))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -114,13 +114,13 @@ class pinvbuf(pgate.pgate):
|
||||||
z1_pin = self.inv1_inst.get_pin("Z")
|
z1_pin = self.inv1_inst.get_pin("Z")
|
||||||
a2_pin = self.inv2_inst.get_pin("A")
|
a2_pin = self.inv2_inst.get_pin("A")
|
||||||
mid_point = vector(z1_pin.cx(), a2_pin.cy())
|
mid_point = vector(z1_pin.cx(), a2_pin.cy())
|
||||||
self.add_path("metal1", [z1_pin.center(), mid_point, a2_pin.center()])
|
self.add_path("m1", [z1_pin.center(), mid_point, a2_pin.center()])
|
||||||
|
|
||||||
# inv2 Z to inv3 A
|
# inv2 Z to inv3 A
|
||||||
z2_pin = self.inv2_inst.get_pin("Z")
|
z2_pin = self.inv2_inst.get_pin("Z")
|
||||||
a3_pin = self.inv3_inst.get_pin("A")
|
a3_pin = self.inv3_inst.get_pin("A")
|
||||||
mid_point = vector(z2_pin.cx(), a3_pin.cy())
|
mid_point = vector(z2_pin.cx(), a3_pin.cy())
|
||||||
self.add_path("metal1", [z2_pin.center(), mid_point, a3_pin.center()])
|
self.add_path("m1", [z2_pin.center(), mid_point, a3_pin.center()])
|
||||||
|
|
||||||
# inv1 Z to inv4 A (up and over)
|
# inv1 Z to inv4 A (up and over)
|
||||||
z1_pin = self.inv1_inst.get_pin("Z")
|
z1_pin = self.inv1_inst.get_pin("Z")
|
||||||
|
|
@ -136,7 +136,7 @@ class pinvbuf(pgate.pgate):
|
||||||
# Continous vdd rail along with label.
|
# Continous vdd rail along with label.
|
||||||
vdd_pin = self.inv1_inst.get_pin("vdd")
|
vdd_pin = self.inv1_inst.get_pin("vdd")
|
||||||
self.add_layout_pin(text="vdd",
|
self.add_layout_pin(text="vdd",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=vdd_pin.ll().scale(0, 1),
|
offset=vdd_pin.ll().scale(0, 1),
|
||||||
width=self.width,
|
width=self.width,
|
||||||
height=vdd_pin.height())
|
height=vdd_pin.height())
|
||||||
|
|
@ -144,7 +144,7 @@ class pinvbuf(pgate.pgate):
|
||||||
# Continous vdd rail along with label.
|
# Continous vdd rail along with label.
|
||||||
gnd_pin = self.inv4_inst.get_pin("gnd")
|
gnd_pin = self.inv4_inst.get_pin("gnd")
|
||||||
self.add_layout_pin(text="gnd",
|
self.add_layout_pin(text="gnd",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=gnd_pin.ll().scale(0, 1),
|
offset=gnd_pin.ll().scale(0, 1),
|
||||||
width=self.width,
|
width=self.width,
|
||||||
height=gnd_pin.height())
|
height=gnd_pin.height())
|
||||||
|
|
@ -152,28 +152,28 @@ class pinvbuf(pgate.pgate):
|
||||||
# Continous gnd rail along with label.
|
# Continous gnd rail along with label.
|
||||||
gnd_pin = self.inv1_inst.get_pin("gnd")
|
gnd_pin = self.inv1_inst.get_pin("gnd")
|
||||||
self.add_layout_pin(text="gnd",
|
self.add_layout_pin(text="gnd",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=gnd_pin.ll().scale(0, 1),
|
offset=gnd_pin.ll().scale(0, 1),
|
||||||
width=self.width,
|
width=self.width,
|
||||||
height=vdd_pin.height())
|
height=vdd_pin.height())
|
||||||
|
|
||||||
z_pin = self.inv4_inst.get_pin("Z")
|
z_pin = self.inv4_inst.get_pin("Z")
|
||||||
self.add_layout_pin_rect_center(text="Z",
|
self.add_layout_pin_rect_center(text="Z",
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=z_pin.center())
|
offset=z_pin.center())
|
||||||
self.add_via_center(layers=self.m1_stack,
|
self.add_via_center(layers=self.m1_stack,
|
||||||
offset=z_pin.center())
|
offset=z_pin.center())
|
||||||
|
|
||||||
zb_pin = self.inv3_inst.get_pin("Z")
|
zb_pin = self.inv3_inst.get_pin("Z")
|
||||||
self.add_layout_pin_rect_center(text="Zb",
|
self.add_layout_pin_rect_center(text="Zb",
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=zb_pin.center())
|
offset=zb_pin.center())
|
||||||
self.add_via_center(layers=self.m1_stack,
|
self.add_via_center(layers=self.m1_stack,
|
||||||
offset=zb_pin.center())
|
offset=zb_pin.center())
|
||||||
|
|
||||||
a_pin = self.inv1_inst.get_pin("A")
|
a_pin = self.inv1_inst.get_pin("A")
|
||||||
self.add_layout_pin_rect_center(text="A",
|
self.add_layout_pin_rect_center(text="A",
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=a_pin.center())
|
offset=a_pin.center())
|
||||||
self.add_via_center(layers=self.m1_stack,
|
self.add_via_center(layers=self.m1_stack,
|
||||||
offset=a_pin.center())
|
offset=a_pin.center())
|
||||||
|
|
|
||||||
|
|
@ -99,8 +99,8 @@ class pnand2(pgate.pgate):
|
||||||
# Two PMOS devices and a well contact. Separation between each.
|
# Two PMOS devices and a well contact. Separation between each.
|
||||||
# Enclosure space on the sides.
|
# Enclosure space on the sides.
|
||||||
self.well_width = 2 * self.pmos.active_width + contact.active.width \
|
self.well_width = 2 * self.pmos.active_width + contact.active.width \
|
||||||
+ 2 * drc("active_to_body_active") \
|
+ 2 * self.active_space \
|
||||||
+ 2 * drc("well_enclosure_active")
|
+ 2 * self.well_enclose_active
|
||||||
|
|
||||||
self.width = self.well_width
|
self.width = self.well_width
|
||||||
# Height is an input parameter, so it is not recomputed.
|
# Height is an input parameter, so it is not recomputed.
|
||||||
|
|
@ -110,17 +110,17 @@ class pnand2(pgate.pgate):
|
||||||
extra_contact_space = max(-self.nmos.get_pin("D").by(), 0)
|
extra_contact_space = max(-self.nmos.get_pin("D").by(), 0)
|
||||||
# This is a poly-to-poly of a flipped cell
|
# This is a poly-to-poly of a flipped cell
|
||||||
self.top_bottom_space = max(0.5 * self.m1_width + self.m1_space + extra_contact_space,
|
self.top_bottom_space = max(0.5 * self.m1_width + self.m1_space + extra_contact_space,
|
||||||
drc("poly_extend_active"), self.poly_space)
|
self.poly_extend_active, self.poly_space)
|
||||||
|
|
||||||
def route_supply_rails(self):
|
def route_supply_rails(self):
|
||||||
""" Add vdd/gnd rails to the top and bottom. """
|
""" Add vdd/gnd rails to the top and bottom. """
|
||||||
self.add_layout_pin_rect_center(text="gnd",
|
self.add_layout_pin_rect_center(text="gnd",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=vector(0.5*self.width, 0),
|
offset=vector(0.5*self.width, 0),
|
||||||
width=self.width)
|
width=self.width)
|
||||||
|
|
||||||
self.add_layout_pin_rect_center(text="vdd",
|
self.add_layout_pin_rect_center(text="vdd",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=vector(0.5 * self.width, self.height),
|
offset=vector(0.5 * self.width, self.height),
|
||||||
width=self.width)
|
width=self.width)
|
||||||
|
|
||||||
|
|
@ -235,13 +235,13 @@ class pnand2(pgate.pgate):
|
||||||
offset=out_offset)
|
offset=out_offset)
|
||||||
|
|
||||||
# PMOS1 to mid-drain to NMOS2 drain
|
# PMOS1 to mid-drain to NMOS2 drain
|
||||||
self.add_path("metal2",
|
self.add_path("m2",
|
||||||
[top_pin_offset, mid1_offset, out_offset,
|
[top_pin_offset, mid1_offset, out_offset,
|
||||||
mid2_offset, bottom_pin_offset])
|
mid2_offset, bottom_pin_offset])
|
||||||
|
|
||||||
# This extends the output to the edge of the cell
|
# This extends the output to the edge of the cell
|
||||||
self.add_layout_pin_rect_center(text="Z",
|
self.add_layout_pin_rect_center(text="Z",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=out_offset,
|
offset=out_offset,
|
||||||
width=contact.m1m2.first_layer_height,
|
width=contact.m1m2.first_layer_height,
|
||||||
height=contact.m1m2.first_layer_width)
|
height=contact.m1m2.first_layer_width)
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,7 @@ class pnand3(pgate.pgate):
|
||||||
# Two PMOS devices and a well contact. Separation between each.
|
# Two PMOS devices and a well contact. Separation between each.
|
||||||
# Enclosure space on the sides.
|
# Enclosure space on the sides.
|
||||||
self.well_width = 3 * self.pmos.active_width + self.pmos.active_contact.width \
|
self.well_width = 3 * self.pmos.active_width + self.pmos.active_contact.width \
|
||||||
+ 2 * drc("active_to_body_active") + 2 * drc("well_enclosure_active") \
|
+ 2 * self.active_space + 2 * self.well_enclose_active \
|
||||||
- self.overlap_offset.x
|
- self.overlap_offset.x
|
||||||
self.width = self.well_width
|
self.width = self.well_width
|
||||||
# Height is an input parameter, so it is not recomputed.
|
# Height is an input parameter, so it is not recomputed.
|
||||||
|
|
@ -107,18 +107,18 @@ class pnand3(pgate.pgate):
|
||||||
# This is a poly-to-poly of a flipped cell
|
# This is a poly-to-poly of a flipped cell
|
||||||
self.top_bottom_space = max(0.5 * self.m1_width + self.m1_space \
|
self.top_bottom_space = max(0.5 * self.m1_width + self.m1_space \
|
||||||
+ extra_contact_space,
|
+ extra_contact_space,
|
||||||
drc("poly_extend_active"),
|
self.poly_extend_active,
|
||||||
self.poly_space)
|
self.poly_space)
|
||||||
|
|
||||||
def route_supply_rails(self):
|
def route_supply_rails(self):
|
||||||
""" Add vdd/gnd rails to the top and bottom. """
|
""" Add vdd/gnd rails to the top and bottom. """
|
||||||
self.add_layout_pin_rect_center(text="gnd",
|
self.add_layout_pin_rect_center(text="gnd",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=vector(0.5 * self.width, 0),
|
offset=vector(0.5 * self.width, 0),
|
||||||
width=self.width)
|
width=self.width)
|
||||||
|
|
||||||
self.add_layout_pin_rect_center(text="vdd",
|
self.add_layout_pin_rect_center(text="vdd",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=vector(0.5 * self.width, self.height),
|
offset=vector(0.5 * self.width, self.height),
|
||||||
width=self.width)
|
width=self.width)
|
||||||
|
|
||||||
|
|
@ -205,7 +205,7 @@ class pnand3(pgate.pgate):
|
||||||
self.m1_space + 0.5 *contact.poly.width + 0.5 * self.m1_width)
|
self.m1_space + 0.5 *contact.poly.width + 0.5 * self.m1_width)
|
||||||
|
|
||||||
active_spacing = max(self.m1_space,
|
active_spacing = max(self.m1_space,
|
||||||
0.5 * contact.poly.first_layer_width + drc("poly_to_active"))
|
0.5 * contact.poly.first_layer_width + self.poly_to_active)
|
||||||
inputC_yoffset = self.nmos3_pos.y + self.nmos.active_height + active_spacing
|
inputC_yoffset = self.nmos3_pos.y + self.nmos.active_height + active_spacing
|
||||||
self.route_input_gate(self.pmos3_inst,
|
self.route_input_gate(self.pmos3_inst,
|
||||||
self.nmos3_inst,
|
self.nmos3_inst,
|
||||||
|
|
@ -245,16 +245,16 @@ class pnand3(pgate.pgate):
|
||||||
offset=nmos3_pin.center())
|
offset=nmos3_pin.center())
|
||||||
|
|
||||||
# PMOS3 and NMOS3 are drain aligned
|
# PMOS3 and NMOS3 are drain aligned
|
||||||
self.add_path("metal2", [pmos3_pin.bc(), nmos3_pin.uc()])
|
self.add_path("m2", [pmos3_pin.bc(), nmos3_pin.uc()])
|
||||||
# Route in the A input track (top track)
|
# Route in the A input track (top track)
|
||||||
mid_offset = vector(nmos3_pin.center().x, self.inputA_yoffset)
|
mid_offset = vector(nmos3_pin.center().x, self.inputA_yoffset)
|
||||||
self.add_path("metal2", [pmos1_pin.bc(), mid_offset, nmos3_pin.uc()])
|
self.add_path("m2", [pmos1_pin.bc(), mid_offset, nmos3_pin.uc()])
|
||||||
|
|
||||||
# This extends the output to the edge of the cell
|
# This extends the output to the edge of the cell
|
||||||
self.add_via_center(layers=self.m1_stack,
|
self.add_via_center(layers=self.m1_stack,
|
||||||
offset=mid_offset)
|
offset=mid_offset)
|
||||||
self.add_layout_pin_rect_center(text="Z",
|
self.add_layout_pin_rect_center(text="Z",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=mid_offset,
|
offset=mid_offset,
|
||||||
width=contact.m1m2.first_layer_width,
|
width=contact.m1m2.first_layer_width,
|
||||||
height=contact.m1m2.first_layer_height)
|
height=contact.m1m2.first_layer_height)
|
||||||
|
|
|
||||||
|
|
@ -97,9 +97,8 @@ class pnor2(pgate.pgate):
|
||||||
# Enclosure space on the sides.
|
# Enclosure space on the sides.
|
||||||
self.well_width = 2 * self.pmos.active_width \
|
self.well_width = 2 * self.pmos.active_width \
|
||||||
+ self.pmos.active_contact.width \
|
+ self.pmos.active_contact.width \
|
||||||
+ 2 * drc("active_to_body_active") \
|
+ 2 * self.active_space \
|
||||||
+ 2 * drc("well_enclosure_active")
|
+ 2 * self.well_enclose_active
|
||||||
|
|
||||||
self.width = self.well_width
|
self.width = self.well_width
|
||||||
# Height is an input parameter, so it is not recomputed.
|
# Height is an input parameter, so it is not recomputed.
|
||||||
|
|
||||||
|
|
@ -108,18 +107,18 @@ class pnor2(pgate.pgate):
|
||||||
extra_contact_space = max(-self.nmos.get_pin("D").by(), 0)
|
extra_contact_space = max(-self.nmos.get_pin("D").by(), 0)
|
||||||
# This is a poly-to-poly of a flipped cell
|
# This is a poly-to-poly of a flipped cell
|
||||||
self.top_bottom_space = max(0.5 * self.m1_width + self.m1_space + extra_contact_space,
|
self.top_bottom_space = max(0.5 * self.m1_width + self.m1_space + extra_contact_space,
|
||||||
drc("poly_extend_active"),
|
self.poly_extend_active,
|
||||||
self.poly_space)
|
self.poly_space)
|
||||||
|
|
||||||
def route_supply_rails(self):
|
def route_supply_rails(self):
|
||||||
""" Add vdd/gnd rails to the top and bottom. """
|
""" Add vdd/gnd rails to the top and bottom. """
|
||||||
self.add_layout_pin_rect_center(text="gnd",
|
self.add_layout_pin_rect_center(text="gnd",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=vector(0.5 * self.width, 0),
|
offset=vector(0.5 * self.width, 0),
|
||||||
width=self.width)
|
width=self.width)
|
||||||
|
|
||||||
self.add_layout_pin_rect_center(text="vdd",
|
self.add_layout_pin_rect_center(text="vdd",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=vector(0.5 * self.width, self.height),
|
offset=vector(0.5 * self.width, self.height),
|
||||||
width=self.width)
|
width=self.width)
|
||||||
|
|
||||||
|
|
@ -226,15 +225,15 @@ class pnor2(pgate.pgate):
|
||||||
mid3_offset = mid2_offset + vector(self.m2_width, 0)
|
mid3_offset = mid2_offset + vector(self.m2_width, 0)
|
||||||
|
|
||||||
# PMOS1 to mid-drain to NMOS2 drain
|
# PMOS1 to mid-drain to NMOS2 drain
|
||||||
self.add_path("metal2",
|
self.add_path("m2",
|
||||||
[pmos_pin.bc(), mid2_offset, mid3_offset])
|
[pmos_pin.bc(), mid2_offset, mid3_offset])
|
||||||
self.add_path("metal2",
|
self.add_path("m2",
|
||||||
[nmos_pin.rc(), mid1_offset, mid2_offset])
|
[nmos_pin.rc(), mid1_offset, mid2_offset])
|
||||||
# This extends the output to the edge of the cell
|
# This extends the output to the edge of the cell
|
||||||
self.add_via_center(layers=self.m1_stack,
|
self.add_via_center(layers=self.m1_stack,
|
||||||
offset=mid3_offset)
|
offset=mid3_offset)
|
||||||
self.add_layout_pin_rect_center(text="Z",
|
self.add_layout_pin_rect_center(text="Z",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=mid3_offset,
|
offset=mid3_offset,
|
||||||
width=contact.m1m2.first_layer_height,
|
width=contact.m1m2.first_layer_height,
|
||||||
height=contact.m1m2.first_layer_width)
|
height=contact.m1m2.first_layer_width)
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ class precharge(design.design):
|
||||||
|
|
||||||
# Adds the rail across the width of the cell
|
# Adds the rail across the width of the cell
|
||||||
vdd_position = vector(0.5 * self.width, self.height)
|
vdd_position = vector(0.5 * self.width, self.height)
|
||||||
self.add_rect_center(layer="metal1",
|
self.add_rect_center(layer="m1",
|
||||||
offset=vdd_position,
|
offset=vdd_position,
|
||||||
width=self.width,
|
width=self.width,
|
||||||
height=self.m1_width)
|
height=self.m1_width)
|
||||||
|
|
@ -80,7 +80,7 @@ class precharge(design.design):
|
||||||
pmos_pin = self.upper_pmos2_inst.get_pin("S")
|
pmos_pin = self.upper_pmos2_inst.get_pin("S")
|
||||||
# center of vdd rail
|
# center of vdd rail
|
||||||
pmos_vdd_pos = vector(pmos_pin.cx(), vdd_position.y)
|
pmos_vdd_pos = vector(pmos_pin.cx(), vdd_position.y)
|
||||||
self.add_path("metal1", [pmos_pin.uc(), pmos_vdd_pos])
|
self.add_path("m1", [pmos_pin.uc(), pmos_vdd_pos])
|
||||||
|
|
||||||
# Add vdd pin above the transistor
|
# Add vdd pin above the transistor
|
||||||
self.add_power_pin("vdd", pmos_pin.center(), vertical=True)
|
self.add_power_pin("vdd", pmos_pin.center(), vertical=True)
|
||||||
|
|
@ -164,7 +164,7 @@ class precharge(design.design):
|
||||||
|
|
||||||
# adds the en rail on metal1
|
# adds the en rail on metal1
|
||||||
self.add_layout_pin_segment_center(text="en_bar",
|
self.add_layout_pin_segment_center(text="en_bar",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
start=offset.scale(0, 1),
|
start=offset.scale(0, 1),
|
||||||
end=offset.scale(0, 1) + vector(self.width, 0))
|
end=offset.scale(0, 1) + vector(self.width, 0))
|
||||||
|
|
||||||
|
|
@ -176,7 +176,7 @@ class precharge(design.design):
|
||||||
# adds the contact from active to metal1
|
# adds the contact from active to metal1
|
||||||
well_contact_pos = self.upper_pmos1_inst.get_pin("D").center().scale(1, 0) \
|
well_contact_pos = self.upper_pmos1_inst.get_pin("D").center().scale(1, 0) \
|
||||||
+ vector(0, self.upper_pmos1_inst.uy() + contact.well.height / 2 \
|
+ vector(0, self.upper_pmos1_inst.uy() + contact.well.height / 2 \
|
||||||
+ drc("well_extend_active"))
|
+ self.well_extend_active)
|
||||||
self.add_via_center(layers=self.active_stack,
|
self.add_via_center(layers=self.active_stack,
|
||||||
offset=well_contact_pos,
|
offset=well_contact_pos,
|
||||||
implant_type="n",
|
implant_type="n",
|
||||||
|
|
@ -200,7 +200,7 @@ class precharge(design.design):
|
||||||
offset = vector(self.bitcell.get_pin(self.bitcell_bl).cx(), 0) \
|
offset = vector(self.bitcell.get_pin(self.bitcell_bl).cx(), 0) \
|
||||||
- vector(0.5 * self.m2_width, 0)
|
- vector(0.5 * self.m2_width, 0)
|
||||||
self.bl_pin = self.add_layout_pin(text="bl",
|
self.bl_pin = self.add_layout_pin(text="bl",
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=offset,
|
offset=offset,
|
||||||
height=self.height)
|
height=self.height)
|
||||||
|
|
||||||
|
|
@ -208,7 +208,7 @@ class precharge(design.design):
|
||||||
offset = vector(self.bitcell.get_pin(self.bitcell_br).cx(), 0) \
|
offset = vector(self.bitcell.get_pin(self.bitcell_br).cx(), 0) \
|
||||||
- vector(0.5 * self.m2_width, 0)
|
- vector(0.5 * self.m2_width, 0)
|
||||||
self.br_pin = self.add_layout_pin(text="br",
|
self.br_pin = self.add_layout_pin(text="br",
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=offset,
|
offset=offset,
|
||||||
height=self.height)
|
height=self.height)
|
||||||
|
|
||||||
|
|
@ -258,7 +258,7 @@ class precharge(design.design):
|
||||||
left_pos = vector(min(pmos_pin.cx(), bit_pin.cx()), pmos_pin.cy())
|
left_pos = vector(min(pmos_pin.cx(), bit_pin.cx()), pmos_pin.cy())
|
||||||
right_pos = vector(max(pmos_pin.cx(), bit_pin.cx()), pmos_pin.cy())
|
right_pos = vector(max(pmos_pin.cx(), bit_pin.cx()), pmos_pin.cy())
|
||||||
|
|
||||||
self.add_path("metal1", [left_pos, right_pos] )
|
self.add_path("m1", [left_pos, right_pos] )
|
||||||
|
|
||||||
def connect_pmos_m2(self, pmos_pin, bit_pin):
|
def connect_pmos_m2(self, pmos_pin, bit_pin):
|
||||||
"""
|
"""
|
||||||
|
|
@ -268,7 +268,7 @@ class precharge(design.design):
|
||||||
left_pos = vector(min(pmos_pin.cx(), bit_pin.cx()), pmos_pin.cy())
|
left_pos = vector(min(pmos_pin.cx(), bit_pin.cx()), pmos_pin.cy())
|
||||||
right_pos = vector(max(pmos_pin.cx(), bit_pin.cx()), pmos_pin.cy())
|
right_pos = vector(max(pmos_pin.cx(), bit_pin.cx()), pmos_pin.cy())
|
||||||
|
|
||||||
self.add_path("metal2", [left_pos, right_pos], self.bl_contact.height)
|
self.add_path("m2", [left_pos, right_pos], self.bl_contact.height)
|
||||||
|
|
||||||
def get_en_cin(self):
|
def get_en_cin(self):
|
||||||
"""Get the relative capacitance of the enable in the precharge cell"""
|
"""Get the relative capacitance of the enable in the precharge cell"""
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ class ptristate_inv(pgate.pgate):
|
||||||
|
|
||||||
# Two PMOS devices and a well contact. Separation between each.
|
# Two PMOS devices and a well contact. Separation between each.
|
||||||
# Enclosure space on the sides.
|
# Enclosure space on the sides.
|
||||||
self.well_width = 2 * self.pmos.active_width + drc("well_enclosure_active")
|
self.well_width = 2 * self.pmos.active_width + self.well_enclose_active
|
||||||
|
|
||||||
# Add an extra space because we route the output on the right of the S/D
|
# Add an extra space because we route the output on the right of the S/D
|
||||||
self.width = self.well_width + 0.5 * self.m1_space
|
self.width = self.well_width + 0.5 * self.m1_space
|
||||||
|
|
@ -101,12 +101,12 @@ class ptristate_inv(pgate.pgate):
|
||||||
def route_supply_rails(self):
|
def route_supply_rails(self):
|
||||||
""" Add vdd/gnd rails to the top and bottom. """
|
""" Add vdd/gnd rails to the top and bottom. """
|
||||||
self.add_layout_pin_rect_center(text="gnd",
|
self.add_layout_pin_rect_center(text="gnd",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=vector(0.5 * self.width, 0),
|
offset=vector(0.5 * self.width, 0),
|
||||||
width=self.width)
|
width=self.width)
|
||||||
|
|
||||||
self.add_layout_pin_rect_center(text="vdd",
|
self.add_layout_pin_rect_center(text="vdd",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=vector(0.5 * self.width, self.height),
|
offset=vector(0.5 * self.width, self.height),
|
||||||
width=self.width)
|
width=self.width)
|
||||||
|
|
||||||
|
|
@ -181,7 +181,7 @@ class ptristate_inv(pgate.pgate):
|
||||||
pmos_drain_pos = pmos_drain_pin.ur()
|
pmos_drain_pos = pmos_drain_pin.ur()
|
||||||
|
|
||||||
self.add_layout_pin(text="out",
|
self.add_layout_pin(text="out",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=nmos_drain_pos,
|
offset=nmos_drain_pos,
|
||||||
height=pmos_drain_pos.y - nmos_drain_pos.y)
|
height=pmos_drain_pos.y - nmos_drain_pos.y)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -91,8 +91,8 @@ class ptx(design.design):
|
||||||
# " ".join(self.pins)))
|
# " ".join(self.pins)))
|
||||||
# Just make a guess since these will actually
|
# Just make a guess since these will actually
|
||||||
# be decided in the layout later.
|
# be decided in the layout later.
|
||||||
area_sd = 2.5 * drc("minwidth_poly") * self.tx_width
|
area_sd = 2.5 * self.poly_width * self.tx_width
|
||||||
perimeter_sd = 2 * drc("minwidth_poly") + 2 * self.tx_width
|
perimeter_sd = 2 * self.poly_width + 2 * self.tx_width
|
||||||
main_str = "M{{0}} {{1}} {0} m={1} w={2}u l={3}u ".format(spice[self.tx_type],
|
main_str = "M{{0}} {{1}} {0} m={1} w={2}u l={3}u ".format(spice[self.tx_type],
|
||||||
self.mults,
|
self.mults,
|
||||||
self.tx_width,
|
self.tx_width,
|
||||||
|
|
@ -136,7 +136,7 @@ class ptx(design.design):
|
||||||
self.contact_pitch = 2 * self.contact_to_gate + self.contact_width + self.poly_width
|
self.contact_pitch = 2 * self.contact_to_gate + self.contact_width + self.poly_width
|
||||||
|
|
||||||
# The enclosure of an active contact. Not sure about second term.
|
# The enclosure of an active contact. Not sure about second term.
|
||||||
active_enclose_contact = max(drc("active_enclosure_contact"),
|
active_enclose_contact = max(self.active_enclose_contact,
|
||||||
(self.active_width - self.contact_width) / 2)
|
(self.active_width - self.contact_width) / 2)
|
||||||
|
|
||||||
# This is the distance from the edge of poly to the contacted end of active
|
# This is the distance from the edge of poly to the contacted end of active
|
||||||
|
|
@ -180,11 +180,11 @@ class ptx(design.design):
|
||||||
|
|
||||||
|
|
||||||
# Min area results are just flagged for now.
|
# Min area results are just flagged for now.
|
||||||
debug.check(self.active_width * self.active_height >= drc("minarea_active"),
|
debug.check(self.active_width * self.active_height >= self.minarea_active,
|
||||||
"Minimum active area violated.")
|
"Minimum active area violated.")
|
||||||
# We do not want to increase the poly dimensions to fix
|
# We do not want to increase the poly dimensions to fix
|
||||||
# an area problem as it would cause an LVS issue.
|
# an area problem as it would cause an LVS issue.
|
||||||
debug.check(self.poly_width * self.poly_height >= drc("minarea_poly"),
|
debug.check(self.poly_width * self.poly_height >= self.minarea_poly,
|
||||||
"Minimum poly area violated.")
|
"Minimum poly area violated.")
|
||||||
|
|
||||||
def connect_fingered_poly(self, poly_positions):
|
def connect_fingered_poly(self, poly_positions):
|
||||||
|
|
@ -219,7 +219,7 @@ class ptx(design.design):
|
||||||
layer="poly",
|
layer="poly",
|
||||||
offset=poly_offset,
|
offset=poly_offset,
|
||||||
width=poly_width,
|
width=poly_width,
|
||||||
height=drc("minwidth_poly"))
|
height=self.poly_width)
|
||||||
|
|
||||||
|
|
||||||
def connect_fingered_active(self, drain_positions, source_positions):
|
def connect_fingered_active(self, drain_positions, source_positions):
|
||||||
|
|
@ -249,12 +249,12 @@ class ptx(design.design):
|
||||||
self.remove_layout_pin("S") # remove the individual connections
|
self.remove_layout_pin("S") # remove the individual connections
|
||||||
# Add each vertical segment
|
# Add each vertical segment
|
||||||
for a in source_positions:
|
for a in source_positions:
|
||||||
self.add_path(("metal1"),
|
self.add_path(("m1"),
|
||||||
[a, a + pin_offset.scale(source_dir,
|
[a, a + pin_offset.scale(source_dir,
|
||||||
source_dir)])
|
source_dir)])
|
||||||
# Add a single horizontal pin
|
# Add a single horizontal pin
|
||||||
self.add_layout_pin_segment_center(text="S",
|
self.add_layout_pin_segment_center(text="S",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
start=source_positions[0] + source_offset - end_offset,
|
start=source_positions[0] + source_offset - end_offset,
|
||||||
end=source_positions[-1] + source_offset + end_offset)
|
end=source_positions[-1] + source_offset + end_offset)
|
||||||
|
|
||||||
|
|
@ -263,10 +263,10 @@ class ptx(design.design):
|
||||||
self.remove_layout_pin("D") # remove the individual connections
|
self.remove_layout_pin("D") # remove the individual connections
|
||||||
# Add each vertical segment
|
# Add each vertical segment
|
||||||
for a in drain_positions:
|
for a in drain_positions:
|
||||||
self.add_path(("metal1"), [a,a+drain_offset])
|
self.add_path(("m1"), [a,a+drain_offset])
|
||||||
# Add a single horizontal pin
|
# Add a single horizontal pin
|
||||||
self.add_layout_pin_segment_center(text="D",
|
self.add_layout_pin_segment_center(text="D",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
start=drain_positions[0] + drain_offset - end_offset,
|
start=drain_positions[0] + drain_offset - end_offset,
|
||||||
end=drain_positions[-1] + drain_offset + end_offset)
|
end=drain_positions[-1] + drain_offset + end_offset)
|
||||||
|
|
||||||
|
|
@ -313,7 +313,7 @@ class ptx(design.design):
|
||||||
height=self.active_height)
|
height=self.active_height)
|
||||||
# If the implant must enclose the active, shift offset
|
# If the implant must enclose the active, shift offset
|
||||||
# and increase width/height
|
# and increase width/height
|
||||||
enclose_width = drc("implant_enclosure_active")
|
enclose_width = self.implant_enclose_active
|
||||||
enclose_offset = [enclose_width] * 2
|
enclose_offset = [enclose_width] * 2
|
||||||
self.add_rect(layer="{}implant".format(self.implant_type),
|
self.add_rect(layer="{}implant".format(self.implant_type),
|
||||||
offset=self.active_offset - enclose_offset,
|
offset=self.active_offset - enclose_offset,
|
||||||
|
|
@ -380,7 +380,7 @@ class ptx(design.design):
|
||||||
implant_type=self.implant_type,
|
implant_type=self.implant_type,
|
||||||
well_type=self.well_type)
|
well_type=self.well_type)
|
||||||
self.add_layout_pin_rect_center(text="S",
|
self.add_layout_pin_rect_center(text="S",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=pos,
|
offset=pos,
|
||||||
width=contact.mod.second_layer_width,
|
width=contact.mod.second_layer_width,
|
||||||
height=contact.mod.second_layer_height)
|
height=contact.mod.second_layer_height)
|
||||||
|
|
@ -394,7 +394,7 @@ class ptx(design.design):
|
||||||
implant_type=self.implant_type,
|
implant_type=self.implant_type,
|
||||||
well_type=self.well_type)
|
well_type=self.well_type)
|
||||||
self.add_layout_pin_rect_center(text="D",
|
self.add_layout_pin_rect_center(text="D",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=pos,
|
offset=pos,
|
||||||
width=contact.mod.second_layer_width,
|
width=contact.mod.second_layer_width,
|
||||||
height=contact.mod.second_layer_height)
|
height=contact.mod.second_layer_height)
|
||||||
|
|
|
||||||
|
|
@ -131,26 +131,26 @@ class pwrite_driver(design.design):
|
||||||
bl_xoffset = left_x
|
bl_xoffset = left_x
|
||||||
bl_out=vector(bl_xoffset, self.height)
|
bl_out=vector(bl_xoffset, self.height)
|
||||||
bl_in=self.bl_inst.get_pin("out").center()
|
bl_in=self.bl_inst.get_pin("out").center()
|
||||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
self.add_via_center(layers=self.m1_stack,
|
||||||
offset=bl_in)
|
offset=bl_in)
|
||||||
|
|
||||||
bl_mid = vector(bl_out.x,bl_in.y)
|
bl_mid = vector(bl_out.x,bl_in.y)
|
||||||
self.add_path("metal2", [bl_in, bl_mid, bl_out])
|
self.add_path("m2", [bl_in, bl_mid, bl_out])
|
||||||
|
|
||||||
self.add_layout_pin_rect_center(text="bl",
|
self.add_layout_pin_rect_center(text="bl",
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=bl_out)
|
offset=bl_out)
|
||||||
|
|
||||||
br_xoffset = right_x
|
br_xoffset = right_x
|
||||||
br_out=vector(br_xoffset, self.height)
|
br_out=vector(br_xoffset, self.height)
|
||||||
br_in=self.br_inst.get_pin("out").center()
|
br_in=self.br_inst.get_pin("out").center()
|
||||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
self.add_via_center(layers=self.m1_stack,
|
||||||
offset=br_in)
|
offset=br_in)
|
||||||
|
|
||||||
br_mid = vector(br_out.x,br_in.y)
|
br_mid = vector(br_out.x,br_in.y)
|
||||||
self.add_path("metal2", [br_in, br_mid, br_out])
|
self.add_path("m2", [br_in, br_mid, br_out])
|
||||||
self.add_layout_pin_rect_center(text="br",
|
self.add_layout_pin_rect_center(text="br",
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=br_out)
|
offset=br_out)
|
||||||
|
|
||||||
#br_xoffset = b.get_pin("br".cx()
|
#br_xoffset = b.get_pin("br".cx()
|
||||||
|
|
@ -162,19 +162,19 @@ class pwrite_driver(design.design):
|
||||||
track_xoff = self.get_m2_track(1)
|
track_xoff = self.get_m2_track(1)
|
||||||
|
|
||||||
din_loc = self.din_inst.get_pin("A").center()
|
din_loc = self.din_inst.get_pin("A").center()
|
||||||
self.add_via_stack("metal1", "metal2", din_loc)
|
self.add_via_stack("m1", "m2", din_loc)
|
||||||
din_track = vector(track_xoff,din_loc.y)
|
din_track = vector(track_xoff,din_loc.y)
|
||||||
|
|
||||||
br_in = self.br_inst.get_pin("in").center()
|
br_in = self.br_inst.get_pin("in").center()
|
||||||
self.add_via_stack("metal1", "metal2", br_in)
|
self.add_via_stack("m1", "m2", br_in)
|
||||||
br_track = vector(track_xoff,br_in.y)
|
br_track = vector(track_xoff,br_in.y)
|
||||||
|
|
||||||
din_in = vector(track_xoff,0)
|
din_in = vector(track_xoff,0)
|
||||||
|
|
||||||
self.add_path("metal2", [din_in, din_track, din_loc, din_track, br_track, br_in])
|
self.add_path("m2", [din_in, din_track, din_loc, din_track, br_track, br_in])
|
||||||
|
|
||||||
self.add_layout_pin_rect_center(text="din",
|
self.add_layout_pin_rect_center(text="din",
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=din_in)
|
offset=din_in)
|
||||||
|
|
||||||
def route_din_bar(self):
|
def route_din_bar(self):
|
||||||
|
|
@ -183,19 +183,19 @@ class pwrite_driver(design.design):
|
||||||
track_xoff = self.get_m4_track(self.din_bar_track)
|
track_xoff = self.get_m4_track(self.din_bar_track)
|
||||||
|
|
||||||
din_bar_in = self.din_inst.get_pin("Z").center()
|
din_bar_in = self.din_inst.get_pin("Z").center()
|
||||||
self.add_via_stack("metal1", "metal3", din_bar_in)
|
self.add_via_stack("m1", "m3", din_bar_in)
|
||||||
din_bar_track = vector(track_xoff,din_bar_in.y)
|
din_bar_track = vector(track_xoff,din_bar_in.y)
|
||||||
|
|
||||||
bl_in = self.bl_inst.get_pin("in").center()
|
bl_in = self.bl_inst.get_pin("in").center()
|
||||||
self.add_via_stack("metal1", "metal3", bl_in)
|
self.add_via_stack("m1", "m3", bl_in)
|
||||||
bl_track = vector(track_xoff,bl_in.y)
|
bl_track = vector(track_xoff,bl_in.y)
|
||||||
|
|
||||||
din_in = vector(track_xoff,0)
|
din_in = vector(track_xoff,0)
|
||||||
|
|
||||||
self.add_wire(("metal3","via3","metal4"), [din_bar_in, din_bar_track, bl_track, bl_in])
|
self.add_wire(self.m3_stack, [din_bar_in, din_bar_track, bl_track, bl_in])
|
||||||
|
|
||||||
self.add_layout_pin_rect_center(text="din",
|
self.add_layout_pin_rect_center(text="din",
|
||||||
layer="metal4",
|
layer="m4",
|
||||||
offset=din_in)
|
offset=din_in)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -206,22 +206,22 @@ class pwrite_driver(design.design):
|
||||||
# This M2 pitch is a hack since the A and Z pins align horizontally
|
# This M2 pitch is a hack since the A and Z pins align horizontally
|
||||||
en_bar_loc = self.en_inst.get_pin("Z").uc()
|
en_bar_loc = self.en_inst.get_pin("Z").uc()
|
||||||
en_bar_track = vector(track_xoff, en_bar_loc.y)
|
en_bar_track = vector(track_xoff, en_bar_loc.y)
|
||||||
self.add_via_stack("metal1", "metal3", en_bar_loc)
|
self.add_via_stack("m1", "m3", en_bar_loc)
|
||||||
|
|
||||||
# This is a U route to the right down then left
|
# This is a U route to the right down then left
|
||||||
bl_en_loc = self.bl_inst.get_pin("en_bar").center()
|
bl_en_loc = self.bl_inst.get_pin("en_bar").center()
|
||||||
bl_en_track = vector(track_xoff, bl_en_loc.y)
|
bl_en_track = vector(track_xoff, bl_en_loc.y)
|
||||||
self.add_via_stack("metal1", "metal3", bl_en_loc)
|
self.add_via_stack("m1", "m3", bl_en_loc)
|
||||||
br_en_loc = self.br_inst.get_pin("en_bar").center()
|
br_en_loc = self.br_inst.get_pin("en_bar").center()
|
||||||
br_en_track = vector(track_xoff, bl_en_loc.y)
|
br_en_track = vector(track_xoff, bl_en_loc.y)
|
||||||
self.add_via_stack("metal1", "metal3", br_en_loc)
|
self.add_via_stack("m1", "m3", br_en_loc)
|
||||||
|
|
||||||
|
|
||||||
# L shape
|
# L shape
|
||||||
self.add_wire(("metal3","via3","metal4"),
|
self.add_wire(self.m3_stack,
|
||||||
[en_bar_loc, en_bar_track, bl_en_track])
|
[en_bar_loc, en_bar_track, bl_en_track])
|
||||||
# U shape
|
# U shape
|
||||||
self.add_wire(("metal3","via3","metal4"),
|
self.add_wire(self.m3_stack,
|
||||||
[bl_en_loc, bl_en_track, br_en_track, br_en_loc])
|
[bl_en_loc, bl_en_track, br_en_track, br_en_loc])
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -233,30 +233,30 @@ class pwrite_driver(design.design):
|
||||||
# The en pin will be over the vdd rail
|
# The en pin will be over the vdd rail
|
||||||
vdd_yloc = self.en_inst.get_pin("vdd").cy()
|
vdd_yloc = self.en_inst.get_pin("vdd").cy()
|
||||||
self.add_layout_pin_segment_center(text="en",
|
self.add_layout_pin_segment_center(text="en",
|
||||||
layer="metal3",
|
layer="m3",
|
||||||
start=vector(0,vdd_yloc),
|
start=vector(0,vdd_yloc),
|
||||||
end=vector(self.width,vdd_yloc))
|
end=vector(self.width,vdd_yloc))
|
||||||
|
|
||||||
en_loc = self.en_inst.get_pin("A").center()
|
en_loc = self.en_inst.get_pin("A").center()
|
||||||
en_rail = vector(en_loc.x, vdd_yloc)
|
en_rail = vector(en_loc.x, vdd_yloc)
|
||||||
self.add_via_stack("metal1", "metal2", en_loc)
|
self.add_via_stack("m1", "m2", en_loc)
|
||||||
self.add_path("metal2", [en_loc, en_rail])
|
self.add_path("m2", [en_loc, en_rail])
|
||||||
self.add_via_stack("metal2", "metal3", en_rail)
|
self.add_via_stack("m2", "m3", en_rail)
|
||||||
|
|
||||||
# Start point in the track on the pin rail
|
# Start point in the track on the pin rail
|
||||||
en_track = vector(track_xoff, vdd_yloc)
|
en_track = vector(track_xoff, vdd_yloc)
|
||||||
self.add_via_stack("metal3", "metal4", en_track)
|
self.add_via_stack("m3", "m4", en_track)
|
||||||
|
|
||||||
# This is a U route to the right down then left
|
# This is a U route to the right down then left
|
||||||
bl_en_loc = self.bl_inst.get_pin("en").center()
|
bl_en_loc = self.bl_inst.get_pin("en").center()
|
||||||
bl_en_track = vector(track_xoff, bl_en_loc.y)
|
bl_en_track = vector(track_xoff, bl_en_loc.y)
|
||||||
self.add_via_stack("metal1", "metal3", bl_en_loc)
|
self.add_via_stack("m1", "m3", bl_en_loc)
|
||||||
br_en_loc = self.br_inst.get_pin("en").center()
|
br_en_loc = self.br_inst.get_pin("en").center()
|
||||||
br_en_track = vector(track_xoff, bl_en_loc.y)
|
br_en_track = vector(track_xoff, bl_en_loc.y)
|
||||||
self.add_via_stack("metal1", "metal3", br_en_loc)
|
self.add_via_stack("m1", "m3", br_en_loc)
|
||||||
|
|
||||||
# U shape
|
# U shape
|
||||||
self.add_wire(("metal3","via3","metal4"),
|
self.add_wire(self.m3_stack,
|
||||||
[en_track, bl_en_track, bl_en_loc, bl_en_track, br_en_track, br_en_loc])
|
[en_track, bl_en_track, bl_en_loc, bl_en_track, br_en_track, br_en_loc])
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -284,7 +284,7 @@ class pwrite_driver(design.design):
|
||||||
# Continous vdd rail along with label.
|
# Continous vdd rail along with label.
|
||||||
vdd_pin=inst.get_pin("vdd")
|
vdd_pin=inst.get_pin("vdd")
|
||||||
self.add_layout_pin(text="vdd",
|
self.add_layout_pin(text="vdd",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=vdd_pin.ll().scale(0,1),
|
offset=vdd_pin.ll().scale(0,1),
|
||||||
width=self.width,
|
width=self.width,
|
||||||
height=vdd_pin.height())
|
height=vdd_pin.height())
|
||||||
|
|
@ -292,7 +292,7 @@ class pwrite_driver(design.design):
|
||||||
# Continous gnd rail along with label.
|
# Continous gnd rail along with label.
|
||||||
gnd_pin=inst.get_pin("gnd")
|
gnd_pin=inst.get_pin("gnd")
|
||||||
self.add_layout_pin(text="gnd",
|
self.add_layout_pin(text="gnd",
|
||||||
layer="metal1",
|
layer="m1",
|
||||||
offset=gnd_pin.ll().scale(0,1),
|
offset=gnd_pin.ll().scale(0,1),
|
||||||
width=self.width,
|
width=self.width,
|
||||||
height=vdd_pin.height())
|
height=vdd_pin.height())
|
||||||
|
|
|
||||||
|
|
@ -65,21 +65,21 @@ class single_level_column_mux(pgate.pgate):
|
||||||
|
|
||||||
# bl and br
|
# bl and br
|
||||||
self.add_layout_pin(text="bl",
|
self.add_layout_pin(text="bl",
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=bl_pos + vector(0, self.height - self.pin_height),
|
offset=bl_pos + vector(0, self.height - self.pin_height),
|
||||||
height=self.pin_height)
|
height=self.pin_height)
|
||||||
self.add_layout_pin(text="br",
|
self.add_layout_pin(text="br",
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=br_pos + vector(0, self.height - self.pin_height),
|
offset=br_pos + vector(0, self.height - self.pin_height),
|
||||||
height=self.pin_height)
|
height=self.pin_height)
|
||||||
|
|
||||||
# bl_out and br_out
|
# bl_out and br_out
|
||||||
self.add_layout_pin(text="bl_out",
|
self.add_layout_pin(text="bl_out",
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=bl_pos,
|
offset=bl_pos,
|
||||||
height=self.pin_height)
|
height=self.pin_height)
|
||||||
self.add_layout_pin(text="br_out",
|
self.add_layout_pin(text="br_out",
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=br_pos,
|
offset=br_pos,
|
||||||
height=self.pin_height)
|
height=self.pin_height)
|
||||||
|
|
||||||
|
|
@ -141,7 +141,7 @@ class single_level_column_mux(pgate.pgate):
|
||||||
|
|
||||||
# bl -> nmos_upper/D on metal1
|
# bl -> nmos_upper/D on metal1
|
||||||
# bl_out -> nmos_upper/S on metal2
|
# bl_out -> nmos_upper/S on metal2
|
||||||
self.add_path("metal1",
|
self.add_path("m1",
|
||||||
[bl_pin.ll(), vector(nmos_upper_d_pin.cx(), bl_pin.by()),
|
[bl_pin.ll(), vector(nmos_upper_d_pin.cx(), bl_pin.by()),
|
||||||
nmos_upper_d_pin.center()])
|
nmos_upper_d_pin.center()])
|
||||||
# halfway up, move over
|
# halfway up, move over
|
||||||
|
|
@ -149,12 +149,12 @@ class single_level_column_mux(pgate.pgate):
|
||||||
+ nmos_upper_s_pin.bc().scale(0, 0.4)
|
+ nmos_upper_s_pin.bc().scale(0, 0.4)
|
||||||
mid2 = bl_out_pin.uc().scale(0, 0.4) \
|
mid2 = bl_out_pin.uc().scale(0, 0.4) \
|
||||||
+ nmos_upper_s_pin.bc().scale(1, 0.4)
|
+ nmos_upper_s_pin.bc().scale(1, 0.4)
|
||||||
self.add_path("metal2",
|
self.add_path("m2",
|
||||||
[bl_out_pin.uc(), mid1, mid2, nmos_upper_s_pin.bc()])
|
[bl_out_pin.uc(), mid1, mid2, nmos_upper_s_pin.bc()])
|
||||||
|
|
||||||
# br -> nmos_lower/D on metal2
|
# br -> nmos_lower/D on metal2
|
||||||
# br_out -> nmos_lower/S on metal1
|
# br_out -> nmos_lower/S on metal1
|
||||||
self.add_path("metal1",
|
self.add_path("m1",
|
||||||
[br_out_pin.uc(),
|
[br_out_pin.uc(),
|
||||||
vector(nmos_lower_s_pin.cx(), br_out_pin.uy()),
|
vector(nmos_lower_s_pin.cx(), br_out_pin.uy()),
|
||||||
nmos_lower_s_pin.center()])
|
nmos_lower_s_pin.center()])
|
||||||
|
|
@ -163,7 +163,7 @@ class single_level_column_mux(pgate.pgate):
|
||||||
+ nmos_lower_d_pin.uc().scale(0,0.5)
|
+ nmos_lower_d_pin.uc().scale(0,0.5)
|
||||||
mid2 = br_pin.bc().scale(0,0.5) \
|
mid2 = br_pin.bc().scale(0,0.5) \
|
||||||
+ nmos_lower_d_pin.uc().scale(1,0.5)
|
+ nmos_lower_d_pin.uc().scale(1,0.5)
|
||||||
self.add_path("metal2",
|
self.add_path("m2",
|
||||||
[br_pin.bc(), mid1, mid2, nmos_lower_d_pin.uc()])
|
[br_pin.bc(), mid1, mid2, nmos_lower_d_pin.uc()])
|
||||||
|
|
||||||
def add_wells(self):
|
def add_wells(self):
|
||||||
|
|
@ -186,7 +186,7 @@ class single_level_column_mux(pgate.pgate):
|
||||||
self.add_via_center(layers=self.m2_stack,
|
self.add_via_center(layers=self.m2_stack,
|
||||||
offset=active_pos)
|
offset=active_pos)
|
||||||
self.add_layout_pin_rect_center(text="gnd",
|
self.add_layout_pin_rect_center(text="gnd",
|
||||||
layer="metal3",
|
layer="m3",
|
||||||
offset=active_pos)
|
offset=active_pos)
|
||||||
|
|
||||||
# Add well enclosure over all the tx and contact
|
# Add well enclosure over all the tx and contact
|
||||||
|
|
|
||||||
|
|
@ -261,18 +261,18 @@ class sram_1bank(sram_base):
|
||||||
|
|
||||||
# This is the steiner point where the net branches out
|
# This is the steiner point where the net branches out
|
||||||
clk_steiner_pos = vector(mid1_pos.x, control_clk_buf_pos.y)
|
clk_steiner_pos = vector(mid1_pos.x, control_clk_buf_pos.y)
|
||||||
self.add_path("metal1", [control_clk_buf_pos, clk_steiner_pos])
|
self.add_path("m1", [control_clk_buf_pos, clk_steiner_pos])
|
||||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
self.add_via_center(layers=self.m1_stack,
|
||||||
offset=clk_steiner_pos)
|
offset=clk_steiner_pos)
|
||||||
|
|
||||||
# Note, the via to the control logic is taken care of above
|
# Note, the via to the control logic is taken care of above
|
||||||
self.add_wire(("metal3","via2","metal2"),[row_addr_clk_pos, mid1_pos, clk_steiner_pos])
|
self.add_wire(("m3","via2","m2"),[row_addr_clk_pos, mid1_pos, clk_steiner_pos])
|
||||||
|
|
||||||
if self.col_addr_dff:
|
if self.col_addr_dff:
|
||||||
dff_clk_pin = self.col_addr_dff_insts[port].get_pin("clk")
|
dff_clk_pin = self.col_addr_dff_insts[port].get_pin("clk")
|
||||||
dff_clk_pos = dff_clk_pin.center()
|
dff_clk_pos = dff_clk_pin.center()
|
||||||
mid_pos = vector(clk_steiner_pos.x, dff_clk_pos.y)
|
mid_pos = vector(clk_steiner_pos.x, dff_clk_pos.y)
|
||||||
self.add_wire(("metal3","via2","metal2"),[dff_clk_pos, mid_pos, clk_steiner_pos])
|
self.add_wire(("m3","via2","m2"),[dff_clk_pos, mid_pos, clk_steiner_pos])
|
||||||
|
|
||||||
if port in self.write_ports:
|
if port in self.write_ports:
|
||||||
data_dff_clk_pin = self.data_dff_insts[port].get_pin("clk")
|
data_dff_clk_pin = self.data_dff_insts[port].get_pin("clk")
|
||||||
|
|
@ -280,8 +280,8 @@ class sram_1bank(sram_base):
|
||||||
mid_pos = vector(clk_steiner_pos.x, data_dff_clk_pos.y)
|
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
|
# In some designs, the steiner via will be too close to the mid_pos via
|
||||||
# so make the wire as wide as the contacts
|
# so make the wire as wide as the contacts
|
||||||
self.add_path("metal2",[mid_pos, clk_steiner_pos], width=max(m2m3.width,m2m3.height))
|
self.add_path("m2",[mid_pos, clk_steiner_pos], width=max(m2m3.width,m2m3.height))
|
||||||
self.add_wire(("metal3","via2","metal2"),[data_dff_clk_pos, mid_pos, clk_steiner_pos])
|
self.add_wire(("m3","via2","m2"),[data_dff_clk_pos, mid_pos, clk_steiner_pos])
|
||||||
|
|
||||||
if self.write_size:
|
if self.write_size:
|
||||||
wmask_dff_clk_pin = self.wmask_dff_insts[port].get_pin("clk")
|
wmask_dff_clk_pin = self.wmask_dff_insts[port].get_pin("clk")
|
||||||
|
|
@ -289,8 +289,8 @@ class sram_1bank(sram_base):
|
||||||
mid_pos = vector(clk_steiner_pos.x, wmask_dff_clk_pos.y)
|
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
|
# In some designs, the steiner via will be too close to the mid_pos via
|
||||||
# so make the wire as wide as the contacts
|
# so make the wire as wide as the contacts
|
||||||
self.add_path("metal2", [mid_pos, clk_steiner_pos], width=max(m2m3.width, m2m3.height))
|
self.add_path("m2", [mid_pos, clk_steiner_pos], width=max(m2m3.width, m2m3.height))
|
||||||
self.add_wire(("metal3", "via2", "metal2"), [wmask_dff_clk_pos, mid_pos, clk_steiner_pos])
|
self.add_wire(("m3", "via2", "m2"), [wmask_dff_clk_pos, mid_pos, clk_steiner_pos])
|
||||||
|
|
||||||
|
|
||||||
def route_control_logic(self):
|
def route_control_logic(self):
|
||||||
|
|
@ -323,8 +323,8 @@ class sram_1bank(sram_base):
|
||||||
flop_pos = flop_pin.center()
|
flop_pos = flop_pin.center()
|
||||||
bank_pos = bank_pin.center()
|
bank_pos = bank_pin.center()
|
||||||
mid_pos = vector(bank_pos.x,flop_pos.y)
|
mid_pos = vector(bank_pos.x,flop_pos.y)
|
||||||
self.add_wire(("metal3","via2","metal2"),[flop_pos, mid_pos,bank_pos])
|
self.add_wire(("m3","via2","m2"),[flop_pos, mid_pos,bank_pos])
|
||||||
self.add_via_center(layers=("metal2","via2","metal3"),
|
self.add_via_center(layers=self.m2_stack,
|
||||||
offset=flop_pos)
|
offset=flop_pos)
|
||||||
|
|
||||||
def route_col_addr_dff(self):
|
def route_col_addr_dff(self):
|
||||||
|
|
@ -336,7 +336,7 @@ class sram_1bank(sram_base):
|
||||||
offset = self.col_addr_dff_insts[port].ul() + vector(0, 2*self.m1_pitch)
|
offset = self.col_addr_dff_insts[port].ul() + vector(0, 2*self.m1_pitch)
|
||||||
|
|
||||||
bus_names = ["addr_{}".format(x) for x in range(self.col_addr_size)]
|
bus_names = ["addr_{}".format(x) for x in range(self.col_addr_size)]
|
||||||
col_addr_bus_offsets = self.create_horizontal_bus(layer="metal1",
|
col_addr_bus_offsets = self.create_horizontal_bus(layer="m1",
|
||||||
pitch=self.m1_pitch,
|
pitch=self.m1_pitch,
|
||||||
offset=offset,
|
offset=offset,
|
||||||
names=bus_names,
|
names=bus_names,
|
||||||
|
|
|
||||||
|
|
@ -103,25 +103,25 @@ class sram_2bank(sram_base):
|
||||||
for n in self.control_logic_outputs + ["vdd", "gnd"]:
|
for n in self.control_logic_outputs + ["vdd", "gnd"]:
|
||||||
pins = self.control_logic_inst.get_pins(n)
|
pins = self.control_logic_inst.get_pins(n)
|
||||||
for pin in pins:
|
for pin in pins:
|
||||||
if pin.layer=="metal2":
|
if pin.layer=="m2":
|
||||||
pin_pos = pin.bc()
|
pin_pos = pin.bc()
|
||||||
break
|
break
|
||||||
rail_pos = vector(pin_pos.x,self.horz_control_bus_positions[n].y)
|
rail_pos = vector(pin_pos.x,self.horz_control_bus_positions[n].y)
|
||||||
self.add_path("metal2",[pin_pos,rail_pos])
|
self.add_path("m2",[pin_pos,rail_pos])
|
||||||
self.add_via_center(("metal1","via1","metal2"),rail_pos)
|
self.add_via_center(self.m1_stack,rail_pos)
|
||||||
|
|
||||||
# connect the control logic cross bar
|
# connect the control logic cross bar
|
||||||
for n in self.control_logic_outputs:
|
for n in self.control_logic_outputs:
|
||||||
cross_pos = vector(self.vert_control_bus_positions[n].x,self.horz_control_bus_positions[n].y)
|
cross_pos = vector(self.vert_control_bus_positions[n].x,self.horz_control_bus_positions[n].y)
|
||||||
self.add_via_center(("metal1","via1","metal2"),cross_pos)
|
self.add_via_center(self.m1_stack,cross_pos)
|
||||||
|
|
||||||
# connect the bank select signals to the vertical bus
|
# connect the bank select signals to the vertical bus
|
||||||
for i in range(self.num_banks):
|
for i in range(self.num_banks):
|
||||||
pin = self.bank_inst[i].get_pin("bank_sel")
|
pin = self.bank_inst[i].get_pin("bank_sel")
|
||||||
pin_pos = pin.rc() if i==0 else pin.lc()
|
pin_pos = pin.rc() if i==0 else pin.lc()
|
||||||
rail_pos = vector(self.vert_control_bus_positions["bank_sel[{}]".format(i)].x,pin_pos.y)
|
rail_pos = vector(self.vert_control_bus_positions["bank_sel[{}]".format(i)].x,pin_pos.y)
|
||||||
self.add_path("metal3",[pin_pos,rail_pos])
|
self.add_path("m3",[pin_pos,rail_pos])
|
||||||
self.add_via_center(("metal2","via2","metal3"),rail_pos)
|
self.add_via_center(self.m2_stack,rail_pos)
|
||||||
|
|
||||||
def route_single_msb_address(self):
|
def route_single_msb_address(self):
|
||||||
""" Route one MSB address bit for 2-bank SRAM """
|
""" Route one MSB address bit for 2-bank SRAM """
|
||||||
|
|
@ -129,37 +129,37 @@ class sram_2bank(sram_base):
|
||||||
# connect the bank MSB flop supplies
|
# connect the bank MSB flop supplies
|
||||||
vdd_pins = self.msb_address_inst.get_pins("vdd")
|
vdd_pins = self.msb_address_inst.get_pins("vdd")
|
||||||
for vdd_pin in vdd_pins:
|
for vdd_pin in vdd_pins:
|
||||||
if vdd_pin.layer != "metal1": continue
|
if vdd_pin.layer != "m1": continue
|
||||||
vdd_pos = vdd_pin.bc()
|
vdd_pos = vdd_pin.bc()
|
||||||
down_pos = vdd_pos - vector(0,self.m1_pitch)
|
down_pos = vdd_pos - vector(0,self.m1_pitch)
|
||||||
rail_pos = vector(vdd_pos.x,self.horz_control_bus_positions["vdd"].y)
|
rail_pos = vector(vdd_pos.x,self.horz_control_bus_positions["vdd"].y)
|
||||||
self.add_path("metal1",[vdd_pos,down_pos])
|
self.add_path("m1",[vdd_pos,down_pos])
|
||||||
self.add_via_center(("metal1","via1","metal2"),down_pos,rotate=90)
|
self.add_via_center(self.m1_stack,down_pos,rotate=90)
|
||||||
self.add_path("metal2",[down_pos,rail_pos])
|
self.add_path("m2",[down_pos,rail_pos])
|
||||||
self.add_via_center(("metal1","via1","metal2"),rail_pos)
|
self.add_via_center(self.m1_stack,rail_pos)
|
||||||
|
|
||||||
gnd_pins = self.msb_address_inst.get_pins("gnd")
|
gnd_pins = self.msb_address_inst.get_pins("gnd")
|
||||||
# Only add the ground connection to the lowest metal2 rail in the flop array
|
# Only add the ground connection to the lowest metal2 rail in the flop array
|
||||||
# FIXME: SCMOS doesn't have a vertical rail in the cell, or we could use those
|
# FIXME: SCMOS doesn't have a vertical rail in the cell, or we could use those
|
||||||
lowest_y = None
|
lowest_y = None
|
||||||
for gnd_pin in gnd_pins:
|
for gnd_pin in gnd_pins:
|
||||||
if gnd_pin.layer != "metal2": continue
|
if gnd_pin.layer != "m2": continue
|
||||||
if lowest_y==None or gnd_pin.by()<lowest_y:
|
if lowest_y==None or gnd_pin.by()<lowest_y:
|
||||||
lowest_y=gnd_pin.by()
|
lowest_y=gnd_pin.by()
|
||||||
gnd_pos = gnd_pin.ur()
|
gnd_pos = gnd_pin.ur()
|
||||||
rail_pos = vector(gnd_pos.x,self.horz_control_bus_positions["gnd"].y)
|
rail_pos = vector(gnd_pos.x,self.horz_control_bus_positions["gnd"].y)
|
||||||
self.add_path("metal2",[gnd_pos,rail_pos])
|
self.add_path("m2",[gnd_pos,rail_pos])
|
||||||
self.add_via_center(("metal1","via1","metal2"),rail_pos)
|
self.add_via_center(self.m1_stack,rail_pos)
|
||||||
|
|
||||||
# connect the MSB flop to the address input bus
|
# connect the MSB flop to the address input bus
|
||||||
msb_pins = self.msb_address_inst.get_pins("din[0]")
|
msb_pins = self.msb_address_inst.get_pins("din[0]")
|
||||||
for msb_pin in msb_pins:
|
for msb_pin in msb_pins:
|
||||||
if msb_pin.layer == "metal3":
|
if msb_pin.layer == "m3":
|
||||||
msb_pin_pos = msb_pin.lc()
|
msb_pin_pos = msb_pin.lc()
|
||||||
break
|
break
|
||||||
rail_pos = vector(self.vert_control_bus_positions[self.msb_bank_sel_addr].x,msb_pin_pos.y)
|
rail_pos = vector(self.vert_control_bus_positions[self.msb_bank_sel_addr].x,msb_pin_pos.y)
|
||||||
self.add_path("metal3",[msb_pin_pos,rail_pos])
|
self.add_path("m3",[msb_pin_pos,rail_pos])
|
||||||
self.add_via_center(("metal2","via2","metal3"),rail_pos)
|
self.add_via_center(self.m2_stack,rail_pos)
|
||||||
|
|
||||||
# Connect the output bar to select 0
|
# Connect the output bar to select 0
|
||||||
msb_out_pin = self.msb_address_inst.get_pin("dout_bar[0]")
|
msb_out_pin = self.msb_address_inst.get_pin("dout_bar[0]")
|
||||||
|
|
@ -167,9 +167,9 @@ class sram_2bank(sram_base):
|
||||||
out_extend_right_pos = msb_out_pos + vector(2*self.m2_pitch,0)
|
out_extend_right_pos = msb_out_pos + vector(2*self.m2_pitch,0)
|
||||||
out_extend_up_pos = out_extend_right_pos + vector(0,self.m2_width)
|
out_extend_up_pos = out_extend_right_pos + vector(0,self.m2_width)
|
||||||
rail_pos = vector(self.vert_control_bus_positions["bank_sel[0]"].x,out_extend_up_pos.y)
|
rail_pos = vector(self.vert_control_bus_positions["bank_sel[0]"].x,out_extend_up_pos.y)
|
||||||
self.add_path("metal2",[msb_out_pos,out_extend_right_pos,out_extend_up_pos])
|
self.add_path("m2",[msb_out_pos,out_extend_right_pos,out_extend_up_pos])
|
||||||
self.add_wire(("metal3","via2","metal2"),[out_extend_right_pos,out_extend_up_pos,rail_pos])
|
self.add_wire(("m3","via2","m2"),[out_extend_right_pos,out_extend_up_pos,rail_pos])
|
||||||
self.add_via_center(("metal2","via2","metal3"),rail_pos)
|
self.add_via_center(self.m2_stack,rail_pos)
|
||||||
|
|
||||||
# Connect the output to select 1
|
# Connect the output to select 1
|
||||||
msb_out_pin = self.msb_address_inst.get_pin("dout[0]")
|
msb_out_pin = self.msb_address_inst.get_pin("dout[0]")
|
||||||
|
|
@ -177,16 +177,16 @@ class sram_2bank(sram_base):
|
||||||
out_extend_right_pos = msb_out_pos + vector(2*self.m2_pitch,0)
|
out_extend_right_pos = msb_out_pos + vector(2*self.m2_pitch,0)
|
||||||
out_extend_down_pos = out_extend_right_pos - vector(0,2*self.m1_pitch)
|
out_extend_down_pos = out_extend_right_pos - vector(0,2*self.m1_pitch)
|
||||||
rail_pos = vector(self.vert_control_bus_positions["bank_sel[1]"].x,out_extend_down_pos.y)
|
rail_pos = vector(self.vert_control_bus_positions["bank_sel[1]"].x,out_extend_down_pos.y)
|
||||||
self.add_path("metal2",[msb_out_pos,out_extend_right_pos,out_extend_down_pos])
|
self.add_path("m2",[msb_out_pos,out_extend_right_pos,out_extend_down_pos])
|
||||||
self.add_wire(("metal3","via2","metal2"),[out_extend_right_pos,out_extend_down_pos,rail_pos])
|
self.add_wire(("m3","via2","m2"),[out_extend_right_pos,out_extend_down_pos,rail_pos])
|
||||||
self.add_via_center(("metal2","via2","metal3"),rail_pos)
|
self.add_via_center(self.m2_stack,rail_pos)
|
||||||
|
|
||||||
# Connect clk
|
# Connect clk
|
||||||
clk_pin = self.msb_address_inst.get_pin("clk")
|
clk_pin = self.msb_address_inst.get_pin("clk")
|
||||||
clk_pos = clk_pin.bc()
|
clk_pos = clk_pin.bc()
|
||||||
rail_pos = self.horz_control_bus_positions["clk_buf"]
|
rail_pos = self.horz_control_bus_positions["clk_buf"]
|
||||||
bend_pos = vector(clk_pos.x,self.horz_control_bus_positions["clk_buf"].y)
|
bend_pos = vector(clk_pos.x,self.horz_control_bus_positions["clk_buf"].y)
|
||||||
self.add_path("metal1",[clk_pos,bend_pos,rail_pos])
|
self.add_path("m1",[clk_pos,bend_pos,rail_pos])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -201,8 +201,8 @@ class sram_2bank(sram_base):
|
||||||
for i in [0,1]:
|
for i in [0,1]:
|
||||||
pin_pos = self.bank_inst[i].get_pin(n).uc()
|
pin_pos = self.bank_inst[i].get_pin(n).uc()
|
||||||
rail_pos = vector(pin_pos.x,self.data_bus_positions[n].y)
|
rail_pos = vector(pin_pos.x,self.data_bus_positions[n].y)
|
||||||
self.add_path("metal2",[pin_pos,rail_pos])
|
self.add_path("m2",[pin_pos,rail_pos])
|
||||||
self.add_via_center(("metal2","via2","metal3"),rail_pos)
|
self.add_via_center(self.m2_stack,rail_pos)
|
||||||
|
|
||||||
self.route_single_msb_address()
|
self.route_single_msb_address()
|
||||||
|
|
||||||
|
|
@ -216,8 +216,8 @@ class sram_2bank(sram_base):
|
||||||
pin0_pos = self.bank_inst[0].get_pin(n).rc()
|
pin0_pos = self.bank_inst[0].get_pin(n).rc()
|
||||||
pin1_pos = self.bank_inst[1].get_pin(n).lc()
|
pin1_pos = self.bank_inst[1].get_pin(n).lc()
|
||||||
rail_pos = vector(self.vert_control_bus_positions[n].x,pin0_pos.y)
|
rail_pos = vector(self.vert_control_bus_positions[n].x,pin0_pos.y)
|
||||||
self.add_path("metal3",[pin0_pos,pin1_pos])
|
self.add_path("m3",[pin0_pos,pin1_pos])
|
||||||
self.add_via_center(("metal2","via2","metal3"),rail_pos)
|
self.add_via_center(self.m2_stack,rail_pos)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -232,9 +232,9 @@ class sram_2bank(sram_base):
|
||||||
|
|
||||||
for n in self.control_bus_names:
|
for n in self.control_bus_names:
|
||||||
self.add_label(text=n,
|
self.add_label(text=n,
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=self.vert_control_bus_positions[n])
|
offset=self.vert_control_bus_positions[n])
|
||||||
for n in self.bank_sel_bus_names:
|
for n in self.bank_sel_bus_names:
|
||||||
self.add_label(text=n,
|
self.add_label(text=n,
|
||||||
layer="metal2",
|
layer="m2",
|
||||||
offset=self.vert_control_bus_positions[n])
|
offset=self.vert_control_bus_positions[n])
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ class sram_base(design, verilog, lef):
|
||||||
"""
|
"""
|
||||||
def __init__(self, name, sram_config):
|
def __init__(self, name, sram_config):
|
||||||
design.__init__(self, name)
|
design.__init__(self, name)
|
||||||
lef.__init__(self, ["metal1", "metal2", "metal3", "metal4"])
|
lef.__init__(self, ["m1", "m2", "m3", "m4"])
|
||||||
verilog.__init__(self)
|
verilog.__init__(self)
|
||||||
|
|
||||||
self.sram_config = sram_config
|
self.sram_config = sram_config
|
||||||
|
|
@ -148,13 +148,13 @@ class sram_base(design, verilog, lef):
|
||||||
if not OPTS.route_supplies:
|
if not OPTS.route_supplies:
|
||||||
# Do not route the power supply (leave as must-connect pins)
|
# Do not route the power supply (leave as must-connect pins)
|
||||||
return
|
return
|
||||||
elif "metal4" in tech.layer:
|
elif "m4" in tech.layer:
|
||||||
# Route a M3/M4 grid
|
# Route a M3/M4 grid
|
||||||
from supply_grid_router import supply_grid_router as router
|
from supply_grid_router import supply_grid_router as router
|
||||||
rtr=router(("metal3","via3","metal4"), self)
|
rtr=router(self.m3_stack, self)
|
||||||
elif "metal3" in tech.layer:
|
elif "m3" in tech.layer:
|
||||||
from supply_tree_router import supply_tree_router as router
|
from supply_tree_router import supply_tree_router as router
|
||||||
rtr=router(("metal3",), self)
|
rtr=router(("m3",), self)
|
||||||
|
|
||||||
rtr.route()
|
rtr.route()
|
||||||
|
|
||||||
|
|
@ -200,14 +200,14 @@ class sram_base(design, verilog, lef):
|
||||||
self.control_bus_names[port].extend([wen, pen])
|
self.control_bus_names[port].extend([wen, pen])
|
||||||
else:
|
else:
|
||||||
self.control_bus_names[port].extend([sen, wen, pen])
|
self.control_bus_names[port].extend([sen, wen, pen])
|
||||||
self.vert_control_bus_positions = self.create_vertical_bus(layer="metal2",
|
self.vert_control_bus_positions = self.create_vertical_bus(layer="m2",
|
||||||
pitch=self.m2_pitch,
|
pitch=self.m2_pitch,
|
||||||
offset=self.vertical_bus_offset,
|
offset=self.vertical_bus_offset,
|
||||||
names=self.control_bus_names[port],
|
names=self.control_bus_names[port],
|
||||||
length=self.vertical_bus_height)
|
length=self.vertical_bus_height)
|
||||||
|
|
||||||
self.addr_bus_names=["A{0}[{1}]".format(port,i) for i in range(self.addr_size)]
|
self.addr_bus_names=["A{0}[{1}]".format(port,i) for i in range(self.addr_size)]
|
||||||
self.vert_control_bus_positions.update(self.create_vertical_pin_bus(layer="metal2",
|
self.vert_control_bus_positions.update(self.create_vertical_pin_bus(layer="m2",
|
||||||
pitch=self.m2_pitch,
|
pitch=self.m2_pitch,
|
||||||
offset=self.addr_bus_offset,
|
offset=self.addr_bus_offset,
|
||||||
names=self.addr_bus_names,
|
names=self.addr_bus_names,
|
||||||
|
|
@ -215,7 +215,7 @@ class sram_base(design, verilog, lef):
|
||||||
|
|
||||||
|
|
||||||
self.bank_sel_bus_names = ["bank_sel{0}_{1}".format(port,i) for i in range(self.num_banks)]
|
self.bank_sel_bus_names = ["bank_sel{0}_{1}".format(port,i) for i in range(self.num_banks)]
|
||||||
self.vert_control_bus_positions.update(self.create_vertical_pin_bus(layer="metal2",
|
self.vert_control_bus_positions.update(self.create_vertical_pin_bus(layer="m2",
|
||||||
pitch=self.m2_pitch,
|
pitch=self.m2_pitch,
|
||||||
offset=self.bank_sel_bus_offset,
|
offset=self.bank_sel_bus_offset,
|
||||||
names=self.bank_sel_bus_names,
|
names=self.bank_sel_bus_names,
|
||||||
|
|
@ -224,7 +224,7 @@ class sram_base(design, verilog, lef):
|
||||||
|
|
||||||
# Horizontal data bus
|
# Horizontal data bus
|
||||||
self.data_bus_names = ["DATA{0}[{1}]".format(port,i) for i in range(self.word_size)]
|
self.data_bus_names = ["DATA{0}[{1}]".format(port,i) for i in range(self.word_size)]
|
||||||
self.data_bus_positions = self.create_horizontal_pin_bus(layer="metal3",
|
self.data_bus_positions = self.create_horizontal_pin_bus(layer="m3",
|
||||||
pitch=self.m3_pitch,
|
pitch=self.m3_pitch,
|
||||||
offset=self.data_bus_offset,
|
offset=self.data_bus_offset,
|
||||||
names=self.data_bus_names,
|
names=self.data_bus_names,
|
||||||
|
|
@ -233,19 +233,19 @@ class sram_base(design, verilog, lef):
|
||||||
# Horizontal control logic bus
|
# Horizontal control logic bus
|
||||||
# vdd/gnd in bus go along whole SRAM
|
# vdd/gnd in bus go along whole SRAM
|
||||||
# FIXME: Fatten these wires?
|
# FIXME: Fatten these wires?
|
||||||
self.horz_control_bus_positions = self.create_horizontal_bus(layer="metal1",
|
self.horz_control_bus_positions = self.create_horizontal_bus(layer="m1",
|
||||||
pitch=self.m1_pitch,
|
pitch=self.m1_pitch,
|
||||||
offset=self.supply_bus_offset,
|
offset=self.supply_bus_offset,
|
||||||
names=["vdd"],
|
names=["vdd"],
|
||||||
length=self.supply_bus_width)
|
length=self.supply_bus_width)
|
||||||
# The gnd rail must not be the entire width since we protrude the right-most vdd rail up for
|
# The gnd rail must not be the entire width since we protrude the right-most vdd rail up for
|
||||||
# the decoder in 4-bank SRAMs
|
# the decoder in 4-bank SRAMs
|
||||||
self.horz_control_bus_positions.update(self.create_horizontal_bus(layer="metal1",
|
self.horz_control_bus_positions.update(self.create_horizontal_bus(layer="m1",
|
||||||
pitch=self.m1_pitch,
|
pitch=self.m1_pitch,
|
||||||
offset=self.supply_bus_offset+vector(0,self.m1_pitch),
|
offset=self.supply_bus_offset+vector(0,self.m1_pitch),
|
||||||
names=["gnd"],
|
names=["gnd"],
|
||||||
length=self.supply_bus_width))
|
length=self.supply_bus_width))
|
||||||
self.horz_control_bus_positions.update(self.create_horizontal_bus(layer="metal1",
|
self.horz_control_bus_positions.update(self.create_horizontal_bus(layer="m1",
|
||||||
pitch=self.m1_pitch,
|
pitch=self.m1_pitch,
|
||||||
offset=self.control_bus_offset,
|
offset=self.control_bus_offset,
|
||||||
names=self.control_bus_names[port],
|
names=self.control_bus_names[port],
|
||||||
|
|
@ -529,12 +529,12 @@ class sram_base(design, verilog, lef):
|
||||||
out_pos = dest_pin.uc()
|
out_pos = dest_pin.uc()
|
||||||
|
|
||||||
# move horizontal first
|
# move horizontal first
|
||||||
self.add_wire(("metal3","via2","metal2"),[in_pos, vector(out_pos.x,in_pos.y),out_pos])
|
self.add_wire(("m3","via2","m2"),[in_pos, vector(out_pos.x,in_pos.y),out_pos])
|
||||||
if src_pin.layer=="metal1":
|
if src_pin.layer=="m1":
|
||||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
self.add_via_center(layers=self.m1_stack,
|
||||||
offset=in_pos)
|
offset=in_pos)
|
||||||
if src_pin.layer in ["metal1","metal2"]:
|
if src_pin.layer in ["m1","m2"]:
|
||||||
self.add_via_center(layers=("metal2","via2","metal3"),
|
self.add_via_center(layers=self.m2_stack,
|
||||||
offset=in_pos)
|
offset=in_pos)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,8 @@ class path_test(openram_test):
|
||||||
import tech
|
import tech
|
||||||
import design
|
import design
|
||||||
|
|
||||||
min_space = 2 * tech.drc["minwidth_metal1"]
|
min_space = 2 * tech.drc["minwidth_m1"]
|
||||||
layer_stack = ("metal1")
|
layer_stack = ("m1")
|
||||||
# checks if we can retrace a path
|
# checks if we can retrace a path
|
||||||
position_list = [[0,0],
|
position_list = [[0,0],
|
||||||
[0, 3 * min_space ],
|
[0, 3 * min_space ],
|
||||||
|
|
@ -37,8 +37,8 @@ class path_test(openram_test):
|
||||||
self.local_drc_check(w)
|
self.local_drc_check(w)
|
||||||
|
|
||||||
|
|
||||||
min_space = 2 * tech.drc["minwidth_metal1"]
|
min_space = 2 * tech.drc["minwidth_m1"]
|
||||||
layer_stack = ("metal1")
|
layer_stack = ("m1")
|
||||||
old_position_list = [[0, 0],
|
old_position_list = [[0, 0],
|
||||||
[0, 3 * min_space],
|
[0, 3 * min_space],
|
||||||
[1 * min_space, 3 * min_space],
|
[1 * min_space, 3 * min_space],
|
||||||
|
|
@ -53,8 +53,8 @@ class path_test(openram_test):
|
||||||
wire_path.wire_path(w,layer_stack, position_list)
|
wire_path.wire_path(w,layer_stack, position_list)
|
||||||
self.local_drc_check(w)
|
self.local_drc_check(w)
|
||||||
|
|
||||||
min_space = 2 * tech.drc["minwidth_metal2"]
|
min_space = 2 * tech.drc["minwidth_m2"]
|
||||||
layer_stack = ("metal2")
|
layer_stack = ("m2")
|
||||||
old_position_list = [[0, 0],
|
old_position_list = [[0, 0],
|
||||||
[0, 3 * min_space],
|
[0, 3 * min_space],
|
||||||
[1 * min_space, 3 * min_space],
|
[1 * min_space, 3 * min_space],
|
||||||
|
|
@ -69,8 +69,8 @@ class path_test(openram_test):
|
||||||
wire_path.wire_path(w, layer_stack, position_list)
|
wire_path.wire_path(w, layer_stack, position_list)
|
||||||
self.local_drc_check(w)
|
self.local_drc_check(w)
|
||||||
|
|
||||||
min_space = 2 * tech.drc["minwidth_metal3"]
|
min_space = 2 * tech.drc["minwidth_m3"]
|
||||||
layer_stack = ("metal3")
|
layer_stack = ("m3")
|
||||||
position_list = [[0, 0],
|
position_list = [[0, 0],
|
||||||
[0, 3 * min_space],
|
[0, 3 * min_space],
|
||||||
[1 * min_space, 3 * min_space],
|
[1 * min_space, 3 * min_space],
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ class wire_test(openram_test):
|
||||||
import design
|
import design
|
||||||
|
|
||||||
min_space = 2 * (tech.drc["minwidth_poly"] +
|
min_space = 2 * (tech.drc["minwidth_poly"] +
|
||||||
tech.drc["minwidth_metal1"])
|
tech.drc["minwidth_m1"])
|
||||||
layer_stack = tech.poly_stack
|
layer_stack = tech.poly_stack
|
||||||
old_position_list = [[0, 0],
|
old_position_list = [[0, 0],
|
||||||
[0, 3 * min_space],
|
[0, 3 * min_space],
|
||||||
|
|
@ -41,7 +41,7 @@ class wire_test(openram_test):
|
||||||
self.local_drc_check(w)
|
self.local_drc_check(w)
|
||||||
|
|
||||||
min_space = 2 * (tech.drc["minwidth_poly"] +
|
min_space = 2 * (tech.drc["minwidth_poly"] +
|
||||||
tech.drc["minwidth_metal1"])
|
tech.drc["minwidth_m1"])
|
||||||
layer_stack = tech.poly_stack
|
layer_stack = tech.poly_stack
|
||||||
old_position_list = [[0, 0],
|
old_position_list = [[0, 0],
|
||||||
[0, 3 * min_space],
|
[0, 3 * min_space],
|
||||||
|
|
@ -57,8 +57,8 @@ class wire_test(openram_test):
|
||||||
wire.wire(w, layer_stack, position_list)
|
wire.wire(w, layer_stack, position_list)
|
||||||
self.local_drc_check(w)
|
self.local_drc_check(w)
|
||||||
|
|
||||||
min_space = 2 * (tech.drc["minwidth_metal2"] +
|
min_space = 2 * (tech.drc["minwidth_m2"] +
|
||||||
tech.drc["minwidth_metal1"])
|
tech.drc["minwidth_m1"])
|
||||||
layer_stack = tech.m1_stack
|
layer_stack = tech.m1_stack
|
||||||
position_list = [[0, 0],
|
position_list = [[0, 0],
|
||||||
[0, 3 * min_space],
|
[0, 3 * min_space],
|
||||||
|
|
@ -74,8 +74,8 @@ class wire_test(openram_test):
|
||||||
self.local_drc_check(w)
|
self.local_drc_check(w)
|
||||||
|
|
||||||
|
|
||||||
min_space = 2 * (tech.drc["minwidth_metal2"] +
|
min_space = 2 * (tech.drc["minwidth_m2"] +
|
||||||
tech.drc["minwidth_metal1"])
|
tech.drc["minwidth_m1"])
|
||||||
layer_stack = tech.m2_stack[::-1]
|
layer_stack = tech.m2_stack[::-1]
|
||||||
position_list = [[0, 0],
|
position_list = [[0, 0],
|
||||||
[0, 3 * min_space],
|
[0, 3 * min_space],
|
||||||
|
|
@ -90,8 +90,8 @@ class wire_test(openram_test):
|
||||||
wire.wire(w, layer_stack, position_list)
|
wire.wire(w, layer_stack, position_list)
|
||||||
self.local_drc_check(w)
|
self.local_drc_check(w)
|
||||||
|
|
||||||
min_space = 2 * (tech.drc["minwidth_metal2"] +
|
min_space = 2 * (tech.drc["minwidth_m2"] +
|
||||||
tech.drc["minwidth_metal3"])
|
tech.drc["minwidth_m3"])
|
||||||
layer_stack = tech.m2_stack
|
layer_stack = tech.m2_stack
|
||||||
position_list = [[0, 0],
|
position_list = [[0, 0],
|
||||||
[0, 3 * min_space],
|
[0, 3 * min_space],
|
||||||
|
|
@ -107,8 +107,8 @@ class wire_test(openram_test):
|
||||||
wire.wire(w, layer_stack, position_list)
|
wire.wire(w, layer_stack, position_list)
|
||||||
self.local_drc_check(w)
|
self.local_drc_check(w)
|
||||||
|
|
||||||
min_space = 2 * (tech.drc["minwidth_metal2"] +
|
min_space = 2 * (tech.drc["minwidth_m2"] +
|
||||||
tech.drc["minwidth_metal3"])
|
tech.drc["minwidth_m3"])
|
||||||
layer_stack = tech.m2_stack[::-1]
|
layer_stack = tech.m2_stack[::-1]
|
||||||
position_list = [[0, 0],
|
position_list = [[0, 0],
|
||||||
[0, 3 * min_space],
|
[0, 3 * min_space],
|
||||||
|
|
|
||||||
|
|
@ -39,17 +39,17 @@ GDS["zoom"] = 0.05
|
||||||
# Interconnect stacks
|
# Interconnect stacks
|
||||||
###################################################
|
###################################################
|
||||||
|
|
||||||
poly_stack = ("poly", "contact", "metal1")
|
poly_stack = ("poly", "contact", "m1")
|
||||||
active_stack = ("active", "contact", "metal1")
|
active_stack = ("active", "contact", "m1")
|
||||||
m1_stack = ("metal1", "via1", "metal2")
|
m1_stack = ("m1", "via1", "m2")
|
||||||
m2_stack = ("metal2", "via2", "metal3")
|
m2_stack = ("m2", "via2", "m3")
|
||||||
m3_stack = ("metal3", "via3", "metal4")
|
m3_stack = ("m3", "via3", "m4")
|
||||||
|
|
||||||
# The FEOL stacks get us up to metal1
|
# The FEOL stacks get us up to m1
|
||||||
feol_stacks = [poly_stack,
|
feol_stacks = [poly_stack,
|
||||||
active_stack]
|
active_stack]
|
||||||
|
|
||||||
# The BEOL stacks are metal1 and up
|
# The BEOL stacks are m1 and up
|
||||||
beol_stacks = [m1_stack,
|
beol_stacks = [m1_stack,
|
||||||
m2_stack,
|
m2_stack,
|
||||||
m3_stack]
|
m3_stack]
|
||||||
|
|
@ -73,25 +73,25 @@ layer["vth"] = (7, 0)
|
||||||
layer["thkox"] = (8, 0)
|
layer["thkox"] = (8, 0)
|
||||||
layer["poly"] = (9, 0)
|
layer["poly"] = (9, 0)
|
||||||
layer["contact"] = (10, 0)
|
layer["contact"] = (10, 0)
|
||||||
layer["metal1"] = (11, 0)
|
layer["m1"] = (11, 0)
|
||||||
layer["via1"] = (12, 0)
|
layer["via1"] = (12, 0)
|
||||||
layer["metal2"] = (13, 0)
|
layer["m2"] = (13, 0)
|
||||||
layer["via2"] = (14, 0)
|
layer["via2"] = (14, 0)
|
||||||
layer["metal3"] = (15, 0)
|
layer["m3"] = (15, 0)
|
||||||
layer["via3"] = (16, 0)
|
layer["via3"] = (16, 0)
|
||||||
layer["metal4"] = (17, 0)
|
layer["m4"] = (17, 0)
|
||||||
layer["via4"] = (18, 0)
|
layer["via4"] = (18, 0)
|
||||||
layer["metal5"] = (19, 0)
|
layer["m5"] = (19, 0)
|
||||||
layer["via5"] = (20, 0)
|
layer["via5"] = (20, 0)
|
||||||
layer["metal6"] = (21, 0)
|
layer["m6"] = (21, 0)
|
||||||
layer["via6"] = (22, 0)
|
layer["via6"] = (22, 0)
|
||||||
layer["metal7"] = (23, 0)
|
layer["m7"] = (23, 0)
|
||||||
layer["via7"] = (24, 0)
|
layer["via7"] = (24, 0)
|
||||||
layer["metal8"] = (25, 0)
|
layer["m8"] = (25, 0)
|
||||||
layer["via8"] = (26, 0)
|
layer["via8"] = (26, 0)
|
||||||
layer["metal9"] = (27, 0)
|
layer["m9"] = (27, 0)
|
||||||
layer["via9"] = (28, 0)
|
layer["via9"] = (28, 0)
|
||||||
layer["metal10"] = (29, 0)
|
layer["m10"] = (29, 0)
|
||||||
layer["text"] = (239, 0)
|
layer["text"] = (239, 0)
|
||||||
layer["boundary"]= (239, 0)
|
layer["boundary"]= (239, 0)
|
||||||
|
|
||||||
|
|
@ -144,7 +144,7 @@ drc["poly_extend_active"] = 0.055
|
||||||
# Not a rule
|
# Not a rule
|
||||||
drc["poly_to_contact"] = 0.075
|
drc["poly_to_contact"] = 0.075
|
||||||
# POLY.4 Minimum enclosure of active around gate
|
# POLY.4 Minimum enclosure of active around gate
|
||||||
drc["active_enclosure_gate"] = 0.07
|
drc["active_enclose_gate"] = 0.07
|
||||||
# POLY.5 Minimum spacing of field poly to active
|
# POLY.5 Minimum spacing of field poly to active
|
||||||
drc["poly_to_active"] = 0.05
|
drc["poly_to_active"] = 0.05
|
||||||
# POLY.6 Minimum Minimum spacing of field poly
|
# POLY.6 Minimum Minimum spacing of field poly
|
||||||
|
|
@ -153,7 +153,7 @@ drc["poly_to_field_poly"] = 0.075
|
||||||
drc["minarea_poly"] = 0.0
|
drc["minarea_poly"] = 0.0
|
||||||
|
|
||||||
# ACTIVE.2 Minimum spacing of active
|
# ACTIVE.2 Minimum spacing of active
|
||||||
drc["active_to_body_active"] = 0.08
|
drc["active_to_active"] = 0.08
|
||||||
# ACTIVE.1 Minimum width of active
|
# ACTIVE.1 Minimum width of active
|
||||||
drc.add_layer("active",
|
drc.add_layer("active",
|
||||||
width = 0.09,
|
width = 0.09,
|
||||||
|
|
@ -212,17 +212,17 @@ drc["contact_to_poly"] = 0.090
|
||||||
|
|
||||||
# METAL1.1 Minimum width of metal1
|
# METAL1.1 Minimum width of metal1
|
||||||
# METAL1.2 Minimum spacing of metal1
|
# METAL1.2 Minimum spacing of metal1
|
||||||
drc.add_layer("metal1",
|
drc.add_layer("m1",
|
||||||
width = 0.065,
|
width = 0.065,
|
||||||
spacing = 0.065)
|
spacing = 0.065)
|
||||||
|
|
||||||
# METAL1.3 Minimum enclosure around contact on two opposite sides
|
# METAL1.3 Minimum enclosure around contact on two opposite sides
|
||||||
drc.add_enclosure("metal1",
|
drc.add_enclosure("m1",
|
||||||
layer = "contact",
|
layer = "contact",
|
||||||
enclosure = 0,
|
enclosure = 0,
|
||||||
extension = 0.035)
|
extension = 0.035)
|
||||||
# METAL1.4 inimum enclosure around via1 on two opposite sides
|
# METAL1.4 inimum enclosure around via1 on two opposite sides
|
||||||
drc.add_enclosure("metal1",
|
drc.add_enclosure("m1",
|
||||||
layer = "via1",
|
layer = "via1",
|
||||||
enclosure = 0,
|
enclosure = 0,
|
||||||
extension = 0.035)
|
extension = 0.035)
|
||||||
|
|
@ -236,18 +236,18 @@ drc.add_layer("via1",
|
||||||
|
|
||||||
# METALINT.1 Minimum width of intermediate metal
|
# METALINT.1 Minimum width of intermediate metal
|
||||||
# METALINT.2 Minimum spacing of intermediate metal
|
# METALINT.2 Minimum spacing of intermediate metal
|
||||||
drc.add_layer("metal2",
|
drc.add_layer("m2",
|
||||||
width = 0.07,
|
width = 0.07,
|
||||||
spacing = 0.07)
|
spacing = 0.07)
|
||||||
|
|
||||||
# METALINT.3 Minimum enclosure around via1 on two opposite sides
|
# METALINT.3 Minimum enclosure around via1 on two opposite sides
|
||||||
drc.add_enclosure("metal2",
|
drc.add_enclosure("m2",
|
||||||
layer = "via1",
|
layer = "via1",
|
||||||
enclosure = 0,
|
enclosure = 0,
|
||||||
extension = 0.035)
|
extension = 0.035)
|
||||||
|
|
||||||
# METALINT.4 Minimum enclosure around via[2-3] on two opposite sides
|
# METALINT.4 Minimum enclosure around via[2-3] on two opposite sides
|
||||||
drc.add_enclosure("metal2",
|
drc.add_enclosure("m2",
|
||||||
layer = "via2",
|
layer = "via2",
|
||||||
enclosure = 0,
|
enclosure = 0,
|
||||||
extension = 0.035)
|
extension = 0.035)
|
||||||
|
|
@ -260,12 +260,12 @@ drc.add_layer("via2",
|
||||||
|
|
||||||
# METALINT.1 Minimum width of intermediate metal
|
# METALINT.1 Minimum width of intermediate metal
|
||||||
# METALINT.2 Minimum spacing of intermediate metal
|
# METALINT.2 Minimum spacing of intermediate metal
|
||||||
# Minimum spacing of metal3 wider than 0.09 & longer than 0.3 = 0.09
|
# Minimum spacing of m3 wider than 0.09 & longer than 0.3 = 0.09
|
||||||
# Minimum spacing of metal3 wider than 0.27 & longer than 0.9 = 0.27
|
# Minimum spacing of m3 wider than 0.27 & longer than 0.9 = 0.27
|
||||||
# Minimum spacing of metal3 wider than 0.5 & longer than 1.8 = 0.5
|
# Minimum spacing of m3 wider than 0.5 & longer than 1.8 = 0.5
|
||||||
# Minimum spacing of metal3 wider than 0.9 & longer than 2.7 = 0.9
|
# Minimum spacing of m3 wider than 0.9 & longer than 2.7 = 0.9
|
||||||
# Minimum spacing of metal3 wider than 1.5 & longer than 4.0 = 1.5
|
# Minimum spacing of m3 wider than 1.5 & longer than 4.0 = 1.5
|
||||||
drc.add_layer("metal3",
|
drc.add_layer("m3",
|
||||||
width = 0.07,
|
width = 0.07,
|
||||||
spacing = drc_lut({(0.00, 0.0) : 0.07,
|
spacing = drc_lut({(0.00, 0.0) : 0.07,
|
||||||
(0.09, 0.3) : 0.09,
|
(0.09, 0.3) : 0.09,
|
||||||
|
|
@ -274,13 +274,13 @@ drc.add_layer("metal3",
|
||||||
(0.90, 2.7) : 0.9,
|
(0.90, 2.7) : 0.9,
|
||||||
(1.50, 4.0) : 1.5}))
|
(1.50, 4.0) : 1.5}))
|
||||||
# METALINT.3 Minimum enclosure around via1 on two opposite sides
|
# METALINT.3 Minimum enclosure around via1 on two opposite sides
|
||||||
drc.add_enclosure("metal3",
|
drc.add_enclosure("m3",
|
||||||
layer = "via2",
|
layer = "via2",
|
||||||
enclosure = 0,
|
enclosure = 0,
|
||||||
extension = 0.035)
|
extension = 0.035)
|
||||||
|
|
||||||
# METALINT.4 Minimum enclosure around via[2-3] on two opposite sides
|
# METALINT.4 Minimum enclosure around via[2-3] on two opposite sides
|
||||||
drc.add_enclosure("metal3",
|
drc.add_enclosure("m3",
|
||||||
layer = "via3",
|
layer = "via3",
|
||||||
enclosure = 0,
|
enclosure = 0,
|
||||||
extension = 0.035)
|
extension = 0.035)
|
||||||
|
|
@ -293,11 +293,11 @@ drc.add_layer("via3",
|
||||||
|
|
||||||
# METALSMG.1 Minimum width of semi-global metal
|
# METALSMG.1 Minimum width of semi-global metal
|
||||||
# METALSMG.2 Minimum spacing of semi-global metal
|
# METALSMG.2 Minimum spacing of semi-global metal
|
||||||
# Minimum spacing of metal4 wider than 0.27 & longer than 0.9 = 0.27
|
# Minimum spacing of m4 wider than 0.27 & longer than 0.9 = 0.27
|
||||||
# Minimum spacing of metal4 wider than 0.5 & longer than 1.8 = 0.5
|
# Minimum spacing of m4 wider than 0.5 & longer than 1.8 = 0.5
|
||||||
# Minimum spacing of metal4 wider than 0.9 & longer than 2.7 = 0.9
|
# Minimum spacing of m4 wider than 0.9 & longer than 2.7 = 0.9
|
||||||
# Minimum spacing of metal4 wider than 1.5 & longer than 4.0 = 1.5
|
# Minimum spacing of m4 wider than 1.5 & longer than 4.0 = 1.5
|
||||||
drc.add_layer("metal4",
|
drc.add_layer("m4",
|
||||||
width = 0.14,
|
width = 0.14,
|
||||||
spacing = drc_lut({(0.00, 0.0) : 0.14,
|
spacing = drc_lut({(0.00, 0.0) : 0.14,
|
||||||
(0.27, 0.9) : 0.27,
|
(0.27, 0.9) : 0.27,
|
||||||
|
|
@ -305,7 +305,7 @@ drc.add_layer("metal4",
|
||||||
(0.90, 2.7) : 0.9,
|
(0.90, 2.7) : 0.9,
|
||||||
(1.50, 4.0) : 1.5}))
|
(1.50, 4.0) : 1.5}))
|
||||||
# METALSMG.3 Minimum enclosure around via[3-6] on two opposite sides
|
# METALSMG.3 Minimum enclosure around via[3-6] on two opposite sides
|
||||||
drc.add_enclosure("metal4",
|
drc.add_enclosure("m4",
|
||||||
layer = "via3",
|
layer = "via3",
|
||||||
enclosure = 0.0025)
|
enclosure = 0.0025)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,17 +39,17 @@ GDS["zoom"] = 0.5
|
||||||
# Interconnect stacks
|
# Interconnect stacks
|
||||||
###################################################
|
###################################################
|
||||||
|
|
||||||
poly_stack = ("poly", "poly_contact", "metal1")
|
poly_stack = ("poly", "poly_contact", "m1")
|
||||||
active_stack = ("active", "active_contact", "metal1")
|
active_stack = ("active", "active_contact", "m1")
|
||||||
m1_stack = ("metal1", "via1", "metal2")
|
m1_stack = ("m1", "via1", "m2")
|
||||||
m2_stack = ("metal2", "via2", "metal3")
|
m2_stack = ("m2", "via2", "m3")
|
||||||
m3_stack = ("metal3", "via3", "metal4")
|
m3_stack = ("m3", "via3", "m4")
|
||||||
|
|
||||||
# The FEOL stacks get us up to metal1
|
# The FEOL stacks get us up to m1
|
||||||
feol_stacks = [poly_stack,
|
feol_stacks = [poly_stack,
|
||||||
active_stack]
|
active_stack]
|
||||||
|
|
||||||
# The BEOL stacks are metal1 and up
|
# The BEOL stacks are m1 and up
|
||||||
beol_stacks = [m1_stack,
|
beol_stacks = [m1_stack,
|
||||||
m2_stack,
|
m2_stack,
|
||||||
m3_stack]
|
m3_stack]
|
||||||
|
|
@ -73,13 +73,13 @@ layer["nimplant"] = (45, 0)
|
||||||
layer["poly"] = (46, 0)
|
layer["poly"] = (46, 0)
|
||||||
layer["poly_contact"] = (47, 0)
|
layer["poly_contact"] = (47, 0)
|
||||||
layer["active_contact"] = (48, 0)
|
layer["active_contact"] = (48, 0)
|
||||||
layer["metal1"] = (49, 0)
|
layer["m1"] = (49, 0)
|
||||||
layer["via1"] = (50, 0)
|
layer["via1"] = (50, 0)
|
||||||
layer["metal2"] = (51, 0)
|
layer["m2"] = (51, 0)
|
||||||
layer["via2"] = (61, 0)
|
layer["via2"] = (61, 0)
|
||||||
layer["metal3"] = (62, 0)
|
layer["m3"] = (62, 0)
|
||||||
layer["via3"] = (30, 0)
|
layer["via3"] = (30, 0)
|
||||||
layer["metal4"] = (31, 0)
|
layer["m4"] = (31, 0)
|
||||||
layer["text"] = (63, 0)
|
layer["text"] = (63, 0)
|
||||||
layer["boundary"] = (63, 0)
|
layer["boundary"] = (63, 0)
|
||||||
|
|
||||||
|
|
@ -132,19 +132,18 @@ drc["poly_extend_active"] = 2*_lambda_
|
||||||
# 5.5.b Minimum spacing between poly contact and other poly (alternative rules)
|
# 5.5.b Minimum spacing between poly contact and other poly (alternative rules)
|
||||||
drc["poly_to_contact"] = 4*_lambda_
|
drc["poly_to_contact"] = 4*_lambda_
|
||||||
# ??
|
# ??
|
||||||
drc["active_enclosure_gate"] = 0.0
|
drc["active_enclose_gate"] = 0.0
|
||||||
# 3.5 Minimum field poly to active
|
# 3.5 Minimum field poly to active
|
||||||
drc["poly_to_active"] = _lambda_
|
drc["poly_to_active"] = _lambda_
|
||||||
# 3.2.a Minimum spacing over field poly
|
# 3.2.a Minimum spacing over field poly
|
||||||
drc["poly_to_field_poly"] = 3*_lambda_
|
drc["poly_to_field_poly"] = 3*_lambda_
|
||||||
|
|
||||||
# ??
|
|
||||||
drc["active_to_body_active"] = 4*_lambda_ # Fix me
|
|
||||||
# 2.1 Minimum width
|
# 2.1 Minimum width
|
||||||
# 2.2 Minimum spacing
|
# 2.2 Minimum spacing
|
||||||
drc.add_layer("active",
|
drc.add_layer("active",
|
||||||
width = 3*_lambda_,
|
width = 3*_lambda_,
|
||||||
spacing = 3*_lambda_)
|
spacing = 4*_lambda_)
|
||||||
|
|
||||||
# 2.3 Source/drain active to well edge
|
# 2.3 Source/drain active to well edge
|
||||||
drc.add_enclosure("well",
|
drc.add_enclosure("well",
|
||||||
layer = "active",
|
layer = "active",
|
||||||
|
|
@ -200,18 +199,18 @@ drc["poly_contact_to_poly"] = 2*_lambda_
|
||||||
|
|
||||||
# 7.1 Minimum width
|
# 7.1 Minimum width
|
||||||
# 7.2 Minimum spacing
|
# 7.2 Minimum spacing
|
||||||
drc.add_layer("metal1",
|
drc.add_layer("m1",
|
||||||
width = 3*_lambda_,
|
width = 3*_lambda_,
|
||||||
spacing = 3*_lambda_)
|
spacing = 3*_lambda_)
|
||||||
# 7.3 Minimum overlap of any contact
|
# 7.3 Minimum overlap of any contact
|
||||||
drc.add_enclosure("metal1",
|
drc.add_enclosure("m1",
|
||||||
layer = "poly_contact",
|
layer = "poly_contact",
|
||||||
enclosure = _lambda_)
|
enclosure = _lambda_)
|
||||||
drc.add_enclosure("metal1",
|
drc.add_enclosure("m1",
|
||||||
layer = "active_contact",
|
layer = "active_contact",
|
||||||
enclosure = _lambda_)
|
enclosure = _lambda_)
|
||||||
# 8.3 Minimum overlap by metal1
|
# 8.3 Minimum overlap by m1
|
||||||
drc.add_enclosure("metal1",
|
drc.add_enclosure("m1",
|
||||||
layer = "via1",
|
layer = "via1",
|
||||||
enclosure = _lambda_)
|
enclosure = _lambda_)
|
||||||
|
|
||||||
|
|
@ -223,15 +222,15 @@ drc.add_layer("via1",
|
||||||
|
|
||||||
# 9.1 Minimum width
|
# 9.1 Minimum width
|
||||||
# 9.2 Minimum spacing
|
# 9.2 Minimum spacing
|
||||||
drc.add_layer("metal2",
|
drc.add_layer("m2",
|
||||||
width = 3*_lambda_,
|
width = 3*_lambda_,
|
||||||
spacing = 3*_lambda_)
|
spacing = 3*_lambda_)
|
||||||
# 9.3 Minimum overlap of via1
|
# 9.3 Minimum overlap of via1
|
||||||
drc.add_enclosure("metal2",
|
drc.add_enclosure("m2",
|
||||||
layer = "via1",
|
layer = "via1",
|
||||||
enclosure = _lambda_)
|
enclosure = _lambda_)
|
||||||
# 14.3 Minimum overlap by metal2
|
# 14.3 Minimum overlap by m2
|
||||||
drc.add_enclosure("metal2",
|
drc.add_enclosure("m2",
|
||||||
layer = "via2",
|
layer = "via2",
|
||||||
enclosure = _lambda_)
|
enclosure = _lambda_)
|
||||||
|
|
||||||
|
|
@ -242,18 +241,18 @@ drc.add_layer("via2",
|
||||||
spacing = 3*_lambda_)
|
spacing = 3*_lambda_)
|
||||||
|
|
||||||
# 15.1 Minimum width
|
# 15.1 Minimum width
|
||||||
# 15.2 Minimum spacing to metal3
|
# 15.2 Minimum spacing to m3
|
||||||
drc.add_layer("metal3",
|
drc.add_layer("m3",
|
||||||
width = 3*_lambda_,
|
width = 3*_lambda_,
|
||||||
spacing = 3*_lambda_)
|
spacing = 3*_lambda_)
|
||||||
|
|
||||||
# 15.3 Minimum overlap of via 2
|
# 15.3 Minimum overlap of via 2
|
||||||
drc.add_enclosure("metal3",
|
drc.add_enclosure("m3",
|
||||||
layer = "via2",
|
layer = "via2",
|
||||||
enclosure = _lambda_)
|
enclosure = _lambda_)
|
||||||
|
|
||||||
# 21.3 Minimum overlap by metal3
|
# 21.3 Minimum overlap by m3
|
||||||
drc.add_enclosure("metal3",
|
drc.add_enclosure("m3",
|
||||||
layer = "via3",
|
layer = "via3",
|
||||||
enclosure = _lambda_)
|
enclosure = _lambda_)
|
||||||
|
|
||||||
|
|
@ -264,13 +263,13 @@ drc.add_layer("via3",
|
||||||
spacing = 3*_lambda_)
|
spacing = 3*_lambda_)
|
||||||
|
|
||||||
# 22.1 Minimum width
|
# 22.1 Minimum width
|
||||||
# 22.2 Minimum spacing to metal4
|
# 22.2 Minimum spacing to m4
|
||||||
drc.add_layer("metal4",
|
drc.add_layer("m4",
|
||||||
width = 6*_lambda_,
|
width = 6*_lambda_,
|
||||||
spacing = 6*_lambda_)
|
spacing = 6*_lambda_)
|
||||||
|
|
||||||
# 22.3 Minimum overlap of via 3
|
# 22.3 Minimum overlap of via 3
|
||||||
drc.add_enclosure("metal4",
|
drc.add_enclosure("m4",
|
||||||
layer = "via3",
|
layer = "via3",
|
||||||
enclosure = 2*_lambda_)
|
enclosure = 2*_lambda_)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue