mirror of https://github.com/VLSIDA/OpenRAM.git
fixing decoder lvs
This commit is contained in:
parent
559300e5cc
commit
16df8e0e43
|
|
@ -65,7 +65,9 @@ class rom_address_control_array(design):
|
||||||
def add_pins(self):
|
def add_pins(self):
|
||||||
for col in range(self.cols):
|
for col in range(self.cols):
|
||||||
self.add_pin("A{0}_in".format(col), "INPUT")
|
self.add_pin("A{0}_in".format(col), "INPUT")
|
||||||
|
for col in range(self.cols):
|
||||||
self.add_pin("A{0}_out".format(col), "OUTPUT")
|
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("Abar{0}_out".format(col), "OUTPUT")
|
||||||
self.add_pin("clk", "INPUT")
|
self.add_pin("clk", "INPUT")
|
||||||
self.add_pin("vdd", "POWER")
|
self.add_pin("vdd", "POWER")
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,7 @@ class rom_base_array(bitcell_base_array):
|
||||||
|
|
||||||
def add_pins(self):
|
def add_pins(self):
|
||||||
for bl_name in self.get_bitline_names():
|
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():
|
for wl_name in self.get_wordline_names():
|
||||||
self.add_pin(wl_name, "INPUT")
|
self.add_pin(wl_name, "INPUT")
|
||||||
self.add_pin("precharge_gate", "INPUT")
|
self.add_pin("precharge_gate", "INPUT")
|
||||||
|
|
|
||||||
|
|
@ -144,8 +144,12 @@ class rom_decoder(design):
|
||||||
|
|
||||||
for i in range(self.num_inputs):
|
for i in range(self.num_inputs):
|
||||||
control_pins.append("A{0}".format(i))
|
control_pins.append("A{0}".format(i))
|
||||||
control_pins.append("in_{0}".format(i))
|
for i in range(self.num_inputs):
|
||||||
control_pins.append("inbar_{0}".format(i))
|
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("clk")
|
||||||
control_pins.append("vdd")
|
control_pins.append("vdd")
|
||||||
control_pins.append("gnd")
|
control_pins.append("gnd")
|
||||||
|
|
@ -163,8 +167,8 @@ class rom_decoder(design):
|
||||||
|
|
||||||
|
|
||||||
for i in reversed(range(self.num_inputs)):
|
for i in reversed(range(self.num_inputs)):
|
||||||
array_pins.append("inbar_{0}".format(i))
|
array_pins.append("Ab_int_{0}".format(i))
|
||||||
array_pins.append("in_{0}".format(i))
|
array_pins.append("A_int_{0}".format(i))
|
||||||
array_pins.append("precharge")
|
array_pins.append("precharge")
|
||||||
array_pins.append("vdd")
|
array_pins.append("vdd")
|
||||||
array_pins.append("gnd")
|
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_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.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)
|
# 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.wordline_buf_inst, "gnd")
|
||||||
self.copy_layout_pin(self.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)
|
# Extend nwells to connect with eachother
|
||||||
# self.add_segment_center("m1", array_vdd.center(), end)
|
self.extend_wells()
|
||||||
# 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)
|
|
||||||
|
|
||||||
# # route pin on inv gnd
|
|
||||||
|
|
||||||
# inv_gnd = self.buf_inst.get_pins("gnd")[0]
|
def extend_wells(self):
|
||||||
# array_gnd = self.array_inst.get_pins("gnd")
|
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
|
||||||
# # 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
|
|
||||||
|
|
||||||
|
|
||||||
# width = minwidth
|
offset = vector(precharge_well_rx ,self.array_inst.by())
|
||||||
# height = array_gnd[0].uy() - array_gnd[-1].uy() + minwidth
|
|
||||||
|
|
||||||
# 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())
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -175,6 +175,7 @@ class rom_precharge_array(design):
|
||||||
self.connect_row_pins(layer=self.strap_layer, pins=array_pins, name=None, round=False)
|
self.connect_row_pins(layer=self.strap_layer, pins=array_pins, name=None, round=False)
|
||||||
|
|
||||||
def extend_well(self):
|
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.pmos_insts[0].get_pin("vdd").cy() - 0.5 * self.nwell_width
|
||||||
|
|
||||||
well_y = self.get_pin("vdd").cy() - 0.5 * self.nwell_width
|
well_y = self.get_pin("vdd").cy() - 0.5 * self.nwell_width
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@ class rom_precharge_cell(rom_base_cell):
|
||||||
source = self.cell_inst.get_pin("S")
|
source = self.cell_inst.get_pin("S")
|
||||||
|
|
||||||
tap_y = source.cy() - self.contact_width - 2 * self.active_enclose_contact - self.active_space
|
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 )
|
pos = vector(source.cx(), tap_y )
|
||||||
|
|
||||||
self.add_via_center(layers=self.active_stack,
|
self.add_via_center(layers=self.active_stack,
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,12 @@ class rom_wordline_driver_array(design):
|
||||||
self.cols = cols
|
self.cols = cols
|
||||||
self.invert_outputs=invert_outputs
|
self.invert_outputs=invert_outputs
|
||||||
self.tap_spacing = tap_spacing
|
self.tap_spacing = tap_spacing
|
||||||
|
|
||||||
|
if OPTS.tech_name == "sky130":
|
||||||
|
self.supply_layer = "m1"
|
||||||
|
else:
|
||||||
|
self.supply_layer = "m2"
|
||||||
|
|
||||||
self.create_netlist()
|
self.create_netlist()
|
||||||
if not OPTS.netlist_only:
|
if not OPTS.netlist_only:
|
||||||
self.create_layout()
|
self.create_layout()
|
||||||
|
|
@ -45,8 +51,8 @@ class rom_wordline_driver_array(design):
|
||||||
self.place_drivers()
|
self.place_drivers()
|
||||||
self.route_layout()
|
self.route_layout()
|
||||||
self.route_supplies()
|
self.route_supplies()
|
||||||
|
self.place_taps()
|
||||||
self.add_boundary()
|
self.add_boundary()
|
||||||
self.DRC_LVS()
|
|
||||||
|
|
||||||
def add_pins(self):
|
def add_pins(self):
|
||||||
# inputs to wordline_driver.
|
# inputs to wordline_driver.
|
||||||
|
|
@ -60,6 +66,7 @@ class rom_wordline_driver_array(design):
|
||||||
|
|
||||||
def add_modules(self):
|
def add_modules(self):
|
||||||
b = factory.create(module_type="rom_base_cell")
|
b = factory.create(module_type="rom_base_cell")
|
||||||
|
self.tap = factory.create(module_type="rom_poly_tap", add_tap = True)
|
||||||
|
|
||||||
if self.invert_outputs:
|
if self.invert_outputs:
|
||||||
self.wl_driver = factory.create(module_type="pinv_dec",
|
self.wl_driver = factory.create(module_type="pinv_dec",
|
||||||
|
|
@ -67,19 +74,12 @@ class rom_wordline_driver_array(design):
|
||||||
height=b.height,
|
height=b.height,
|
||||||
add_wells=False)
|
add_wells=False)
|
||||||
|
|
||||||
self.wl_driver_tap = factory.create(module_type="pinv_dec",
|
|
||||||
size=self.cols,
|
|
||||||
add_wells=True)
|
|
||||||
else:
|
else:
|
||||||
self.wl_driver = factory.create(module_type="pbuf_dec",
|
self.wl_driver = factory.create(module_type="pbuf_dec",
|
||||||
size=self.cols,
|
size=self.cols,
|
||||||
height=b.height,
|
height=b.height,
|
||||||
add_wells=False)
|
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):
|
def route_supplies(self):
|
||||||
"""
|
"""
|
||||||
|
|
@ -89,6 +89,8 @@ class rom_wordline_driver_array(design):
|
||||||
if layer_props.wordline_driver.vertical_supply:
|
if layer_props.wordline_driver.vertical_supply:
|
||||||
self.route_vertical_pins("vdd", self.wld_inst)
|
self.route_vertical_pins("vdd", self.wld_inst)
|
||||||
self.route_vertical_pins("gnd", 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:
|
else:
|
||||||
self.route_vertical_pins("vdd", self.wld_inst, xside="rx",)
|
self.route_vertical_pins("vdd", self.wld_inst, xside="rx",)
|
||||||
self.route_vertical_pins("gnd", self.wld_inst, xside="lx",)
|
self.route_vertical_pins("gnd", self.wld_inst, xside="lx",)
|
||||||
|
|
@ -96,12 +98,8 @@ class rom_wordline_driver_array(design):
|
||||||
def create_drivers(self):
|
def create_drivers(self):
|
||||||
self.wld_inst = []
|
self.wld_inst = []
|
||||||
for row in range(self.rows):
|
for row in range(self.rows):
|
||||||
if row % self.tap_spacing == 0:
|
self.wld_inst.append(self.add_inst(name="wld{0}".format(row),
|
||||||
self.wld_inst.append(self.add_inst(name="wld{0}".format(row),
|
mod=self.wl_driver))
|
||||||
mod=self.wl_driver_tap))
|
|
||||||
else:
|
|
||||||
self.wld_inst.append(self.add_inst(name="wld{0}".format(row),
|
|
||||||
mod=self.wl_driver))
|
|
||||||
self.connect_inst(["in_{0}".format(row),
|
self.connect_inst(["in_{0}".format(row),
|
||||||
"out_{0}".format(row),
|
"out_{0}".format(row),
|
||||||
"vdd", "gnd"])
|
"vdd", "gnd"])
|
||||||
|
|
@ -109,13 +107,14 @@ class rom_wordline_driver_array(design):
|
||||||
def place_drivers(self):
|
def place_drivers(self):
|
||||||
y_offset = 0
|
y_offset = 0
|
||||||
for row in range(self.rows):
|
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]
|
offset = [0, y_offset]
|
||||||
|
|
||||||
self.wld_inst[row].place(offset=offset)
|
self.wld_inst[row].place(offset=offset)
|
||||||
y_offset += self.wld_inst[row].height
|
y_offset += self.wld_inst[row].height
|
||||||
|
|
||||||
|
|
||||||
self.width = self.wl_driver.width
|
self.width = self.wl_driver.width
|
||||||
self.height = self.wl_driver.height * self.rows
|
self.height = self.wl_driver.height * self.rows
|
||||||
|
|
||||||
|
|
@ -137,3 +136,46 @@ class rom_wordline_driver_array(design):
|
||||||
end=end)
|
end=end)
|
||||||
|
|
||||||
self.add_layout_pin_rect_center(text="out_{}".format(row), layer=self.route_layer, offset=end - vector(0, 0.5 * route_width))
|
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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ class rom_decoder_test(openram_test):
|
||||||
debug.info(2, "Testing 2x4 decoder for rom cell")
|
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)
|
self.local_check(a)
|
||||||
openram.end_openram()
|
openram.end_openram()
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue