From 1269bf6e16d7b3639c0a61d1e8a5f66771204749 Mon Sep 17 00:00:00 2001 From: mrg Date: Fri, 4 Sep 2020 13:06:58 -0700 Subject: [PATCH] Global bitcell working --- compiler/modules/bank.py | 2 +- compiler/modules/bitcell_base_array.py | 11 +-- compiler/modules/global_bitcell_array.py | 91 ++++++++++++++--------- compiler/modules/local_bitcell_array.py | 4 +- compiler/modules/replica_bitcell_array.py | 62 +++++++++------ 5 files changed, 102 insertions(+), 68 deletions(-) diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index a0b6c9b5..fb909465 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -439,7 +439,7 @@ class bank(design.design): for port in self.all_ports: self.port_data_inst[port]=self.add_inst(name="port_data{}".format(port), mod=self.port_data[port]) - + import pdb; pdb.set_trace() temp = [] temp.extend(["rbl_bl_{0}_{0}".format(port), "rbl_br_{0}_{0}".format(port)]) temp.extend(self.bitcell_array.get_bitline_names(port)) diff --git a/compiler/modules/bitcell_base_array.py b/compiler/modules/bitcell_base_array.py index 00ea49b0..9f27f5b4 100644 --- a/compiler/modules/bitcell_base_array.py +++ b/compiler/modules/bitcell_base_array.py @@ -115,7 +115,7 @@ class bitcell_base_array(design.design): def get_all_wordline_names(self, port=None): """ Return all the wordline names """ temp = [] - temp.extend(self.get_dummy_wordline_names(0)) + temp.extend(self.get_dummy_wordline_names()) temp.extend(self.get_rbl_wordline_names(0)) if port == None: temp.extend(self.all_wordline_names) @@ -123,17 +123,14 @@ class bitcell_base_array(design.design): temp.extend(self.wordline_names[port]) if len(self.all_ports) > 1: temp.extend(self.get_rbl_wordline_names(1)) - temp.extend(self.get_dummy_wordline_names(1)) + temp.extend(self.get_dummy_wordline_names()) return temp - def get_dummy_wordline_names(self, port=None): + def get_dummy_wordline_names(self): """ Return the ACTIVE WL for the given dummy port. """ - if port == None: - return self.all_dummy_row_wordline_names - else: - return self.dummy_row_wordline_names[port] + return self.dummy_row_wordline_names def add_layout_pins(self): """ Add the layout pins """ diff --git a/compiler/modules/global_bitcell_array.py b/compiler/modules/global_bitcell_array.py index d5e5678b..319a85cc 100644 --- a/compiler/modules/global_bitcell_array.py +++ b/compiler/modules/global_bitcell_array.py @@ -22,16 +22,14 @@ class global_bitcell_array(bitcell_base_array.bitcell_base_array): """ def __init__(self, rows, cols, name=""): # The total of all columns will be the number of columns - super().__init__(name=name, rows=rows, cols=cols, column_offset=0) - self.cols = cols - self.num_cols = sum(cols) - self.col_offsets = [0] + list(cumsum(self.cols)[:-1]) - self.rows = rows + super().__init__(name=name, rows=rows, cols=sum(cols), column_offset=0) + self.column_sizes = cols + self.col_offsets = [0] + list(cumsum(cols)[:-1]) debug.check(len(self.all_ports)<=2, "Only support dual port or less in global bitcell array.") self.rbl = [1, 1 if len(self.all_ports)>1 else 0] - self.left_rbl = self.rbl[0] - self.right_rbl = self.rbl[1] + self.add_left_rbl = self.rbl[0] + self.add_right_rbl = self.rbl[1] self.create_netlist() if not OPTS.netlist_only: @@ -59,32 +57,24 @@ class global_bitcell_array(bitcell_base_array.bitcell_base_array): """ Add the modules used in this design """ self.local_mods = [] - if self.cols == 1: - la = factory.create(module_type="local_bitcell_array", rows=self.rows, cols=self.cols[0], rbl=self.rbl, add_rbl=[self.left_rbl, self.right_rbl]) + if len(self.column_sizes) == 1: + la = factory.create(module_type="local_bitcell_array", rows=self.row_size, cols=self.column_sizes[0], rbl=self.rbl, add_rbl=[self.add_left_rbl, self.add_right_rbl]) self.add_mod(la) self.local_mods.append(la) return - for i, cols in enumerate(self.cols): + for i, cols in enumerate(self.column_sizes): # Always add the left RBLs to the first subarray and the right RBLs to the last subarray if i == 0: - la = factory.create(module_type="local_bitcell_array", rows=self.rows, cols=cols, rbl=self.rbl, add_rbl=[self.left_rbl, 0]) - elif i == len(self.cols) - 1: - la = factory.create(module_type="local_bitcell_array", rows=self.rows, cols=cols, rbl=self.rbl, add_rbl=[0, self.right_rbl]) + la = factory.create(module_type="local_bitcell_array", rows=self.row_size, cols=cols, rbl=self.rbl, add_rbl=[self.add_left_rbl, 0]) + elif i == len(self.column_sizes) - 1: + la = factory.create(module_type="local_bitcell_array", rows=self.row_size, cols=cols, rbl=self.rbl, add_rbl=[0, self.add_right_rbl]) else: - la = factory.create(module_type="local_bitcell_array", rows=self.rows, cols=cols, rbl=self.rbl, add_rbl=[0, 0]) + la = factory.create(module_type="local_bitcell_array", rows=self.row_size, cols=cols, rbl=self.rbl, add_rbl=[0, 0]) self.add_mod(la) self.local_mods.append(la) - # We make these on our own and don't use the base names - def create_all_wordline_names(self): - pass - - # We make these on our own and don't use the base names - def create_all_bitline_names(self): - pass - def add_pins(self): self.add_bitline_pins() @@ -94,37 +84,55 @@ class global_bitcell_array(bitcell_base_array.bitcell_base_array): self.add_pin("gnd", "GROUND") def add_bitline_pins(self): - self.bitline_names = [] + self.bitline_names = [[] for x in self.all_ports] + self.rbl_bitline_names = [[] for x in self.all_ports] for port in self.all_ports: - self.bitline_names.append("rbl_bl_{0}_{1}".format(port, 0)) - self.bitline_names.append("rbl_br_{0}_{1}".format(port, 0)) + self.bitline_names[port].append("rbl_bl_{}_0".format(port)) + self.rbl_bitline_names[port].append("rbl_bl_{}_0".format(port)) + for port in self.all_ports: + self.bitline_names[port].append("rbl_br_{}_0".format(port)) + self.rbl_bitline_names[port].append("rbl_br_{}_0".format(port)) - for col in range(self.num_cols): + for col in range(self.column_size): for port in self.all_ports: - self.bitline_names.append("bl_{0}_{1}".format(port, col)) - self.bitline_names.append("br_{0}_{1}".format(port, col)) + self.bitline_names[port].append("bl_{0}_{1}".format(port, col)) + for port in self.all_ports: + self.bitline_names[port].append("br_{0}_{1}".format(port, col)) if len(self.all_ports) > 1: for port in self.all_ports: - self.bitline_names.append("rbl_bl_{0}_{1}".format(port, 1)) - self.bitline_names.append("rbl_br_{0}_{1}".format(port, 1)) + self.bitline_names[port].append("rbl_bl_{}_1".format(port)) + self.rbl_bitline_names[port].append("rbl_bl_{}_1".format(port)) + for port in self.all_ports: + self.bitline_names[port].append("rbl_br_{}_1".format(port)) + self.rbl_bitline_names[port].append("rbl_br_{}_1".format(port)) - self.add_pin_list(self.bitline_names, "INOUT") + # Make a flat list too + self.all_bitline_names = [x for sl in zip(*self.bitline_names) for x in sl] + + self.add_pin_list(self.all_bitline_names, "INOUT") def add_wordline_pins(self): - self.wordline_names = [] + self.dummy_row_wordline_names = [[] for x in self.all_ports] + self.rbl_wordline_names = [] + + self.wordline_names = [] + self.wordline_names.append("rbl_wl_0_0") + # This is to keep it the same as a plain replica_bitline_array + self.rbl_wordline_names.append("rbl_wl_0_0") # Regular WLs - for row in range(self.rows): + for row in range(self.row_size): for port in self.all_ports: self.wordline_names.append("wl_{0}_{1}".format(port, row)) if len(self.all_ports) > 1: self.wordline_names.append("rbl_wl_1_1") + self.rbl_wordline_names.append("rbl_wl_1_1") self.add_pin_list(self.wordline_names, "INPUT") @@ -141,9 +149,10 @@ class global_bitcell_array(bitcell_base_array.bitcell_base_array): temp = [] if col == 0: temp.append("rbl_bl_0_0") - temp.append("rbl_br_0_0") if len(self.all_ports) > 1: temp.append("rbl_bl_1_0") + temp.append("rbl_br_0_0") + if len(self.all_ports) > 1: temp.append("rbl_br_1_0") port_inouts = [x for x in mod.get_inouts() if x.startswith("bl") or x.startswith("br")] @@ -161,8 +170,8 @@ class global_bitcell_array(bitcell_base_array.bitcell_base_array): if len(self.all_ports) > 1 and mod == self.local_mods[-1]: temp.append("rbl_bl_0_1") - temp.append("rbl_br_0_1") temp.append("rbl_bl_1_1") + temp.append("rbl_br_0_1") temp.append("rbl_br_1_1") for port in self.all_ports: @@ -228,14 +237,22 @@ class global_bitcell_array(bitcell_base_array.bitcell_base_array): new_name = "{0}_{1}".format(base_name, col + col_value) self.copy_layout_pin(inst, pin_name, new_name) + # Replica wordlines + self.copy_layout_pin(self.local_insts[0], "rbl_wl_0_0") + if len(self.all_ports) > 1: + self.copy_layout_pin(self.local_insts[-1], "rbl_wl_1_1") # Replica bitlines self.copy_layout_pin(self.local_insts[0], "rbl_bl_0_0") self.copy_layout_pin(self.local_insts[0], "rbl_br_0_0") if len(self.all_ports) > 1: - self.copy_layout_pin(self.local_insts[-1], "rbl_bl_1_0") - self.copy_layout_pin(self.local_insts[-1], "rbl_br_1_0") + self.copy_layout_pin(self.local_insts[0], "rbl_bl_1_0") + self.copy_layout_pin(self.local_insts[0], "rbl_br_1_0") + self.copy_layout_pin(self.local_insts[-1], "rbl_bl_0_0", "rbl_bl_0_1") + self.copy_layout_pin(self.local_insts[-1], "rbl_br_0_0", "rbl_br_0_1") + self.copy_layout_pin(self.local_insts[-1], "rbl_bl_1_0", "rbl_bl_1_1") + self.copy_layout_pin(self.local_insts[-1], "rbl_br_1_0", "rbl_br_1_1") for inst in self.insts: self.copy_power_pins(inst, "vdd") diff --git a/compiler/modules/local_bitcell_array.py b/compiler/modules/local_bitcell_array.py index b125fb01..d3881830 100644 --- a/compiler/modules/local_bitcell_array.py +++ b/compiler/modules/local_bitcell_array.py @@ -100,8 +100,8 @@ class local_bitcell_array(bitcell_base_array.bitcell_base_array): wordline_inputs += [self.bitcell_array.get_rbl_wordline_names(1)[1]] self.wordline_names.append(wordline_inputs) self.driver_wordline_outputs.append([x + "i" for x in self.wordline_names[-1]]) - - self.all_array_wordline_inputs = [x + "i" for x in self.bitcell_array.get_all_wordline_names() if x != "gnd"] + + self.all_array_wordline_inputs = [x + "i" for x in self.bitcell_array.get_inputs() if "wl" in x] self.bitline_names = self.bitcell_array.bitline_names self.all_array_bitline_names = self.bitcell_array.get_all_bitline_names() diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index 894b4460..efbc14cf 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -195,6 +195,7 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array): self.rbl_bitline_names.append([]) for port in self.all_ports: self.rbl_bitline_names[-1].append("rbl_bl_{0}_{1}".format(port, x)) + for port in self.all_ports: self.rbl_bitline_names[-1].append("rbl_br_{0}_{1}".format(port, x)) # Make a flat list too @@ -218,12 +219,18 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array): self.wordline_names = [] # Replica wordlines by port self.rbl_wordline_names = [] + # Wordlines to ground + self.gnd_wordline_names = [] self.dummy_row_wordline_names = ["gnd"] * len(self.col_cap.get_wordline_names()) for port in range(self.left_rbl + self.right_rbl): - wordline_names=["rbl_wl_{0}_{1}".format(x, port) for x in self.all_ports] - self.rbl_wordline_names.append(wordline_names) + self.rbl_wordline_names.append([]) + for x in self.all_ports: + self.rbl_wordline_names[-1].append("rbl_wl_{0}_{1}".format(x, port)) + if x != port: + self.gnd_wordline_names.append("rbl_wl_{0}_{1}".format(x, port)) + self.all_rbl_wordline_names = [x for sl in self.rbl_wordline_names for x in sl] for port in self.all_ports: @@ -235,17 +242,17 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array): self.replica_array_wordline_names = [] self.replica_array_wordline_names.extend(self.dummy_row_wordline_names) for p in range(self.left_rbl): - self.replica_array_wordline_names.extend(self.rbl_wordline_names[p]) + self.replica_array_wordline_names.extend([x if x not in self.gnd_wordline_names else "gnd" for x in self.rbl_wordline_names[p]]) self.replica_array_wordline_names.extend(self.all_wordline_names) for p in range(self.left_rbl, self.left_rbl + self.right_rbl): - self.replica_array_wordline_names.extend(self.rbl_wordline_names[p]) + self.replica_array_wordline_names.extend([x if x not in self.gnd_wordline_names else "gnd" for x in self.rbl_wordline_names[p]]) self.replica_array_wordline_names.extend(self.dummy_row_wordline_names) for port in range(self.left_rbl): - self.add_pin_list(self.rbl_wordline_names[port], "INPUT") + self.add_pin(self.rbl_wordline_names[port][0], "INPUT") self.add_pin_list(self.all_wordline_names, "INPUT") for port in range(self.left_rbl, self.left_rbl + self.right_rbl): - self.add_pin_list(self.rbl_wordline_names[port], "INPUT") + self.add_pin(self.rbl_wordline_names[port][1], "INPUT") def create_instances(self): """ Create the module instances used in this design """ @@ -273,7 +280,7 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array): for port in range(self.left_rbl + self.right_rbl): self.dummy_row_replica_insts.append(self.add_inst(name="dummy_row_{}".format(port), mod=self.dummy_row)) - self.connect_inst(self.rbl_wordline_names[port] + supplies) + self.connect_inst([x if x not in self.gnd_wordline_names else "gnd" for x in self.rbl_wordline_names[port]] + supplies) # Top/bottom dummy rows or col caps self.dummy_row_insts = [] @@ -370,7 +377,7 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array): def add_layout_pins(self): """ Add the layout pins """ - + # All wordlines # Main array wl and bl/br for pin_name in self.all_wordline_names: @@ -381,6 +388,7 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array): offset=pin.ll().scale(0, 1), width=self.width, height=pin.height()) + for pin_name in self.all_bitline_names: pin_list = self.bitcell_array_inst.get_pins(pin_name) for pin in pin_list: @@ -394,6 +402,8 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array): # even though the column is in another local bitcell array) for (names, inst) in zip(self.rbl_wordline_names, self.dummy_row_replica_insts): for (wl_name, pin_name) in zip(names, self.dummy_row.get_wordline_names()): + if wl_name in self.gnd_wordline_names: + continue pin = inst.get_pin(pin_name) self.add_layout_pin(text=wl_name, layer=pin.layer, @@ -446,23 +456,33 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array): def route_unused_wordlines(self): """ Connect the unused RBL and dummy wordlines to gnd """ + # This grounds all the dummy row word lines for inst in self.dummy_row_insts: for wl_name in self.col_cap.get_wordline_names(): - pin = inst.get_pin(wl_name) - pin_layer = pin.layer - layer_pitch = 1.5 * getattr(self, "{}_pitch".format(pin_layer)) - left_pin_loc = vector(self.dummy_col_insts[0].lx(), pin.cy()) - right_pin_loc = vector(self.dummy_col_insts[1].rx(), pin.cy()) + self.ground_pin(inst, wl_name) - # Place the pins a track outside of the array - left_loc = left_pin_loc - vector(layer_pitch, 0) - right_loc = right_pin_loc + vector(layer_pitch, 0) - self.add_power_pin("gnd", left_loc, directions=("H", "H")) - self.add_power_pin("gnd", right_loc, directions=("H", "H")) + # Ground the unused replica wordlines + for (names, inst) in zip(self.rbl_wordline_names, self.dummy_row_replica_insts): + for (wl_name, pin_name) in zip(names, self.dummy_row.get_wordline_names()): + if wl_name in self.gnd_wordline_names: + self.ground_pin(inst, pin_name) - # Add a path to connect to the array - self.add_path(pin_layer, [left_loc, left_pin_loc]) - self.add_path(pin_layer, [right_loc, right_pin_loc]) + def ground_pin(self, inst, name): + pin = inst.get_pin(name) + pin_layer = pin.layer + layer_pitch = 1.5 * getattr(self, "{}_pitch".format(pin_layer)) + left_pin_loc = vector(self.dummy_col_insts[0].lx(), pin.cy()) + right_pin_loc = vector(self.dummy_col_insts[1].rx(), pin.cy()) + + # Place the pins a track outside of the array + left_loc = left_pin_loc - vector(layer_pitch, 0) + right_loc = right_pin_loc + vector(layer_pitch, 0) + self.add_power_pin("gnd", left_loc, directions=("H", "H")) + self.add_power_pin("gnd", right_loc, directions=("H", "H")) + + # Add a path to connect to the array + self.add_path(pin_layer, [left_loc, left_pin_loc]) + self.add_path(pin_layer, [right_loc, right_pin_loc]) def gen_bl_wire(self): if OPTS.netlist_only: