From f84ee04fa9e000da364024f557a757a9e947e8d6 Mon Sep 17 00:00:00 2001 From: mrg Date: Thu, 25 Jun 2020 14:03:59 -0700 Subject: [PATCH] Single bank passing. Parameterized gate column mux of dff height. End-cap only supply option instead of no vdd in bitcell. --- compiler/modules/bank.py | 14 ++++--- compiler/modules/bitcell_base_array.py | 16 ++++---- compiler/modules/hierarchical_decoder.py | 6 +-- compiler/modules/hierarchical_predecode.py | 44 +++++++++++----------- compiler/modules/replica_bitcell_array.py | 19 ++++++---- compiler/modules/replica_column.py | 13 +++++-- 6 files changed, 61 insertions(+), 51 deletions(-) diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index 12fcb6dd..6134b143 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -497,18 +497,20 @@ class bank(design.design): Create a 2:4 or 3:8 column address decoder. """ - # Height is a multiple of DFF so that it can be staggered - # and rows do not align with the control logic module - self.dff = factory.create(module_type="dff") + self.dff =factory.create(module_type="dff") if self.col_addr_size == 0: return elif self.col_addr_size == 1: - self.column_decoder = factory.create(module_type="pinvbuf", height=self.dff.height) + self.column_decoder = factory.create(module_type="pinvbuf", + height=self.dff.height) elif self.col_addr_size == 2: - self.column_decoder = factory.create(module_type="hierarchical_predecode2x4", height=self.dff.height) + self.column_decoder = factory.create(module_type="hierarchical_predecode2x4", + height=self.dff.height) + elif self.col_addr_size == 3: - self.column_decoder = factory.create(module_type="hierarchical_predecode3x8", height=self.dff.height) + self.column_decoder = factory.create(module_type="hierarchical_predecode3x8", + height=self.dff.height) else: # No error checking before? debug.error("Invalid column decoder?", -1) diff --git a/compiler/modules/bitcell_base_array.py b/compiler/modules/bitcell_base_array.py index e601208b..6698df33 100644 --- a/compiler/modules/bitcell_base_array.py +++ b/compiler/modules/bitcell_base_array.py @@ -110,17 +110,17 @@ class bitcell_base_array(design.design): # For specific technologies, there is no vdd via within the bitcell. Instead vdd is connect via end caps. try: - bitcell_no_vdd_pin = cell_properties.bitcell.no_vdd_via + end_caps_enabled = cell_properties.bitcell.end_caps except AttributeError: - bitcell_no_vdd_pin = False + end_caps_enabled = False # Add vdd/gnd via stacks - for row in range(self.row_size): - for col in range(self.column_size): - inst = self.cell_inst[row,col] - for pin_name in ["vdd", "gnd"]: - for pin in inst.get_pins(pin_name): - if not (pin_name == "vdd" and bitcell_no_vdd_pin): + if not end_caps_enabled: + for row in range(self.row_size): + for col in range(self.column_size): + 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(), directions=bitcell_power_pin_directions, diff --git a/compiler/modules/hierarchical_decoder.py b/compiler/modules/hierarchical_decoder.py index 3233bdc8..141387b4 100644 --- a/compiler/modules/hierarchical_decoder.py +++ b/compiler/modules/hierarchical_decoder.py @@ -78,12 +78,10 @@ class hierarchical_decoder(design.design): def add_decoders(self): """ Create the decoders based on the number of pre-decodes """ - self.pre2_4 = factory.create(module_type="hierarchical_predecode2x4", - height=self.cell_height) + self.pre2_4 = factory.create(module_type="hierarchical_predecode2x4") self.add_mod(self.pre2_4) - self.pre3_8 = factory.create(module_type="hierarchical_predecode3x8", - height=self.cell_height) + self.pre3_8 = factory.create(module_type="hierarchical_predecode3x8") self.add_mod(self.pre3_8) def determine_predecodes(self, num_inputs): diff --git a/compiler/modules/hierarchical_predecode.py b/compiler/modules/hierarchical_predecode.py index f2274c6e..d4cb51ce 100644 --- a/compiler/modules/hierarchical_predecode.py +++ b/compiler/modules/hierarchical_predecode.py @@ -20,12 +20,17 @@ class hierarchical_predecode(design.design): def __init__(self, name, input_number, height=None): self.number_of_inputs = input_number + b = factory.create(module_type="bitcell") if not height: - b = factory.create(module_type="bitcell") self.cell_height = b.height - else: + self.column_decoder = False + elif height != b.height: self.cell_height = height - + self.column_decoder = True + else: + self.cell_height = b.height + self.column_decoder = False + self.number_of_outputs = int(math.pow(2, self.number_of_inputs)) design.design.__init__(self, name) @@ -40,21 +45,21 @@ class hierarchical_predecode(design.design): def add_modules(self): """ Add the INV and AND gate modules """ - if self.number_of_inputs == 2: - self.and_mod = factory.create(module_type="and2_dec", - height=self.cell_height) - elif self.number_of_inputs == 3: - self.and_mod = factory.create(module_type="and3_dec", - height=self.cell_height) - elif self.number_of_inputs == 4: - self.and_mod = factory.create(module_type="and4_dec", - height=self.cell_height) + debug.check(self.number_of_inputs < 4, + "Invalid number of predecode inputs: {}".format(self.number_of_inputs)) + + if self.column_decoder: + and_type = "pand{}".format(self.number_of_inputs) + inv_type = "pinv" else: - debug.error("Invalid number of predecode inputs: {}".format(self.number_of_inputs), -1) + and_type = "and{}_dec".format(self.number_of_inputs) + inv_type = "inv_dec" + self.and_mod = factory.create(module_type=and_type, + height=self.cell_height) self.add_mod(self.and_mod) # This uses the pinv_dec parameterized cell - self.inv = factory.create(module_type="inv_dec", + self.inv = factory.create(module_type=inv_type, height=self.cell_height, size=1) self.add_mod(self.inv) @@ -80,7 +85,7 @@ class hierarchical_predecode(design.design): # Outputs from cells are on output layer if OPTS.tech_name == "sky130": self.bus_layer = "m1" - self.bus_directions = None + self.bus_directions = "nonpref" self.bus_pitch = self.m1_pitch self.bus_space = 1.5 * self.m1_space self.input_layer = "m2" @@ -88,7 +93,7 @@ class hierarchical_predecode(design.design): self.output_layer_pitch = self.li_pitch else: self.bus_layer = "m2" - self.bus_directions = None + self.bus_directions = "pref" self.bus_pitch = self.m2_pitch self.bus_space = self.m2_space # This requires a special jog to ensure to conflicts with the output layers @@ -238,10 +243,7 @@ class hierarchical_predecode(design.design): # add output so that it is just below the vdd or gnd rail # since this is where the p/n devices are and there are no # pins in the and gates. - if OPTS.tech_name == "sky130": - inv_out_pos = inv_out_pin.lr() - else: - inv_out_pos = inv_out_pin.rc() + inv_out_pos = inv_out_pin.rc() 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].cx(), y_offset) @@ -309,7 +311,7 @@ class hierarchical_predecode(design.design): """ Add a pin for each row of vdd/gnd which are must-connects next level up. """ # In sky130, we use hand-made decoder cells with vertical power - if OPTS.tech_name == "sky130": + if not self.column_decoder: for n in ["vdd", "gnd"]: # This makes a wire from top to bottom for both inv and and gates for i in [self.inv_inst, self.and_inst]: diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index 05cb1ac6..57bb3cf9 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -380,19 +380,22 @@ class replica_bitcell_array(design.design): # For specific technologies, there is no vdd via within the bitcell. Instead vdd is connect via end caps. try: - bitcell_no_vdd_pin = cell_properties.bitcell.no_vdd_via + if cell_properties.bitcell.end_caps_enabled: + supply_insts = [self.dummy_col_left_inst, self.dummy_col_right_inst, + self.dummy_row_top_inst, self.dummy_row_bot_inst] + list(self.replica_col_inst.values()) + else: + supply_insts = self.insts except AttributeError: - bitcell_no_vdd_pin = False + supply_insts = self.insts for pin_name in ["vdd", "gnd"]: - for inst in self.insts: + for inst in supply_insts: pin_list = inst.get_pins(pin_name) for pin in pin_list: - if not (pin_name == "vdd" and bitcell_no_vdd_pin): - self.add_power_pin(name=pin_name, - loc=pin.center(), - directions=("V", "V"), - start_layer=pin.layer) + self.add_power_pin(name=pin_name, + loc=pin.center(), + directions=("V", "V"), + start_layer=pin.layer) def get_rbl_wl_name(self, port): """ Return the WL for the given RBL port """ diff --git a/compiler/modules/replica_column.py b/compiler/modules/replica_column.py index 3a58668c..58d35e7f 100644 --- a/compiler/modules/replica_column.py +++ b/compiler/modules/replica_column.py @@ -183,11 +183,16 @@ class replica_column(design.design): width=self.width, height=wl_pin.height()) - # For every second row and column, add a via for gnd and vdd - for row in range(row_range_min, row_range_max): - inst = self.cell_inst[row] + # For specific technologies, there is no vdd via within the bitcell. Instead vdd is connect via end caps. + if end_caps_enabled: + supply_insts = [self.cell_inst[0], self.cell_inst[self.total_size - 1]] + else: + supply_insts = self.cell_inst.values() + + for inst in supply_insts: for pin_name in ["vdd", "gnd"]: - self.copy_layout_pin(inst, pin_name) + if pin_name in inst.mod.pins: + self.copy_layout_pin(inst, pin_name) def get_bitcell_pins(self, col, row): """ Creates a list of connections in the bitcell,