From 8499983cc2bf13d30924698d713aff4326f61b65 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Sat, 6 Oct 2018 08:30:38 -0700 Subject: [PATCH] Add supply router to top-level SRAM. Change get_pins to elegantly fail. --- compiler/base/hierarchy_layout.py | 5 +- compiler/globals.py | 2 +- compiler/sram_1bank.py | 95 ------------------------------- compiler/sram_base.py | 33 ++++++++++- 4 files changed, 37 insertions(+), 98 deletions(-) diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index bd6c85f8..0fc89e5d 100644 --- a/compiler/base/hierarchy_layout.py +++ b/compiler/base/hierarchy_layout.py @@ -192,7 +192,10 @@ class layout(lef.lef): def get_pins(self, text): """ Return a pin list (instead of a single pin) """ - return self.pin_map[text] + if text in self.pin_map.keys(): + return self.pin_map[text] + else: + return [] def copy_layout_pin(self, instance, pin_name, new_name=""): """ diff --git a/compiler/globals.py b/compiler/globals.py index c555f9fc..3b043bf3 100644 --- a/compiler/globals.py +++ b/compiler/globals.py @@ -281,7 +281,7 @@ def setup_paths(): # Add all of the subdirs to the python path # These subdirs are modules and don't need to be added: characterizer, verify - for subdir in ["gdsMill", "tests", "modules", "base", "pgates", "bitcells"]: + for subdir in ["gdsMill", "tests", "modules", "base", "pgates", "bitcells", "router"]: full_path = "{0}/{1}".format(OPENRAM_HOME,subdir) debug.check(os.path.isdir(full_path), "$OPENRAM_HOME/{0} does not exist: {1}".format(subdir,full_path)) diff --git a/compiler/sram_1bank.py b/compiler/sram_1bank.py index 1eaa6abb..0353ddbc 100644 --- a/compiler/sram_1bank.py +++ b/compiler/sram_1bank.py @@ -119,8 +119,6 @@ class sram_1bank(sram_base): self.add_layout_pins() - self.route_vdd_gnd() - self.route_clk() self.route_control_logic() @@ -172,99 +170,6 @@ class sram_1bank(sram_base): # the control logic to the bank self.add_wire(("metal3","via2","metal2"),[row_addr_clk_pos, mid1_pos, mid2_pos, control_clk_buf_pos]) - def route_vdd_gnd(self): - """ Propagate all vdd/gnd pins up to this level for all modules """ - - # These are the instances that every bank has - top_instances = [self.bank_inst, - self.row_addr_dff_inst, - self.data_dff_inst, - self.control_logic_inst[0]] - if self.col_addr_dff: - top_instances.append(self.col_addr_dff_inst) - - - for inst in top_instances: - self.copy_layout_pin(inst, "vdd") - self.copy_layout_pin(inst, "gnd") - - def new_route_vdd_gnd(self): - """ Propagate all vdd/gnd pins up to this level for all modules """ - - # These are the instances that every bank has - top_instances = [self.bank_inst, - self.row_addr_dff_inst, - self.data_dff_inst, - self.control_logic_inst[0]] - if self.col_addr_dff: - top_instances.append(self.col_addr_dff_inst) - - - # for inst in top_instances: - # self.copy_layout_pin(inst, "vdd") - # self.copy_layout_pin(inst, "gnd") - - blockages=self.get_blockages("metal3", top_level=True) - - # Gather all of the vdd/gnd pins - vdd_pins=[] - gnd_pins=[] - for inst in top_instances: - vdd_pins.extend([x for x in inst.get_pins("vdd") if x.layer == "metal3"]) - gnd_pins.extend([x for x in inst.get_pins("gnd") if x.layer == "metal3"]) - - # Create candidate stripes on M3/M4 - lowest=self.find_lowest_coords() - highest=self.find_highest_coords() - m3_y_coords = np.arange(lowest[1],highest[1],self.m2_pitch) - - # These are the rails that will be available for vdd/gnd - m3_rects = [] - # These are the "inflated" shapes for DRC checks - m3_drc_rects = [] - for y in m3_y_coords: - # This is just what metal will be drawn - ll = vector(lowest[0], y - 0.5*self.m3_width) - ur = vector(highest[0], y + 0.5*self.m3_width) - m3_rects.append([ll, ur]) - # This is a full m3 pitch for DRC conflict checking - ll = vector(lowest[0], y - 0.5*self.m3_pitch ) - ur = vector(highest[0], y + 0.5*self.m3_pitch) - m3_drc_rects.append([ll, ur]) - - vdd_rects = [] - gnd_rects = [] - - # Now, figure how if the rails intersect a blockage, vdd, or gnd pin - # Divide the rails up alternately - # This should be done in less than n^2 using a kd-tree or something - # for drc_rect,rect in zip(m3_drc_rects,m3_rects): - # for b in blockages: - # if rect_overlaps(b,drc_rect): - # break - # else: - # gnd_rects.append(rect) - - - - # Create the vdd and gnd rails - for rect in m3_rects: - (ll,ur) = rect - - for rect in gnd_rects: - (ll,ur) = rect - self.add_layout_pin(text="gnd", - layer="metal3", - offset=ll, - width=ur.x-ll.x, - height=ur.y-ll.y) - for rect in vdd_rects: - (ll,ur) = rect - self.add_layout_pin(text="vdd", - layer="metal3", - offset=ll, - width=ur.x-ll.x, - height=ur.y-ll.y) def route_control_logic(self): """ Route the outputs from the control logic module """ diff --git a/compiler/sram_base.py b/compiler/sram_base.py index 9a511bd4..e2fe318d 100644 --- a/compiler/sram_base.py +++ b/compiler/sram_base.py @@ -7,7 +7,7 @@ from vector import vector from globals import OPTS, print_time from design import design - + class sram_base(design): """ Dynamically generated SRAM by connecting banks to control logic. The @@ -80,6 +80,7 @@ class sram_base(design): """ Layout creation """ self.place_modules() self.route() + self.supply_route() self.add_lvs_correspondence_points() self.offset_all_coordinates() @@ -90,6 +91,36 @@ class sram_base(design): self.DRC_LVS(final_verification=True) + def route_vdd_gnd_pins(self): + """ Propagate all vdd/gnd pins up to this level for all modules """ + + #These are the instances that every bank has + top_instances = [self.bank_inst, + self.row_addr_dff_inst, + self.data_dff_inst, + self.control_logic_inst[0]] + if self.col_addr_dff: + top_instances.append(self.col_addr_dff_inst) + + for inst in top_instances: + self.copy_layout_pin(inst, "vdd") + self.copy_layout_pin(inst, "gnd") + + + def supply_route(self): + """ Route the supply grid and connect the pins to them. """ + + for inst in self.insts: + self.copy_layout_pin(inst, "vdd") + self.copy_layout_pin(inst, "gnd") + + from supply_router import supply_router as router + layer_stack =("metal3","via3","metal4") + rtr=router(layer_stack, self) + rtr.route() + + + def compute_bus_sizes(self): """ Compute the independent bus widths shared between two and four bank SRAMs """