From 78be9f367a3efa6c7df338766500d5d82a78bbd3 Mon Sep 17 00:00:00 2001 From: mrg Date: Sun, 14 Jun 2020 15:52:09 -0700 Subject: [PATCH] Add brain-dead router pins to perimeter --- compiler/base/hierarchy_layout.py | 42 +++++++++++- compiler/modules/control_logic.py | 2 +- compiler/sram/sram_1bank.py | 110 ++++++++++++++++++++++-------- 3 files changed, 123 insertions(+), 31 deletions(-) diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index 4716c15c..c9b6a7a8 100644 --- a/compiler/base/hierarchy_layout.py +++ b/compiler/base/hierarchy_layout.py @@ -1354,7 +1354,7 @@ class layout(): # Hack for min area if OPTS.tech_name == "sky130": width = round_to_grid(sqrt(drc["minarea_m3"])) - height = round_to_grid(drc["minarea_m3"]/width) + height = round_to_grid(drc["minarea_m3"] / width) else: width = via.width height = via.height @@ -1364,6 +1364,46 @@ class layout(): width=width, height=height) + def add_perimeter_pin(self, name, pin, side, bbox): + """ + Add a pin along the perimeter side specified by the bbox with + the given name and layer from the pin starting location. + """ + (ll, ur) = bbox + left = ll.x + bottom = ll.y + right = ur.x + top = ur.y + + pin_loc = pin.center() + if side == "left": + peri_pin_loc = vector(left, pin_loc.y) + layer = "m3" + elif side == "right": + layer = "m3" + peri_pin_loc = vector(right, pin_loc.x) + elif side == "top": + layer = "m4" + peri_pin_loc = vector(pin_loc.x, top) + elif side == "bottom": + layer = "m4" + peri_pin_loc = vector(pin_loc.x, bottom) + + self.add_via_stack_center(from_layer=pin.layer, + to_layer=layer, + offset=pin_loc) + + self.add_path(layer, + [pin_loc, peri_pin_loc]) + + self.add_via_stack_center(from_layer=layer, + to_layer="m4", + offset=peri_pin_loc) + + self.add_layout_pin_rect_center(text=name, + layer="m4", + offset=peri_pin_loc) + def add_power_ring(self, bbox): """ Create vdd and gnd power rings around an area of the bounding box diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index 64fc4fc8..b85a0d4a 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -1005,7 +1005,7 @@ class control_logic(design.design): def route_output_to_bus_jogged(self, inst, name): # 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) + mid1 = vector(out_pos.x, out_pos.y - 0.4 * inst.mod.height) 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]) diff --git a/compiler/sram/sram_1bank.py b/compiler/sram/sram_1bank.py index eb0fe3ad..d1398307 100644 --- a/compiler/sram/sram_1bank.py +++ b/compiler/sram/sram_1bank.py @@ -246,46 +246,100 @@ class sram_1bank(sram_base): """ Add the top-level pins for a single bank SRAM with control. """ - for port in self.all_ports: - # Connect the control pins as inputs - for signal in self.control_logic_inputs[port] + ["clk"]: - self.copy_layout_pin(self.control_logic_insts[port], - signal, - signal + "{}".format(port)) + highest_coord = self.find_highest_coords() + lowest_coord = self.find_lowest_coords() + bbox = [lowest_coord, highest_coord] + + + for port in self.all_ports: + # Depending on the port, use the bottom/top or left/right sides + # Port 0 is left/bottom + # Port 1 is right/top + bottom_or_top = "bottom" if port==0 else "top" + left_or_right = "left" if port==0 else "right" + + # Connect the control pins as inputs + for signal in self.control_logic_inputs[port]: + if signal == "clk": + continue + self.add_perimeter_pin(name=signal + "{}".format(port), + pin=self.control_logic_insts[port].get_pin(signal), + side=left_or_right, + bbox=bbox) + # self.copy_layout_pin(self.control_logic_insts[port], + # signal, + # signal + "{}".format(port)) + + self.add_perimeter_pin(name="clk{}".format(port), + pin=self.control_logic_insts[port].get_pin("clk"), + side=bottom_or_top, + bbox=bbox) + + # Data output pins go to BOTTOM/TOP if port in self.read_ports: for bit in range(self.word_size + self.num_spare_cols): - self.copy_layout_pin(self.bank_inst, - "dout{0}_{1}".format(port, bit), - "dout{0}[{1}]".format(port, bit)) + self.add_perimeter_pin(name="dout{0}[{1}]".format(port, bit), + pin=self.bank_inst.get_pin("dout{0}_{1}".format(port, bit)), + side=bottom_or_top, + bbox=bbox) + # self.copy_layout_pin(self.bank_inst, + # "dout{0}_{1}".format(port, bit), + # "dout{0}[{1}]".format(port, bit)) - # Lower address bits + # Lower address bits go to BOTTOM/TOP for bit in range(self.col_addr_size): - self.copy_layout_pin(self.col_addr_dff_insts[port], - "din_{}".format(bit), - "addr{0}[{1}]".format(port, bit)) - # Upper address bits + self.add_perimeter_pin(name="addr{0}[{1}]".format(port, bit), + pin=self.col_addr_dff_insts[port].get_pin("din_{}".format(bit)), + side=bottom_or_top, + bbox=bbox) + # self.copy_layout_pin(self.col_addr_dff_insts[port], + # "din_{}".format(bit), + # "addr{0}[{1}]".format(port, bit)) + + # Upper address bits go to LEFT/RIGHT for bit in range(self.row_addr_size): - self.copy_layout_pin(self.row_addr_dff_insts[port], - "din_{}".format(bit), - "addr{0}[{1}]".format(port, bit + self.col_addr_size)) + self.add_perimeter_pin(name="addr{0}[{1}]".format(port, bit + self.col_addr_size), + pin=self.row_addr_dff_insts[port].get_pin("din_{}".format(bit)), + side=left_or_right, + bbox=bbox) + # self.copy_layout_pin(self.row_addr_dff_insts[port], + # "din_{}".format(bit), + # "addr{0}[{1}]".format(port, bit + self.col_addr_size)) + # Data input pins go to BOTTOM/TOP if port in self.write_ports: for bit in range(self.word_size + self.num_spare_cols): - self.copy_layout_pin(self.data_dff_insts[port], - "din_{}".format(bit), - "din{0}[{1}]".format(port, bit)) + self.add_perimeter_pin(name="din{0}[{1}]".format(port, bit), + pin=self.data_dff_insts[port].get_pin("din_{}".format(bit)), + side=bottom_or_top, + bbox=bbox) + # self.copy_layout_pin(self.data_dff_insts[port], + # "din_{}".format(bit), + # "din{0}[{1}]".format(port, bit)) + # Write mask pins go to BOTTOM/TOP + if port in self.write_ports: if self.write_size: for bit in range(self.num_wmasks): - self.copy_layout_pin(self.wmask_dff_insts[port], - "din_{}".format(bit), - "wmask{0}[{1}]".format(port, bit)) - + self.add_perimeter_pin(name="wmask{0}[{1}]".format(port, bit), + pin=self.wmask_dff_insts[port].get_pin("din_{}".format(bit)), + side=bottom_or_top, + bbox=bbox) + # self.copy_layout_pin(self.wmask_dff_insts[port], + # "din_{}".format(bit), + # "wmask{0}[{1}]".format(port, bit)) + + # Spare wen pins go to BOTTOM/TOP + if port in self.write_ports: for bit in range(self.num_spare_cols): - self.copy_layout_pin(self.spare_wen_dff_insts[port], - "din_{}".format(bit), - "spare_wen{0}[{1}]".format(port, bit)) + self.add_perimeter_pin(name="spare_wen{0}[{1}]".format(port, bit), + pin=self.spare_wen_dff_insts[port].get_pin("din_{}".format(bit)), + side=left_or_right, + bbox=bbox) + # self.copy_layout_pin(self.spare_wen_dff_insts[port], + # "din_{}".format(bit), + # "spare_wen{0}[{1}]".format(port, bit)) def route_layout(self): """ Route a single bank SRAM """ @@ -314,8 +368,6 @@ class sram_1bank(sram_base): # This is the actual input to the SRAM for port in self.all_ports: - self.copy_layout_pin(self.control_logic_insts[port], "clk", "clk{}".format(port)) - # Connect all of these clock pins to the clock in the central bus # This is something like a "spine" clock distribution. The two spines # are clk_buf and clk_buf_bar