From ed28b4983bdd6232e91472fd82022fd7cc2f1966 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Tue, 17 Dec 2019 11:03:36 -0800 Subject: [PATCH] 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. --- compiler/base/contact.py | 18 ++-- compiler/base/design.py | 88 ++++++++++++------- compiler/base/hierarchy_layout.py | 54 ++++++------ compiler/bitcells/pbitcell.py | 54 ++++++------ compiler/drc/design_rules.py | 8 +- compiler/modules/bank.py | 26 +++--- compiler/modules/bank_select.py | 26 +++--- compiler/modules/bitcell_array.py | 4 +- compiler/modules/control_logic.py | 54 ++++++------ compiler/modules/delay_chain.py | 28 +++--- compiler/modules/dff_array.py | 12 +-- compiler/modules/dff_buf.py | 26 +++--- compiler/modules/dff_buf_array.py | 16 ++-- compiler/modules/dff_inv.py | 16 ++-- compiler/modules/dff_inv_array.py | 16 ++-- compiler/modules/dummy_array.py | 4 +- compiler/modules/hierarchical_decoder.py | 16 ++-- compiler/modules/hierarchical_predecode.py | 18 ++-- compiler/modules/multibank.py | 58 ++++++------ compiler/modules/port_address.py | 4 +- compiler/modules/port_data.py | 8 +- compiler/modules/precharge_array.py | 12 +-- compiler/modules/replica_bitcell_array.py | 2 +- compiler/modules/replica_column.py | 4 +- compiler/modules/sense_amp_array.py | 14 +-- .../modules/single_level_column_mux_array.py | 20 ++--- compiler/modules/tri_gate_array.py | 14 +-- compiler/modules/wordline_driver.py | 12 +-- compiler/modules/write_driver_array.py | 10 +-- compiler/modules/write_mask_and_array.py | 6 +- compiler/pgates/pand2.py | 6 +- compiler/pgates/pand3.py | 6 +- compiler/pgates/pbuf.py | 6 +- compiler/pgates/pdriver.py | 6 +- compiler/pgates/pgate.py | 12 +-- compiler/pgates/pinv.py | 16 ++-- compiler/pgates/pinvbuf.py | 16 ++-- compiler/pgates/pnand2.py | 14 +-- compiler/pgates/pnand3.py | 16 ++-- compiler/pgates/pnor2.py | 17 ++-- compiler/pgates/precharge.py | 16 ++-- compiler/pgates/ptristate_inv.py | 8 +- compiler/pgates/ptx.py | 26 +++--- compiler/pgates/pwrite_driver.py | 58 ++++++------ compiler/pgates/single_level_column_mux.py | 18 ++-- compiler/sram/sram_1bank.py | 22 ++--- compiler/sram/sram_2bank.py | 60 ++++++------- compiler/sram/sram_base.py | 34 +++---- compiler/tests/03_path_test.py | 16 ++-- compiler/tests/03_wire_test.py | 20 ++--- technology/freepdk45/tech/tech.py | 78 ++++++++-------- technology/scn4m_subm/tech/tech.py | 63 +++++++------ 52 files changed, 604 insertions(+), 578 deletions(-) diff --git a/compiler/base/contact.py b/compiler/base/contact.py index 5f169e07..c5b1ef9e 100644 --- a/compiler/base/contact.py +++ b/compiler/base/contact.py @@ -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")) diff --git a/compiler/base/design.py b/compiler/base/design.py index 7ee1624d..3b6ae914 100644 --- a/compiler/base/design.py +++ b/compiler/base/design.py @@ -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. diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index ad1e3edb..7f23e942 100644 --- a/compiler/base/hierarchy_layout.py +++ b/compiler/base/hierarchy_layout.py @@ -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 diff --git a/compiler/bitcells/pbitcell.py b/compiler/bitcells/pbitcell.py index 8f9cd602..bdb9161b 100644 --- a/compiler/bitcells/pbitcell.py +++ b/compiler/bitcells/pbitcell.py @@ -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): """ diff --git a/compiler/drc/design_rules.py b/compiler/drc/design_rules.py index cf54bdb3..05168b77 100644 --- a/compiler/drc/design_rules.py +++ b/compiler/drc/design_rules.py @@ -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) diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index b1ce2d55..4527044c 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -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) diff --git a/compiler/modules/bank_select.py b/compiler/modules/bank_select.py index 14b6b203..4b49750d 100644 --- a/compiler/modules/bank_select.py +++ b/compiler/modules/bank_select.py @@ -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()) diff --git a/compiler/modules/bitcell_array.py b/compiler/modules/bitcell_array.py index b1b61487..bf43736b 100644 --- a/compiler/modules/bitcell_array.py +++ b/compiler/modules/bitcell_array.py @@ -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 diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index 3256c9ac..dbb7c3b7 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -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()) diff --git a/compiler/modules/delay_chain.py b/compiler/modules/delay_chain.py index bc932a26..a07576d4 100644 --- a/compiler/modules/delay_chain.py +++ b/compiler/modules/delay_chain.py @@ -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)) diff --git a/compiler/modules/dff_array.py b/compiler/modules/dff_array.py index 89b29476..6ba020c7 100644 --- a/compiler/modules/dff_array.py +++ b/compiler/modules/dff_array.py @@ -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): diff --git a/compiler/modules/dff_buf.py b/compiler/modules/dff_buf.py index f6fc1cf2..9e2ff0aa 100644 --- a/compiler/modules/dff_buf.py +++ b/compiler/modules/dff_buf.py @@ -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): diff --git a/compiler/modules/dff_buf_array.py b/compiler/modules/dff_buf_array.py index 2fafee76..8b8e21dc 100644 --- a/compiler/modules/dff_buf_array.py +++ b/compiler/modules/dff_buf_array.py @@ -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): diff --git a/compiler/modules/dff_inv.py b/compiler/modules/dff_inv.py index 207a5ad0..9dcb84c5 100644 --- a/compiler/modules/dff_inv.py +++ b/compiler/modules/dff_inv.py @@ -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): diff --git a/compiler/modules/dff_inv_array.py b/compiler/modules/dff_inv_array.py index 760a2337..aadb4257 100644 --- a/compiler/modules/dff_inv_array.py +++ b/compiler/modules/dff_inv_array.py @@ -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): diff --git a/compiler/modules/dummy_array.py b/compiler/modules/dummy_array.py index f1f433ce..1e5a2121 100644 --- a/compiler/modules/dummy_array.py +++ b/compiler/modules/dummy_array.py @@ -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()) diff --git a/compiler/modules/hierarchical_decoder.py b/compiler/modules/hierarchical_decoder.py index 9c7cafd8..bb637ed1 100644 --- a/compiler/modules/hierarchical_decoder.py +++ b/compiler/modules/hierarchical_decoder.py @@ -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) diff --git a/compiler/modules/hierarchical_predecode.py b/compiler/modules/hierarchical_predecode.py index 0de67cae..dec04073 100644 --- a/compiler/modules/hierarchical_predecode.py +++ b/compiler/modules/hierarchical_predecode.py @@ -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()) diff --git a/compiler/modules/multibank.py b/compiler/modules/multibank.py index 3459f5e0..33076bfb 100644 --- a/compiler/modules/multibank.py +++ b/compiler/modules/multibank.py @@ -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) diff --git a/compiler/modules/port_address.py b/compiler/modules/port_address.py index 0a624c60..7f1fdd49 100644 --- a/compiler/modules/port_address.py +++ b/compiler/modules/port_address.py @@ -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) diff --git a/compiler/modules/port_data.py b/compiler/modules/port_data.py index a5bc4399..33ecdd01 100644 --- a/compiler/modules/port_data.py +++ b/compiler/modules/port_data.py @@ -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): diff --git a/compiler/modules/precharge_array.py b/compiler/modules/precharge_array.py index 2d98ba14..c2617f50 100644 --- a/compiler/modules/precharge_array.py +++ b/compiler/modules/precharge_array.py @@ -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()) diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index 639d0714..74962ba2 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -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 diff --git a/compiler/modules/replica_column.py b/compiler/modules/replica_column.py index c3f63b19..5552ed55 100644 --- a/compiler/modules/replica_column.py +++ b/compiler/modules/replica_column.py @@ -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()) diff --git a/compiler/modules/sense_amp_array.py b/compiler/modules/sense_amp_array.py index 21ee4a8d..2447e4b8 100644 --- a/compiler/modules/sense_amp_array.py +++ b/compiler/modules/sense_amp_array.py @@ -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() diff --git a/compiler/modules/single_level_column_mux_array.py b/compiler/modules/single_level_column_mux_array.py index 3e6420b9..09f21cfa 100644 --- a/compiler/modules/single_level_column_mux_array.py +++ b/compiler/modules/single_level_column_mux_array.py @@ -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, diff --git a/compiler/modules/tri_gate_array.py b/compiler/modules/tri_gate_array.py index 501e2389..e7ebd802 100644 --- a/compiler/modules/tri_gate_array.py +++ b/compiler/modules/tri_gate_array.py @@ -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")) \ No newline at end of file + height=drc("minwidth_m1")) \ No newline at end of file diff --git a/compiler/modules/wordline_driver.py b/compiler/modules/wordline_driver.py index 99365659..2af2c8c9 100644 --- a/compiler/modules/wordline_driver.py +++ b/compiler/modules/wordline_driver.py @@ -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)) diff --git a/compiler/modules/write_driver_array.py b/compiler/modules/write_driver_array.py index 4dfa938c..ac4dab00 100644 --- a/compiler/modules/write_driver_array.py +++ b/compiler/modules/write_driver_array.py @@ -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) diff --git a/compiler/modules/write_mask_and_array.py b/compiler/modules/write_mask_and_array.py index 3a4ec651..40f386d2 100644 --- a/compiler/modules/write_mask_and_array.py +++ b/compiler/modules/write_mask_and_array.py @@ -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""" diff --git a/compiler/pgates/pand2.py b/compiler/pgates/pand2.py index d410a8c7..23fd5e5b 100644 --- a/compiler/pgates/pand2.py +++ b/compiler/pgates/pand2.py @@ -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()) diff --git a/compiler/pgates/pand3.py b/compiler/pgates/pand3.py index b02e18e4..dd1d87f7 100644 --- a/compiler/pgates/pand3.py +++ b/compiler/pgates/pand3.py @@ -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()) diff --git a/compiler/pgates/pbuf.py b/compiler/pgates/pbuf.py index 0149f75f..3171324b 100644 --- a/compiler/pgates/pbuf.py +++ b/compiler/pgates/pbuf.py @@ -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()) diff --git a/compiler/pgates/pdriver.py b/compiler/pgates/pdriver.py index bb7739b7..5aa5393e 100644 --- a/compiler/pgates/pdriver.py +++ b/compiler/pgates/pdriver.py @@ -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()) diff --git a/compiler/pgates/pgate.py b/compiler/pgates/pgate.py index b55ad9c3..d5f2395b 100644 --- a/compiler/pgates/pgate.py +++ b/compiler/pgates/pgate.py @@ -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) diff --git a/compiler/pgates/pinv.py b/compiler/pgates/pinv.py index 5c53480b..1ff5b67b 100644 --- a/compiler/pgates/pinv.py +++ b/compiler/pgates/pinv.py @@ -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)) diff --git a/compiler/pgates/pinvbuf.py b/compiler/pgates/pinvbuf.py index 579e1198..b8ecb3bf 100644 --- a/compiler/pgates/pinvbuf.py +++ b/compiler/pgates/pinvbuf.py @@ -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()) diff --git a/compiler/pgates/pnand2.py b/compiler/pgates/pnand2.py index 4623048c..8acde2ce 100644 --- a/compiler/pgates/pnand2.py +++ b/compiler/pgates/pnand2.py @@ -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) diff --git a/compiler/pgates/pnand3.py b/compiler/pgates/pnand3.py index 6d885e25..7a773497 100644 --- a/compiler/pgates/pnand3.py +++ b/compiler/pgates/pnand3.py @@ -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) diff --git a/compiler/pgates/pnor2.py b/compiler/pgates/pnor2.py index a79d19a0..d75df0a9 100644 --- a/compiler/pgates/pnor2.py +++ b/compiler/pgates/pnor2.py @@ -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) diff --git a/compiler/pgates/precharge.py b/compiler/pgates/precharge.py index 9641a1f3..784bb418 100644 --- a/compiler/pgates/precharge.py +++ b/compiler/pgates/precharge.py @@ -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""" diff --git a/compiler/pgates/ptristate_inv.py b/compiler/pgates/ptristate_inv.py index 4a17b46a..5c0028b2 100644 --- a/compiler/pgates/ptristate_inv.py +++ b/compiler/pgates/ptristate_inv.py @@ -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) diff --git a/compiler/pgates/ptx.py b/compiler/pgates/ptx.py index 61610a88..9907485f 100644 --- a/compiler/pgates/ptx.py +++ b/compiler/pgates/ptx.py @@ -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) diff --git a/compiler/pgates/pwrite_driver.py b/compiler/pgates/pwrite_driver.py index a808737b..2dc356c3 100644 --- a/compiler/pgates/pwrite_driver.py +++ b/compiler/pgates/pwrite_driver.py @@ -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()) diff --git a/compiler/pgates/single_level_column_mux.py b/compiler/pgates/single_level_column_mux.py index 525c1680..18b4b10f 100644 --- a/compiler/pgates/single_level_column_mux.py +++ b/compiler/pgates/single_level_column_mux.py @@ -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 diff --git a/compiler/sram/sram_1bank.py b/compiler/sram/sram_1bank.py index 6c887790..151c8a70 100644 --- a/compiler/sram/sram_1bank.py +++ b/compiler/sram/sram_1bank.py @@ -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, diff --git a/compiler/sram/sram_2bank.py b/compiler/sram/sram_2bank.py index e1224795..dace1ed9 100644 --- a/compiler/sram/sram_2bank.py +++ b/compiler/sram/sram_2bank.py @@ -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()