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.
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))
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))
# In some technologies, the minimum width may be larger
@ -204,16 +204,16 @@ class contact(hierarchy_design.hierarchy_design):
height=self.second_layer_height)
def create_implant_well_enclosures(self):
implant_position = self.first_layer_position - [drc("implant_enclosure_active")] * 2
implant_width = self.first_layer_width + 2 * drc("implant_enclosure_active")
implant_height = self.first_layer_height + 2 * drc("implant_enclosure_active")
implant_position = self.first_layer_position - [drc("implant_enclose_active")] * 2
implant_width = self.first_layer_width + 2 * drc("implant_enclose_active")
implant_height = self.first_layer_height + 2 * drc("implant_enclose_active")
self.add_rect(layer="{}implant".format(self.implant_type),
offset=implant_position,
width=implant_width,
height=implant_height)
well_position = self.first_layer_position - [drc("well_enclosure_active")] * 2
well_width = self.first_layer_width + 2 * drc("well_enclosure_active")
well_height = self.first_layer_height + 2 * drc("well_enclosure_active")
well_position = self.first_layer_position - [drc("well_enclose_active")] * 2
well_width = self.first_layer_width + 2 * drc("well_enclose_active")
well_height = self.first_layer_height + 2 * drc("well_enclose_active")
self.add_rect(layer="{}well".format(self.well_type),
offset=well_position,
width=well_width,
@ -250,7 +250,7 @@ m1m2 = factory.create(module_type="contact",
m2m3 = factory.create(module_type="contact",
layer_stack=m2_stack,
directions=("V", "H"))
if "metal4" in layer.keys():
if "m4" in layer.keys():
m3m4 = factory.create(module_type="contact",
layer_stack=m3_stack,
directions=("H", "V"))

View File

@ -8,7 +8,7 @@
from hierarchy_design import hierarchy_design
import contact
from globals import OPTS
import re
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.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)
else:
self.m3_pitch = self.m2_pitch
@ -46,36 +46,62 @@ class design(hierarchy_design):
def setup_drc_constants(self):
""" These are some DRC constants used in many places in the compiler."""
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")
self.poly_extend_active = drc("poly_extend_active")
if "contact" in layer:
self.poly_to_contact = drc("poly_to_contact")
else:
self.poly_to_contact = drc("poly_to_active_contact")
self.contact_to_gate = drc("contact_to_gate")
self.well_enclose_active = drc("well_enclosure_active")
self.implant_enclose_active = drc("implant_enclosure_active")
self.implant_space = drc("implant_to_implant")
# Make some local rules for convenience
for rule in drc.keys():
# Single layer width rules
match = re.search(r"minwidth_(.*)", rule)
if match:
if match.group(1)=="active_contact":
setattr(self, "contact_width", drc(match.group(0)))
else:
setattr(self, match.group(1)+"_width", drc(match.group(0)))
# 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):
"""
These are contants and lists that aid multiport design.

View File

@ -61,7 +61,7 @@ class layout():
y_dir = 1
else:
# 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
return (base_offset,y_dir)
@ -388,9 +388,9 @@ class layout():
def get_preferred_direction(self, layer):
""" Return the preferred routing directions """
if layer in ["metal1", "metal3", "metal5"]:
if layer in ["m1", "m3", "m5"]:
return "H"
elif layer in ["active", "poly", "metal2", "metal4"]:
elif layer in ["active", "poly", "m2", "m4"]:
return "V"
else:
return "N"
@ -682,12 +682,12 @@ class layout():
return line_positions
def connect_horizontal_bus(self, mapping, inst, bus_offsets,
layer_stack=("metal1","via1","metal2")):
layer_stack=("m1", "via1", "m2")):
""" Horizontal version of connect_bus. """
self.connect_bus(mapping, inst, bus_offsets, layer_stack, True)
def connect_vertical_bus(self, mapping, inst, bus_offsets,
layer_stack=("metal1","via1","metal2")):
layer_stack=("m1", "via1", "m2")):
""" Vertical version of connect_bus. """
self.connect_bus(mapping, inst, bus_offsets, layer_stack, False)
@ -734,15 +734,15 @@ class layout():
rotate=90)
def get_layer_pitch(self, 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)
elif layer=="metal2":
elif layer=="m2":
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)
elif layer=="metal4":
elif layer=="m4":
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)
else:
return (self.m3_pitch,self.m3_pitch-self.m3_space,self.m3_space)
@ -1006,16 +1006,16 @@ class layout():
"""
pins=inst.get_pins(name)
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())
elif pin.layer=="metal1":
elif pin.layer=="m1":
self.add_power_pin(name, pin.center())
else:
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.
The starting layer is specified to determine which vias are needed.
@ -1025,24 +1025,24 @@ class layout():
else:
direction=("H","H")
if start_layer=="metal1":
if start_layer=="m1":
self.add_via_center(layers=self.m1_stack,
offset=loc,
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,
offset=loc,
directions=direction)
if start_layer=="metal3":
if start_layer=="m3":
self.add_layout_pin_rect_center(text=name,
layer="metal3",
layer="m3",
offset=loc)
else:
self.add_layout_pin_rect_center(text=name,
layer="metal3",
layer="m3",
offset=loc,
width=via.width,
height=via.height)
@ -1064,7 +1064,7 @@ class layout():
# LEFT vertical rails
offset = ll + vector(-2*self.supply_rail_pitch, -2*self.supply_rail_pitch)
left_gnd_pin=self.add_layout_pin(text="gnd",
layer="metal2",
layer="m2",
offset=offset,
width=self.supply_rail_width,
height=height)
@ -1072,7 +1072,7 @@ class layout():
offset = ll + vector(-1*self.supply_rail_pitch, -1*self.supply_rail_pitch)
left_vdd_pin=self.add_layout_pin(text="vdd",
layer="metal2",
layer="m2",
offset=offset,
width=self.supply_rail_width,
height=height)
@ -1080,14 +1080,14 @@ class layout():
# RIGHT vertical rails
offset = vector(ur.x,ll.y) + vector(0,-2*self.supply_rail_pitch)
right_gnd_pin = self.add_layout_pin(text="gnd",
layer="metal2",
layer="m2",
offset=offset,
width=self.supply_rail_width,
height=height)
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",
layer="metal2",
layer="m2",
offset=offset,
width=self.supply_rail_width,
height=height)
@ -1095,14 +1095,14 @@ class layout():
# BOTTOM horizontal rails
offset = ll + vector(-2*self.supply_rail_pitch, -2*self.supply_rail_pitch)
bottom_gnd_pin=self.add_layout_pin(text="gnd",
layer="metal1",
layer="m1",
offset=offset,
width=width,
height=self.supply_rail_width)
offset = ll + vector(-1*self.supply_rail_pitch, -1*self.supply_rail_pitch)
bottom_vdd_pin=self.add_layout_pin(text="vdd",
layer="metal1",
layer="m1",
offset=offset,
width=width,
height=self.supply_rail_width)
@ -1110,14 +1110,14 @@ class layout():
# TOP horizontal rails
offset = vector(ll.x, ur.y) + vector(-2*self.supply_rail_pitch,0)
top_gnd_pin=self.add_layout_pin(text="gnd",
layer="metal1",
layer="m1",
offset=offset,
width=width,
height=self.supply_rail_width)
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",
layer="metal1",
layer="m1",
offset=offset,
width=width,
height=self.supply_rail_width)
@ -1139,7 +1139,7 @@ class layout():
from sram_factory import factory
while True:
c=factory.create(module_type="contact",
layer_stack=("metal1","via1","metal2"),
layer_stack=self.m1_stack,
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:
self.supply_vias += 1

View File

@ -364,11 +364,11 @@ class pbitcell(bitcell_base.bitcell_base):
self.inverter_pmos_right.get_pin("G").bc()])
# connect output (drain/source) of inverters
self.add_path("metal1",
self.add_path("m1",
[self.inverter_nmos_left.get_pin("D").uc(),
self.inverter_pmos_left.get_pin("D").bc()],
width=contact.active.second_layer_width)
self.add_path("metal1",
self.add_path("m1",
[self.inverter_nmos_right.get_pin("S").uc(),
self.inverter_pmos_right.get_pin("S").bc()],
width=contact.active.second_layer_width)
@ -404,7 +404,7 @@ class pbitcell(bitcell_base.bitcell_base):
# Add rails for vdd and gnd
gnd_ypos = self.m1_offset - self.total_ports * self.m1_pitch
self.gnd_position = vector(0, gnd_ypos)
self.add_rect_center(layer="metal1",
self.add_rect_center(layer="m1",
offset=self.gnd_position,
width=self.width)
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.vdd_offset
self.vdd_position = vector(0, vdd_ypos)
self.add_rect_center(layer="metal1",
self.add_rect_center(layer="m1",
offset=self.vdd_position,
width=self.width)
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
self.rwwl_positions[k] = vector(0, rwwl_ypos)
self.add_layout_pin_rect_center(text=self.rw_wl_names[k],
layer="metal1",
layer="m1",
offset=self.rwwl_positions[k],
width=self.width)
@ -499,7 +499,7 @@ class pbitcell(bitcell_base.bitcell_base):
+ 0.5 * self.m2_width
self.rwbl_positions[k] = vector(rwbl_xpos, self.center_ypos)
self.add_layout_pin_rect_center(text=self.rw_bl_names[k],
layer="metal2",
layer="m2",
offset=self.rwbl_positions[k],
height=self.height)
@ -509,7 +509,7 @@ class pbitcell(bitcell_base.bitcell_base):
- 0.5 * self.m2_width
self.rwbr_positions[k] = vector(rwbr_xpos, self.center_ypos)
self.add_layout_pin_rect_center(text=self.rw_br_names[k],
layer="metal2",
layer="m2",
offset=self.rwbr_positions[k],
height=self.height)
@ -586,7 +586,7 @@ class pbitcell(bitcell_base.bitcell_base):
- k * self.m1_pitch
self.wwl_positions[k] = vector(0, wwl_ypos)
self.add_layout_pin_rect_center(text=self.w_wl_names[k],
layer="metal1",
layer="m1",
offset=self.wwl_positions[k],
width=self.width)
@ -596,7 +596,7 @@ class pbitcell(bitcell_base.bitcell_base):
+ 0.5 * self.m2_width
self.wbl_positions[k] = vector(wbl_xpos, self.center_ypos)
self.add_layout_pin_rect_center(text=self.w_bl_names[k],
layer="metal2",
layer="m2",
offset=self.wbl_positions[k],
height=self.height)
@ -606,7 +606,7 @@ class pbitcell(bitcell_base.bitcell_base):
- 0.5 * self.m2_width
self.wbr_positions[k] = vector(wbr_xpos, self.center_ypos)
self.add_layout_pin_rect_center(text=self.w_br_names[k],
layer="metal2",
layer="m2",
offset=self.wbr_positions[k],
height=self.height)
@ -713,7 +713,7 @@ class pbitcell(bitcell_base.bitcell_base):
- k * self.m1_pitch
self.rwl_positions[k] = vector(0, rwl_ypos)
self.add_layout_pin_rect_center(text=self.r_wl_names[k],
layer="metal1",
layer="m1",
offset=self.rwl_positions[k],
width=self.width)
@ -723,7 +723,7 @@ class pbitcell(bitcell_base.bitcell_base):
+ 0.5 * self.m2_width
self.rbl_positions[k] = vector(rbl_xpos, self.center_ypos)
self.add_layout_pin_rect_center(text=self.r_bl_names[k],
layer="metal2",
layer="m2",
offset=self.rbl_positions[k],
height=self.height)
@ -733,7 +733,7 @@ class pbitcell(bitcell_base.bitcell_base):
- 0.5 * self.m2_width
self.rbr_positions[k] = vector(rbr_xpos, self.center_ypos)
self.add_layout_pin_rect_center(text=self.r_br_names[k],
layer="metal2",
layer="m2",
offset=self.rbr_positions[k],
height=self.height)
@ -775,7 +775,7 @@ class pbitcell(bitcell_base.bitcell_base):
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])
else:
@ -789,7 +789,7 @@ class pbitcell(bitcell_base.bitcell_base):
directions=("H", "H"))
self.add_path("poly", [gate_offset, port_contact_offset])
self.add_path("metal2",
self.add_path("m2",
[port_contact_offset, wl_contact_offset])
def route_bitlines(self):
@ -827,7 +827,7 @@ class pbitcell(bitcell_base.bitcell_base):
self.add_via_center(layers=self.m1_stack,
offset=port_contact_offest)
self.add_path("metal2",
self.add_path("m2",
[port_contact_offest, bl_offset], width=contact.m1m2.height)
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,
offset=port_contact_offest)
self.add_path("metal2",
self.add_path("m2",
[port_contact_offest, br_offset], width=contact.m1m2.height)
def route_supply(self):
@ -866,17 +866,17 @@ class pbitcell(bitcell_base.bitcell_base):
offset=supply_offset,
directions=("H", "H"))
self.add_path("metal2", [position, supply_offset])
self.add_path("m2", [position, supply_offset])
# route inverter pmos to vdd
vdd_pos_left = vector(self.inverter_nmos_left.get_pin("S").uc().x,
self.vdd_position.y)
self.add_path("metal1",
self.add_path("m1",
[self.inverter_pmos_left.get_pin("S").uc(), vdd_pos_left])
vdd_pos_right = vector(self.inverter_nmos_right.get_pin("D").uc().x,
self.vdd_position.y)
self.add_path("metal1",
self.add_path("m1",
[self.inverter_pmos_right.get_pin("D").uc(), vdd_pos_right])
def route_readwrite_access(self):
@ -889,14 +889,14 @@ class pbitcell(bitcell_base.bitcell_base):
self.cross_couple_lower_ypos)
Q_pos = vector(self.inverter_nmos_left.get_pin("D").lx(),
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])
mid = vector(self.readwrite_nmos_right[k].get_pin("S").uc().x,
self.cross_couple_lower_ypos)
Q_bar_pos = vector(self.inverter_nmos_right.get_pin("S").rx(),
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])
def route_write_access(self):
@ -909,14 +909,14 @@ class pbitcell(bitcell_base.bitcell_base):
self.cross_couple_lower_ypos)
Q_pos = vector(self.inverter_nmos_left.get_pin("D").lx(),
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])
mid = vector(self.write_nmos_right[k].get_pin("S").uc().x,
self.cross_couple_lower_ypos)
Q_bar_pos = vector(self.inverter_nmos_right.get_pin("S").rx(),
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])
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,
self.cross_couple_upper_ypos)
self.add_path("metal1",
self.add_path("m1",
[port_contact_offset, mid, left_storage_contact])
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,
self.cross_couple_upper_ypos)
self.add_path("metal1",
self.add_path("m1",
[port_contact_offset, mid, right_storage_contact])
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()
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):
"""

View File

@ -9,7 +9,7 @@ import debug
from drc_value import *
from drc_lut import *
class design_rules():
class design_rules(dict):
"""
This is a class that implements the design rules structures.
"""
@ -43,7 +43,9 @@ class design_rules():
else:
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):
# Minimum width
self.add("minwidth_{}".format(name), width)
@ -53,7 +55,7 @@ class design_rules():
self.add("minarea_{}".format(name), area)
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
if 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
# 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)
@ -605,7 +605,7 @@ class bank(design.design):
out_pos = self.bank_select_inst[port].get_pin(gated_bank_sel_signals[signal]).rc()
name = self.control_signals[port][signal]
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,
offset=bus_pos)
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)
# 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
self.bus_xoffset[0] = self.create_bus(layer="metal2",
self.bus_xoffset[0] = self.create_bus(layer="m2",
pitch=self.m2_pitch,
offset=control_bus_offset,
names=self.control_signals[0],
@ -663,7 +663,7 @@ class bank(design.design):
control_bus_offset = vector(self.bitcell_array_right + self.m2_pitch,
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
self.bus_xoffset[1] = self.create_bus(layer="metal2",
self.bus_xoffset[1] = self.create_bus(layer="m2",
pitch=self.m2_pitch,
offset=control_bus_offset,
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()
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)
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):
@ -829,7 +829,7 @@ class bank(design.design):
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)
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):
""" 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_pin = self.bitcell_array_inst.get_pin(wl_name)
self.add_label(text=wl_name,
layer="metal1",
layer="m1",
offset=wl_pin.center())
# Add the bitline names
@ -888,10 +888,10 @@ class bank(design.design):
bl_pin = self.bitcell_array_inst.get_pin(bl_name)
br_pin = self.bitcell_array_inst.get_pin(br_name)
self.add_label(text=bl_name,
layer="metal2",
layer="m2",
offset=bl_pin.center())
self.add_label(text=br_name,
layer="metal2",
layer="m2",
offset=br_pin.center())
# # Add the data output names to the sense amp output
@ -899,7 +899,7 @@ class bank(design.design):
# data_name = "data_{}".format(i)
# data_pin = self.sense_amp_array_inst.get_pin(data_name)
# self.add_label(text="sa_out_{}".format(i),
# layer="metal2",
# layer="m2",
# offset=data_pin.center())
# Add labels on the decoder
@ -909,7 +909,7 @@ class bank(design.design):
pin_name = "in_{}".format(i)
data_pin = self.wordline_driver_inst[port].get_pin(pin_name)
self.add_label(text=data_name,
layer="metal1",
layer="m1",
offset=data_pin.center())
@ -941,7 +941,7 @@ class bank(design.design):
for (control_signal, pin_pos) in connection:
control_mid_pos = self.bus_xoffset[port][control_signal]
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,
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
control_x_offset = self.bus_xoffset[port][control_signal].x
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,
offset=control_pos)

View File

@ -208,18 +208,18 @@ class bank_select(design.design):
xoffset_bank_sel = bank_sel_inv_pin.lx()
bank_sel_line_pos = vector(xoffset_bank_sel, 0)
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_via_center(layers=("metal1","via1","metal2"),
self.add_path("m2", [bank_sel_line_pos, bank_sel_line_end])
self.add_via_center(layers=self.m1_stack,
offset=bank_sel_inv_pin.lc())
# Route the pin to the left edge as well
bank_sel_pin_pos=vector(0, 0)
bank_sel_pin_end=vector(bank_sel_line_pos.x, bank_sel_pin_pos.y)
self.add_layout_pin_segment_center(text="bank_sel",
layer="metal3",
layer="m3",
start=bank_sel_pin_pos,
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,
directions=("H","H"))
@ -227,10 +227,10 @@ class bank_select(design.design):
bank_sel_bar_pin = self.bank_sel_inv.get_pin("Z")
xoffset_bank_sel_bar = bank_sel_bar_pin.rx()
self.add_label_pin(text="bank_sel_bar",
layer="metal2",
layer="m2",
offset=vector(xoffset_bank_sel_bar, 0),
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())
@ -251,13 +251,13 @@ class bank_select(design.design):
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)
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
logic_pos = logic_inst.get_pin("B").lc() - vector(0.5*contact.m1m2.height,0)
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,
offset=logic_pos,
directions=("H","H"))
@ -273,7 +273,7 @@ class bank_select(design.design):
offset=logic_pos,
directions=("H","H"))
self.add_layout_pin_segment_center(text=input_name,
layer="metal3",
layer="m3",
start=input_pos,
end=logic_pos)
@ -294,7 +294,7 @@ class bank_select(design.design):
for n in ["vdd", "gnd"]:
supply_pin = self.inv_inst[num].get_pin(n)
supply_offset = supply_pin.ll().scale(0,1)
self.add_rect(layer="metal1",
self.add_rect(layer="m1",
offset=supply_offset,
width=self.width)
@ -308,20 +308,20 @@ class bank_select(design.design):
offset=pin_pos,
directions=("H","H"))
self.add_layout_pin_rect_center(text=n,
layer="metal3",
layer="m3",
offset=pin_pos)
# Add vdd/gnd supply rails
gnd_pin = inv_inst.get_pin("gnd")
left_gnd_pos = vector(0, gnd_pin.cy())
self.add_layout_pin_segment_center(text="gnd",
layer="metal1",
layer="m1",
start=left_gnd_pos,
end=gnd_pin.rc())
vdd_pin = inv_inst.get_pin("vdd")
left_vdd_pos = vector(0, vdd_pin.cy())
self.add_layout_pin_segment_center(text="vdd",
layer="metal1",
layer="m1",
start=left_vdd_pos,
end=vdd_pin.rc())

View File

@ -173,7 +173,7 @@ class bitcell_array(design.design):
width = 0
else:
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
return wl_wire
@ -183,7 +183,7 @@ class bitcell_array(design.design):
else:
height = self.height
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
return bl_wire

View File

@ -371,7 +371,7 @@ class control_logic(design.design):
height = self.control_logic_center.y - self.m2_pitch
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):
@ -483,8 +483,8 @@ class control_logic(design.design):
vdd_ypos = self.p_en_bar_nand_inst.get_pin("vdd").by()
in_pos = vector(self.rail_offsets["rbl_bl_delay"].x,vdd_ypos)
mid1 = vector(out_pos.x,in_pos.y)
self.add_wire(("metal1","via1","metal2"),[out_pos, mid1, in_pos])
self.add_via_center(layers=("metal1","via1","metal2"),
self.add_wire(self.m1_stack,[out_pos, mid1, in_pos])
self.add_via_center(layers=self.m1_stack,
offset=in_pos)
@ -509,10 +509,10 @@ class control_logic(design.design):
clk_pin = self.clk_buf_inst.get_pin("A")
clk_pos = clk_pin.center()
self.add_layout_pin_segment_center(text="clk",
layer="metal2",
layer="m2",
start=clk_pos,
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)
@ -521,9 +521,9 @@ class control_logic(design.design):
mid1 = vector(out_pos.x,2*self.m2_pitch)
mid2 = vector(self.rail_offsets["clk_buf"].x, mid1.y)
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
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())
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()
in_pos = self.gated_clk_bar_inst.get_pin("B").center()
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
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
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())
# This is the second gate over, so it needs to be on M3
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
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())
def create_gated_clk_buf_row(self):
@ -587,9 +587,9 @@ class control_logic(design.design):
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
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())
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()
in_pos = self.p_en_bar_driver_inst.get_pin("A").lc()
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")
@ -694,9 +694,9 @@ class control_logic(design.design):
# Connect to rail
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
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())
@ -754,14 +754,14 @@ class control_logic(design.design):
dff_out_map = zip(["dout_bar_0", "dout_0"], ["cs", "cs_bar"])
else:
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
in_pos = self.ctrl_dff_inst.get_pin("clk").uc()
mid_pos = in_pos + vector(0,2*self.m2_pitch)
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_via_center(layers=("metal1","via1","metal2"),
self.add_wire(self.m1_stack,[in_pos, mid_pos, rail_pos])
self.add_via_center(layers=self.m1_stack,
offset=rail_pos)
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)
right_pos=out_pin.center() + vector(self.width-out_pin.cx(),0)
self.add_layout_pin_segment_center(text=out_name,
layer="metal1",
layer="m1",
start=out_pin.center(),
end=right_pos)
@ -799,19 +799,19 @@ class control_logic(design.design):
for inst in self.row_end_inst:
pins = inst.get_pins("vdd")
for pin in pins:
if pin.layer == "metal1":
if pin.layer == "m1":
row_loc = pin.rc()
pin_loc = vector(max_row_x_loc, pin.rc().y)
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")
for pin in pins:
if pin.layer == "metal1":
if pin.layer == "m1":
row_loc = pin.rc()
pin_loc = vector(max_row_x_loc, pin.rc().y)
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,"vdd")
@ -828,14 +828,14 @@ class control_logic(design.design):
"""
# pin=self.clk_inv1.get_pin("Z")
# self.add_label_pin(text="clk1_bar",
# layer="metal1",
# layer="m1",
# offset=pin.ll(),
# height=pin.height(),
# width=pin.width())
# pin=self.clk_inv2.get_pin("Z")
# self.add_label_pin(text="clk2",
# layer="metal1",
# layer="m1",
# offset=pin.ll(),
# height=pin.height(),
# width=pin.width())

View File

@ -132,11 +132,11 @@ class delay_chain(design.design):
pin1_pos = pin1.center()
pin2_pos = pin2.center()
if pin1_pos.y == pin2_pos.y:
self.add_path("metal2", [pin1_pos, pin2_pos])
self.add_path("m2", [pin1_pos, pin2_pos])
else:
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
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):
""" 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]:
# Drop a via on each A pin
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())
self.add_via_center(layers=("metal2","via2","metal3"),
self.add_via_center(layers=self.m2_stack,
offset=a_pin.center())
# Route an M3 horizontal wire to the furthest
z_pin = inv.get_pin("Z")
a_pin = 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())
self.add_via_center(layers=("metal1","via1","metal2"),
self.add_via_center(layers=self.m1_stack,
offset=z_pin.center())
self.add_via_center(layers=("metal2","via2","metal3"),
self.add_via_center(layers=self.m2_stack,
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
@ -172,7 +172,7 @@ class delay_chain(design.design):
y_mid = (z_pin.cy() + next_a_pin.cy())/2
mid1_point = vector(z_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):
@ -205,10 +205,10 @@ class delay_chain(design.design):
# input is A pin of first inverter
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())
self.add_layout_pin(text="in",
layer="metal2",
layer="m2",
offset=a_pin.ll().scale(1,0),
height=a_pin.cy())
@ -216,12 +216,12 @@ class delay_chain(design.design):
# output is A pin of last load inverter
last_driver_inst = self.driver_inst_list[-1]
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())
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",
layer="metal2",
layer="m2",
start=mid_point,
end=mid_point.scale(1,0))

