diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index 12a9826e..d3b84ca5 100644 --- a/compiler/base/hierarchy_layout.py +++ b/compiler/base/hierarchy_layout.py @@ -219,8 +219,6 @@ class layout(): if not height: height = drc["minwidth_{}".format(layer)] lpp = techlayer[layer] - if abs(offset[0]-5.16250)<0.01 and abs(offset[1]-8.70750)<0.01: - import pdb; pdb.set_trace() self.objs.append(geometry.rectangle(lpp, offset, width, @@ -838,51 +836,57 @@ class layout(): if not pitch: pitch = getattr(self, "{}_pitch".format(layer)) - line_positions = {} + pins = {} if vertical: for i in range(len(names)): line_offset = offset + vector(i * pitch, 0) if make_pins: - self.add_layout_pin(text=names[i], - layer=layer, - offset=line_offset, - height=length) + new_pin = self.add_layout_pin(text=names[i], + layer=layer, + offset=line_offset, + height=length) else: - self.add_rect(layer=layer, - offset=line_offset, - height=length) - line_positions[names[i]] = line_offset + vector(half_minwidth, 0) + rect = self.add_rect(layer=layer, + offset=line_offset, + height=length) + new_pin = pin_layout(names[i], + [rect.ll(), rect.ur()], + layer) + + pins[names[i]] = new_pin else: for i in range(len(names)): line_offset = offset + vector(0, i * pitch + half_minwidth) if make_pins: - self.add_layout_pin(text=names[i], - layer=layer, - offset=line_offset, - width=length) + new_pin = self.add_layout_pin(text=names[i], + layer=layer, + offset=line_offset, + width=length) else: - self.add_rect(layer=layer, - offset=line_offset, - width=length) - # Make this the center of the rail - line_positions[names[i]] = line_offset + vector(0.5 * length, - half_minwidth) + rect = self.add_rect(layer=layer, + offset=line_offset, + width=length) + new_pin = pin_layout(names[i], + [rect.ll(), rect.ur()], + layer) + + pins[names[i]] = new_pin - return line_positions + return pins - def connect_horizontal_bus(self, mapping, inst, bus_offsets, + def connect_horizontal_bus(self, mapping, inst, bus_pins, layer_stack=("m1", "via1", "m2")): """ Horizontal version of connect_bus. """ - self.connect_bus(mapping, inst, bus_offsets, layer_stack, True) + self.connect_bus(mapping, inst, bus_pins, layer_stack, True) - def connect_vertical_bus(self, mapping, inst, bus_offsets, + def connect_vertical_bus(self, mapping, inst, bus_pins, layer_stack=("m1", "via1", "m2")): """ Vertical version of connect_bus. """ - self.connect_bus(mapping, inst, bus_offsets, layer_stack, False) + self.connect_bus(mapping, inst, bus_pins, layer_stack, False) - def connect_bus(self, mapping, inst, bus_offsets, layer_stack, horizontal): + def connect_bus(self, mapping, inst, bus_pins, layer_stack, horizontal): """ Connect a mapping of pin -> name for a bus. This could be replaced with a channel router in the future. @@ -898,7 +902,7 @@ class layout(): for (pin_name, bus_name) in mapping: pin = inst.get_pin(pin_name) pin_pos = pin.center() - bus_pos = bus_offsets[bus_name] + bus_pos = bus_pins[bus_name].center() if horizontal: # up/down then left/right diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index d9659cd5..36fecfc4 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -593,7 +593,7 @@ class bank(design.design): # Connect the inverter output to the central bus 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) + bus_pos = vector(self.bus_pins[port][name].cx(), out_pos.y) self.add_path("m3", [out_pos, bus_pos]) self.add_via_center(layers=self.m2_stack, offset=bus_pos) @@ -628,19 +628,19 @@ class bank(design.design): # Overall central bus width. It includes all the column mux lines, # and control lines. - self.bus_xoffset = [None] * len(self.all_ports) + self.bus_pins = [None] * len(self.all_ports) # Port 0 # The bank is at (0,0), so this is to the left of the y-axis. # 2 pitches on the right for vias/jogs to access the inputs control_bus_offset = vector(-self.m3_pitch * self.num_control_lines[0] - self.m3_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="m2", - offset=control_bus_offset, - names=self.control_signals[0], - length=control_bus_length, - vertical=True, - make_pins=(self.num_banks==1)) + self.bus_pins[0] = self.create_bus(layer="m2", + offset=control_bus_offset, + names=self.control_signals[0], + length=control_bus_length, + vertical=True, + make_pins=(self.num_banks==1)) # Port 1 if len(self.all_ports)==2: @@ -649,12 +649,12 @@ class bank(design.design): control_bus_offset = vector(self.bitcell_array_right + self.m3_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="m2", - offset=control_bus_offset, - names=list(reversed(self.control_signals[1])), - length=control_bus_length, - vertical=True, - make_pins=(self.num_banks==1)) + self.bus_pins[1] = self.create_bus(layer="m2", + offset=control_bus_offset, + names=list(reversed(self.control_signals[1])), + length=control_bus_length, + vertical=True, + make_pins=(self.num_banks==1)) def route_port_data_to_bitcell_array(self, port): """ Routing of BL and BR between port data and bitcell array """ @@ -919,39 +919,32 @@ class bank(design.design): # pre-decoder and this connection is in metal3 connection = [] connection.append((self.prefix + "p_en_bar{}".format(port), - self.port_data_inst[port].get_pin("p_en_bar").lc(), - self.port_data_inst[port].get_pin("p_en_bar").layer)) + self.port_data_inst[port].get_pin("p_en_bar"))) rbl_wl_name = self.bitcell_array.get_rbl_wl_name(self.port_rbl_map[port]) connection.append((self.prefix + "wl_en{}".format(port), - self.bitcell_array_inst.get_pin(rbl_wl_name).lc(), - self.bitcell_array_inst.get_pin(rbl_wl_name).layer)) + self.bitcell_array_inst.get_pin(rbl_wl_name))) if port in self.write_ports: - if port % 2: - connection.append((self.prefix + "w_en{}".format(port), - self.port_data_inst[port].get_pin("w_en").rc(), - self.port_data_inst[port].get_pin("w_en").layer)) - else: - connection.append((self.prefix + "w_en{}".format(port), - self.port_data_inst[port].get_pin("w_en").lc(), - self.port_data_inst[port].get_pin("w_en").layer)) + connection.append((self.prefix + "w_en{}".format(port), + self.port_data_inst[port].get_pin("w_en"))) if port in self.read_ports: connection.append((self.prefix + "s_en{}".format(port), - self.port_data_inst[port].get_pin("s_en").lc(), - self.port_data_inst[port].get_pin("s_en").layer)) + self.port_data_inst[port].get_pin("s_en"))) - for (control_signal, pin_pos, pin_layer) in connection: - if port==0: - y_offset = self.min_y_offset - else: - y_offset = self.max_y_offset - control_pos = vector(self.bus_xoffset[port][control_signal].x, y_offset) - if pin_layer == "m1": - self.add_wire(self.m1_stack, [control_pos, pin_pos]) - elif pin_layer == "m3": - self.add_wire(self.m2_stack[::-1], [control_pos, pin_pos]) + for (control_signal, pin) in connection: + control_pin = self.bus_pins[port][control_signal] + control_pos = vector(control_pin.cx(), pin.cy()) + # If the y doesn't overlap the bus, add a segment + if pin.cy() < control_pin.by(): + self.add_path("m2", [control_pos, control_pin.bc()]) + elif pin.cy() > control_pin.uy(): + self.add_path("m2", [control_pos, control_pin.uc()]) + self.add_path(pin.layer, [control_pos, pin.center()]) + self.add_via_stack_center(from_layer=pin.layer, + to_layer="m2", + offset=control_pos) # clk to wordline_driver control_signal = self.prefix + "wl_en{}".format(port) @@ -961,7 +954,7 @@ class bank(design.design): else: pin_pos = self.port_address_inst[port].get_pin("wl_en").bc() mid_pos = pin_pos - vector(0, 2 * self.m2_gap) # to route down to the top of the bus - control_x_offset = self.bus_xoffset[port][control_signal].x + control_x_offset = self.bus_pins[port][control_signal].cx() control_pos = vector(control_x_offset, mid_pos.y) self.add_wire(self.m1_stack, [pin_pos, mid_pos, control_pos]) self.add_via_center(layers=self.m1_stack, diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index 078dc3ae..c4d9f034 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -384,10 +384,10 @@ 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("m2", - offset, - self.internal_bus_list, - height) + self.input_bus = self.create_vertical_bus("m2", + offset, + self.internal_bus_list, + height) def create_instances(self): """ Create all the instances """ @@ -493,7 +493,7 @@ class control_logic(design.design): # Connect to the rail level with the vdd rail # Use pen since it is in every type of control logic vdd_ypos = self.p_en_bar_nand_inst.get_pin("vdd").by() - in_pos = vector(self.rail_offsets["rbl_bl_delay"].x, vdd_ypos) + in_pos = vector(self.input_bus["rbl_bl_delay"].cx(), vdd_ypos) mid1 = vector(out_pos.x, in_pos.y) self.add_wire(self.m1_stack, [out_pos, mid1, in_pos]) self.add_via_center(layers=self.m1_stack, @@ -548,7 +548,7 @@ class control_logic(design.design): def route_gated_clk_bar(self): clkbuf_map = zip(["A"], ["clk_buf"]) - self.connect_vertical_bus(clkbuf_map, self.clk_bar_inst, self.rail_offsets) + self.connect_vertical_bus(clkbuf_map, self.clk_bar_inst, self.input_bus) out_pos = self.clk_bar_inst.get_pin("Z").center() in_pos = self.gated_clk_bar_inst.get_pin("A").center() @@ -558,7 +558,7 @@ class control_logic(design.design): clkbuf_map = zip(["B"], ["cs"]) self.connect_vertical_bus(clkbuf_map, self.gated_clk_bar_inst, - self.rail_offsets, + self.input_bus, self.m2_stack[::-1]) # The pin is on M1, so we need another via as well b_pin = self.gated_clk_bar_inst.get_pin("B") @@ -586,12 +586,12 @@ class control_logic(design.design): clkbuf_map = zip(["A", "B"], ["clk_buf", "cs"]) self.connect_vertical_bus(clkbuf_map, self.gated_clk_buf_inst, - self.rail_offsets) + self.input_bus) clkbuf_map = zip(["Z"], ["gated_clk_buf"]) self.connect_vertical_bus(clkbuf_map, self.gated_clk_buf_inst, - self.rail_offsets, + self.input_bus, self.m2_stack[::-1]) # The pin is on M1, so we need another via as well z_pin = self.gated_clk_buf_inst.get_pin("Z") @@ -614,7 +614,7 @@ class control_logic(design.design): def route_wlen(self): wlen_map = zip(["A"], ["gated_clk_bar"]) - self.connect_vertical_bus(wlen_map, self.wl_en_inst, self.rail_offsets) + self.connect_vertical_bus(wlen_map, self.wl_en_inst, self.input_bus) self.connect_output(self.wl_en_inst, "Z", "wl_en") @@ -639,7 +639,7 @@ class control_logic(design.design): def route_pen(self): in_map = zip(["A", "B"], ["gated_clk_buf", "rbl_bl_delay"]) - self.connect_vertical_bus(in_map, self.p_en_bar_nand_inst, self.rail_offsets) + self.connect_vertical_bus(in_map, self.p_en_bar_nand_inst, self.input_bus) out_pin = self.p_en_bar_nand_inst.get_pin("Z") out_pos = out_pin.center() @@ -682,7 +682,7 @@ class control_logic(design.design): input_name = "cs" sen_map = zip(["A", "B", "C"], ["rbl_bl_delay", "gated_clk_bar", input_name]) - self.connect_vertical_bus(sen_map, self.s_en_gate_inst, self.rail_offsets) + self.connect_vertical_bus(sen_map, self.s_en_gate_inst, self.input_bus) self.connect_output(self.s_en_gate_inst, "Z", "s_en") @@ -706,7 +706,7 @@ class control_logic(design.design): self.route_output_to_bus_jogged(self.rbl_bl_delay_inv_inst, "rbl_bl_delay_bar") rbl_map = zip(["A"], ["rbl_bl_delay"]) - self.connect_vertical_bus(rbl_map, self.rbl_bl_delay_inv_inst, self.rail_offsets) + self.connect_vertical_bus(rbl_map, self.rbl_bl_delay_inv_inst, self.input_bus) def create_wen_row(self): @@ -738,7 +738,7 @@ class control_logic(design.design): input_name = "cs" wen_map = zip(["A", "B", "C"], [input_name, "rbl_bl_delay_bar", "gated_clk_bar"]) - self.connect_vertical_bus(wen_map, self.w_en_gate_inst, self.rail_offsets) + self.connect_vertical_bus(wen_map, self.w_en_gate_inst, self.input_bus) self.connect_output(self.w_en_gate_inst, "Z", "w_en") @@ -761,13 +761,13 @@ 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, self.m2_stack[::-1]) + self.connect_vertical_bus(dff_out_map, self.ctrl_dff_inst, self.input_bus, self.m2_stack[::-1]) # Connect the clock rail to the other clock rail # by routing in the supply rail track to avoid channel conflicts in_pos = self.ctrl_dff_inst.get_pin("clk").uc() mid_pos = in_pos + vector(0, self.and2.height) - rail_pos = vector(self.rail_offsets["clk_buf"].x, mid_pos.y) + rail_pos = vector(self.input_bus["clk_buf"].cx(), mid_pos.y) self.add_wire(self.m1_stack, [in_pos, mid_pos, rail_pos]) self.add_via_center(layers=self.m1_stack, offset=rail_pos) @@ -1001,8 +1001,8 @@ class control_logic(design.design): # Connect this at the bottom of the buffer out_pos = inst.get_pin("Z").center() mid1 = vector(out_pos.x, out_pos.y - 0.25 * inst.mod.height) - mid2 = vector(self.rail_offsets[name].x, mid1.y) - bus_pos = self.rail_offsets[name] + mid2 = vector(self.input_bus[name].cx(), mid1.y) + bus_pos = self.input_bus[name].center() self.add_wire(self.m2_stack[::-1], [out_pos, mid1, mid2, bus_pos]) # The pin is on M1, so we need another via as well self.add_via_center(layers=self.m1_stack, diff --git a/compiler/modules/hierarchical_decoder.py b/compiler/modules/hierarchical_decoder.py index fbf8ef29..bb2b37ab 100644 --- a/compiler/modules/hierarchical_decoder.py +++ b/compiler/modules/hierarchical_decoder.py @@ -209,7 +209,7 @@ class hierarchical_decoder(design.design): for i in range(2): index = pre_num * 2 + i - input_pos = self.input_bus["addr_{}".format(index)] + input_pos = self.input_bus["addr_{}".format(index)].center() in_name = "in_{}".format(i) decoder_pin = self.pre2x4_inst[pre_num].get_pin(in_name) @@ -223,7 +223,7 @@ class hierarchical_decoder(design.design): for i in range(3): index = pre_num * 3 + i + self.no_of_pre2x4 * 2 - input_pos = self.input_bus["addr_{}".format(index)] + input_pos = self.input_bus["addr_{}".format(index)].center() in_name = "in_{}".format(i) decoder_pin = self.pre3x8_inst[pre_num].get_pin(in_name) @@ -572,7 +572,7 @@ class hierarchical_decoder(design.design): """ pin_pos = pin.center() - rail_pos = vector(self.predecode_bus[rail_name].x, pin_pos.y) + rail_pos = vector(self.predecode_bus[rail_name].cx(), pin_pos.y) self.add_path(self.input_layer, [rail_pos, pin_pos]) self.add_via_stack_center(from_layer=self.bus_layer, @@ -595,11 +595,11 @@ class hierarchical_decoder(design.design): pin_pos = pin.rc() mid_point1 = vector(x_offset, pin_pos.y) mid_point2 = vector(x_offset, y_offset) - rail_pos = vector(self.predecode_bus[rail_name].x, mid_point2.y) + rail_pos = vector(self.predecode_bus[rail_name].cx(), mid_point2.y) self.add_path(self.output_layer, [pin_pos, mid_point1, mid_point2, rail_pos]) # pin_pos = pin.center() - # rail_pos = vector(self.predecode_bus[rail_name].x, pin_pos.y) + # rail_pos = vector(self.predecode_bus[rail_name].cx(), pin_pos.y) # self.add_path(self.output_layer, [pin_pos, rail_pos]) self.add_via_stack_center(from_layer=pin.layer, to_layer=self.output_layer, diff --git a/compiler/modules/hierarchical_predecode.py b/compiler/modules/hierarchical_predecode.py index d998d882..03d866fb 100644 --- a/compiler/modules/hierarchical_predecode.py +++ b/compiler/modules/hierarchical_predecode.py @@ -202,15 +202,15 @@ class hierarchical_predecode(design.design): y_offset = pin.cy() in_pin = "in_{}".format(num) 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) + in_pos = vector(self.input_rails[in_pin].cx(), y_offset) + a_pos = vector(self.decode_rails[a_pin].cx(), y_offset) self.add_path(self.input_layer, [in_pos, a_pos]) self.add_via_stack_center(from_layer=self.input_layer, to_layer=self.bus_layer, - offset=[self.input_rails[in_pin].x, y_offset]) + offset=[self.input_rails[in_pin].cx(), y_offset]) self.add_via_stack_center(from_layer=self.input_layer, to_layer=self.bus_layer, - offset=[self.decode_rails[a_pin].x, y_offset]) + offset=[self.decode_rails[a_pin].cx(), y_offset]) def route_output_and(self): """ @@ -240,12 +240,12 @@ class hierarchical_predecode(design.design): # since this is where the p/n devices are and there are no # pins in the and gates. if OPTS.tech_name == "s8": - rail_pos = vector(self.decode_rails[out_pin].x, inv_out_pos.y) + rail_pos = vector(self.decode_rails[out_pin].cx(), inv_out_pos.y) self.add_path(self.output_layer, [inv_out_pos, rail_pos]) else: y_offset = (inv_num + 1) * self.inv.height - self.output_layer_pitch right_pos = inv_out_pos + vector(self.inv.width - self.inv.get_pin("Z").rx(), 0) - rail_pos = vector(self.decode_rails[out_pin].x, y_offset) + rail_pos = vector(self.decode_rails[out_pin].cx(), y_offset) self.add_path(self.output_layer, [inv_out_pos, right_pos, vector(right_pos.x, y_offset), rail_pos]) self.add_via_stack_center(from_layer=inv_out_pin.layer, @@ -259,7 +259,7 @@ class hierarchical_predecode(design.design): # route input pin = self.inv_inst[inv_num].get_pin("A") inv_in_pos = pin.center() - in_pos = vector(self.input_rails[in_pin].x, inv_in_pos.y) + in_pos = vector(self.input_rails[in_pin].cx(), inv_in_pos.y) self.add_path(self.input_layer, [in_pos, inv_in_pos]) self.add_via_stack_center(from_layer=pin.layer, to_layer=self.input_layer, @@ -290,7 +290,7 @@ class hierarchical_predecode(design.design): for rail_pin, gate_pin in zip(index_lst, gate_lst): pin = self.and_inst[k].get_pin(gate_pin) pin_pos = pin.center() - rail_pos = vector(self.decode_rails[rail_pin].x, pin_pos.y) + rail_pos = vector(self.decode_rails[rail_pin].cx(), pin_pos.y) self.add_path(self.input_layer, [rail_pos, pin_pos]) self.add_via_stack_center(from_layer=self.input_layer, to_layer=self.bus_layer, diff --git a/compiler/modules/precharge_array.py b/compiler/modules/precharge_array.py index 84f27fba..2cf4718a 100644 --- a/compiler/modules/precharge_array.py +++ b/compiler/modules/precharge_array.py @@ -10,6 +10,7 @@ import debug from vector import vector from sram_factory import factory from globals import OPTS +from tech import layer class precharge_array(design.design): diff --git a/compiler/pgates/precharge.py b/compiler/pgates/precharge.py index cfc2a688..76fc8676 100644 --- a/compiler/pgates/precharge.py +++ b/compiler/pgates/precharge.py @@ -13,7 +13,7 @@ from tech import parameter from vector import vector from globals import OPTS from sram_factory import factory -from tech import drc +from tech import drc, layer class precharge(design.design): @@ -38,10 +38,16 @@ class precharge(design.design): if self.bitcell_bl_pin.layer == "m1": self.bitline_layer = "m1" - self.en_layer = "m2" + if "li" in layer: + self.en_layer = "li" + else: + self.en_layer = "m2" else: self.bitline_layer = "m2" - self.en_layer = "m1" + if "li" in layer: + self.en_layer = "li" + else: + self.en_layer = "m1" # Creates the netlist and layout # Since it has variable height, it is not a pgate.