mirror of
https://github.com/VLSIDA/OpenRAM.git
synced 2026-09-03 08:27:11 +02:00
fixing contact placement for gf180 in rom
This commit is contained in:
@@ -10,6 +10,8 @@ from openram.base import design
|
||||
from openram.sram_factory import factory
|
||||
from openram.base import vector
|
||||
from openram.tech import layer, drc
|
||||
from openram import OPTS
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -111,16 +113,25 @@ class rom_address_control_buf(design):
|
||||
Aint_in = self.addr_bar_nand.get_pin("B")
|
||||
A_in = self.inv_inst.get_pin("A")
|
||||
|
||||
|
||||
vdd_rail = self.addr_nand.get_pin("vdd")
|
||||
# Find the center of the pmos poly/gate
|
||||
poly_right = clk1_pin.cx() + self.poly_enclose_contact + 0.5 * self.contact_width
|
||||
|
||||
ppoly_center = poly_right - 0.7 * self.poly_width
|
||||
poly_y = A_out.cy()
|
||||
if OPTS.tech_name == "gf180mcu":
|
||||
poly_y = vdd_rail.cy() + 0.5 * drc("minwidth_tx") * 3 + self.poly_extend_active
|
||||
ppoly_center = A_out.cx() + 0.5 * self.interconnect_width + 0.5 * self.poly_width
|
||||
else:
|
||||
ppoly_center = poly_right - 0.7 * self.poly_width
|
||||
poly_y = A_out.cy()
|
||||
|
||||
contact_offset = vector(ppoly_center, clk2_pin.cy())
|
||||
self.add_layout_pin_rect_center("cont", offset=contact_offset, layer="poly")
|
||||
self.add_layout_pin_rect_center("ppoly", offset=vector(ppoly_center, poly_y), layer="poly")
|
||||
|
||||
# Route the two shared clk inputs together by connecting poly
|
||||
self.add_segment_center("poly", contact_offset, vector(ppoly_center, A_out.cy()))
|
||||
self.add_segment_center("poly", contact_offset, vector(ppoly_center, poly_y))
|
||||
|
||||
|
||||
clk_offset = vector(clk2_pin.cx(), self.addr_nand.uy())
|
||||
|
||||
@@ -88,6 +88,8 @@ class rom_base_array(bitcell_base_array):
|
||||
else:
|
||||
self.poly_tap = factory.create(module_type="rom_poly_tap", add_active_tap=True)
|
||||
self.end_poly_tap = factory.create(module_type="rom_poly_tap", place_poly=True)
|
||||
|
||||
print("poly tap width", self.poly_tap.width, "height", self.poly_tap.height, self.tap_direction)
|
||||
self.precharge_array = factory.create(module_type="rom_precharge_array",
|
||||
cols=self.column_size,
|
||||
strap_spacing=self.strap_spacing,
|
||||
@@ -100,6 +102,7 @@ class rom_base_array(bitcell_base_array):
|
||||
self.route_pitch = drc("{0}_to_{0}".format(self.bitline_layer))
|
||||
|
||||
def add_pins(self):
|
||||
print(self.get_wordline_names())
|
||||
for bl_name in self.get_bitline_names():
|
||||
self.add_pin(bl_name, "OUTPUT")
|
||||
for wl_name in self.get_wordline_names():
|
||||
@@ -215,7 +218,7 @@ class rom_base_array(bitcell_base_array):
|
||||
self.remove_layout_pin("gnd")
|
||||
|
||||
active_tap_pins = [self.active_tap_list[i].get_pin("active_tap") for i in range(len(self.active_tap_list))]
|
||||
self.connect_col_pins(layer=self.supply_stack[0], pins=active_tap_pins, name="gnd_tmp")
|
||||
self.connect_col_pins(layer=self.supply_stack[0], pins=active_tap_pins, name="gnd_tmp", directions="nonpref")
|
||||
|
||||
gnd_y = gnd_l.y
|
||||
min_x = float('inf')
|
||||
@@ -246,7 +249,6 @@ class rom_base_array(bitcell_base_array):
|
||||
self.cell_pos = {}
|
||||
self.strap_pos = {}
|
||||
pitch_offset = 0
|
||||
|
||||
for row in range(self.row_size + 1):
|
||||
|
||||
if row % self.tap_spacing == 0 and self.pitch_match and row != self.row_size:
|
||||
@@ -331,7 +333,7 @@ class rom_base_array(bitcell_base_array):
|
||||
else:
|
||||
output_layer = "m3"
|
||||
rail_y = self.precharge_inst.get_pins("vdd")[0].cy()
|
||||
|
||||
print("cols ", self.bitline_names[0])
|
||||
for bl in range(self.column_size):
|
||||
|
||||
src_pin = self.cell_list[0][bl].get_pin("S")
|
||||
@@ -382,3 +384,5 @@ class rom_base_array(bitcell_base_array):
|
||||
poly_tap_pins = [self.poly_tap_list[i].get_pin("poly_tap") for i in range(len(self.poly_tap_list))]
|
||||
|
||||
self.connect_row_pins(layer=self.wordline_layer, pins=poly_tap_pins)
|
||||
self.connect_row_pins(layer="poly", pins=poly_tap_pins)
|
||||
|
||||
|
||||
@@ -9,15 +9,19 @@ from math import ceil, log
|
||||
from openram.sram_factory import factory
|
||||
from openram.base import vector, design
|
||||
from openram import OPTS
|
||||
from openram.tech import drc
|
||||
|
||||
from openram.tech import drc, layer
|
||||
class rom_decoder(design):
|
||||
def __init__(self, num_outputs, fanout, strap_spacing, name="", route_layer="m1", output_layer="m1", invert_outputs=False):
|
||||
|
||||
# word lines in the base array become the address lines/cols in the decoder
|
||||
# bit lines in the base array become the word lines/rows in the decoder
|
||||
# array gets rotated 90deg so rows/cols switch
|
||||
|
||||
if "li" in layer:
|
||||
self.output_layer = "m1"
|
||||
self.inv_route_layer = "m2"
|
||||
else:
|
||||
self.output_layer = "m1"
|
||||
self.inv_route_layer = "m3"
|
||||
self.strap_spacing=strap_spacing
|
||||
self.num_outputs = num_outputs
|
||||
self.num_inputs = ceil(log(num_outputs, 2))
|
||||
@@ -28,8 +32,6 @@ class rom_decoder(design):
|
||||
b = factory.create(module_type=OPTS.bitcell)
|
||||
self.cell_height = b.height
|
||||
self.route_layer = route_layer
|
||||
self.output_layer = output_layer
|
||||
self.inv_route_layer = "m2"
|
||||
self.fanout=fanout
|
||||
self.invert_outputs=invert_outputs
|
||||
self.create_netlist()
|
||||
@@ -203,13 +205,12 @@ class rom_decoder(design):
|
||||
for j in range(self.num_outputs):
|
||||
|
||||
self.copy_layout_pin(self.wordline_buf_inst, "out_{}".format(j), "wl_{}".format(j))
|
||||
offset = self.wordline_buf_inst.get_pin("out_{}".format(j)).center()
|
||||
|
||||
array_pins = [self.array_inst.get_pin("bl_0_{}".format(bl)) for bl in range(self.num_outputs)]
|
||||
driver_pins = [self.wordline_buf_inst.get_pin("in_{}".format(bl)) for bl in range(self.num_outputs)]
|
||||
|
||||
route_pins = array_pins + driver_pins
|
||||
self.connect_row_pins(self.output_layer, route_pins, round=True)
|
||||
self.connect_row_pins(self.inv_route_layer, route_pins, round=True)
|
||||
|
||||
def connect_inputs(self):
|
||||
|
||||
|
||||
@@ -35,17 +35,19 @@ class rom_poly_tap(design):
|
||||
def create_layout(self):
|
||||
|
||||
self.place_via()
|
||||
self.add_boundary()
|
||||
# self.extend_poly()
|
||||
|
||||
if self.add_tap or self.place_poly:
|
||||
self.place_active_tap()
|
||||
|
||||
self.add_boundary()
|
||||
|
||||
|
||||
def add_boundary(self):
|
||||
contact_width = self.poly_contact.width
|
||||
self.height = self.dummy.height
|
||||
self.width = contact_width + self.pitch_offset
|
||||
|
||||
print("pitch off", self.pitch_offset)
|
||||
super().add_boundary()
|
||||
|
||||
def place_via(self):
|
||||
@@ -60,14 +62,9 @@ class rom_poly_tap(design):
|
||||
contact_x = contact_width * 0.5 + self.contact_x_offset
|
||||
self.contact_offset = vector(contact_x, contact_y)
|
||||
|
||||
if OPTS.tech_name == "sky130":
|
||||
directions="pref"
|
||||
else:
|
||||
directions="nonpref"
|
||||
self.via = self.add_via_stack_center(from_layer="poly",
|
||||
to_layer=self.strap_layer,
|
||||
offset=self.contact_offset,
|
||||
directions=directions)
|
||||
offset=self.contact_offset)
|
||||
self.add_layout_pin_rect_center("poly_tap", self.strap_layer, self.contact_offset)
|
||||
|
||||
def extend_poly(self):
|
||||
|
||||
@@ -17,24 +17,17 @@ class rom_precharge_array(design):
|
||||
"""
|
||||
An array of inverters to create the inverted address lines for the rom decoder
|
||||
"""
|
||||
def __init__(self, cols, name="", bitline_layer="m2", strap_spacing=None, strap_layer="m3", tap_direction="row"):
|
||||
def __init__(self, cols, name="", bitline_layer="m2", strap_spacing=0, strap_layer="m3", tap_direction="row"):
|
||||
self.cols = cols
|
||||
self.strap_layer = strap_layer
|
||||
self.bitline_layer = bitline_layer
|
||||
self.tap_direction = tap_direction
|
||||
|
||||
self.strap_spacing = strap_spacing
|
||||
if "li" in layer:
|
||||
self.supply_layer = "li"
|
||||
else:
|
||||
self.supply_layer = "m1"
|
||||
|
||||
|
||||
if strap_spacing != None:
|
||||
self.strap_spacing = strap_spacing
|
||||
else:
|
||||
self.strap_spacing = 0
|
||||
|
||||
|
||||
if strap_spacing != 0:
|
||||
self.num_straps = ceil(self.cols / self.strap_spacing)
|
||||
self.array_col_size = self.cols + self.num_straps
|
||||
@@ -158,11 +151,17 @@ class rom_precharge_array(design):
|
||||
self.add_segment_center(layer="poly", start=offset_start, end=offset_end)
|
||||
self.add_segment_center(layer="poly", start=self.pmos_insts[-1].get_pin("G").center(), end=offset_end)
|
||||
|
||||
|
||||
gate_y = self.pmos_insts[0].get_pin('G').cy()
|
||||
start = vector( self.get_pin("gate").lx(), gate_y)
|
||||
end = vector( self.get_pin("precharge_r").rx(), gate_y )
|
||||
|
||||
self.add_segment_center(layer="poly", start=start, end=end)
|
||||
|
||||
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
|
||||
well_y = self.get_pin("vdd").by() - self.nwell_enclose_active
|
||||
well_ll = vector(0, well_y)
|
||||
|
||||
self.add_rect("nwell", well_ll, self.width , self.height - well_y)
|
||||
@@ -214,7 +214,8 @@ class rom_wordline_driver_array(design):
|
||||
directions="nonpref")
|
||||
self.add_via_stack_center(offset=offset,
|
||||
from_layer=self.active_stack[2],
|
||||
to_layer=self.supply_layer)
|
||||
to_layer=self.supply_layer,
|
||||
directions="nonpref")
|
||||
if well_type == "p":
|
||||
pin = "gnd_tap"
|
||||
self.gnd_taps.append(self.add_layout_pin_rect_center(text=pin, layer=self.supply_layer, offset=offset))
|
||||
|
||||
Reference in New Issue
Block a user