View File

@ -124,7 +124,7 @@ class dff_array(design.design):
for row in range(self.rows):
for col in range(self.columns):
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),
layer=din_pin.layer,
offset=din_pin.ll(),
@ -132,7 +132,7 @@ class dff_array(design.design):
height=din_pin.height())
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),
layer=dout_pin.layer,
offset=dout_pin.ll(),
@ -144,20 +144,20 @@ class dff_array(design.design):
# Create vertical spines to a single horizontal rail
clk_pin = self.dff_insts[0,0].get_pin("clk")
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",
layer="metal3",
layer="m3",
start=vector(0,clk_ypos),
end=vector(self.width,clk_ypos))
for col in range(self.columns):
clk_pin = self.dff_insts[0,col].get_pin("clk")
# Make a vertical strip for each column
self.add_rect(layer="metal2",
self.add_rect(layer="m2",
offset=clk_pin.ll().scale(1,0),
width=self.m2_width,
height=self.height)
# 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))
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())
mid1 = vector(mid_x_offset, q_pin.cy())
mid2 = vector(mid_x_offset, a1_pin.cy())
self.add_path("metal3", [q_pin.center(), mid1, mid2, a1_pin.center()])
self.add_via_center(layers=("metal2","via2","metal3"),
self.add_path("m3", [q_pin.center(), mid1, mid2, a1_pin.center()])
self.add_via_center(layers=self.m2_stack,
offset=q_pin.center())
self.add_via_center(layers=("metal2","via2","metal3"),
self.add_via_center(layers=self.m2_stack,
offset=a1_pin.center())
self.add_via_center(layers=("metal1","via1","metal2"),
self.add_via_center(layers=self.m1_stack,
offset=a1_pin.center())
# 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())
self.mid_qb_pos = vector(mid_x_offset, z1_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):
# Continous vdd rail along with label.
vdd_pin=self.dff_inst.get_pin("vdd")
self.add_layout_pin(text="vdd",
layer="metal1",
layer="m1",
offset=vdd_pin.ll(),
width=self.width,
height=vdd_pin.height())
@ -141,7 +141,7 @@ class dff_buf(design.design):
# Continous gnd rail along with label.
gnd_pin=self.dff_inst.get_pin("gnd")
self.add_layout_pin(text="gnd",
layer="metal1",
layer="m1",
offset=gnd_pin.ll(),
width=self.width,
height=vdd_pin.height())
@ -164,18 +164,18 @@ class dff_buf(design.design):
mid_pos = dout_pin.center() + vector(self.m1_pitch,0)
q_pos = mid_pos - vector(0,self.m2_pitch)
self.add_layout_pin_rect_center(text="Q",
layer="metal2",
layer="m2",
offset=q_pos)
self.add_path("metal1", [dout_pin.center(), mid_pos, q_pos])
self.add_via_center(layers=("metal1","via1","metal2"),
self.add_path("m1", [dout_pin.center(), mid_pos, q_pos])
self.add_via_center(layers=self.m1_stack,
offset=q_pos)
qb_pos = self.mid_qb_pos + vector(0,self.m2_pitch)
self.add_layout_pin_rect_center(text="Qb",
layer="metal2",
layer="m2",
offset=qb_pos)
self.add_path("metal1", [self.mid_qb_pos, qb_pos])
self.add_via_center(layers=("metal1","via1","metal2"),
self.add_path("m1", [self.mid_qb_pos, qb_pos])
self.add_via_center(layers=self.m1_stack,
offset=qb_pos)
def get_clk_cin(self):

View File

@ -142,7 +142,7 @@ class dff_buf_array(design.design):
for row in range(self.rows):
for col in range(self.columns):
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),
layer=din_pin.layer,
offset=din_pin.ll(),
@ -150,7 +150,7 @@ class dff_buf_array(design.design):
height=din_pin.height())
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),
layer=dout_pin.layer,
offset=dout_pin.ll(),
@ -158,7 +158,7 @@ class dff_buf_array(design.design):
height=dout_pin.height())
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),
layer=dout_bar_pin.layer,
offset=dout_bar_pin.ll(),
@ -169,28 +169,28 @@ class dff_buf_array(design.design):
# Create vertical spines to a single horizontal rail
clk_pin = self.dff_insts[0,0].get_pin("clk")
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:
self.add_layout_pin(text="clk",
layer="metal2",
layer="m2",
offset=clk_pin.ll().scale(1,0),
width=self.m2_width,
height=self.height)
else:
self.add_layout_pin_segment_center(text="clk",
layer="metal3",
layer="m3",
start=vector(0,clk_ypos),
end=vector(self.width,clk_ypos))
for col in range(self.columns):
clk_pin = self.dff_insts[0,col].get_pin("clk")
# Make a vertical strip for each column
self.add_rect(layer="metal2",
self.add_rect(layer="m2",
offset=clk_pin.ll().scale(1,0),
width=self.m2_width,
height=self.height)
# 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))
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())
mid1 = vector(mid_x_offset, q_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()])
self.add_via_center(layers=("metal2","via2","metal3"),
self.add_via_center(layers=self.m2_stack,
offset=q_pin.center())
self.add_via_center(layers=("metal2","via2","metal3"),
self.add_via_center(layers=self.m2_stack,
offset=a1_pin.center())
self.add_via_center(layers=("metal1","via1","metal2"),
self.add_via_center(layers=self.m1_stack,
offset=a1_pin.center())
@ -112,7 +112,7 @@ class dff_inv(design.design):
# Continous vdd rail along with label.
vdd_pin=self.dff_inst.get_pin("vdd")
self.add_layout_pin(text="vdd",
layer="metal1",
layer="m1",
offset=vdd_pin.ll(),
width=self.width,
height=vdd_pin.height())
@ -120,7 +120,7 @@ class dff_inv(design.design):
# Continous gnd rail along with label.
gnd_pin=self.dff_inst.get_pin("gnd")
self.add_layout_pin(text="gnd",
layer="metal1",
layer="m1",
offset=gnd_pin.ll(),
width=self.width,
height=vdd_pin.height())
@ -146,9 +146,9 @@ class dff_inv(design.design):
dout_pin = self.inv1_inst.get_pin("Z")
self.add_layout_pin_rect_center(text="Qb",
layer="metal2",
layer="m2",
offset=dout_pin.center())
self.add_via_center(layers=("metal1","via1","metal2"),
self.add_via_center(layers=self.m1_stack,
offset=dout_pin.center())
def get_clk_cin(self):

View File

@ -140,7 +140,7 @@ class dff_inv_array(design.design):
for row in range(self.rows):
for col in range(self.columns):
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),
layer=din_pin.layer,
offset=din_pin.ll(),
@ -148,7 +148,7 @@ class dff_inv_array(design.design):
height=din_pin.height())
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),
layer=dout_pin.layer,
offset=dout_pin.ll(),
@ -156,7 +156,7 @@ class dff_inv_array(design.design):
height=dout_pin.height())
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),
layer=dout_bar_pin.layer,
offset=dout_bar_pin.ll(),
@ -167,27 +167,27 @@ class dff_inv_array(design.design):
# Create vertical spines to a single horizontal rail
clk_pin = self.dff_insts[0,0].get_pin("clk")
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:
self.add_layout_pin(text="clk",
layer="metal2",
layer="m2",
offset=clk_pin.ll().scale(1,0),
width=self.m2_width,
height=self.height)
else:
self.add_layout_pin_segment_center(text="clk",
layer="metal3",
layer="m3",
start=vector(0,clk_ypos),
end=vector(self.width,clk_ypos))
for col in range(self.columns):
clk_pin = self.dff_insts[0,col].get_pin("clk")
# Make a vertical strip for each column
self.add_rect(layer="metal2",
self.add_rect(layer="m2",
offset=clk_pin.ll().scale(1,0),
width=self.m2_width,
height=self.height)
# 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))
def get_clk_cin(self):

View File

@ -122,7 +122,7 @@ class dummy_array(design.design):
for cell_column in column_list:
bl_pin = self.cell_inst[0,col].get_pin(cell_column)
self.add_layout_pin(text=cell_column+"_{0}".format(col),
layer="metal2",
layer="m2",
offset=bl_pin.ll(),
width=bl_pin.width(),
height=self.height)
@ -131,7 +131,7 @@ class dummy_array(design.design):
for cell_row in row_list:
wl_pin = self.cell_inst[row,0].get_pin(cell_row)
self.add_layout_pin(text=cell_row+"_{0}".format(row),
layer="metal1",
layer="m1",
offset=wl_pin.ll(),
width=self.width,
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_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,
offset=input_offset,
names=input_bus_names,
@ -225,7 +225,7 @@ class hierarchical_decoder(design.design):
offset=input_offset)
self.add_via_center(layers=self.m2_stack,
offset=output_offset)
self.add_path(("metal3"), [input_offset, output_offset])
self.add_path(("m3"), [input_offset, output_offset])
def add_pins(self):
@ -467,11 +467,11 @@ class hierarchical_decoder(design.design):
# ensure the bend is in the middle
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)
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")
self.add_layout_pin(text="decode_{0}".format(row),
layer="metal1",
layer="m1",
offset=z_pin.ll(),
width=z_pin.width(),
height=z_pin.height())
@ -485,7 +485,7 @@ class hierarchical_decoder(design.design):
if (self.num_inputs >= 4):
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)]
self.predecode_rails = self.create_vertical_pin_bus(layer="metal2",
self.predecode_rails = self.create_vertical_pin_bus(layer="m2",
pitch=self.m2_pitch,
offset=input_offset,
names=input_bus_names,
@ -570,7 +570,7 @@ class hierarchical_decoder(design.design):
start = self.nand_inst[num].get_pin(pin_name).lc()
end = self.inv_inst[num].get_pin(pin_name).rc()
mid = (start+end).scale(0.5,0.5)
self.add_rect_center(layer="metal1",
self.add_rect_center(layer="m1",
offset=mid,
width=end.x-start.x)
@ -584,7 +584,7 @@ class hierarchical_decoder(design.design):
def route_predecode_rail(self, rail_name, pin):
""" Connect the routing rail to the given metal1 pin """
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,
offset=rail_pos)
@ -597,7 +597,7 @@ class hierarchical_decoder(design.design):
rail_pos = vector(self.predecode_rails[rail_name].x,mid_point.y)
self.add_via_center(layers=self.m1_stack,
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,
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 """
input_names = ["in_{}".format(x) for x in range(self.number_of_inputs)]
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,
offset=offset,
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)]
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)
self.decode_rails = self.create_vertical_bus(layer="metal2",
self.decode_rails = self.create_vertical_bus(layer="m2",
pitch=self.m2_pitch,
offset=offset,
names=decode_names,
@ -183,7 +183,7 @@ class hierarchical_predecode(design.design):
a_pin = "A_{}".format(num)
in_pos = vector(self.input_rails[in_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,
offset=[self.input_rails[in_pin].x, y_offset])
self.add_via_center(layers = self.m1_stack,
@ -201,11 +201,11 @@ class hierarchical_predecode(design.design):
# ensure the bend is in the middle
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)
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")
self.add_layout_pin(text="out_{}".format(num),
layer="metal1",
layer="m1",
offset=z_pin.ll(),
height=z_pin.height(),
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()
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)
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,
offset=rail_pos)
@ -234,7 +234,7 @@ class hierarchical_predecode(design.design):
#route input
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)
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,
offset=in_pos)
@ -255,7 +255,7 @@ class hierarchical_predecode(design.design):
for rail_pin,gate_pin in zip(index_lst,gate_lst):
pin_pos = self.nand_inst[k].get_pin(gate_pin).lc()
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,
offset=rail_pos)
@ -275,7 +275,7 @@ class hierarchical_predecode(design.design):
for n in ["vdd", "gnd"]:
nand_pin = self.nand_inst[num].get_pin(n)
supply_offset = nand_pin.ll().scale(0,1)
self.add_rect(layer="metal1",
self.add_rect(layer="m1",
offset=supply_offset,
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
# 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)
@ -451,7 +451,7 @@ class multibank(design.design):
# Connect the inverter output to the central bus
out_pos = self.bank_select_inst.get_pin(gated_name).rc()
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,
offset=bus_pos,
rotate=90)
@ -512,7 +512,7 @@ class multibank(design.design):
# 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_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,
offset=control_bus_offset,
names=self.control_signals,
@ -530,9 +530,9 @@ class multibank(design.design):
bitcell_br = self.bitcell_array_inst.get_pin("br_{}".format(i)).uc()
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])
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])
@ -550,9 +550,9 @@ class multibank(design.design):
bitcell_br = self.bitcell_array_inst.get_pin("br_{}".format(i)).bc()
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])
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])
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)
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])
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])
def route_sense_amp_to_trigate(self):
@ -590,7 +590,7 @@ class multibank(design.design):
offset=tri_gate_in)
self.add_via_center(layers=self.m2_stack,
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):
""" 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()
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)
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.
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()
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)
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:
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)
#self.add_wire(("metal1","via1","metal2"),[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_wire(self.m1_stack,[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_pin = self.bitcell_array_inst.get_pin(wl_name)
self.add_label(text=wl_name,
layer="metal1",
layer="m1",
offset=wl_pin.center())
# Add the bitline names
@ -725,10 +725,10 @@ class multibank(design.design):
bl_pin = self.bitcell_array_inst.get_pin(bl_name)
br_pin = self.bitcell_array_inst.get_pin(br_name)
self.add_label(text=bl_name,
layer="metal2",
layer="m2",
offset=bl_pin.center())
self.add_label(text=br_name,
layer="metal2",
layer="m2",
offset=br_pin.center())
# # Add the data output names to the sense amp output
@ -736,7 +736,7 @@ class multibank(design.design):
# data_name = "data_{}".format(i)
# data_pin = self.sense_amp_array_inst.get_pin(data_name)
# self.add_label(text="sa_out_{}".format(i),
# layer="metal2",
# layer="m2",
# offset=data_pin.center())
# Add labels on the decoder
@ -745,7 +745,7 @@ class multibank(design.design):
pin_name = "in_{}".format(i)
data_pin = self.wordline_driver_inst.get_pin(pin_name)
self.add_label(text=data_name,
layer="metal1",
layer="m1",
offset=data_pin.center())
@ -765,7 +765,7 @@ class multibank(design.design):
for (control_signal, pin_pos) in connection:
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,
offset=control_pos,
rotate=90)
@ -776,7 +776,7 @@ class multibank(design.design):
mid_pos = pin_pos + vector(0,self.m1_pitch)
control_x_offset = self.bus_xoffset[control_signal].x
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)
self.add_via_center(layers=self.m1_stack,
offset=control_via_pos,
@ -791,13 +791,13 @@ class multibank(design.design):
if self.num_banks > 1:
# it's not an input pin if we have multiple banks
self.add_label_pin(text=ctrl,
layer="metal2",
layer="m2",
offset=vector(x_offset, self.min_y_offset),
width=self.m2_width,
height=self.max_y_offset-self.min_y_offset)
else:
self.add_layout_pin(text=ctrl,
layer="metal2",
layer="m2",
offset=vector(x_offset, self.min_y_offset),
width=self.m2_width,
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 """
in_pin = inst.get_pin(pin).lc()
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
self.add_via(layers=("metal1","via1","metal2"),
self.add_via(layers=self.m1_stack,
offset=in_pin + contact.m1m2.offset,
rotate=90)
self.add_via(layers=("metal2","via2","metal3"),
self.add_via(layers=self.m2_stack,
offset=in_pin + self.m2m3_via_offset,
rotate=90)
@ -821,10 +821,10 @@ class multibank(design.design):
""" Helper routine to connect an unrotated/mirrored oriented instance to the rails """
in_pin = inst.get_pin(pin).rc()
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_via(layers=("metal1","via1","metal2"),
self.add_wire(("m3","via2","m2"),[in_pin, rail_pos, rail_pos - vector(0,self.m2_pitch)])
self.add_via(layers=self.m1_stack,
offset=in_pin + contact.m1m2.offset,
rotate=90)
self.add_via(layers=("metal2","via2","metal3"),
self.add_via(layers=self.m2_stack,
offset=in_pin + self.m2m3_via_offset,
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()
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)
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
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)
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
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)
@ -479,7 +479,7 @@ class port_data(design.design):
offset=end_pos)
# 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):
@ -655,9 +655,9 @@ class port_data(design.design):
top_br = top_inst.get_pin(top_br_name.format(col+top_start_bit)).bc()
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])
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])
def graph_exclude_precharge(self):

View File

@ -68,10 +68,10 @@ class precharge_array(design.design):
def add_layout_pins(self):
self.add_layout_pin(text="en_bar",
layer="metal1",
layer="m1",
offset=self.pc_cell.get_pin("en_bar").ll(),
width=self.width,
height=drc("minwidth_metal1"))
height=drc("minwidth_m1"))
for inst in self.local_insts:
self.copy_layout_pin(inst, "vdd")
@ -80,15 +80,15 @@ class precharge_array(design.design):
inst = self.local_insts[i]
bl_pin = inst.get_pin("bl")
self.add_layout_pin(text="bl_{0}".format(i),
layer="metal2",
layer="m2",
offset=bl_pin.ll(),
width=drc("minwidth_metal2"),
width=drc("minwidth_m2"),
height=bl_pin.height())
br_pin = inst.get_pin("br")
self.add_layout_pin(text="br_{0}".format(i),
layer="metal2",
layer="m2",
offset=br_pin.ll(),
width=drc("minwidth_metal2"),
width=drc("minwidth_m2"),
height=bl_pin.height())

View File

@ -399,7 +399,7 @@ class replica_bitcell_array(design.design):
else:
height = self.height
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
return bl_wire

View File

@ -116,7 +116,7 @@ class replica_column(design.design):
for bl_name in self.cell.get_all_bitline_names():
bl_pin = self.cell_inst[0].get_pin(bl_name)
self.add_layout_pin(text=bl_name,
layer="metal2",
layer="m2",
offset=bl_pin.ll(),
width=bl_pin.width(),
height=self.height)
@ -125,7 +125,7 @@ class replica_column(design.design):
for wl_name in self.cell.get_all_wl_names():
wl_pin = self.cell_inst[row].get_pin(wl_name)
self.add_layout_pin(text="{0}_{1}".format(wl_name,row),
layer="metal1",
layer="m1",
offset=wl_pin.ll().scale(0,1),
width=self.width,
height=wl_pin.height())

View File

@ -102,13 +102,13 @@ class sense_amp_array(design.design):
self.add_via_center(layers=self.m2_stack,
offset=gnd_pos)
self.add_layout_pin_rect_center(text="gnd",
layer="metal3",
layer="m3",
offset=gnd_pos)
vdd_pos = inst.get_pin("vdd").center()
self.add_via_center(layers=self.m2_stack,
offset=vdd_pos)
self.add_layout_pin_rect_center(text="vdd",
layer="metal3",
layer="m3",
offset=vdd_pos)
bl_pin = inst.get_pin("bl")
@ -116,18 +116,18 @@ class sense_amp_array(design.design):
dout_pin = inst.get_pin("dout")
self.add_layout_pin(text="bl_{0}".format(i),
layer="metal2",
layer="m2",
offset=bl_pin.ll(),
width=bl_pin.width(),
height=bl_pin.height())
self.add_layout_pin(text="br_{0}".format(i),
layer="metal2",
layer="m2",
offset=br_pin.ll(),
width=br_pin.width(),
height=br_pin.height())
self.add_layout_pin(text="data_{0}".format(i),
layer="metal2",
layer="m2",
offset=dout_pin.ll(),
width=dout_pin.width(),
height=dout_pin.height())
@ -137,10 +137,10 @@ class sense_amp_array(design.design):
# add sclk rail across entire array
sclk_offset = self.amp.get_pin("en").ll().scale(0,1)
self.add_layout_pin(text="en",
layer="metal1",
layer="m1",
offset=sclk_offset,
width=self.width,
height=drc("minwidth_metal1"))
height=drc("minwidth_m1"))
def input_load(self):
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]
offset = mux_inst.get_pin("bl").ll()
self.add_layout_pin(text="bl_{}".format(col_num),
layer="metal2",
layer="m2",
offset=offset,
height=self.height-offset.y)
offset = mux_inst.get_pin("br").ll()
self.add_layout_pin(text="br_{}".format(col_num),
layer="metal2",
layer="m2",
offset=offset,
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):
offset = vector(0, self.route_height + (j-self.words_per_row)*self.m1_pitch)
self.add_layout_pin(text="sel_{}".format(j),
layer="metal1",
layer="m1",
offset=offset,
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
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
self.add_via_center(layers=("metal1", "contact", "poly"),
self.add_via_center(layers=("m1", "contact", "poly"),
offset=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
# to ensure vias are enclosed and M1 min width rules.
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("metal1", [br_out_offset, br_out_offset+vector(width,0)])
self.add_path("m1", [bl_out_offset, bl_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
self.add_layout_pin_segment_center(text="bl_out_{}".format(int(j/self.words_per_row)),
layer="metal2",
layer="m2",
start=bl_out_offset,
end=bl_out_offset_end)
self.add_layout_pin_segment_center(text="br_out_{}".format(int(j/self.words_per_row)),
layer="metal2",
layer="m2",
start=br_out_offset,
end=br_out_offset_end)
@ -200,8 +200,8 @@ class single_level_column_mux_array(design.design):
else:
self.add_path("metal2", [ bl_out_offset, bl_out_offset_end])
self.add_path("metal2", [ br_out_offset, br_out_offset_end])
self.add_path("m2", [ bl_out_offset, bl_out_offset_end])
self.add_path("m2", [ br_out_offset, br_out_offset_end])
# This via is on the right of the wire
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")
self.add_layout_pin(text="in_{0}".format(index),
layer="metal2",
layer="m2",
offset=in_pin.ll(),
width=in_pin.width(),
height=in_pin.height())
out_pin = self.tri_inst[i].get_pin("out")
self.add_layout_pin(text="out_{0}".format(index),
layer="metal2",
layer="m2",
offset=out_pin.ll(),
width=out_pin.width(),
height=out_pin.height())
@ -103,21 +103,21 @@ class tri_gate_array(design.design):
self.add_via_center(layers=self.m2_stack,
offset=pin_pos)
self.add_layout_pin_rect_center(text=n,
layer="metal3",
layer="m3",
offset=pin_pos)
width = self.tri.width * self.columns - (self.words_per_row - 1) * self.tri.width
en_pin = self.tri_inst[0].get_pin("en")
self.add_layout_pin(text="en",
layer="metal1",
layer="m1",
offset=en_pin.ll().scale(0, 1),
width=width,
height=drc("minwidth_metal1"))
height=drc("minwidth_m1"))
enbar_pin = self.tri_inst[0].get_pin("en_bar")
self.add_layout_pin(text="en_bar",
layer="metal1",
layer="m1",
offset=enbar_pin.ll().scale(0, 1),
width=width,
height=drc("minwidth_metal1"))
height=drc("minwidth_m1"))

View File

@ -142,7 +142,7 @@ class wordline_driver(design.design):
# Wordline enable connection
en_offset = [self.m1_width + 2 * self.m1_space, 0]
en_pin = self.add_layout_pin(text="en",
layer="metal2",
layer="m2",
offset=en_offset,
width=self.m2_width,
height=self.height)
@ -155,7 +155,7 @@ class wordline_driver(design.design):
a_pin = nand_inst.get_pin("A")
a_pos = a_pin.lc()
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,
end=a_pos)
self.add_via_center(layers=self.m1_stack,
@ -167,7 +167,7 @@ class wordline_driver(design.design):
# ensure the bend is in the middle
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)
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
b_pin = nand_inst.get_pin("B")
@ -182,7 +182,7 @@ class wordline_driver(design.design):
# must under the clk line in M1
self.add_layout_pin_segment_center(text="in_{0}".format(row),
layer="metal1",
layer="m1",
start=input_offset,
end=mid_via_offset)
self.add_via_center(layers=self.m1_stack,
@ -190,7 +190,7 @@ class wordline_driver(design.design):
directions=("V", "V"))
# 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)
self.add_via_center(layers=self.m1_stack,
offset=contact_offset,
@ -199,7 +199,7 @@ class wordline_driver(design.design):
# output each WL on the right
wl_offset = inv2_inst.get_pin("Z").rc()
self.add_layout_pin_segment_center(text="wl_{0}".format(row),
layer="metal1",
layer="m1",
start=wl_offset,
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):
din_pin = self.driver_insts[i].get_pin("din")
self.add_layout_pin(text="data_{0}".format(i),
layer="metal2",
layer="m2",
offset=din_pin.ll(),
width=din_pin.width(),
height=din_pin.height())
bl_pin = self.driver_insts[i].get_pin("bl")
self.add_layout_pin(text="bl_{0}".format(i),
layer="metal2",
layer="m2",
offset=bl_pin.ll(),
width=bl_pin.width(),
height=bl_pin.height())
br_pin = self.driver_insts[i].get_pin("br")
self.add_layout_pin(text="br_{0}".format(i),
layer="metal2",
layer="m2",
offset=br_pin.ll(),
width=br_pin.width(),
height=br_pin.height())
@ -146,7 +146,7 @@ class write_driver_array(design.design):
self.add_via_center(layers=self.m2_stack,
offset=pin_pos)
self.add_layout_pin_rect_center(text=n,
layer="metal3",
layer="m3",
offset=pin_pos)
if self.write_size:
for bit in range(self.num_wmasks):
@ -165,7 +165,7 @@ class write_driver_array(design.design):
height=en_pin.height())
else:
self.add_layout_pin(text="en",
layer="metal1",
layer="m1",
offset=self.driver_insts[0].get_pin("en").ll().scale(0,1),
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
en_to_edge = self.and2.width - beg_en_pin.cx()
self.add_layout_pin(text="en",
layer="metal3",
layer="m3",
offset=beg_en_pin.bc(),
width=end_en_pin.cx() - beg_en_pin.cx() + en_to_edge)
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()))
else:
self.add_layout_pin(text="en",
layer="metal3",
layer="m3",
offset=beg_en_pin.bc(),
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"]:
pin = self.and2_insts[i].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):
"""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")
mid1_point = vector(0.5 * (z1_pin.cx() + a2_pin.cx()), z1_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()])
def add_layout_pins(self):
# Continous vdd rail along with label.
vdd_pin = self.inv_inst.get_pin("vdd")
self.add_layout_pin(text="vdd",
layer="metal1",
layer="m1",
offset=vdd_pin.ll().scale(0, 1),
width=self.width,
height=vdd_pin.height())
@ -91,7 +91,7 @@ class pand2(pgate.pgate):
# Continous gnd rail along with label.
gnd_pin = self.inv_inst.get_pin("gnd")
self.add_layout_pin(text="gnd",
layer="metal1",
layer="m1",
offset=gnd_pin.ll().scale(0, 1),
width=self.width,
height=vdd_pin.height())

View File

@ -76,14 +76,14 @@ class pand3(pgate.pgate):
a2_pin = self.inv_inst.get_pin("A")
mid1_point = vector(0.5 * (z1_pin.cx()+a2_pin.cx()), z1_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()])
def add_layout_pins(self):
# Continous vdd rail along with label.
vdd_pin = self.inv_inst.get_pin("vdd")
self.add_layout_pin(text="vdd",
layer="metal1",
layer="m1",
offset=vdd_pin.ll().scale(0, 1),
width=self.width,
height=vdd_pin.height())
@ -91,7 +91,7 @@ class pand3(pgate.pgate):
# Continous gnd rail along with label.
gnd_pin = self.inv_inst.get_pin("gnd")
self.add_layout_pin(text="gnd",
layer="metal1",
layer="m1",
offset=gnd_pin.ll().scale(0, 1),
width=self.width,
height=vdd_pin.height())

View File

@ -78,13 +78,13 @@ class pbuf(pgate.pgate):
z1_pin = self.inv1_inst.get_pin("Z")
a2_pin = self.inv2_inst.get_pin("A")
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):
# Continous vdd rail along with label.
vdd_pin = self.inv1_inst.get_pin("vdd")
self.add_layout_pin(text="vdd",
layer="metal1",
layer="m1",
offset=vdd_pin.ll().scale(0, 1),
width=self.width,
height=vdd_pin.height())
@ -92,7 +92,7 @@ class pbuf(pgate.pgate):
# Continous gnd rail along with label.
gnd_pin = self.inv1_inst.get_pin("gnd")
self.add_layout_pin(text="gnd",
layer="metal1",
layer="m1",
offset=gnd_pin.ll().scale(0, 1),
width=self.width,
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"))
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())
self.add_path("metal1",
self.add_path("m1",
[z_inst_list[x].center(), mid_point,
a_inst_list[x].center()])
@ -148,7 +148,7 @@ class pdriver(pgate.pgate):
# Continous vdd rail along with label.
vdd_pin = self.inv_inst_list[0].get_pin("vdd")
self.add_layout_pin(text="vdd",
layer="metal1",
layer="m1",
offset=vdd_pin.ll().scale(0, 1),
width=self.width,
height=vdd_pin.height())
@ -156,7 +156,7 @@ class pdriver(pgate.pgate):
# Continous gnd rail along with label.
gnd_pin = self.inv_inst_list[0].get_pin("gnd")
self.add_layout_pin(text="gnd",
layer="metal1",
layer="m1",
offset=gnd_pin.ll().scale(0, 1),
width=self.width,
height=vdd_pin.height())

View File

@ -59,7 +59,7 @@ class pgate(design.design):
debug.error("Invalid supply name.", -1)
if abs(height) > 0:
self.add_rect(layer="metal1",
self.add_rect(layer="m1",
offset=source_pin.ll(),
height=height,
width=source_pin.width())
@ -120,7 +120,7 @@ class pgate(design.design):
directions=directions)
self.add_layout_pin_rect_center(text=name,
layer="metal1",
layer="m1",
offset=contact_offset,
width=contact_m1_width,
height=contact_m1_height)
@ -172,7 +172,7 @@ class pgate(design.design):
# To the right a spacing away from the pmos right active edge
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
# from the top of the well
@ -189,7 +189,7 @@ class pgate(design.design):
directions=("H", "V"),
implant_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)),
width=self.nwell_contact.mod.second_layer_width,
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
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
# from the bottom of the well
contact_yoffset = max(nmos_pos.y,
@ -243,7 +243,7 @@ class pgate(design.design):
directions=("H", "V"),
implant_type="p",
well_type="p")
self.add_rect_center(layer="metal1",
self.add_rect_center(layer="m1",
offset=contact_offset.scale(1,0.5),
width=self.pwell_contact.mod.second_layer_width,
height=contact_offset.y)

View File

@ -96,14 +96,14 @@ class pinv(pgate.pgate):
tx_height = nmos.poly_height + pmos.poly_height
# rotated m1 pitch or poly to active spacing
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
# to the active contacts
extra_contact_space = max(-nmos.get_pin("D").by(), 0)
# 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,
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
debug.check(self.height > total_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 contact width and half well enclosure on both sides
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
# Height is an input parameter, so it is not recomputed.
@ -178,12 +178,12 @@ class pinv(pgate.pgate):
def route_supply_rails(self):
""" Add vdd/gnd rails to the top and bottom. """
self.add_layout_pin_rect_center(text="gnd",
layer="metal1",
layer="m1",
offset=vector(0.5 * self.width, 0),
width=self.width)
self.add_layout_pin_rect_center(text="vdd",
layer="metal1",
layer="m1",
offset=vector(0.5 * self.width, self.height),
width=self.width)
@ -238,7 +238,7 @@ class pinv(pgate.pgate):
# Pick point at right most of NMOS and connect down to PMOS
nmos_drain_pos = nmos_drain_pin.bc()
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
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
output_offset = mid_drain_offset.scale(0, 1) + vector(self.width, 0)
self.add_layout_pin_segment_center(text="Z",
layer="metal1",
layer="m1",
start=mid_drain_offset,
end=output_offset)
else:
# This leaves the output as an internal pin (min sized)
self.add_layout_pin_rect_center(text="Z",
layer="metal1",
layer="m1",
offset=mid_drain_offset \
+ 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")
a2_pin = self.inv2_inst.get_pin("A")
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
z2_pin = self.inv2_inst.get_pin("Z")
a3_pin = self.inv3_inst.get_pin("A")
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)
z1_pin = self.inv1_inst.get_pin("Z")
@ -136,7 +136,7 @@ class pinvbuf(pgate.pgate):
# Continous vdd rail along with label.
vdd_pin = self.inv1_inst.get_pin("vdd")
self.add_layout_pin(text="vdd",
layer="metal1",
layer="m1",
offset=vdd_pin.ll().scale(0, 1),
width=self.width,
height=vdd_pin.height())
@ -144,7 +144,7 @@ class pinvbuf(pgate.pgate):
# Continous vdd rail along with label.
gnd_pin = self.inv4_inst.get_pin("gnd")
self.add_layout_pin(text="gnd",
layer="metal1",
layer="m1",
offset=gnd_pin.ll().scale(0, 1),
width=self.width,
height=gnd_pin.height())
@ -152,28 +152,28 @@ class pinvbuf(pgate.pgate):
# Continous gnd rail along with label.
gnd_pin = self.inv1_inst.get_pin("gnd")
self.add_layout_pin(text="gnd",
layer="metal1",
layer="m1",
offset=gnd_pin.ll().scale(0, 1),
width=self.width,
height=vdd_pin.height())
z_pin = self.inv4_inst.get_pin("Z")
self.add_layout_pin_rect_center(text="Z",
layer="metal2",
layer="m2",
offset=z_pin.center())
self.add_via_center(layers=self.m1_stack,
offset=z_pin.center())
zb_pin = self.inv3_inst.get_pin("Z")
self.add_layout_pin_rect_center(text="Zb",
layer="metal2",
layer="m2",
offset=zb_pin.center())
self.add_via_center(layers=self.m1_stack,
offset=zb_pin.center())
a_pin = self.inv1_inst.get_pin("A")
self.add_layout_pin_rect_center(text="A",
layer="metal2",
layer="m2",
offset=a_pin.center())
self.add_via_center(layers=self.m1_stack,
offset=a_pin.center())

View File

@ -99,8 +99,8 @@ class pnand2(pgate.pgate):
# Two PMOS devices and a well contact. Separation between each.
# Enclosure space on the sides.
self.well_width = 2 * self.pmos.active_width + contact.active.width \
+ 2 * drc("active_to_body_active") \
+ 2 * drc("well_enclosure_active")
+ 2 * self.active_space \
+ 2 * self.well_enclose_active
self.width = self.well_width
# 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)
# 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,
drc("poly_extend_active"), self.poly_space)
self.poly_extend_active, self.poly_space)
def route_supply_rails(self):
""" Add vdd/gnd rails to the top and bottom. """
self.add_layout_pin_rect_center(text="gnd",
layer="metal1",
layer="m1",
offset=vector(0.5*self.width, 0),
width=self.width)
self.add_layout_pin_rect_center(text="vdd",
layer="metal1",
layer="m1",
offset=vector(0.5 * self.width, self.height),
width=self.width)
@ -235,13 +235,13 @@ class pnand2(pgate.pgate):
offset=out_offset)
# PMOS1 to mid-drain to NMOS2 drain
self.add_path("metal2",
self.add_path("m2",
[top_pin_offset, mid1_offset, out_offset,
mid2_offset, bottom_pin_offset])
# This extends the output to the edge of the cell
self.add_layout_pin_rect_center(text="Z",
layer="metal1",
layer="m1",
offset=out_offset,
width=contact.m1m2.first_layer_height,
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.
# Enclosure space on the sides.
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.width = self.well_width
# 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
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)
def route_supply_rails(self):
""" Add vdd/gnd rails to the top and bottom. """
self.add_layout_pin_rect_center(text="gnd",
layer="metal1",
layer="m1",
offset=vector(0.5 * self.width, 0),
width=self.width)
self.add_layout_pin_rect_center(text="vdd",
layer="metal1",
layer="m1",
offset=vector(0.5 * self.width, self.height),
width=self.width)
@ -205,7 +205,7 @@ class pnand3(pgate.pgate):
self.m1_space + 0.5 *contact.poly.width + 0.5 * self.m1_width)
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
self.route_input_gate(self.pmos3_inst,
self.nmos3_inst,
@ -245,16 +245,16 @@ class pnand3(pgate.pgate):
offset=nmos3_pin.center())
# 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)
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
self.add_via_center(layers=self.m1_stack,
offset=mid_offset)
self.add_layout_pin_rect_center(text="Z",
layer="metal1",
layer="m1",
offset=mid_offset,
width=contact.m1m2.first_layer_width,
height=contact.m1m2.first_layer_height)

