diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index f39cfba8..3aa21794 100644 --- a/compiler/base/hierarchy_layout.py +++ b/compiler/base/hierarchy_layout.py @@ -127,6 +127,7 @@ class layout(lef.lef): inst.mirror = mirror inst.rotate = rotate inst.update_boundary() + return inst def add_inst(self, name, mod, offset=[0,0], mirror="R0",rotate=0): """Adds an instance of a mod to this module""" diff --git a/compiler/modules/sense_amp_array.py b/compiler/modules/sense_amp_array.py index 5d16b323..5a513583 100644 --- a/compiler/modules/sense_amp_array.py +++ b/compiler/modules/sense_amp_array.py @@ -27,7 +27,7 @@ class sense_amp_array(design.design): self.height = self.amp.height self.width = self.amp.width * self.word_size * self.words_per_row - self.add_pins() + self.create_netlist() self.create_layout() self.DRC_LVS() @@ -42,36 +42,42 @@ class sense_amp_array(design.design): self.add_pin("vdd") self.add_pin("gnd") + def create_netlist(self): + self.add_pins() + self.create_sense_amp_array() + def create_layout(self): - - self.add_sense_amp() - self.connect_rails() + self.place_sense_amp_array() + self.add_layout_pins() + self.route_rails() - def add_sense_amp(self): - - bl_pin = self.amp.get_pin("bl") - br_pin = self.amp.get_pin("br") - dout_pin = self.amp.get_pin("dout") - - amp_spacing = self.amp.width * self.words_per_row + def create_sense_amp_array(self): + self.local_insts = [] for i in range(0,self.word_size): name = "sa_d{0}".format(i) - amp_position = vector(amp_spacing * i, 0) - - bl_offset = amp_position + bl_pin.ll().scale(1,0) - br_offset = amp_position + br_pin.ll().scale(1,0) - dout_offset = amp_position + dout_pin.ll() - - inst = self.add_inst(name=name, - mod=self.amp, - offset=amp_position) + self.local_insts.append(self.add_inst(name=name, + mod=self.amp)) self.connect_inst(["bl[{0}]".format(i), "br[{0}]".format(i), "data[{0}]".format(i), "en", "vdd", "gnd"]) + def place_sense_amp_array(self): + + amp_spacing = self.amp.width * self.words_per_row + for i in range(0,self.word_size): + + name = "sa_d{0}".format(i) + amp_position = vector(amp_spacing * i, 0) + self.place_inst(name=name, + offset=amp_position) + + + def add_layout_pins(self): + for i in range(len(self.local_insts)): + inst = self.local_insts[i] gnd_pos = inst.get_pin("gnd").center() self.add_via_center(layers=("metal2", "via2", "metal3"), @@ -79,33 +85,36 @@ class sense_amp_array(design.design): self.add_layout_pin_rect_center(text="gnd", layer="metal3", offset=gnd_pos) - vdd_pos = inst.get_pin("vdd").center() self.add_via_center(layers=("metal2", "via2", "metal3"), offset=vdd_pos) self.add_layout_pin_rect_center(text="vdd", layer="metal3", offset=vdd_pos) + + bl_pin = inst.get_pin("bl") + br_pin = inst.get_pin("br") + dout_pin = inst.get_pin("dout") self.add_layout_pin(text="bl[{0}]".format(i), layer="metal2", - offset=bl_offset, + offset=bl_pin.ll(), width=bl_pin.width(), height=bl_pin.height()) self.add_layout_pin(text="br[{0}]".format(i), layer="metal2", - offset=br_offset, + offset=br_pin.ll(), width=br_pin.width(), height=br_pin.height()) self.add_layout_pin(text="data[{0}]".format(i), layer="metal2", - offset=dout_offset, + offset=dout_pin.ll(), width=dout_pin.width(), height=dout_pin.height()) - - def connect_rails(self): + + def route_rails(self): # add sclk rail across entire array sclk_offset = self.amp.get_pin("en").ll().scale(0,1) self.add_layout_pin(text="en", diff --git a/compiler/modules/single_level_column_mux_array.py b/compiler/modules/single_level_column_mux_array.py index 777958a5..4913bfb7 100644 --- a/compiler/modules/single_level_column_mux_array.py +++ b/compiler/modules/single_level_column_mux_array.py @@ -20,9 +20,8 @@ class single_level_column_mux_array(design.design): self.columns = columns self.word_size = word_size self.words_per_row = int(self.columns / self.word_size) - self.add_pins() + self.create_netlist() self.create_layout() - self.DRC_LVS() def add_pins(self): for i in range(self.columns): @@ -35,10 +34,14 @@ class single_level_column_mux_array(design.design): self.add_pin("br_out[{}]".format(i)) self.add_pin("gnd") - def create_layout(self): + def create_netlist(self): + self.add_pins() self.add_modules() - self.setup_layout_constants() self.create_array() + + def create_layout(self): + self.setup_layout_constants() + self.place_array() self.add_routing() # Find the highest shapes to determine height before adding well highest = self.find_highest_coords() @@ -46,6 +49,7 @@ class single_level_column_mux_array(design.design): self.add_layout_pins() self.add_enclosure(self.mux_inst, "pwell") + self.DRC_LVS() def add_modules(self): @@ -65,14 +69,11 @@ class single_level_column_mux_array(design.design): def create_array(self): self.mux_inst = [] - # For every column, add a pass gate for col_num in range(self.columns): name = "XMUX{0}".format(col_num) - x_off = vector(col_num * self.mux.width, self.route_height) self.mux_inst.append(self.add_inst(name=name, - mod=self.mux, - offset=x_off)) + mod=self.mux)) self.connect_inst(["bl[{}]".format(col_num), "br[{}]".format(col_num), @@ -81,6 +82,14 @@ class single_level_column_mux_array(design.design): "sel[{}]".format(col_num % self.words_per_row), "gnd"]) + def place_array(self): + # For every column, add a pass gate + for col_num in range(self.columns): + name = "XMUX{0}".format(col_num) + x_off = vector(col_num * self.mux.width, self.route_height) + self.place_inst(name=name, + offset=x_off) + def add_layout_pins(self): """ Add the pins after we determine the height. """ diff --git a/compiler/modules/tri_gate_array.py b/compiler/modules/tri_gate_array.py index b18461cc..22004a9f 100644 --- a/compiler/modules/tri_gate_array.py +++ b/compiler/modules/tri_gate_array.py @@ -27,14 +27,17 @@ class tri_gate_array(design.design): self.width = (self.columns / self.words_per_row) * self.tri.width self.height = self.tri.height + self.create_netlist() self.create_layout() - self.DRC_LVS() - def create_layout(self): - """generate layout """ + def create_netlist(self): self.add_pins() self.create_array() + + def create_layout(self): + self.place_array() self.add_layout_pins() + self.DRC_LVS() def add_pins(self): """create the name of pins depend on the word size""" @@ -50,15 +53,21 @@ class tri_gate_array(design.design): self.tri_inst = {} for i in range(0,self.columns,self.words_per_row): name = "Xtri_gate{0}".format(i) - base = vector(i*self.tri.width, 0) self.tri_inst[i]=self.add_inst(name=name, - mod=self.tri, - offset=base) + mod=self.tri) index = int(i/self.words_per_row) self.connect_inst(["in[{0}]".format(index), "out[{0}]".format(index), "en", "en_bar", "vdd", "gnd"]) + def place_array(self): + """ Place the tri gate to the array """ + for i in range(0,self.columns,self.words_per_row): + name = "Xtri_gate{0}".format(i) + base = vector(i*self.tri.width, 0) + self.place_inst(name=name, + offset=base) + def add_layout_pins(self): diff --git a/compiler/modules/wordline_driver.py b/compiler/modules/wordline_driver.py index 2ddda761..4aa7526b 100644 --- a/compiler/modules/wordline_driver.py +++ b/compiler/modules/wordline_driver.py @@ -20,8 +20,8 @@ class wordline_driver(design.design): design.design.__init__(self, "wordline_driver") self.rows = rows - self.add_pins() - self.design_layout() + self.create_netlist() + self.create_layout() self.offset_all_coordinates() self.DRC_LVS() @@ -36,14 +36,18 @@ class wordline_driver(design.design): self.add_pin("vdd") self.add_pin("gnd") - def design_layout(self): - self.create_modules() + def create_netlist(self): + self.add_pins() self.add_modules() + self.create_drivers() + + def create_layout(self): + self.place_drivers() self.route_layout() self.route_vdd_gnd() - def create_modules(self): + def add_modules(self): self.inv = pinv() self.add_mod(self.inv) @@ -84,7 +88,37 @@ class wordline_driver(design.design): - def add_modules(self): + def create_drivers(self): + self.inv1_inst = [] + self.nand_inst = [] + self.inv2_inst = [] + for row in range(self.rows): + name_inv1 = "wl_driver_inv_en{}".format(row) + name_nand = "wl_driver_nand{}".format(row) + name_inv2 = "wl_driver_inv{}".format(row) + + # add inv1 based on the info above + self.inv1_inst.append(self.add_inst(name=name_inv1, + mod=self.inv_no_output)) + self.connect_inst(["en", + "en_bar[{0}]".format(row), + "vdd", "gnd"]) + # add nand 2 + self.nand_inst.append(self.add_inst(name=name_nand, + mod=self.nand2)) + self.connect_inst(["en_bar[{0}]".format(row), + "in[{0}]".format(row), + "wl_bar[{0}]".format(row), + "vdd", "gnd"]) + # add inv2 + self.inv2_inst.append(self.add_inst(name=name_inv2, + mod=self.inv)) + self.connect_inst(["wl_bar[{0}]".format(row), + "wl[{0}]".format(row), + "vdd", "gnd"]) + + + def place_drivers(self): inv1_xoffset = 2*self.m1_width + 5*self.m1_space nand2_xoffset = inv1_xoffset + self.inv.width inv2_xoffset = nand2_xoffset + self.nand2.width @@ -93,9 +127,6 @@ class wordline_driver(design.design): self.height = self.inv.height * self.rows - self.inv1_inst = [] - self.nand_inst = [] - self.inv2_inst = [] for row in range(self.rows): name_inv1 = "wl_driver_inv_en{}".format(row) name_nand = "wl_driver_nand{}".format(row) @@ -113,30 +144,17 @@ class wordline_driver(design.design): inv2_offset=[inv2_xoffset, y_offset] # add inv1 based on the info above - self.inv1_inst.append(self.add_inst(name=name_inv1, - mod=self.inv_no_output, - offset=inv1_offset, - mirror=inst_mirror)) - self.connect_inst(["en", - "en_bar[{0}]".format(row), - "vdd", "gnd"]) + self.place_inst(name=name_inv1, + offset=inv1_offset, + mirror=inst_mirror) # add nand 2 - self.nand_inst.append(self.add_inst(name=name_nand, - mod=self.nand2, - offset=nand2_offset, - mirror=inst_mirror)) - self.connect_inst(["en_bar[{0}]".format(row), - "in[{0}]".format(row), - "wl_bar[{0}]".format(row), - "vdd", "gnd"]) + self.place_inst(name=name_nand, + offset=nand2_offset, + mirror=inst_mirror) # add inv2 - self.inv2_inst.append(self.add_inst(name=name_inv2, - mod=self.inv, - offset=inv2_offset, - mirror=inst_mirror)) - self.connect_inst(["wl_bar[{0}]".format(row), - "wl[{0}]".format(row), - "vdd", "gnd"]) + self.place_inst(name=name_inv2, + offset=inv2_offset, + mirror=inst_mirror) def route_layout(self): diff --git a/compiler/modules/write_driver_array.py b/compiler/modules/write_driver_array.py index 650361eb..2d5bea87 100644 --- a/compiler/modules/write_driver_array.py +++ b/compiler/modules/write_driver_array.py @@ -28,9 +28,8 @@ class write_driver_array(design.design): self.width = self.columns * self.driver.width self.height = self.height = self.driver.height - self.add_pins() + self.create_netlist() self.create_layout() - self.DRC_LVS() def add_pins(self): for i in range(self.word_size): @@ -42,20 +41,22 @@ class write_driver_array(design.design): self.add_pin("vdd") self.add_pin("gnd") - def create_layout(self): + def create_netlist(self): + self.add_pins() self.create_write_array() + + def create_layout(self): + self.place_write_array() self.add_layout_pins() + self.DRC_LVS() def create_write_array(self): self.driver_insts = {} for i in range(0,self.columns,self.words_per_row): name = "Xwrite_driver{}".format(i) - base = vector(i * self.driver.width,0) - index = int(i/self.words_per_row) self.driver_insts[index]=self.add_inst(name=name, - mod=self.driver, - offset=base) + mod=self.driver) self.connect_inst(["data[{0}]".format(index), "bl[{0}]".format(index), @@ -63,6 +64,15 @@ class write_driver_array(design.design): "en", "vdd", "gnd"]) + def place_write_array(self): + for i in range(0,self.columns,self.words_per_row): + name = "Xwrite_driver{}".format(i) + base = vector(i * self.driver.width,0) + + self.place_inst(name=name, + offset=base) + + def add_layout_pins(self): for i in range(self.word_size): din_pin = self.driver_insts[i].get_pin("din")