diff --git a/compiler/base/contact.py b/compiler/base/contact.py index 26a59d31..5f169e07 100644 --- a/compiler/base/contact.py +++ b/compiler/base/contact.py @@ -245,14 +245,14 @@ else: lim1 = None m1m2 = factory.create(module_type="contact", - layer_stack=metal1_stack, + layer_stack=m1_stack, directions=("H", "V")) m2m3 = factory.create(module_type="contact", - layer_stack=metal2_stack, + layer_stack=m2_stack, directions=("V", "H")) if "metal4" in layer.keys(): m3m4 = factory.create(module_type="contact", - layer_stack=metal3_stack, + layer_stack=m3_stack, directions=("H", "V")) else: m3m4 = None diff --git a/compiler/base/design.py b/compiler/base/design.py index 0ecfbbd4..16237cfd 100644 --- a/compiler/base/design.py +++ b/compiler/base/design.py @@ -13,7 +13,7 @@ from globals import OPTS class design(hierarchy_design): """ This is the same as the hierarchy_design class except it contains - some DRC constants and analytical models for other modules to reuse. + some DRC/layer constants and analytical models for other modules to reuse. """ @@ -21,16 +21,28 @@ class design(hierarchy_design): hierarchy_design.__init__(self, name) self.setup_drc_constants() + self.setup_layer_constants() self.setup_multiport_constants() - from tech import layer + + def setup_layer_constants(self): + """ These are some layer constants used in many places in the compiler.""" + + import tech + 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 layer: + if "metal4" 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 + self.poly_stack = tech.poly_stack + self.active_stack = tech.active_stack + self.m1_stack = tech.m1_stack + self.m2_stack = tech.m2_stack + self.m3_stack = tech.m3_stack + def setup_drc_constants(self): """ These are some DRC constants used in many places in the compiler.""" from tech import drc, layer diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index 494ab4ca..ad1e3edb 100644 --- a/compiler/base/hierarchy_layout.py +++ b/compiler/base/hierarchy_layout.py @@ -824,7 +824,7 @@ class layout(): def create_channel_route(self, netlist, offset, - layer_stack=("metal1", "via1", "metal2"), + layer_stack, vertical=False): """ The net list is a list of the nets. Each net is a list of pins @@ -950,15 +950,13 @@ class layout(): offset += vector(0,self.horizontal_pitch) - def create_vertical_channel_route(self, netlist, offset, - layer_stack=("metal1", "via1", "metal2")): + def create_vertical_channel_route(self, netlist, offset, layer_stack): """ Wrapper to create a vertical channel route """ self.create_channel_route(netlist, offset, layer_stack, vertical=True) - def create_horizontal_channel_route(self, netlist, offset, - layer_stack=("metal1", "via1", "metal2")): + def create_horizontal_channel_route(self, netlist, offset, layer_stack): """ Wrapper to create a horizontal channel route """ @@ -1028,13 +1026,13 @@ class layout(): direction=("H","H") if start_layer=="metal1": - self.add_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=loc, directions=direction) if start_layer=="metal1" or start_layer=="metal2": - via=self.add_via_center(layers=("metal2", "via2", "metal3"), + via=self.add_via_center(layers=self.m2_stack, offset=loc, directions=direction) @@ -1159,7 +1157,7 @@ class layout(): vector(self.right_vdd_x_center, self.top_vdd_y_center)] for pt in via_points: - self.add_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=pt, size = (self.supply_vias, self.supply_vias)) diff --git a/compiler/bitcells/pbitcell.py b/compiler/bitcells/pbitcell.py index 1e3eb506..0f4b8183 100644 --- a/compiler/bitcells/pbitcell.py +++ b/compiler/bitcells/pbitcell.py @@ -378,7 +378,7 @@ class pbitcell(bitcell_base.bitcell_base): contact_offset_left = vector(self.inverter_nmos_left.get_pin("D").rc().x \ + 0.5 * contact.poly.height, self.cross_couple_upper_ypos) - self.add_via_center(layers=("poly", "contact", "metal1"), + self.add_via_center(layers=self.poly_stack, offset=contact_offset_left, directions=("H", "H")) @@ -386,7 +386,7 @@ class pbitcell(bitcell_base.bitcell_base): contact_offset_right = vector(self.inverter_nmos_right.get_pin("S").lc().x \ - 0.5*contact.poly.height, self.cross_couple_lower_ypos) - self.add_via_center(layers=("poly", "contact", "metal1"), + self.add_via_center(layers=self.poly_stack, offset=contact_offset_right, directions=("H", "H")) @@ -771,7 +771,7 @@ class pbitcell(bitcell_base.bitcell_base): # first transistor on either side of the cross coupled inverters # does not need to route to wordline on metal2 if (k == 0) or (k == 1): - self.add_via_center(layers=("poly", "contact", "metal1"), + self.add_via_center(layers=self.poly_stack, offset=port_contact_offset) self.add_path("poly", [gate_offset, port_contact_offset]) @@ -779,12 +779,12 @@ class pbitcell(bitcell_base.bitcell_base): [port_contact_offset, wl_contact_offset]) else: - self.add_via_center(layers=("poly", "contact", "metal1"), + self.add_via_center(layers=self.poly_stack, offset=port_contact_offset) - self.add_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=port_contact_offset) - self.add_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=wl_contact_offset, directions=("H", "H")) @@ -824,7 +824,7 @@ class pbitcell(bitcell_base.bitcell_base): # Leave bitline disconnected if a dummy cell if not self.dummy_bitcell: - self.add_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=port_contact_offest) self.add_path("metal2", @@ -836,7 +836,7 @@ class pbitcell(bitcell_base.bitcell_base): # Leave bitline disconnected if a dummy cell if not self.dummy_bitcell: - self.add_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=port_contact_offest) self.add_path("metal2", @@ -853,7 +853,7 @@ class pbitcell(bitcell_base.bitcell_base): nmos_contact_positions.append(self.read_access_nmos_right[k].get_pin("S").center()) for position in nmos_contact_positions: - self.add_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=position) if position.x > 0: @@ -862,7 +862,7 @@ class pbitcell(bitcell_base.bitcell_base): contact_correct = -0.5 * contact.m1m2.height supply_offset = vector(position.x + contact_correct, self.gnd_position.y) - self.add_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=supply_offset, directions=("H", "H")) @@ -928,14 +928,14 @@ class pbitcell(bitcell_base.bitcell_base): left_storage_contact = vector(self.inverter_nmos_left.get_pin("G").lc().x \ - self.poly_to_contact - 0.5*contact.poly.width, self.cross_couple_upper_ypos) - self.add_via_center(layers=("poly", "contact", "metal1"), + self.add_via_center(layers=self.poly_stack, offset=left_storage_contact, directions=("H", "H")) right_storage_contact = vector(self.inverter_nmos_right.get_pin("G").rc().x \ + self.poly_to_contact + 0.5*contact.poly.width, self.cross_couple_upper_ypos) - self.add_via_center(layers=("poly", "contact", "metal1"), + self.add_via_center(layers=self.poly_stack, offset=right_storage_contact, directions=("H", "H")) @@ -952,7 +952,7 @@ class pbitcell(bitcell_base.bitcell_base): + vector(0, self.gate_contact_yoffset - self.poly_extend_active) - self.add_via_center(layers=("poly", "contact", "metal1"), + self.add_via_center(layers=self.poly_stack, offset=port_contact_offset) self.add_path("poly", @@ -967,7 +967,7 @@ class pbitcell(bitcell_base.bitcell_base): + vector(0, self.gate_contact_yoffset - self.poly_extend_active) - self.add_via_center(layers=("poly", "contact", "metal1"), + self.add_via_center(layers=self.poly_stack, offset=port_contact_offset) self.add_path("poly", diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index 3e105d09..b1ce2d55 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -606,11 +606,11 @@ class bank(design.design): 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_via_center(layers=("metal2", "via2", "metal3"), + self.add_via_center(layers=self.m2_stack, offset=bus_pos) - self.add_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=out_pos) - self.add_via_center(layers=("metal2", "via2", "metal3"), + self.add_via_center(layers=self.m2_stack, offset=out_pos) @@ -756,7 +756,7 @@ class bank(design.design): bottom_names = [bottom_inst.get_pin(bottom_bl_name.format(bit)), bottom_inst.get_pin(bottom_br_name.format(bit))] top_names = [top_inst.get_pin(top_bl_name.format(bit)), top_inst.get_pin(top_br_name.format(bit))] route_map = list(zip(bottom_names, top_names)) - self.create_horizontal_channel_route(route_map, offset) + self.create_horizontal_channel_route(route_map, offset, self.m1_stack) def connect_bitline(self, inst1, inst2, inst1_name, inst2_name): """ @@ -865,7 +865,7 @@ class bank(design.design): column_mux_pins = [self.port_data_inst[port].get_pin(x) for x in sel_names] route_map = list(zip(decode_pins, column_mux_pins)) - self.create_vertical_channel_route(route_map, offset) + self.create_vertical_channel_route(route_map, offset, self.m1_stack) def add_lvs_correspondence_points(self): @@ -942,7 +942,7 @@ class bank(design.design): 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_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=control_pos) @@ -957,7 +957,7 @@ class bank(design.design): 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_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=control_pos) def determine_wordline_stage_efforts(self, external_cout, inp_is_rise=True): diff --git a/compiler/modules/bank_select.py b/compiler/modules/bank_select.py index 296cef8b..14b6b203 100644 --- a/compiler/modules/bank_select.py +++ b/compiler/modules/bank_select.py @@ -258,7 +258,7 @@ class bank_select(design.design): 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_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=logic_pos, directions=("H","H")) @@ -266,10 +266,10 @@ class bank_select(design.design): # Connect the logic A input to the input pin logic_pos = logic_inst.get_pin("A").lc() input_pos = vector(0,logic_pos.y) - self.add_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=logic_pos, directions=("H","H")) - self.add_via_center(layers=("metal2", "via2", "metal3"), + self.add_via_center(layers=self.m2_stack, offset=logic_pos, directions=("H","H")) self.add_layout_pin_segment_center(text=input_name, @@ -301,10 +301,10 @@ class bank_select(design.design): # Add pins in two locations for xoffset in [a_xoffset, b_xoffset]: pin_pos = vector(xoffset, supply_pin.cy()) - self.add_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=pin_pos, directions=("H","H")) - self.add_via_center(layers=("metal2", "via2", "metal3"), + self.add_via_center(layers=self.m2_stack, offset=pin_pos, directions=("H","H")) self.add_layout_pin_rect_center(text=n, diff --git a/compiler/modules/hierarchical_decoder.py b/compiler/modules/hierarchical_decoder.py index 4648519a..9c7cafd8 100644 --- a/compiler/modules/hierarchical_decoder.py +++ b/compiler/modules/hierarchical_decoder.py @@ -221,9 +221,9 @@ class hierarchical_decoder(design.design): def route_input_rail(self, input_offset, output_offset): """ Route a vertical M2 coordinate to another vertical M2 coordinate to the predecode inputs """ - self.add_via_center(layers=("metal2", "via2", "metal3"), + self.add_via_center(layers=self.m2_stack, offset=input_offset) - self.add_via_center(layers=("metal2", "via2", "metal3"), + self.add_via_center(layers=self.m2_stack, offset=output_offset) self.add_path(("metal3"), [input_offset, output_offset]) @@ -585,7 +585,7 @@ class hierarchical_decoder(design.design): """ 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_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=rail_pos) @@ -595,10 +595,10 @@ class hierarchical_decoder(design.design): # It would be fixed with a channel router. mid_point = vector(pin.cx(), pin.cy()+self.inv.height/2) rail_pos = vector(self.predecode_rails[rail_name].x,mid_point.y) - self.add_via_center(layers=("metal1", "via1", "metal2"), + 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_via_center(layers=("metal2", "via2", "metal3"), + self.add_via_center(layers=self.m2_stack, offset=rail_pos) def input_load(self): diff --git a/compiler/modules/hierarchical_predecode.py b/compiler/modules/hierarchical_predecode.py index bec0ce06..0de67cae 100644 --- a/compiler/modules/hierarchical_predecode.py +++ b/compiler/modules/hierarchical_predecode.py @@ -184,9 +184,9 @@ class hierarchical_predecode(design.design): 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_via_center(layers = ("metal1", "via1", "metal2"), + self.add_via_center(layers = self.m1_stack, offset=[self.input_rails[in_pin].x, y_offset]) - self.add_via_center(layers = ("metal1", "via1", "metal2"), + self.add_via_center(layers = self.m1_stack, offset=[self.decode_rails[a_pin].x, y_offset]) def route_output_inverters(self): @@ -227,7 +227,7 @@ class hierarchical_predecode(design.design): 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_via_center(layers = ("metal1", "via1", "metal2"), + self.add_via_center(layers = self.m1_stack, offset=rail_pos) @@ -235,7 +235,7 @@ class hierarchical_predecode(design.design): 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_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=in_pos) @@ -256,7 +256,7 @@ class hierarchical_predecode(design.design): 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_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=rail_pos) diff --git a/compiler/modules/multibank.py b/compiler/modules/multibank.py index 2f933a2d..3459f5e0 100644 --- a/compiler/modules/multibank.py +++ b/compiler/modules/multibank.py @@ -452,13 +452,13 @@ class multibank(design.design): 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_via_center(layers=("metal2", "via2", "metal3"), + self.add_via_center(layers=self.m2_stack, offset=bus_pos, rotate=90) - self.add_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=out_pos, rotate=90) - self.add_via_center(layers=("metal2", "via2", "metal3"), + self.add_via_center(layers=self.m2_stack, offset=out_pos, rotate=90) @@ -586,9 +586,9 @@ class multibank(design.design): tri_gate_in = self.tri_gate_array_inst.get_pin("in_{}".format(i)).lc() sa_data_out = self.sense_amp_array_inst.get_pin("data_{}".format(i)).bc() - self.add_via_center(layers=("metal2", "via2", "metal3"), + self.add_via_center(layers=self.m2_stack, offset=tri_gate_in) - self.add_via_center(layers=("metal2", "via2", "metal3"), + self.add_via_center(layers=self.m2_stack, offset=sa_data_out) self.add_path("metal3",[sa_data_out,tri_gate_in]) @@ -766,7 +766,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_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=control_pos, rotate=90) @@ -778,7 +778,7 @@ class multibank(design.design): control_pos = vector(control_x_offset + self.m1_width, mid_pos.y) self.add_wire(("metal1","via1","metal2"),[pin_pos, mid_pos, control_pos]) control_via_pos = vector(control_x_offset, mid_pos.y) - self.add_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=control_via_pos, rotate=90) diff --git a/compiler/modules/port_data.py b/compiler/modules/port_data.py index c3473803..a5bc4399 100644 --- a/compiler/modules/port_data.py +++ b/compiler/modules/port_data.py @@ -475,7 +475,7 @@ class port_data(design.design): end_pos = vector(length, wdriver_en_pin.cy()) # Add via for the write driver array's enable input - self.add_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=end_pos) # Route between write mask AND array and write driver array @@ -626,7 +626,7 @@ class port_data(design.design): bottom_names = [bottom_inst.get_pin(bottom_bl_name.format(bit+bottom_start_bit)), bottom_inst.get_pin(bottom_br_name.format(bit+bottom_start_bit))] top_names = [top_inst.get_pin(top_bl_name.format(bit+top_start_bit)), top_inst.get_pin(top_br_name.format(bit+top_start_bit))] route_map = list(zip(bottom_names, top_names)) - self.create_horizontal_channel_route(route_map, offset) + self.create_horizontal_channel_route(route_map, offset, self.m1_stack) def connect_bitlines(self, inst1, inst2, num_bits, diff --git a/compiler/modules/sense_amp_array.py b/compiler/modules/sense_amp_array.py index 598886c0..21ee4a8d 100644 --- a/compiler/modules/sense_amp_array.py +++ b/compiler/modules/sense_amp_array.py @@ -99,13 +99,13 @@ class sense_amp_array(design.design): inst = self.local_insts[i] gnd_pos = inst.get_pin("gnd").center() - self.add_via_center(layers=("metal2", "via2", "metal3"), + self.add_via_center(layers=self.m2_stack, offset=gnd_pos) self.add_layout_pin_rect_center(text="gnd", layer="metal3", offset=gnd_pos) vdd_pos = inst.get_pin("vdd").center() - self.add_via_center(layers=("metal2", "via2", "metal3"), + self.add_via_center(layers=self.m2_stack, offset=vdd_pos) self.add_layout_pin_rect_center(text="vdd", layer="metal3", diff --git a/compiler/modules/single_level_column_mux_array.py b/compiler/modules/single_level_column_mux_array.py index 7e3beaad..3e6420b9 100644 --- a/compiler/modules/single_level_column_mux_array.py +++ b/compiler/modules/single_level_column_mux_array.py @@ -191,11 +191,11 @@ class single_level_column_mux_array(design.design): # This via is on the right of the wire - self.add_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=bl_out_offset) # This via is on the left of the wire - self.add_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=br_out_offset) else: @@ -204,10 +204,10 @@ class single_level_column_mux_array(design.design): self.add_path("metal2", [ br_out_offset, br_out_offset_end]) # This via is on the right of the wire - self.add_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=bl_out_offset) # This via is on the left of the wire - self.add_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=br_out_offset) def get_drain_cin(self): diff --git a/compiler/modules/tri_gate_array.py b/compiler/modules/tri_gate_array.py index 7d1c21d0..501e2389 100644 --- a/compiler/modules/tri_gate_array.py +++ b/compiler/modules/tri_gate_array.py @@ -100,7 +100,7 @@ class tri_gate_array(design.design): for n in ["vdd", "gnd"]: for supply_pin in self.tri_inst[i].get_pins(n): pin_pos = supply_pin.center() - self.add_via_center(layers=("metal2", "via2", "metal3"), + self.add_via_center(layers=self.m2_stack, offset=pin_pos) self.add_layout_pin_rect_center(text=n, layer="metal3", diff --git a/compiler/modules/wordline_driver.py b/compiler/modules/wordline_driver.py index fbd800b2..99365659 100644 --- a/compiler/modules/wordline_driver.py +++ b/compiler/modules/wordline_driver.py @@ -158,7 +158,7 @@ class wordline_driver(design.design): self.add_segment_center(layer="metal1", start=clk_offset, end=a_pos) - self.add_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=clk_offset) # Nand2 out to 2nd inv @@ -185,14 +185,14 @@ class wordline_driver(design.design): layer="metal1", start=input_offset, end=mid_via_offset) - self.add_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=mid_via_offset, directions=("V", "V")) # now connect to the nand2 B self.add_path("metal2", [mid_via_offset, b_pos]) contact_offset = b_pos - vector(0.5 * contact.m1m2.height, 0) - self.add_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=contact_offset, directions=("H", "H")) diff --git a/compiler/modules/write_driver_array.py b/compiler/modules/write_driver_array.py index 100ee3a2..4dfa938c 100644 --- a/compiler/modules/write_driver_array.py +++ b/compiler/modules/write_driver_array.py @@ -143,7 +143,7 @@ class write_driver_array(design.design): for pin in pin_list: pin_pos = pin.center() # Add the M2->M3 stack - self.add_via_center(layers=("metal2", "via2", "metal3"), + self.add_via_center(layers=self.m2_stack, offset=pin_pos) self.add_layout_pin_rect_center(text=n, layer="metal3", diff --git a/compiler/modules/write_mask_and_array.py b/compiler/modules/write_mask_and_array.py index 258bbd8d..3a4ec651 100644 --- a/compiler/modules/write_mask_and_array.py +++ b/compiler/modules/write_mask_and_array.py @@ -117,9 +117,9 @@ class write_mask_and_array(design.design): layer="metal3", offset=beg_en_pin.bc(), width=end_en_pin.cx() - beg_en_pin.cx() + en_to_edge) - self.add_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=vector(end_en_pin.cx() + en_to_edge, end_en_pin.cy())) - self.add_via_center(layers=("metal2", "via2", "metal3"), + self.add_via_center(layers=self.m2_stack, offset=vector(end_en_pin.cx() + en_to_edge, end_en_pin.cy())) else: self.add_layout_pin(text="en", @@ -134,9 +134,9 @@ class write_mask_and_array(design.design): # Add via connections to metal3 for AND array's B pin en_pin = self.and2_insts[i].get_pin("B") - self.add_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=en_pin.center()) - self.add_via_center(layers=("metal2", "via2", "metal3"), + self.add_via_center(layers=self.m2_stack, offset=en_pin.center()) self.add_power_pin("gnd", vector(supply_pin.width() + i * self.wmask_en_len, 0)) diff --git a/compiler/pgates/pgate.py b/compiler/pgates/pgate.py index 0c1c0b52..5ad98fad 100644 --- a/compiler/pgates/pgate.py +++ b/compiler/pgates/pgate.py @@ -115,7 +115,7 @@ class pgate(design.design): # Non-preferred direction via - self.add_via_center(layers=("poly", "contact", "metal1"), + self.add_via_center(layers=self.poly_stack, offset=contact_offset, directions=directions) diff --git a/compiler/pgates/pinv.py b/compiler/pgates/pinv.py index 2b8ec7b7..5c53480b 100644 --- a/compiler/pgates/pinv.py +++ b/compiler/pgates/pinv.py @@ -115,8 +115,8 @@ class pinv(pgate.pgate): # Divide the height in half. Could divide proportional to beta, # but this makes connecting wells of multiple cells easier. # Subtract the poly space under the rail of the tx - nmos_height_available = 0.5 * tx_height_available - 0.5 * drc("poly_to_poly") - pmos_height_available = 0.5 * tx_height_available - 0.5 * drc("poly_to_poly") + nmos_height_available = 0.5 * tx_height_available - 0.5 * self.poly_space + pmos_height_available = 0.5 * tx_height_available - 0.5 * self.poly_space debug.info(2, "Height avail {0:.4f} PMOS {1:.4f} NMOS {2:.4f}".format(tx_height_available, diff --git a/compiler/pgates/pinvbuf.py b/compiler/pgates/pinvbuf.py index 75b7ce6f..579e1198 100644 --- a/compiler/pgates/pinvbuf.py +++ b/compiler/pgates/pinvbuf.py @@ -126,9 +126,9 @@ class pinvbuf(pgate.pgate): z1_pin = self.inv1_inst.get_pin("Z") a4_pin = self.inv4_inst.get_pin("A") mid_point = vector(z1_pin.cx(), a4_pin.cy()) - self.add_wire(("metal1", "via1", "metal2"), + self.add_wire(self.m1_stack, [z1_pin.center(), mid_point, a4_pin.center()]) - self.add_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=z1_pin.center()) def add_layout_pins(self): @@ -161,21 +161,21 @@ class pinvbuf(pgate.pgate): self.add_layout_pin_rect_center(text="Z", layer="metal2", offset=z_pin.center()) - self.add_via_center(layers=("metal1", "via1", "metal2"), + 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", offset=zb_pin.center()) - self.add_via_center(layers=("metal1", "via1", "metal2"), + 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", offset=a_pin.center()) - self.add_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=a_pin.center()) def determine_clk_buf_stage_efforts(self, external_cout, inp_is_rise=False): diff --git a/compiler/pgates/pnand2.py b/compiler/pgates/pnand2.py index c5c69fd4..4623048c 100644 --- a/compiler/pgates/pnand2.py +++ b/compiler/pgates/pnand2.py @@ -225,13 +225,13 @@ class pnand2(pgate.pgate): mid1_offset = vector(out_offset.x, top_pin_offset.y) mid2_offset = vector(out_offset.x, bottom_pin_offset.y) - self.add_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=pmos_pin.center(), directions=("V", "H")) - self.add_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=nmos_pin.center(), directions=("V", "H")) - self.add_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=out_offset) # PMOS1 to mid-drain to NMOS2 drain diff --git a/compiler/pgates/pnand3.py b/compiler/pgates/pnand3.py index 621829f1..6d885e25 100644 --- a/compiler/pgates/pnand3.py +++ b/compiler/pgates/pnand3.py @@ -237,11 +237,11 @@ class pnand3(pgate.pgate): nmos3_pin = self.nmos3_inst.get_pin("D") # Go up to metal2 for ease on all output pins - self.add_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=pmos1_pin.center()) - self.add_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=pmos3_pin.center()) - self.add_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=nmos3_pin.center()) # PMOS3 and NMOS3 are drain aligned @@ -251,7 +251,7 @@ class pnand3(pgate.pgate): self.add_path("metal2", [pmos1_pin.bc(), mid_offset, nmos3_pin.uc()]) # This extends the output to the edge of the cell - self.add_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=mid_offset) self.add_layout_pin_rect_center(text="Z", layer="metal1", diff --git a/compiler/pgates/pnor2.py b/compiler/pgates/pnor2.py index a99253cd..a79d19a0 100644 --- a/compiler/pgates/pnor2.py +++ b/compiler/pgates/pnor2.py @@ -216,9 +216,9 @@ class pnor2(pgate.pgate): nmos2_pin = self.nmos2_inst.get_pin("D") # Go up to metal2 for ease on all output pins - self.add_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=pmos_pin.center()) - m1m2_contact = self.add_via_center(layers=("metal1", "via1", "metal2"), + m1m2_contact = self.add_via_center(layers=self.m1_stack, offset=nmos_pin.center()) mid1_offset = vector(pmos_pin.center().x, nmos2_pin.center().y) @@ -231,7 +231,7 @@ class pnor2(pgate.pgate): self.add_path("metal2", [nmos_pin.rc(), mid1_offset, mid2_offset]) # This extends the output to the edge of the cell - self.add_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=mid3_offset) self.add_layout_pin_rect_center(text="Z", layer="metal1", diff --git a/compiler/pgates/precharge.py b/compiler/pgates/precharge.py index bd391ecc..d27b9f9c 100644 --- a/compiler/pgates/precharge.py +++ b/compiler/pgates/precharge.py @@ -159,7 +159,7 @@ class precharge(design.design): # adds the en contact to connect the gates to the en rail on metal1 offset = self.lower_pmos_inst.get_pin("G").ul() \ + vector(0, 0.5 * self.poly_space) - self.add_via_center(layers=("poly", "contact", "metal1"), + self.add_via_center(layers=self.poly_stack, offset=offset) # adds the en rail on metal1 @@ -202,7 +202,6 @@ class precharge(design.design): self.bl_pin = self.add_layout_pin(text="bl", layer="metal2", offset=offset, - width=drc("minwidth_metal2"), height=self.height) # adds the BR on metal 2 @@ -211,7 +210,6 @@ class precharge(design.design): self.br_pin = self.add_layout_pin(text="br", layer="metal2", offset=offset, - width=drc("minwidth_metal2"), height=self.height) def connect_to_bitlines(self): @@ -233,23 +231,22 @@ class precharge(design.design): Adds contacts/via from metal1 to metal2 for bit-lines """ - stack = ("metal1", "via1", "metal2") upper_pin = self.upper_pmos1_inst.get_pin("S") lower_pin = self.lower_pmos_inst.get_pin("S") # BL goes up to M2 at the transistor - self.bl_contact =self.add_via_center(layers=stack, + self.bl_contact =self.add_via_center(layers=self.m1_stack, offset=upper_pin.center(), directions=("V", "V")) - self.add_via_center(layers=stack, + self.add_via_center(layers=self.m1_stack, offset=lower_pin.center(), directions=("V", "V")) # BR routes over on M1 first - self.add_via_center(layers=stack, + self.add_via_center(layers=self.m1_stack, offset=vector(self.br_pin.cx(), upper_pin.cy()), directions=("V", "V")) - self.add_via_center(layers=stack, + self.add_via_center(layers=self.m1_stack, offset=vector(self.br_pin.cx(), lower_pin.cy()), directions=("V", "V")) diff --git a/compiler/pgates/ptx.py b/compiler/pgates/ptx.py index 588152c0..d0854711 100644 --- a/compiler/pgates/ptx.py +++ b/compiler/pgates/ptx.py @@ -52,7 +52,6 @@ class ptx(design.design): self.connect_poly = connect_poly self.num_contacts = num_contacts - # Do NOT create the netlist and layout (not a pgate) # Since it has variable height, it is not a pgate. self.create_netlist() # We must always create ptx layout for pbitcell diff --git a/compiler/pgates/single_level_column_mux.py b/compiler/pgates/single_level_column_mux.py index ffe313c8..a642eeca 100644 --- a/compiler/pgates/single_level_column_mux.py +++ b/compiler/pgates/single_level_column_mux.py @@ -126,16 +126,16 @@ class single_level_column_mux(pgate.pgate): nmos_upper_d_pin = self.nmos_upper.get_pin("D") # Add vias to bl, br_out, nmos_upper/S, nmos_lower/D - self.add_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=bl_pin.bc(), directions=("V", "V")) - self.add_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=br_out_pin.uc(), directions=("V", "V")) - self.add_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=nmos_upper_s_pin.center(), directions=("V", "V")) - self.add_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=nmos_lower_d_pin.center(), directions=("V", "V")) @@ -181,9 +181,9 @@ class single_level_column_mux(pgate.pgate): well_type="p") # Add the M1->M2->M3 stack - self.add_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=active_pos) - self.add_via_center(layers=("metal2", "via2", "metal3"), + self.add_via_center(layers=self.m2_stack, offset=active_pos) self.add_layout_pin_rect_center(text="gnd", layer="metal3", diff --git a/compiler/sram/sram_1bank.py b/compiler/sram/sram_1bank.py index 9e578c7c..6c887790 100644 --- a/compiler/sram/sram_1bank.py +++ b/compiler/sram/sram_1bank.py @@ -371,12 +371,12 @@ class sram_1bank(sram_base): if self.write_size: for x in dff_names: pin_offset = self.data_dff_insts[port].get_pin(x).center() - self.add_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=pin_offset, directions = ("V", "V")) - self.add_via_center(layers=("metal2", "via2", "metal3"), + self.add_via_center(layers=self.m2_stack, offset=pin_offset) - self.add_via_center(layers=("metal3", "via3", "metal4"), + self.add_via_center(layers=self.m3_stack, offset=pin_offset) bank_names = ["din{0}_{1}".format(port,x) for x in range(self.word_size)] @@ -387,20 +387,21 @@ class sram_1bank(sram_base): pin_offset = self.bank_inst.get_pin(x).uc() else: pin_offset = self.bank_inst.get_pin(x).bc() - self.add_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=pin_offset) - self.add_via_center(layers=("metal2", "via2", "metal3"), + self.add_via_center(layers=self.m2_stack, offset=pin_offset) - self.add_via_center(layers=("metal3", "via3", "metal4"), + self.add_via_center(layers=self.m3_stack, offset=pin_offset) route_map = list(zip(bank_pins, dff_pins)) if self.write_size: - self.create_horizontal_channel_route(netlist=route_map, - offset=offset, - layer_stack=("metal3", "via3", "metal4")) + layer_stack = self.m3_stack else: - self.create_horizontal_channel_route(route_map, offset) + layer_stack = self.m1_stack + self.create_horizontal_channel_route(netlist=route_map, + offset=offset, + layer_stack=layer_stack) def route_wmask_dff(self): """ Connect the output of the wmask flops to the write mask AND array """ @@ -415,7 +416,7 @@ class sram_1bank(sram_base): dff_pins = [self.wmask_dff_insts[port].get_pin(x) for x in dff_names] for x in dff_names: offset_pin = self.wmask_dff_insts[port].get_pin(x).center() - self.add_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=offset_pin, directions=("V", "V")) @@ -423,12 +424,14 @@ class sram_1bank(sram_base): bank_pins = [self.bank_inst.get_pin(x) for x in bank_names] for x in bank_names: offset_pin = self.bank_inst.get_pin(x).center() - self.add_via_center(layers=("metal1", "via1", "metal2"), + self.add_via_center(layers=self.m1_stack, offset=offset_pin) route_map = list(zip(bank_pins, dff_pins)) - self.create_horizontal_channel_route(route_map,offset) + self.create_horizontal_channel_route(netlist=route_map, + offset=offset, + layer_stack=self.m1_stack) def add_lvs_correspondence_points(self): diff --git a/compiler/tests/03_wire_test.py b/compiler/tests/03_wire_test.py index 74d5ae1e..0ea079e4 100755 --- a/compiler/tests/03_wire_test.py +++ b/compiler/tests/03_wire_test.py @@ -25,7 +25,7 @@ class wire_test(openram_test): min_space = 2 * (tech.drc["minwidth_poly"] + tech.drc["minwidth_metal1"]) - layer_stack = ("poly", "contact", "metal1") + layer_stack = tech.poly_stack old_position_list = [[0, 0], [0, 3 * min_space], [1 * min_space, 3 * min_space], @@ -42,7 +42,7 @@ class wire_test(openram_test): min_space = 2 * (tech.drc["minwidth_poly"] + tech.drc["minwidth_metal1"]) - layer_stack = ("poly", "contact", "metal1") + layer_stack = tech.poly_stack old_position_list = [[0, 0], [0, 3 * min_space], [1 * min_space, 3 * min_space], @@ -59,7 +59,7 @@ class wire_test(openram_test): min_space = 2 * (tech.drc["minwidth_metal2"] + tech.drc["minwidth_metal1"]) - layer_stack = ("metal1", "via1", "metal2") + layer_stack = tech.m1_stack position_list = [[0, 0], [0, 3 * min_space], [1 * min_space, 3 * min_space], @@ -76,7 +76,7 @@ class wire_test(openram_test): min_space = 2 * (tech.drc["minwidth_metal2"] + tech.drc["minwidth_metal1"]) - layer_stack = ("metal2", "via1", "metal1") + layer_stack = tech.m2_stack[::-1] position_list = [[0, 0], [0, 3 * min_space], [1 * min_space, 3 * min_space], @@ -92,7 +92,7 @@ class wire_test(openram_test): min_space = 2 * (tech.drc["minwidth_metal2"] + tech.drc["minwidth_metal3"]) - layer_stack = ("metal2", "via2", "metal3") + layer_stack = tech.m2_stack position_list = [[0, 0], [0, 3 * min_space], [1 * min_space, 3 * min_space], @@ -109,7 +109,7 @@ class wire_test(openram_test): min_space = 2 * (tech.drc["minwidth_metal2"] + tech.drc["minwidth_metal3"]) - layer_stack = ("metal3", "via2", "metal2") + layer_stack = tech.m2_stack[::-1] position_list = [[0, 0], [0, 3 * min_space], [1 * min_space, 3 * min_space], diff --git a/technology/scn4m_subm/tech/tech.py b/technology/scn4m_subm/tech/tech.py index 23a0d9fe..3f42e8b3 100644 --- a/technology/scn4m_subm/tech/tech.py +++ b/technology/scn4m_subm/tech/tech.py @@ -34,18 +34,18 @@ GDS["zoom"] = 0.5 poly_stack = ("poly", "poly_contact", "metal1") active_stack = ("active", "active_contact", "metal1") -metal1_stack = ("metal1", "via1", "metal2") -metal2_stack = ("metal2", "via2", "metal3") -metal3_stack = ("metal3", "via3", "metal4") +m1_stack = ("metal1", "via1", "metal2") +m2_stack = ("metal2", "via2", "metal3") +m3_stack = ("metal3", "via3", "metal4") # The FEOL stacks get us up to metal1 feol_stacks = [poly_stack, active_stack] # The BEOL stacks are metal1 and up -beol_stacks = [metal1_stack, - metal2_stack, - metal3_stack] +beol_stacks = [m1_stack, + m2_stack, + m3_stack] layer_stacks = feol_stacks + beol_stacks