View File

@ -97,9 +97,8 @@ class pnor2(pgate.pgate):
# Enclosure space on the sides.
self.well_width = 2 * 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.width = self.well_width
# 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)
# 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,
drc("poly_extend_active"),
self.poly_extend_active,
self.poly_space)
def route_supply_rails(self):
""" Add vdd/gnd rails to the top and bottom. """
self.add_layout_pin_rect_center(text="gnd",
layer="metal1",
layer="m1",
offset=vector(0.5 * self.width, 0),
width=self.width)
self.add_layout_pin_rect_center(text="vdd",
layer="metal1",
layer="m1",
offset=vector(0.5 * self.width, self.height),
width=self.width)
@ -226,15 +225,15 @@ class pnor2(pgate.pgate):
mid3_offset = mid2_offset + vector(self.m2_width, 0)
# PMOS1 to mid-drain to NMOS2 drain
self.add_path("metal2",
self.add_path("m2",
[pmos_pin.bc(), mid2_offset, mid3_offset])
self.add_path("metal2",
self.add_path("m2",
[nmos_pin.rc(), mid1_offset, mid2_offset])
# This extends the output to the edge of the cell
self.add_via_center(layers=self.m1_stack,
offset=mid3_offset)
self.add_layout_pin_rect_center(text="Z",
layer="metal1",
layer="m1",
offset=mid3_offset,
width=contact.m1m2.first_layer_height,
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
vdd_position = vector(0.5 * self.width, self.height)
self.add_rect_center(layer="metal1",
self.add_rect_center(layer="m1",
offset=vdd_position,
width=self.width,
height=self.m1_width)
@ -80,7 +80,7 @@ class precharge(design.design):
pmos_pin = self.upper_pmos2_inst.get_pin("S")
# center of vdd rail
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
self.add_power_pin("vdd", pmos_pin.center(), vertical=True)
@ -164,7 +164,7 @@ class precharge(design.design):
# adds the en rail on metal1
self.add_layout_pin_segment_center(text="en_bar",
layer="metal1",
layer="m1",
start=offset.scale(0, 1),
end=offset.scale(0, 1) + vector(self.width, 0))
@ -176,7 +176,7 @@ class precharge(design.design):
# adds the contact from active to metal1
well_contact_pos = self.upper_pmos1_inst.get_pin("D").center().scale(1, 0) \
+ vector(0, self.upper_pmos1_inst.uy() + contact.well.height / 2 \
+ drc("well_extend_active"))
+ self.well_extend_active)
self.add_via_center(layers=self.active_stack,
offset=well_contact_pos,
implant_type="n",
@ -200,7 +200,7 @@ class precharge(design.design):
offset = vector(self.bitcell.get_pin(self.bitcell_bl).cx(), 0) \
- vector(0.5 * self.m2_width, 0)
self.bl_pin = self.add_layout_pin(text="bl",
layer="metal2",
layer="m2",
offset=offset,
height=self.height)
@ -208,7 +208,7 @@ class precharge(design.design):
offset = vector(self.bitcell.get_pin(self.bitcell_br).cx(), 0) \
- vector(0.5 * self.m2_width, 0)
self.br_pin = self.add_layout_pin(text="br",
layer="metal2",
layer="m2",
offset=offset,
height=self.height)
@ -258,7 +258,7 @@ class precharge(design.design):
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())
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):
"""
@ -268,7 +268,7 @@ class precharge(design.design):
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())
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):
"""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.
# 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
self.width = self.well_width + 0.5 * self.m1_space
@ -101,12 +101,12 @@ class ptristate_inv(pgate.pgate):
def route_supply_rails(self):
""" Add vdd/gnd rails to the top and bottom. """
self.add_layout_pin_rect_center(text="gnd",
layer="metal1",
layer="m1",
offset=vector(0.5 * self.width, 0),
width=self.width)
self.add_layout_pin_rect_center(text="vdd",
layer="metal1",
layer="m1",
offset=vector(0.5 * self.width, self.height),
width=self.width)
@ -181,7 +181,7 @@ class ptristate_inv(pgate.pgate):
pmos_drain_pos = pmos_drain_pin.ur()
self.add_layout_pin(text="out",
layer="metal1",
layer="m1",
offset=nmos_drain_pos,
height=pmos_drain_pos.y - nmos_drain_pos.y)

View File

@ -91,8 +91,8 @@ class ptx(design.design):
# " ".join(self.pins)))
# Just make a guess since these will actually
# be decided in the layout later.
area_sd = 2.5 * drc("minwidth_poly") * self.tx_width
perimeter_sd = 2 * drc("minwidth_poly") + 2 * self.tx_width
area_sd = 2.5 * self.poly_width * 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],
self.mults,
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
# 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)
# 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.
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.")
# We do not want to increase the poly dimensions to fix
# 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.")
def connect_fingered_poly(self, poly_positions):
@ -219,7 +219,7 @@ class ptx(design.design):
layer="poly",
offset=poly_offset,
width=poly_width,
height=drc("minwidth_poly"))
height=self.poly_width)
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
# Add each vertical segment
for a in source_positions:
self.add_path(("metal1"),
self.add_path(("m1"),
[a, a + pin_offset.scale(source_dir,
source_dir)])
# Add a single horizontal pin
self.add_layout_pin_segment_center(text="S",
layer="metal1",
layer="m1",
start=source_positions[0] + 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
# Add each vertical segment
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
self.add_layout_pin_segment_center(text="D",
layer="metal1",
layer="m1",
start=drain_positions[0] + drain_offset - end_offset,
end=drain_positions[-1] + drain_offset + end_offset)
@ -313,7 +313,7 @@ class ptx(design.design):
height=self.active_height)
# If the implant must enclose the active, shift offset
# and increase width/height
enclose_width = drc("implant_enclosure_active")
enclose_width = self.implant_enclose_active
enclose_offset = [enclose_width] * 2
self.add_rect(layer="{}implant".format(self.implant_type),
offset=self.active_offset - enclose_offset,
@ -380,7 +380,7 @@ class ptx(design.design):
implant_type=self.implant_type,
well_type=self.well_type)
self.add_layout_pin_rect_center(text="S",
layer="metal1",
layer="m1",
offset=pos,
width=contact.mod.second_layer_width,
height=contact.mod.second_layer_height)
@ -394,7 +394,7 @@ class ptx(design.design):
implant_type=self.implant_type,
well_type=self.well_type)
self.add_layout_pin_rect_center(text="D",
layer="metal1",
layer="m1",
offset=pos,
width=contact.mod.second_layer_width,
height=contact.mod.second_layer_height)

