diff --git a/compiler/modules/rom_address_control_array.py b/compiler/modules/rom_address_control_array.py index 2b195bd8..cfb8a278 100644 --- a/compiler/modules/rom_address_control_array.py +++ b/compiler/modules/rom_address_control_array.py @@ -65,7 +65,9 @@ class rom_address_control_array(design): def add_pins(self): for col in range(self.cols): self.add_pin("A{0}_in".format(col), "INPUT") + for col in range(self.cols): self.add_pin("A{0}_out".format(col), "OUTPUT") + for col in range(self.cols): self.add_pin("Abar{0}_out".format(col), "OUTPUT") self.add_pin("clk", "INPUT") self.add_pin("vdd", "POWER") diff --git a/compiler/modules/rom_base_array.py b/compiler/modules/rom_base_array.py index 2d2be82a..7c329c67 100644 --- a/compiler/modules/rom_base_array.py +++ b/compiler/modules/rom_base_array.py @@ -117,7 +117,7 @@ class rom_base_array(bitcell_base_array): def add_pins(self): for bl_name in self.get_bitline_names(): - self.add_pin(bl_name, "INOUT") + self.add_pin(bl_name, "OUTPUT") for wl_name in self.get_wordline_names(): self.add_pin(wl_name, "INPUT") self.add_pin("precharge_gate", "INPUT") diff --git a/compiler/modules/rom_decoder.py b/compiler/modules/rom_decoder.py index 4a40444b..e1a642fd 100644 --- a/compiler/modules/rom_decoder.py +++ b/compiler/modules/rom_decoder.py @@ -144,8 +144,12 @@ class rom_decoder(design): for i in range(self.num_inputs): control_pins.append("A{0}".format(i)) - control_pins.append("in_{0}".format(i)) - control_pins.append("inbar_{0}".format(i)) + for i in range(self.num_inputs): + control_pins.append("A_int_{0}".format(i)) + for i in range(self.num_inputs): + control_pins.append("Ab_int_{0}".format(i)) + + control_pins.append("clk") control_pins.append("vdd") control_pins.append("gnd") @@ -163,8 +167,8 @@ class rom_decoder(design): for i in reversed(range(self.num_inputs)): - array_pins.append("inbar_{0}".format(i)) - array_pins.append("in_{0}".format(i)) + array_pins.append("Ab_int_{0}".format(i)) + array_pins.append("A_int_{0}".format(i)) array_pins.append("precharge") array_pins.append("vdd") array_pins.append("gnd") @@ -236,6 +240,7 @@ class rom_decoder(design): self.add_path(self.inv_route_layer, [addr_out_pin.center(), addr_middle, addr_pin.center()]) self.add_path(self.inv_route_layer, [addr_bar_out_pin.center(), addr_bar_middle, addr_bar_pin.center()]) + self.copy_layout_pin(self.buf_inst, "A{}_in".format(i), "A{}".format(i)) # self.add_segment_center(self.inv_route_layer, addr_bar_middle + vector(0, self.inv_route_width * 0.5), addr_bar_out_pin.center() + vector(0, self.inv_route_width * 0.5), self.inv_route_width) @@ -250,42 +255,28 @@ class rom_decoder(design): self.copy_layout_pin(self.wordline_buf_inst, "gnd") self.copy_layout_pin(self.buf_inst, "gnd") - # route decode array vdd and inv array vdd together - # array_vdd = self.array_inst.get_pin("vdd") - # inv_vdd = self.buf_inst.get_pins("vdd")[-1] - # end = vector(array_vdd.cx(), inv_vdd.cy() - 0.5 * minwidth) - # self.add_segment_center("m1", array_vdd.center(), end) - # end = vector(array_vdd.cx() + 0.5 * minwidth, inv_vdd.cy()) - # self.add_segment_center(self.route_layer, inv_vdd.center(), end) - - # end = vector(array_vdd.cx(), inv_vdd.cy()) - # self.add_via_stack_center(end, self.route_layer, "m1") - # self.add_layout_pin_rect_center("vdd", "m1", end) + # Extend nwells to connect with eachother + self.extend_wells() - # # route pin on inv gnd - # inv_gnd = self.buf_inst.get_pins("gnd")[0] - # array_gnd = self.array_inst.get_pins("gnd") - - # # add x jog - - # start = vector(array_gnd[0].cx(), inv_gnd.cy()) - # self.add_via_stack_center(start, self.route_layer, "m1") - # self.add_layout_pin_rect_center("gnd", "m1", start) - - # end = array_gnd[0].center() - # self.add_segment_center("m1", start, end) - # # add y jog + def extend_wells(self): + precharge_well_rx = self.array_inst.get_pins("vdd")[0].cx() + 0.5 * self.nwell_width + precharge_well_lx = precharge_well_rx - self.array_mod.precharge_array.height - 0.5 * self.nwell_width - self.array_mod.precharge_array.well_offset - # width = minwidth - # height = array_gnd[0].uy() - array_gnd[-1].uy() + minwidth + offset = vector(precharge_well_rx ,self.array_inst.by()) - # offset = vector(-0.5 *width ,0.5 * (array_gnd[0].cy() + array_gnd[-1].cy())) + self.add_label(text="well_right", layer="nwell", offset=offset) + offset = vector(precharge_well_lx ,self.array_inst.by()) + self.add_label(text="well_left", layer="nwell", offset=offset) + vdd_pins=self.buf_inst.get_pins("vdd").copy() + print(vdd_pins) + well_by = vdd_pins[1].cy() + well_ll = vector(precharge_well_lx, well_by) + + self.add_rect(layer="nwell", offset=well_ll, height = self.array_inst.by() - well_by, width=precharge_well_rx - precharge_well_lx) - # start = end - vector(0, 0.5 * minwidth) - # end = vector(start.x, array_gnd[1].uy()) diff --git a/compiler/modules/rom_precharge_array.py b/compiler/modules/rom_precharge_array.py index 5fd585d1..d473357e 100644 --- a/compiler/modules/rom_precharge_array.py +++ b/compiler/modules/rom_precharge_array.py @@ -175,6 +175,7 @@ class rom_precharge_array(design): self.connect_row_pins(layer=self.strap_layer, pins=array_pins, name=None, round=False) def extend_well(self): + self.well_offset = self.pmos.tap_offset well_y = self.pmos_insts[0].get_pin("vdd").cy() - 0.5 * self.nwell_width well_y = self.get_pin("vdd").cy() - 0.5 * self.nwell_width diff --git a/compiler/modules/rom_precharge_cell.py b/compiler/modules/rom_precharge_cell.py index 4108f7cb..25201ffd 100644 --- a/compiler/modules/rom_precharge_cell.py +++ b/compiler/modules/rom_precharge_cell.py @@ -78,7 +78,7 @@ class rom_precharge_cell(rom_base_cell): source = self.cell_inst.get_pin("S") tap_y = source.cy() - self.contact_width - 2 * self.active_enclose_contact - self.active_space - + self.tap_offset = abs(tap_y) pos = vector(source.cx(), tap_y ) self.add_via_center(layers=self.active_stack, diff --git a/compiler/modules/rom_wordline_driver_array.py b/compiler/modules/rom_wordline_driver_array.py index b50b7fc8..cb4a6768 100644 --- a/compiler/modules/rom_wordline_driver_array.py +++ b/compiler/modules/rom_wordline_driver_array.py @@ -28,6 +28,12 @@ class rom_wordline_driver_array(design): self.cols = cols self.invert_outputs=invert_outputs self.tap_spacing = tap_spacing + + if OPTS.tech_name == "sky130": + self.supply_layer = "m1" + else: + self.supply_layer = "m2" + self.create_netlist() if not OPTS.netlist_only: self.create_layout() @@ -45,8 +51,8 @@ class rom_wordline_driver_array(design): self.place_drivers() self.route_layout() self.route_supplies() + self.place_taps() self.add_boundary() - self.DRC_LVS() def add_pins(self): # inputs to wordline_driver. @@ -60,6 +66,7 @@ class rom_wordline_driver_array(design): def add_modules(self): b = factory.create(module_type="rom_base_cell") + self.tap = factory.create(module_type="rom_poly_tap", add_tap = True) if self.invert_outputs: self.wl_driver = factory.create(module_type="pinv_dec", @@ -67,19 +74,12 @@ class rom_wordline_driver_array(design): height=b.height, add_wells=False) - self.wl_driver_tap = factory.create(module_type="pinv_dec", - size=self.cols, - add_wells=True) else: self.wl_driver = factory.create(module_type="pbuf_dec", size=self.cols, height=b.height, add_wells=False) - self.wl_driver_tap = factory.create(module_type="pbuf_dec", - size=self.cols, - add_wells=True) - print(self.wl_driver.height) - print(self.wl_driver_tap.height) + def route_supplies(self): """ @@ -89,6 +89,8 @@ class rom_wordline_driver_array(design): if layer_props.wordline_driver.vertical_supply: self.route_vertical_pins("vdd", self.wld_inst) self.route_vertical_pins("gnd", self.wld_inst) + self.route_vertical_pins("vdd", self.wld_inst, layer=self.supply_layer) + self.route_vertical_pins("gnd", self.wld_inst, layer=self.supply_layer) else: self.route_vertical_pins("vdd", self.wld_inst, xside="rx",) self.route_vertical_pins("gnd", self.wld_inst, xside="lx",) @@ -96,12 +98,8 @@ class rom_wordline_driver_array(design): def create_drivers(self): self.wld_inst = [] for row in range(self.rows): - if row % self.tap_spacing == 0: - self.wld_inst.append(self.add_inst(name="wld{0}".format(row), - mod=self.wl_driver_tap)) - else: - self.wld_inst.append(self.add_inst(name="wld{0}".format(row), - mod=self.wl_driver)) + self.wld_inst.append(self.add_inst(name="wld{0}".format(row), + mod=self.wl_driver)) self.connect_inst(["in_{0}".format(row), "out_{0}".format(row), "vdd", "gnd"]) @@ -109,13 +107,14 @@ class rom_wordline_driver_array(design): def place_drivers(self): y_offset = 0 for row in range(self.rows): - # These are flipped since we always start with an RBL on the bottom - + if row % self.tap_spacing == 0: + y_offset += self.tap.pitch_offset offset = [0, y_offset] self.wld_inst[row].place(offset=offset) y_offset += self.wld_inst[row].height + self.width = self.wl_driver.width self.height = self.wl_driver.height * self.rows @@ -137,3 +136,46 @@ class rom_wordline_driver_array(design): end=end) self.add_layout_pin_rect_center(text="out_{}".format(row), layer=self.route_layer, offset=end - vector(0, 0.5 * route_width)) + + + def place_taps(self): + + for wl in range(0 , self.rows, self.tap_spacing): + driver = self.wld_inst[wl] + + source_pin1 = driver.get_pins("vdd")[0] + gnd_pin1 = driver.get_pins("gnd")[0] + + left_edge = driver.get_pin("Z").cy() - 0.5 * self.contact_width - self.active_enclose_contact - self.active_space - 0.5 * self.active_contact.width + + contact_pos = vector(source_pin1.cx(), left_edge) + self.place_tap(contact_pos, "n") + + contact_pos = vector( gnd_pin1.cx(), left_edge) + self.place_tap(contact_pos, "p") + + if not self.invert_outputs: + source_pin2 = driver.get_pins("vdd")[1] + gnd_pin2 = driver.get_pins("gnd")[1] + contact_pos = vector(source_pin2.cx(), left_edge) + self.place_tap(contact_pos, "n") + + contact_pos = vector( gnd_pin2.cx(), left_edge) + self.place_tap(contact_pos, "p") + + + def place_tap(self, offset, well_type): + self.add_via_center(layers=self.active_stack, + offset=offset, + implant_type=well_type, + well_type=well_type, + directions="nonpref") + self.add_via_stack_center(offset=offset, + from_layer=self.active_stack[2], + to_layer=self.supply_layer) + if well_type == "p": + pin = "gnd" + else: + pin = "vdd" + self.add_layout_pin_rect_center(text=pin, layer=self.supply_layer, offset=offset) + diff --git a/compiler/tests/05_rom_decoder_test.py b/compiler/tests/05_rom_decoder_test.py index 48f977c8..b2447fb4 100644 --- a/compiler/tests/05_rom_decoder_test.py +++ b/compiler/tests/05_rom_decoder_test.py @@ -25,7 +25,7 @@ class rom_decoder_test(openram_test): debug.info(2, "Testing 2x4 decoder for rom cell") - a = factory.create(module_type="rom_decoder", num_outputs=20, strap_spacing=2, cols=16) + a = factory.create(module_type="rom_decoder", num_outputs=16, strap_spacing=4, cols=16) self.local_check(a) openram.end_openram()