From 01d312d65c1586bfa552fb76fc53437a0a13228d Mon Sep 17 00:00:00 2001 From: mrg Date: Wed, 13 Jan 2021 10:57:12 -0800 Subject: [PATCH] Refactor add power pins --- compiler/base/hierarchy_layout.py | 57 ++++++++++++++++------ compiler/modules/bank.py | 4 +- compiler/modules/col_cap_array.py | 4 +- compiler/modules/delay_chain.py | 8 +-- compiler/modules/dff_array.py | 4 +- compiler/modules/dff_buf_array.py | 4 +- compiler/modules/dff_inv_array.py | 5 +- compiler/modules/hierarchical_decoder.py | 11 +---- compiler/modules/hierarchical_predecode.py | 11 +---- compiler/modules/local_bitcell_array.py | 4 +- compiler/modules/port_address.py | 4 +- compiler/modules/replica_bitcell_array.py | 4 +- compiler/modules/replica_column.py | 3 +- compiler/modules/row_cap_array.py | 4 +- compiler/modules/sense_amp_array.py | 10 +--- compiler/modules/wordline_buffer_array.py | 2 +- compiler/modules/wordline_driver_array.py | 2 +- compiler/modules/write_driver_array.py | 6 +-- compiler/modules/write_mask_and_array.py | 4 +- 19 files changed, 70 insertions(+), 81 deletions(-) diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index 1ec5a2f0..ef077c8d 100644 --- a/compiler/base/hierarchy_layout.py +++ b/compiler/base/hierarchy_layout.py @@ -56,6 +56,8 @@ class layout(): self.visited = [] # Flag for library cells self.is_library_cell = False + # Flag for top level (used for min area metal pins etc.) + self.is_top_level = False self.gds_read() @@ -1220,30 +1222,21 @@ class layout(): pin.height()) elif add_vias: - self.add_power_pin(name, pin.center(), start_layer=pin.layer) + self.add_power_pin(pin) - def add_io_pin(self, instance, pin_name, new_name="", start_layer=None): + def add_io_pin(self, instance, pin_name, new_name, start_layer=None): """ Add a signle input or output pin up to metal 3. """ pin = instance.get_pin(pin_name) - if new_name == "": - new_name = pin_name - if not start_layer: start_layer = pin.layer - + # Just use the power pin function for now to save code - self.add_power_pin(name=new_name, loc=pin.center(), start_layer=start_layer) - - def add_power_pin(self, name, loc, size=[1, 1], directions=None, start_layer="m1"): - """ - Add a single power pin from the lowest power_grid layer down to M1 (or li) at - the given center location. The starting layer is specified to determine - which vias are needed. - """ + self.add_power_pin(new_name, pin.center(), start_layer=start_layer) + def add_power_pin(self, name, loc, directions=None, start_layer="m1"): if start_layer == self.pwr_grid_layer: self.add_layout_pin_rect_center(text=name, layer=self.pwr_grid_layer, @@ -1251,12 +1244,11 @@ class layout(): else: via = self.add_via_stack_center(from_layer=start_layer, to_layer=self.pwr_grid_layer, - size=size, offset=loc, directions=directions) # Hack for min area - if OPTS.tech_name == "sky130": + if OPTS.tech_name == "sky130" and self.is_top_level: width = round_to_grid(sqrt(drc["minarea_m3"])) height = round_to_grid(drc["minarea_m3"] / width) else: @@ -1268,6 +1260,39 @@ class layout(): width=width, height=height) + def copy_power_pin(self, pin, loc=None, directions=None): + """ + Add a single power pin from the lowest power_grid layer down to M1 (or li) at + the given center location. The starting layer is specified to determine + which vias are needed. + """ + + if not loc: + loc = pin.center() + + if pin.layer == self.pwr_grid_layer: + self.add_layout_pin_rect_center(text=pin.name, + layer=self.pwr_grid_layer, + offset=loc) + else: + via = self.add_via_stack_center(from_layer=pin.layer, + to_layer=self.pwr_grid_layer, + offset=loc, + directions=directions) + + # Hack for min area + if OPTS.tech_name == "sky130" and self.is_top_level: + width = round_to_grid(sqrt(drc["minarea_m3"])) + height = round_to_grid(drc["minarea_m3"] / width) + else: + width = via.width + height = via.height + self.add_layout_pin_rect_center(text=pin.name, + layer=self.pwr_grid_layer, + offset=loc, + 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 diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index fbe60ff0..1e821e99 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -615,9 +615,7 @@ class bank(design.design): for pin_name in ["vdd", "gnd"]: pin_list = inst.get_pins(pin_name) for pin in pin_list: - self.add_power_pin(pin_name, - pin.center(), - start_layer=pin.layer) + self.copy_power_pin(pin, pin.center()) def route_bank_select(self, port): """ Route the bank select logic. """ diff --git a/compiler/modules/col_cap_array.py b/compiler/modules/col_cap_array.py index 1be29327..498f5076 100644 --- a/compiler/modules/col_cap_array.py +++ b/compiler/modules/col_cap_array.py @@ -100,7 +100,5 @@ class col_cap_array(bitcell_base_array): inst = self.cell_inst[row, col] for pin_name in ["vdd", "gnd"]: for pin in inst.get_pins(pin_name): - self.add_power_pin(name=pin_name, - loc=pin.center(), - start_layer=pin.layer) + self.copy_power_pin(pin) diff --git a/compiler/modules/delay_chain.py b/compiler/modules/delay_chain.py index fa6df322..54fbf414 100644 --- a/compiler/modules/delay_chain.py +++ b/compiler/modules/delay_chain.py @@ -177,14 +177,10 @@ class delay_chain(design.design): load_list = self.load_inst_map[inst] for pin_name in ["vdd", "gnd"]: pin = load_list[0].get_pin(pin_name) - self.add_power_pin(pin_name, - pin.rc() - vector(self.m1_pitch, 0), - start_layer=pin.layer) + self.copy_power_pin(pin, loc=pin.rc() - vector(self.m1_pitch, 0)) pin = load_list[-2].get_pin(pin_name) - self.add_power_pin(pin_name, - pin.rc() - vector(self.m1_pitch, 0), - start_layer=pin.layer) + self.copy_power_pin(pin, loc=pin.rc() - vector(self.m1_pitch, 0)) def add_layout_pins(self): diff --git a/compiler/modules/dff_array.py b/compiler/modules/dff_array.py index 82746a06..e60ed146 100644 --- a/compiler/modules/dff_array.py +++ b/compiler/modules/dff_array.py @@ -112,11 +112,11 @@ class dff_array(design.design): for col in range(self.columns): # Continous vdd rail along with label. vdd_pin=self.dff_insts[row, col].get_pin("vdd") - self.add_power_pin("vdd", vdd_pin.center(), start_layer=vdd_pin.layer) + self.copy_power_pin(vdd_pin) # Continous gnd rail along with label. gnd_pin=self.dff_insts[row, col].get_pin("gnd") - self.add_power_pin("gnd", gnd_pin.center(), start_layer=gnd_pin.layer) + self.copy_power_pin(gnd_pin) for row in range(self.rows): for col in range(self.columns): diff --git a/compiler/modules/dff_buf_array.py b/compiler/modules/dff_buf_array.py index ea811e76..1ce78f3a 100644 --- a/compiler/modules/dff_buf_array.py +++ b/compiler/modules/dff_buf_array.py @@ -159,11 +159,11 @@ class dff_buf_array(design.design): for col in range(self.columns): # Continous vdd rail along with label. vdd_pin=self.dff_insts[row, col].get_pin("vdd") - self.add_power_pin("vdd", vdd_pin.lc(), start_layer=vdd_pin.layer) + self.copy_power_pin(vdd_pin, loc=vdd_pin.lc()) # Continous gnd rail along with label. gnd_pin=self.dff_insts[row, col].get_pin("gnd") - self.add_power_pin("gnd", gnd_pin.lc(), start_layer=gnd_pin.layer) + self.copy_power_pin(gnd_pin, loc=gnd_pin.lc()) def add_layout_pins(self): diff --git a/compiler/modules/dff_inv_array.py b/compiler/modules/dff_inv_array.py index 59fdfade..aba5e34b 100644 --- a/compiler/modules/dff_inv_array.py +++ b/compiler/modules/dff_inv_array.py @@ -130,12 +130,11 @@ class dff_inv_array(design.design): for col in range(self.columns): # Adds power pin on left of row vdd_pin=self.dff_insts[row,col].get_pin("vdd") - self.add_power_pin("vdd", vdd_pin.lc()) + self.add_power_pin(vdd_pin, loc=vdd_pin.lc()) # Adds gnd pin on left of row gnd_pin=self.dff_insts[row,col].get_pin("gnd") - self.add_power_pin("gnd", gnd_pin.lc()) - + self.add_power_pin(gnd_pin, loc=gnd_pin.lc()) for row in range(self.rows): for col in range(self.columns): diff --git a/compiler/modules/hierarchical_decoder.py b/compiler/modules/hierarchical_decoder.py index 372e9792..9a5127e2 100644 --- a/compiler/modules/hierarchical_decoder.py +++ b/compiler/modules/hierarchical_decoder.py @@ -611,12 +611,7 @@ class hierarchical_decoder(design.design): for i in self.and_inst[:-1]: pins = i.get_pins(n) for pin in pins: - self.add_power_pin(name=n, - loc=pin.uc(), - start_layer=pin.layer) - self.add_power_pin(name=n, - loc=pin.uc(), - start_layer=pin.layer) + self.copy_power_pin(pin, loc=pin.uc()) for i in self.pre2x4_inst + self.pre3x8_inst: self.copy_layout_pin(i, n) @@ -628,9 +623,7 @@ class hierarchical_decoder(design.design): # The nand and inv are the same height rows... supply_pin = self.and_inst[row].get_pin(pin_name) pin_pos = vector(xoffset, supply_pin.cy()) - self.add_power_pin(name=pin_name, - loc=pin_pos, - start_layer=supply_pin.layer) + self.copy_power_pin(supply_pin, loc=pin_pos) # Copy the pins from the predecoders for pre in self.pre2x4_inst + self.pre3x8_inst + self.pre4x16_inst: diff --git a/compiler/modules/hierarchical_predecode.py b/compiler/modules/hierarchical_predecode.py index 72fb2a6d..b9d71a2c 100644 --- a/compiler/modules/hierarchical_predecode.py +++ b/compiler/modules/hierarchical_predecode.py @@ -330,12 +330,7 @@ class hierarchical_predecode(design.design): for i in self.inv_inst[:-1:2] + self.and_inst[:-1:2]: pins = i.get_pins(n) for pin in pins: - self.add_power_pin(name=n, - loc=pin.uc(), - start_layer=pin.layer) - self.add_power_pin(name=n, - loc=pin.uc(), - start_layer=pin.layer) + self.copy_power_pin(pin, loc=pin.uc()) # In other techs, we are using standard cell decoder cells with horizontal power else: @@ -353,9 +348,7 @@ class hierarchical_predecode(design.design): for xoffset in [self.inv_inst[0].lx() - self.bus_space, self.and_inst[0].lx() - self.bus_space]: pin_pos = vector(xoffset, and_pin.cy()) - self.add_power_pin(name=n, - loc=pin_pos, - start_layer=and_pin.layer) + self.copy_power_pin(and_pin, loc=pin_pos) diff --git a/compiler/modules/local_bitcell_array.py b/compiler/modules/local_bitcell_array.py index 5ff91268..b29cacb1 100644 --- a/compiler/modules/local_bitcell_array.py +++ b/compiler/modules/local_bitcell_array.py @@ -186,9 +186,7 @@ class local_bitcell_array(bitcell_base_array.bitcell_base_array): for inst in supply_insts: pin_list = inst.get_pins(pin_name) for pin in pin_list: - self.add_power_pin(name=pin_name, - loc=pin.center(), - start_layer=pin.layer) + self.copy_power_pin(pin) def route(self): diff --git a/compiler/modules/port_address.py b/compiler/modules/port_address.py index 382aca56..d4546178 100644 --- a/compiler/modules/port_address.py +++ b/compiler/modules/port_address.py @@ -82,9 +82,9 @@ class port_address(design.design): for rbl_vdd_pin in self.rbl_driver_inst.get_pins("vdd"): if layer_props.port_address.supply_offset: - self.add_power_pin("vdd", rbl_vdd_pin.center()) + self.copy_power_pin(rbl_vdd_pin) else: - self.add_power_pin("vdd", rbl_vdd_pin.lc()) + self.copy_power_pin(rbl_vdd_pin, loc=rbl_vdd_pin.lc()) # Also connect the B input of the RBL and_dec to vdd if OPTS.local_array_size == 0: diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index 6e1bca40..85225292 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -473,9 +473,7 @@ class replica_bitcell_array(bitcell_base_array): for inst in supply_insts: pin_list = inst.get_pins(pin_name) for pin in pin_list: - self.add_power_pin(name=pin_name, - loc=pin.center(), - start_layer=pin.layer) + self.copy_power_pin(pin) for inst in self.replica_col_insts: if inst: diff --git a/compiler/modules/replica_column.py b/compiler/modules/replica_column.py index 15d71685..94de906e 100644 --- a/compiler/modules/replica_column.py +++ b/compiler/modules/replica_column.py @@ -190,7 +190,8 @@ class replica_column(bitcell_base_array): for (index, inst) in enumerate(self.cell_inst): for pin_name in ["vdd", "gnd"]: if inst in [self.cell_inst[0], self.cell_inst[self.total_size - 1]]: - self.copy_power_pins(inst, pin_name) + for pin in inst.get_pins(pin_name): + self.copy_power_pin(pin) else: self.copy_layout_pin(inst, pin_name) diff --git a/compiler/modules/row_cap_array.py b/compiler/modules/row_cap_array.py index 850dd5f9..59da5fc2 100644 --- a/compiler/modules/row_cap_array.py +++ b/compiler/modules/row_cap_array.py @@ -113,7 +113,5 @@ class row_cap_array(bitcell_base_array): inst = self.cell_inst[row, col] for pin_name in ["vdd", "gnd"]: for pin in inst.get_pins(pin_name): - self.add_power_pin(name=pin_name, - loc=pin.center(), - start_layer=pin.layer) + self.add_power_pin(pin) diff --git a/compiler/modules/sense_amp_array.py b/compiler/modules/sense_amp_array.py index d3ab94a5..e4975574 100644 --- a/compiler/modules/sense_amp_array.py +++ b/compiler/modules/sense_amp_array.py @@ -146,16 +146,10 @@ class sense_amp_array(design.design): inst = self.local_insts[i] for gnd_pin in inst.get_pins("gnd"): - self.add_power_pin(name="gnd", - loc=gnd_pin.center(), - start_layer=gnd_pin.layer, - directions=("V", "V")) + self.copy_power_pin(gnd_pin, directions=("V", "V")) for vdd_pin in inst.get_pins("vdd"): - self.add_power_pin(name="vdd", - loc=vdd_pin.center(), - start_layer=vdd_pin.layer, - directions=("V", "V")) + self.copy_power_pin(vdd_pin, directions=("V", "V")) bl_pin = inst.get_pin(inst.mod.get_bl_names()) br_pin = inst.get_pin(inst.mod.get_br_names()) diff --git a/compiler/modules/wordline_buffer_array.py b/compiler/modules/wordline_buffer_array.py index d3132861..24529ff7 100644 --- a/compiler/modules/wordline_buffer_array.py +++ b/compiler/modules/wordline_buffer_array.py @@ -96,7 +96,7 @@ class wordline_buffer_array(design.design): # Add pins in two locations for xoffset in xoffset_list: pin_pos = vector(xoffset, supply_pin.cy()) - self.add_power_pin(name, pin_pos) + self.copy_power_pin(supply_pin, loc=pin_pos) def create_drivers(self): self.wld_inst = [] diff --git a/compiler/modules/wordline_driver_array.py b/compiler/modules/wordline_driver_array.py index a310a26f..10816020 100644 --- a/compiler/modules/wordline_driver_array.py +++ b/compiler/modules/wordline_driver_array.py @@ -97,7 +97,7 @@ class wordline_driver_array(design.design): # Add pins in two locations for xoffset in xoffset_list: pin_pos = vector(xoffset, supply_pin.cy()) - self.add_power_pin(name, pin_pos) + self.copy_power_pin(supply_pin, loc=pin_pos) def create_drivers(self): self.wld_inst = [] diff --git a/compiler/modules/write_driver_array.py b/compiler/modules/write_driver_array.py index afd21de5..8ba0d1d1 100644 --- a/compiler/modules/write_driver_array.py +++ b/compiler/modules/write_driver_array.py @@ -208,10 +208,8 @@ class write_driver_array(design.design): for n in ["vdd", "gnd"]: pin_list = self.driver_insts[i].get_pins(n) for pin in pin_list: - self.add_power_pin(name=n, - loc=pin.center(), - directions=("V", "V"), - start_layer=pin.layer) + self.copy_power_pin(pin, directions=("V", "V")) + if self.write_size: for bit in range(self.num_wmasks): inst = self.driver_insts[bit * self.write_size] diff --git a/compiler/modules/write_mask_and_array.py b/compiler/modules/write_mask_and_array.py index f25a71c5..cb6c1db4 100644 --- a/compiler/modules/write_mask_and_array.py +++ b/compiler/modules/write_mask_and_array.py @@ -145,6 +145,6 @@ class write_mask_and_array(design.design): left_loc = vector(0, supply_pin_yoffset) right_loc = vector(self.width, supply_pin_yoffset) self.add_path(supply_pin.layer, [left_loc, right_loc]) - self.add_power_pin(supply, left_loc, start_layer=supply_pin.layer) - self.add_power_pin(supply, right_loc, start_layer=supply_pin.layer) + self.copy_power_pin(supply_pin, loc=left_loc) + self.copy_power_pin(supply_pin, loc=right_loc)