View File

@ -131,26 +131,26 @@ class pwrite_driver(design.design):
bl_xoffset = left_x
bl_out=vector(bl_xoffset, self.height)
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)
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",
layer="metal2",
layer="m2",
offset=bl_out)
br_xoffset = right_x
br_out=vector(br_xoffset, self.height)
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)
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",
layer="metal2",
layer="m2",
offset=br_out)
#br_xoffset = b.get_pin("br".cx()
@ -162,19 +162,19 @@ class pwrite_driver(design.design):
track_xoff = self.get_m2_track(1)
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)
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)
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",
layer="metal2",
layer="m2",
offset=din_in)
def route_din_bar(self):
@ -183,19 +183,19 @@ class pwrite_driver(design.design):
track_xoff = self.get_m4_track(self.din_bar_track)
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)
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)
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",
layer="metal4",
layer="m4",
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
en_bar_loc = self.en_inst.get_pin("Z").uc()
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
bl_en_loc = self.bl_inst.get_pin("en_bar").center()
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_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
self.add_wire(("metal3","via3","metal4"),
self.add_wire(self.m3_stack,
[en_bar_loc, en_bar_track, bl_en_track])
# 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])
@ -233,30 +233,30 @@ class pwrite_driver(design.design):
# The en pin will be over the vdd rail
vdd_yloc = self.en_inst.get_pin("vdd").cy()
self.add_layout_pin_segment_center(text="en",
layer="metal3",
layer="m3",
start=vector(0,vdd_yloc),
end=vector(self.width,vdd_yloc))
en_loc = self.en_inst.get_pin("A").center()
en_rail = vector(en_loc.x, vdd_yloc)
self.add_via_stack("metal1", "metal2", en_loc)
self.add_path("metal2", [en_loc, en_rail])
self.add_via_stack("metal2", "metal3", en_rail)
self.add_via_stack("m1", "m2", en_loc)
self.add_path("m2", [en_loc, en_rail])
self.add_via_stack("m2", "m3", en_rail)
# Start point in the track on the pin rail
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
bl_en_loc = self.bl_inst.get_pin("en").center()
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_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
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])
@ -284,7 +284,7 @@ class pwrite_driver(design.design):
# Continous vdd rail along with label.
vdd_pin=inst.get_pin("vdd")
self.add_layout_pin(text="vdd",
layer="metal1",
layer="m1",
offset=vdd_pin.ll().scale(0,1),
width=self.width,
height=vdd_pin.height())
@ -292,7 +292,7 @@ class pwrite_driver(design.design):
# Continous gnd rail along with label.
gnd_pin=inst.get_pin("gnd")
self.add_layout_pin(text="gnd",
layer="metal1",
layer="m1",
offset=gnd_pin.ll().scale(0,1),
width=self.width,
height=vdd_pin.height())

View File

