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:
Matt Guthaus 2019-12-17 11:03:36 -08:00
parent a79d03fef4
commit ed28b4983b
52 changed files with 604 additions and 578 deletions

View File

@ -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"))

View File

@ -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.

View File

@ -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

View File

@ -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):
""" """

View File

@ -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)

View File

@ -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)

View File

@ -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())

View File

@ -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

View File

@ -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())

View File

@ -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))

View File

@ -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):

View File

@ -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):

View File

@ -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):

View File

@ -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):

View File

@ -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):

View File

@ -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())

View File

@ -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)

View File

@ -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())

View File

@ -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)

View File

@ -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)

View File

@ -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):

View File

@ -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())

View File

@ -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

View File

@ -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())

View File

@ -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()

View File

@ -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,

View File

@ -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"))

View File

@ -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))

View File

@ -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)

View File

@ -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"""

View File

@ -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())

View File

@ -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())

View File

@ -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())

View File

@ -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())

View File

@ -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)

View File

@ -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))

View File

@ -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())

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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"""

View File

@ -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)

View File

@ -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)

View File

@ -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())

View File

@ -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

View File

@ -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,

View File

@ -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])

View File

@ -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)

View File

@ -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],

View File

@ -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],

View File

@ -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)

View File

@ -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_)