@ -65,21 +65,21 @@ class single_level_column_mux(pgate.pgate):
# bl and br
self.add_layout_pin(text="bl",
layer="metal2",
layer="m2",
offset=bl_pos + vector(0, self.height - self.pin_height),
height=self.pin_height)
self.add_layout_pin(text="br",
layer="metal2",
layer="m2",
offset=br_pos + vector(0, self.height - self.pin_height),
height=self.pin_height)
# bl_out and br_out
self.add_layout_pin(text="bl_out",
layer="metal2",
layer="m2",
offset=bl_pos,
height=self.pin_height)
self.add_layout_pin(text="br_out",
layer="metal2",
layer="m2",
offset=br_pos,
height=self.pin_height)
@ -141,7 +141,7 @@ class single_level_column_mux(pgate.pgate):
# bl -> nmos_upper/D on metal1
# 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()),
nmos_upper_d_pin.center()])
# halfway up, move over
@ -149,12 +149,12 @@ class single_level_column_mux(pgate.pgate):
+ nmos_upper_s_pin.bc().scale(0, 0.4)
mid2 = bl_out_pin.uc().scale(0, 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()])
# br -> nmos_lower/D on metal2
# br_out -> nmos_lower/S on metal1
self.add_path("metal1",
self.add_path("m1",
[br_out_pin.uc(),
vector(nmos_lower_s_pin.cx(), br_out_pin.uy()),
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)
mid2 = br_pin.bc().scale(0,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()])
def add_wells(self):
@ -186,7 +186,7 @@ class single_level_column_mux(pgate.pgate):
self.add_via_center(layers=self.m2_stack,
offset=active_pos)
self.add_layout_pin_rect_center(text="gnd",
layer="metal3",
layer="m3",
offset=active_pos)
# 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
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_via_center(layers=("metal1","via1","metal2"),
self.add_path("m1", [control_clk_buf_pos, clk_steiner_pos])
self.add_via_center(layers=self.m1_stack,
offset=clk_steiner_pos)
# 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:
dff_clk_pin = self.col_addr_dff_insts[port].get_pin("clk")
dff_clk_pos = dff_clk_pin.center()
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:
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)
# In some designs, the steiner via will be too close to the mid_pos via
# so make the wire as wide as the contacts
self.add_path("metal2",[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_path("m2",[mid_pos, clk_steiner_pos], width=max(m2m3.width,m2m3.height))
self.add_wire(("m3","via2","m2"),[data_dff_clk_pos, mid_pos, clk_steiner_pos])
if self.write_size:
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)
# In some designs, the steiner via will be too close to the mid_pos via
# so make the wire as wide as the contacts
self.add_path("metal2", [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_path("m2", [mid_pos, clk_steiner_pos], width=max(m2m3.width, m2m3.height))
self.add_wire(("m3", "via2", "m2"), [wmask_dff_clk_pos, mid_pos, clk_steiner_pos])
def route_control_logic(self):
@ -323,8 +323,8 @@ class sram_1bank(sram_base):
flop_pos = flop_pin.center()
bank_pos = bank_pin.center()
mid_pos = vector(bank_pos.x,flop_pos.y)
self.add_wire(("metal3","via2","metal2"),[flop_pos, mid_pos,bank_pos])
self.add_via_center(layers=("metal2","via2","metal3"),
self.add_wire(("m3","via2","m2"),[flop_pos, mid_pos,bank_pos])
self.add_via_center(layers=self.m2_stack,
offset=flop_pos)
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)
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,
offset=offset,
names=bus_names,

View File

@ -103,25 +103,25 @@ class sram_2bank(sram_base):
for n in self.control_logic_outputs + ["vdd", "gnd"]:
pins = self.control_logic_inst.get_pins(n)
for pin in pins:
if pin.layer=="metal2":
if pin.layer=="m2":
pin_pos = pin.bc()
break
rail_pos = vector(pin_pos.x,self.horz_control_bus_positions[n].y)
self.add_path("metal2",[pin_pos,rail_pos])
self.add_via_center(("metal1","via1","metal2"),rail_pos)
self.add_path("m2",[pin_pos,rail_pos])
self.add_via_center(self.m1_stack,rail_pos)
# connect the control logic cross bar
for n in self.control_logic_outputs:
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
for i in range(self.num_banks):
pin = self.bank_inst[i].get_pin("bank_sel")
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)
self.add_path("metal3",[pin_pos,rail_pos])
self.add_via_center(("metal2","via2","metal3"),rail_pos)
self.add_path("m3",[pin_pos,rail_pos])
self.add_via_center(self.m2_stack,rail_pos)
def route_single_msb_address(self):
""" Route one MSB address bit for 2-bank SRAM """
@ -129,37 +129,37 @@ class sram_2bank(sram_base):
# connect the bank MSB flop supplies
vdd_pins = self.msb_address_inst.get_pins("vdd")
for vdd_pin in vdd_pins:
if vdd_pin.layer != "metal1": continue
if vdd_pin.layer != "m1": continue
vdd_pos = vdd_pin.bc()
down_pos = vdd_pos - vector(0,self.m1_pitch)
rail_pos = vector(vdd_pos.x,self.horz_control_bus_positions["vdd"].y)
self.add_path("metal1",[vdd_pos,down_pos])
self.add_via_center(("metal1","via1","metal2"),down_pos,rotate=90)
self.add_path("metal2",[down_pos,rail_pos])
self.add_via_center(("metal1","via1","metal2"),rail_pos)
self.add_path("m1",[vdd_pos,down_pos])
self.add_via_center(self.m1_stack,down_pos,rotate=90)
self.add_path("m2",[down_pos,rail_pos])
self.add_via_center(self.m1_stack,rail_pos)
gnd_pins = self.msb_address_inst.get_pins("gnd")
# 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
lowest_y = None
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:
lowest_y=gnd_pin.by()
gnd_pos = gnd_pin.ur()
rail_pos = vector(gnd_pos.x,self.horz_control_bus_positions["gnd"].y)
self.add_path("metal2",[gnd_pos,rail_pos])
self.add_via_center(("metal1","via1","metal2"),rail_pos)
self.add_path("m2",[gnd_pos,rail_pos])
self.add_via_center(self.m1_stack,rail_pos)
# connect the MSB flop to the address input bus
msb_pins = self.msb_address_inst.get_pins("din[0]")
for msb_pin in msb_pins:
if msb_pin.layer == "metal3":
if msb_pin.layer == "m3":
msb_pin_pos = msb_pin.lc()
break
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_via_center(("metal2","via2","metal3"),rail_pos)
self.add_path("m3",[msb_pin_pos,rail_pos])
self.add_via_center(self.m2_stack,rail_pos)
# Connect the output bar to select 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_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)
self.add_path("metal2",[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_via_center(("metal2","via2","metal3"),rail_pos)
self.add_path("m2",[msb_out_pos,out_extend_right_pos,out_extend_up_pos])
self.add_wire(("m3","via2","m2"),[out_extend_right_pos,out_extend_up_pos,rail_pos])
self.add_via_center(self.m2_stack,rail_pos)
# Connect the output to select 1
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_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)
self.add_path("metal2",[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_via_center(("metal2","via2","metal3"),rail_pos)
self.add_path("m2",[msb_out_pos,out_extend_right_pos,out_extend_down_pos])
self.add_wire(("m3","via2","m2"),[out_extend_right_pos,out_extend_down_pos,rail_pos])
self.add_via_center(self.m2_stack,rail_pos)
# Connect clk
clk_pin = self.msb_address_inst.get_pin("clk")
clk_pos = clk_pin.bc()
rail_pos = self.horz_control_bus_positions["clk_buf"]
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]:
pin_pos = self.bank_inst[i].get_pin(n).uc()
rail_pos = vector(pin_pos.x,self.data_bus_positions[n].y)
self.add_path("metal2",[pin_pos,rail_pos])
self.add_via_center(("metal2","via2","metal3"),rail_pos)
self.add_path("m2",[pin_pos,rail_pos])
self.add_via_center(self.m2_stack,rail_pos)
self.route_single_msb_address()
@ -216,8 +216,8 @@ class sram_2bank(sram_base):
pin0_pos = self.bank_inst[0].get_pin(n).rc()
pin1_pos = self.bank_inst[1].get_pin(n).lc()
rail_pos = vector(self.vert_control_bus_positions[n].x,pin0_pos.y)
self.add_path("metal3",[pin0_pos,pin1_pos])
self.add_via_center(("metal2","via2","metal3"),rail_pos)
self.add_path("m3",[pin0_pos,pin1_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:
self.add_label(text=n,
layer="metal2",
layer="m2",
offset=self.vert_control_bus_positions[n])
for n in self.bank_sel_bus_names:
self.add_label(text=n,
layer="metal2",
layer="m2",
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):
design.__init__(self, name)
lef.__init__(self, ["metal1", "metal2", "metal3", "metal4"])
lef.__init__(self, ["m1", "m2", "m3", "m4"])
verilog.__init__(self)
self.sram_config = sram_config
@ -148,13 +148,13 @@ class sram_base(design, verilog, lef):
if not OPTS.route_supplies:
# Do not route the power supply (leave as must-connect pins)
return
elif "metal4" in tech.layer:
elif "m4" in tech.layer:
# Route a M3/M4 grid
from supply_grid_router import supply_grid_router as router
rtr=router(("metal3","via3","metal4"), self)
elif "metal3" in tech.layer:
rtr=router(self.m3_stack, self)
elif "m3" in tech.layer:
from supply_tree_router import supply_tree_router as router
rtr=router(("metal3",), self)
rtr=router(("m3",), self)
rtr.route()
@ -200,14 +200,14 @@ class sram_base(design, verilog, lef):
self.control_bus_names[port].extend([wen, pen])
else:
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,
offset=self.vertical_bus_offset,
names=self.control_bus_names[port],
length=self.vertical_bus_height)
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,
offset=self.addr_bus_offset,
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.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,
offset=self.bank_sel_bus_offset,
names=self.bank_sel_bus_names,
@ -224,7 +224,7 @@ class sram_base(design, verilog, lef):
# Horizontal data bus
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,
offset=self.data_bus_offset,
names=self.data_bus_names,
@ -233,19 +233,19 @@ class sram_base(design, verilog, lef):
# Horizontal control logic bus
# vdd/gnd in bus go along whole SRAM
# 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,
offset=self.supply_bus_offset,
names=["vdd"],
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 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,
offset=self.supply_bus_offset+vector(0,self.m1_pitch),
names=["gnd"],
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,
offset=self.control_bus_offset,
names=self.control_bus_names[port],
@ -529,12 +529,12 @@ class sram_base(design, verilog, lef):
out_pos = dest_pin.uc()
# move horizontal first
self.add_wire(("metal3","via2","metal2"),[in_pos, vector(out_pos.x,in_pos.y),out_pos])
if src_pin.layer=="metal1":
self.add_via_center(layers=("metal1","via1","metal2"),
self.add_wire(("m3","via2","m2"),[in_pos, vector(out_pos.x,in_pos.y),out_pos])
if src_pin.layer=="m1":
self.add_via_center(layers=self.m1_stack,
offset=in_pos)
if src_pin.layer in ["metal1","metal2"]:
self.add_via_center(layers=("metal2","via2","metal3"),
if src_pin.layer in ["m1","m2"]:
self.add_via_center(layers=self.m2_stack,
offset=in_pos)

View File

@ -23,8 +23,8 @@ class path_test(openram_test):
import tech
import design
min_space = 2 * tech.drc["minwidth_metal1"]
layer_stack = ("metal1")
min_space = 2 * tech.drc["minwidth_m1"]
layer_stack = ("m1")
# checks if we can retrace a path
position_list = [[0,0],
[0, 3 * min_space ],
@ -37,8 +37,8 @@ class path_test(openram_test):
self.local_drc_check(w)
min_space = 2 * tech.drc["minwidth_metal1"]
layer_stack = ("metal1")
min_space = 2 * tech.drc["minwidth_m1"]
layer_stack = ("m1")
old_position_list = [[0, 0],
[0, 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)
self.local_drc_check(w)
min_space = 2 * tech.drc["minwidth_metal2"]
layer_stack = ("metal2")
min_space = 2 * tech.drc["minwidth_m2"]
layer_stack = ("m2")
old_position_list = [[0, 0],
[0, 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)
self.local_drc_check(w)
min_space = 2 * tech.drc["minwidth_metal3"]
layer_stack = ("metal3")
min_space = 2 * tech.drc["minwidth_m3"]
layer_stack = ("m3")
position_list = [[0, 0],
[0, 3 * min_space],
[1 * min_space, 3 * min_space],

View File

@ -24,7 +24,7 @@ class wire_test(openram_test):
import design
min_space = 2 * (tech.drc["minwidth_poly"] +
tech.drc["minwidth_metal1"])
tech.drc["minwidth_m1"])
layer_stack = tech.poly_stack
old_position_list = [[0, 0],
[0, 3 * min_space],
@ -41,7 +41,7 @@ class wire_test(openram_test):
self.local_drc_check(w)
min_space = 2 * (tech.drc["minwidth_poly"] +
tech.drc["minwidth_metal1"])
tech.drc["minwidth_m1"])
layer_stack = tech.poly_stack
old_position_list = [[0, 0],
[0, 3 * min_space],
@ -57,8 +57,8 @@ class wire_test(openram_test):
wire.wire(w, layer_stack, position_list)
self.local_drc_check(w)
min_space = 2 * (tech.drc["minwidth_metal2"] +
tech.drc["minwidth_metal1"])
min_space = 2 * (tech.drc["minwidth_m2"] +
tech.drc["minwidth_m1"])
layer_stack = tech.m1_stack
position_list = [[0, 0],
[0, 3 * min_space],
@ -74,8 +74,8 @@ class wire_test(openram_test):
self.local_drc_check(w)
min_space = 2 * (tech.drc["minwidth_metal2"] +
tech.drc["minwidth_metal1"])
min_space = 2 * (tech.drc["minwidth_m2"] +
tech.drc["minwidth_m1"])
layer_stack = tech.m2_stack[::-1]
position_list = [[0, 0],
[0, 3 * min_space],
@ -90,8 +90,8 @@ class wire_test(openram_test):
wire.wire(w, layer_stack, position_list)
self.local_drc_check(w)
min_space = 2 * (tech.drc["minwidth_metal2"] +
tech.drc["minwidth_metal3"])
min_space = 2 * (tech.drc["minwidth_m2"] +
tech.drc["minwidth_m3"])
layer_stack = tech.m2_stack
position_list = [[0, 0],
[0, 3 * min_space],
@ -107,8 +107,8 @@ class wire_test(openram_test):
wire.wire(w, layer_stack, position_list)
self.local_drc_check(w)
min_space = 2 * (tech.drc["minwidth_metal2"] +
tech.drc["minwidth_metal3"])
min_space = 2 * (tech.drc["minwidth_m2"] +
tech.drc["minwidth_m3"])
layer_stack = tech.m2_stack[::-1]
position_list = [[0, 0],
[0, 3 * min_space],

View File

@ -39,17 +39,17 @@ GDS["zoom"] = 0.05
# Interconnect stacks
###################################################
poly_stack = ("poly", "contact", "metal1")
active_stack = ("active", "contact", "metal1")
m1_stack = ("metal1", "via1", "metal2")
m2_stack = ("metal2", "via2", "metal3")
m3_stack = ("metal3", "via3", "metal4")
poly_stack = ("poly", "contact", "m1")
active_stack = ("active", "contact", "m1")
m1_stack = ("m1", "via1", "m2")
m2_stack = ("m2", "via2", "m3")
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,
active_stack]
# The BEOL stacks are metal1 and up
# The BEOL stacks are m1 and up
beol_stacks = [m1_stack,
m2_stack,
m3_stack]
@ -73,25 +73,25 @@ layer["vth"] = (7, 0)
layer["thkox"] = (8, 0)
layer["poly"] = (9, 0)
layer["contact"] = (10, 0)
layer["metal1"] = (11, 0)
layer["m1"] = (11, 0)
layer["via1"] = (12, 0)
layer["metal2"] = (13, 0)
layer["m2"] = (13, 0)
layer["via2"] = (14, 0)
layer["metal3"] = (15, 0)
layer["m3"] = (15, 0)
layer["via3"] = (16, 0)
layer["metal4"] = (17, 0)
layer["m4"] = (17, 0)
layer["via4"] = (18, 0)
layer["metal5"] = (19, 0)
layer["m5"] = (19, 0)
layer["via5"] = (20, 0)
layer["metal6"] = (21, 0)
layer["m6"] = (21, 0)
layer["via6"] = (22, 0)
layer["metal7"] = (23, 0)
layer["m7"] = (23, 0)
layer["via7"] = (24, 0)
layer["metal8"] = (25, 0)
layer["m8"] = (25, 0)
layer["via8"] = (26, 0)
layer["metal9"] = (27, 0)
layer["m9"] = (27, 0)
layer["via9"] = (28, 0)
layer["metal10"] = (29, 0)
layer["m10"] = (29, 0)
layer["text"] = (239, 0)
layer["boundary"]= (239, 0)
@ -144,7 +144,7 @@ drc["poly_extend_active"] = 0.055
# Not a rule
drc["poly_to_contact"] = 0.075
# 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
drc["poly_to_active"] = 0.05
# POLY.6 Minimum Minimum spacing of field poly
@ -153,7 +153,7 @@ drc["poly_to_field_poly"] = 0.075
drc["minarea_poly"] = 0.0
# 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
drc.add_layer("active",
width = 0.09,
@ -212,17 +212,17 @@ drc["contact_to_poly"] = 0.090
# METAL1.1 Minimum width of metal1
# METAL1.2 Minimum spacing of metal1
drc.add_layer("metal1",
drc.add_layer("m1",
width = 0.065,
spacing = 0.065)
# METAL1.3 Minimum enclosure around contact on two opposite sides
drc.add_enclosure("metal1",
drc.add_enclosure("m1",
layer = "contact",
enclosure = 0,
extension = 0.035)
# METAL1.4 inimum enclosure around via1 on two opposite sides
drc.add_enclosure("metal1",
drc.add_enclosure("m1",
layer = "via1",
enclosure = 0,
extension = 0.035)
@ -236,18 +236,18 @@ drc.add_layer("via1",
# METALINT.1 Minimum width of intermediate metal
# METALINT.2 Minimum spacing of intermediate metal
drc.add_layer("metal2",
drc.add_layer("m2",
width = 0.07,
spacing = 0.07)
# METALINT.3 Minimum enclosure around via1 on two opposite sides
drc.add_enclosure("metal2",
drc.add_enclosure("m2",
layer = "via1",
enclosure = 0,
extension = 0.035)
# METALINT.4 Minimum enclosure around via[2-3] on two opposite sides
drc.add_enclosure("metal2",
drc.add_enclosure("m2",
layer = "via2",
enclosure = 0,
extension = 0.035)
@ -260,12 +260,12 @@ drc.add_layer("via2",
# METALINT.1 Minimum width 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 metal3 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 metal3 wider than 0.9 & longer than 2.7 = 0.9
# Minimum spacing of metal3 wider than 1.5 & longer than 4.0 = 1.5
drc.add_layer("metal3",
# Minimum spacing of m3 wider than 0.09 & longer than 0.3 = 0.09
# Minimum spacing of m3 wider than 0.27 & longer than 0.9 = 0.27
# Minimum spacing of m3 wider than 0.5 & longer than 1.8 = 0.5
# Minimum spacing of m3 wider than 0.9 & longer than 2.7 = 0.9
# Minimum spacing of m3 wider than 1.5 & longer than 4.0 = 1.5
drc.add_layer("m3",
width = 0.07,
spacing = drc_lut({(0.00, 0.0) : 0.07,
(0.09, 0.3) : 0.09,
@ -274,13 +274,13 @@ drc.add_layer("metal3",
(0.90, 2.7) : 0.9,
(1.50, 4.0) : 1.5}))
# METALINT.3 Minimum enclosure around via1 on two opposite sides
drc.add_enclosure("metal3",
drc.add_enclosure("m3",
layer = "via2",
enclosure = 0,
extension = 0.035)
# METALINT.4 Minimum enclosure around via[2-3] on two opposite sides
drc.add_enclosure("metal3",
drc.add_enclosure("m3",
layer = "via3",
enclosure = 0,
extension = 0.035)
@ -293,11 +293,11 @@ drc.add_layer("via3",
# METALSMG.1 Minimum width 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 metal4 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 metal4 wider than 1.5 & longer than 4.0 = 1.5
drc.add_layer("metal4",
# Minimum spacing of m4 wider than 0.27 & longer than 0.9 = 0.27
# Minimum spacing of m4 wider than 0.5 & longer than 1.8 = 0.5
# Minimum spacing of m4 wider than 0.9 & longer than 2.7 = 0.9
# Minimum spacing of m4 wider than 1.5 & longer than 4.0 = 1.5
drc.add_layer("m4",
width = 0.14,
spacing = drc_lut({(0.00, 0.0) : 0.14,
(0.27, 0.9) : 0.27,
@ -305,7 +305,7 @@ drc.add_layer("metal4",
(0.90, 2.7) : 0.9,
(1.50, 4.0) : 1.5}))
# METALSMG.3 Minimum enclosure around via[3-6] on two opposite sides
drc.add_enclosure("metal4",
drc.add_enclosure("m4",
layer = "via3",
enclosure = 0.0025)

View File

@ -39,17 +39,17 @@ GDS["zoom"] = 0.5
# Interconnect stacks
###################################################
poly_stack = ("poly", "poly_contact", "metal1")
active_stack = ("active", "active_contact", "metal1")
m1_stack = ("metal1", "via1", "metal2")
m2_stack = ("metal2", "via2", "metal3")
m3_stack = ("metal3", "via3", "metal4")
poly_stack = ("poly", "poly_contact", "m1")
active_stack = ("active", "active_contact", "m1")
m1_stack = ("m1", "via1", "m2")
m2_stack = ("m2", "via2", "m3")
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,
active_stack]
# The BEOL stacks are metal1 and up
# The BEOL stacks are m1 and up
beol_stacks = [m1_stack,
m2_stack,
m3_stack]
@ -73,13 +73,13 @@ layer["nimplant"] = (45, 0)
layer["poly"] = (46, 0)
layer["poly_contact"] = (47, 0)
layer["active_contact"] = (48, 0)
layer["metal1"] = (49, 0)
layer["m1"] = (49, 0)
layer["via1"] = (50, 0)
layer["metal2"] = (51, 0)
layer["m2"] = (51, 0)
layer["via2"] = (61, 0)
layer["metal3"] = (62, 0)
layer["m3"] = (62, 0)
layer["via3"] = (30, 0)
layer["metal4"] = (31, 0)
layer["m4"] = (31, 0)
layer["text"] = (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)
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
drc["poly_to_active"] = _lambda_
# 3.2.a Minimum spacing over field poly
drc["poly_to_field_poly"] = 3*_lambda_
# ??
drc["active_to_body_active"] = 4*_lambda_ # Fix me
# 2.1 Minimum width
# 2.2 Minimum spacing
drc.add_layer("active",
width = 3*_lambda_,
spacing = 3*_lambda_)
spacing = 4*_lambda_)
# 2.3 Source/drain active to well edge
drc.add_enclosure("well",
layer = "active",
@ -200,18 +199,18 @@ drc["poly_contact_to_poly"] = 2*_lambda_
# 7.1 Minimum width
# 7.2 Minimum spacing
drc.add_layer("metal1",
drc.add_layer("m1",
width = 3*_lambda_,
spacing = 3*_lambda_)
# 7.3 Minimum overlap of any contact
drc.add_enclosure("metal1",
drc.add_enclosure("m1",
layer = "poly_contact",
enclosure = _lambda_)
drc.add_enclosure("metal1",
drc.add_enclosure("m1",
layer = "active_contact",
enclosure = _lambda_)
# 8.3 Minimum overlap by metal1
drc.add_enclosure("metal1",
# 8.3 Minimum overlap by m1
drc.add_enclosure("m1",
layer = "via1",
enclosure = _lambda_)
@ -223,15 +222,15 @@ drc.add_layer("via1",
# 9.1 Minimum width
# 9.2 Minimum spacing
drc.add_layer("metal2",
drc.add_layer("m2",
width = 3*_lambda_,
spacing = 3*_lambda_)
# 9.3 Minimum overlap of via1
drc.add_enclosure("metal2",
drc.add_enclosure("m2",
layer = "via1",
enclosure = _lambda_)
# 14.3 Minimum overlap by metal2
drc.add_enclosure("metal2",
# 14.3 Minimum overlap by m2
drc.add_enclosure("m2",
layer = "via2",
enclosure = _lambda_)
@ -242,18 +241,18 @@ drc.add_layer("via2",
spacing = 3*_lambda_)
# 15.1 Minimum width
# 15.2 Minimum spacing to metal3
drc.add_layer("metal3",
# 15.2 Minimum spacing to m3
drc.add_layer("m3",
width = 3*_lambda_,
spacing = 3*_lambda_)
# 15.3 Minimum overlap of via 2
drc.add_enclosure("metal3",
drc.add_enclosure("m3",
layer = "via2",
enclosure = _lambda_)
# 21.3 Minimum overlap by metal3
drc.add_enclosure("metal3",
# 21.3 Minimum overlap by m3
drc.add_enclosure("m3",
layer = "via3",
enclosure = _lambda_)
@ -264,13 +263,13 @@ drc.add_layer("via3",
spacing = 3*_lambda_)
# 22.1 Minimum width
# 22.2 Minimum spacing to metal4
drc.add_layer("metal4",
# 22.2 Minimum spacing to m4
drc.add_layer("m4",
width = 6*_lambda_,
spacing = 6*_lambda_)
# 22.3 Minimum overlap of via 3
drc.add_enclosure("metal4",
drc.add_enclosure("m4",
layer = "via3",
enclosure = 2*_lambda_)