mirror of
https://github.com/VLSIDA/OpenRAM.git
synced 2026-08-29 01:24:39 +02:00
Switched to GF180D for extra metal layers, Fixed drc parameters so contacts are valid. ptx.py modified to achieve proper layer placement with gf180. ROM array and precharge DRC clean.
This commit is contained in:
+15
-8
@@ -129,12 +129,15 @@ class ptx(design):
|
||||
# be decided in the layout later.
|
||||
area_sd = 2.5 * self.poly_width * self.tx_width
|
||||
perimeter_sd = 2 * self.poly_width + 2 * self.tx_width
|
||||
|
||||
# self.channel_length = drc("minlength_channel") if OPTS.tech_name != "gf180mcu" else drc("minlength_channel_" + self.tx_type)
|
||||
self.channel_length = drc("minlength_channel")
|
||||
if cell_props.ptx.model_is_subckt:
|
||||
# sky130
|
||||
main_str = "X{{0}} {{1}} {0} m={1} w={2} l={3} ".format(spice[self.tx_type],
|
||||
self.mults,
|
||||
self.tx_width,
|
||||
drc("minwidth_poly"))
|
||||
self.channel_length)
|
||||
# Perimeters are in microns
|
||||
# Area is in u since it is microns square
|
||||
area_str = "pd={0:.2f} ps={0:.2f} as={1:.2f}u ad={1:.2f}u".format(perimeter_sd,
|
||||
@@ -143,7 +146,7 @@ class ptx(design):
|
||||
main_str = "M{{0}} {{1}} {0} m={1} w={2}u l={3}u ".format(spice[self.tx_type],
|
||||
self.mults,
|
||||
self.tx_width,
|
||||
drc("minwidth_poly"))
|
||||
self.channel_length)
|
||||
area_str = "pd={0:.2f}u ps={0:.2f}u as={1:.2f}p ad={1:.2f}p".format(perimeter_sd,
|
||||
area_sd)
|
||||
self.spice_device = main_str + area_str
|
||||
@@ -160,17 +163,17 @@ class ptx(design):
|
||||
self.lvs_device = "M{{0}} {{1}} {0} m={1} w={2} l={3} mult=1".format("nshort" if self.tx_type == "nmos" else "pshort",
|
||||
self.mults,
|
||||
self.tx_width,
|
||||
drc("minwidth_poly"))
|
||||
self.channel_length)
|
||||
elif cell_props.ptx.model_is_subckt:
|
||||
self.lvs_device = "X{{0}} {{1}} {0} m={1} w={2}u l={3}u".format(spice[self.tx_type],
|
||||
self.mults,
|
||||
self.tx_width,
|
||||
drc("minwidth_poly"))
|
||||
self.channel_length)
|
||||
else:
|
||||
self.lvs_device = "M{{0}} {{1}} {0} m={1} w={2}u l={3}u ".format(spice[self.tx_type],
|
||||
self.mults,
|
||||
self.tx_width,
|
||||
drc("minwidth_poly"))
|
||||
self.channel_length)
|
||||
|
||||
def setup_layout_constants(self):
|
||||
"""
|
||||
@@ -196,6 +199,9 @@ class ptx(design):
|
||||
directions=("V", "V"),
|
||||
dimensions=(1, self.num_contacts))
|
||||
|
||||
if OPTS.tech_name == "gf180mcu":
|
||||
self.poly_width = self.channel_length
|
||||
|
||||
# This is the extra poly spacing due to the poly contact to poly contact pitch
|
||||
# of contacted gates
|
||||
extra_poly_contact_width = self.poly_contact.width - self.poly_width
|
||||
@@ -216,11 +222,12 @@ class ptx(design):
|
||||
self.active_width = 2 * self.end_to_contact + self.active_contact.width \
|
||||
+ 2 * self.active_contact_to_gate + self.poly_width + (self.mults - 1) * self.poly_pitch
|
||||
|
||||
# Active height is just the transistor width
|
||||
self.active_height = self.tx_width
|
||||
# Active height is either the transistor width or the wide enough to enclose the active contact
|
||||
self.active_height = max(self.tx_width, self.active_contact.width + 2 * self.active_enclose_contact)
|
||||
|
||||
# Poly height must include poly extension over active
|
||||
self.poly_height = self.tx_width + 2 * self.poly_extend_active
|
||||
self.poly_height = self.active_height + 2 * self.poly_extend_active
|
||||
|
||||
|
||||
self.active_offset = vector([self.well_enclose_active] * 2)
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
import math
|
||||
from .bitcell_base_array import bitcell_base_array
|
||||
from openram.base import vector
|
||||
from openram import OPTS, debug
|
||||
from openram import debug
|
||||
from openram.sram_factory import factory
|
||||
from openram.tech import drc, layer
|
||||
|
||||
@@ -156,7 +156,7 @@ class rom_base_array(bitcell_base_array):
|
||||
name = "bit_r{0}_c{1}".format(row, col)
|
||||
|
||||
# when col = 0, bl_h is connected to precharge, otherwise connect to previous bl connection
|
||||
# when col = col_size - 1 connected column_sizeto gnd otherwise create new bl connection
|
||||
# when col = col_size - 1 connected to gnd otherwise create new bl connection
|
||||
# debug.info(1, "Create cell: r{0}, c{1}".format(row, col))
|
||||
if row == self.row_size:
|
||||
|
||||
|
||||
@@ -80,6 +80,8 @@ class rom_base_cell(design):
|
||||
self.cell_inst = self.add_inst( name=self.name + "_nmos",
|
||||
mod=self.nmos,
|
||||
)
|
||||
print("bitmos", self.cell_inst.height, self.cell_inst.width)
|
||||
|
||||
if self.bit_value == 0:
|
||||
self.connect_inst(["bl", "wl", "bl", "gnd"])
|
||||
else:
|
||||
@@ -103,6 +105,8 @@ class rom_base_cell(design):
|
||||
|
||||
self.copy_layout_pin(self.cell_inst, "S", "S")
|
||||
self.copy_layout_pin(self.cell_inst, "D", "D")
|
||||
self.copy_layout_pin(self.cell_inst, "G", "G")
|
||||
|
||||
self.source_pos = self.cell_inst.get_pin("S").center()
|
||||
|
||||
def place_poly(self):
|
||||
|
||||
@@ -36,7 +36,7 @@ class rom_poly_tap(design):
|
||||
|
||||
self.place_via()
|
||||
self.add_boundary()
|
||||
self.extend_poly()
|
||||
# self.extend_poly()
|
||||
|
||||
if self.add_tap or self.place_poly:
|
||||
self.place_active_tap()
|
||||
|
||||
@@ -17,9 +17,10 @@ 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=None, strap_spacing=None, strap_layer="m2", tap_direction="row"):
|
||||
def __init__(self, cols, name="", bitline_layer="m2", strap_spacing=None, strap_layer="m3", tap_direction="row"):
|
||||
self.cols = cols
|
||||
self.strap_layer = strap_layer
|
||||
self.bitline_layer = bitline_layer
|
||||
self.tap_direction = tap_direction
|
||||
|
||||
if "li" in layer:
|
||||
@@ -27,14 +28,6 @@ class rom_precharge_array(design):
|
||||
else:
|
||||
self.supply_layer = "m1"
|
||||
|
||||
if bitline_layer is not None:
|
||||
self.bitline_layer = bitline_layer
|
||||
else:
|
||||
self.bitline_layer = self.supply_layer
|
||||
|
||||
|
||||
if name=="":
|
||||
name = "rom_inv_array_{0}".format(cols)
|
||||
|
||||
if strap_spacing != None:
|
||||
self.strap_spacing = strap_spacing
|
||||
@@ -128,7 +121,7 @@ class rom_precharge_array(design):
|
||||
for col in range(self.cols):
|
||||
|
||||
if col % self.strap_spacing == 0:
|
||||
self.tap_insts[strap_num].place(vector(cell_x, cell_y + self.poly_tap.height))
|
||||
self.tap_insts[strap_num].place(vector(cell_x + self.poly_space, cell_y + self.poly_tap.height))
|
||||
strap_num += 1
|
||||
|
||||
if self.tap_direction == "col":
|
||||
@@ -137,7 +130,7 @@ class rom_precharge_array(design):
|
||||
self.pmos_insts[col].place(vector(cell_x, cell_y))
|
||||
cell_x += self.pmos.width
|
||||
|
||||
self.tap_insts[strap_num].place(vector(cell_x, cell_y + self.poly_tap.height))
|
||||
self.tap_insts[strap_num].place(vector(cell_x + self.poly_space, cell_y + self.poly_tap.height))
|
||||
|
||||
def create_layout_pins(self):
|
||||
self.copy_layout_pin(self.tap_insts[0], "poly_tap", "gate")
|
||||
@@ -158,11 +151,12 @@ class rom_precharge_array(design):
|
||||
for tap in self.tap_insts:
|
||||
tap_pin = tap.get_pin("poly_tap")
|
||||
start = vector(tap_pin.cx(), tap_pin.by())
|
||||
end = vector(start.x, tap.mod.get_pin("poly_tap").cy())
|
||||
end = vector(start.x, self.pmos_insts[0].get_pin("G").cy())
|
||||
self.add_segment_center(layer="poly", start=start, end=end)
|
||||
offset_start = vector(end.x - self.poly_tap.width + self.poly_extend_active, end.y)
|
||||
offset_end = end + vector(0.5*self.poly_width, 0)
|
||||
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)
|
||||
|
||||
def extend_well(self):
|
||||
self.well_offset = self.pmos.tap_offset
|
||||
|
||||
@@ -24,6 +24,8 @@ class rom_precharge_cell(rom_base_cell):
|
||||
|
||||
self.place_tap()
|
||||
self.extend_well()
|
||||
print("precharge", self.height, self.width)
|
||||
|
||||
|
||||
def add_modules(self):
|
||||
if OPTS.tech_name == "sky130":
|
||||
@@ -42,6 +44,7 @@ class rom_precharge_cell(rom_base_cell):
|
||||
self.cell_inst = self.add_inst( name="precharge_pmos",
|
||||
mod=self.pmos,
|
||||
)
|
||||
print("premos", self.cell_inst.height, self.cell_inst.width)
|
||||
self.connect_inst(["bitline", "gate", "vdd", "vdd"])
|
||||
|
||||
def add_pins(self):
|
||||
@@ -55,10 +58,10 @@ class rom_precharge_cell(rom_base_cell):
|
||||
self.poly_size = (self.cell_inst.width + self.active_space) - (self.cell_inst.height + 2 * self.poly_extend_active)
|
||||
|
||||
def extend_well(self):
|
||||
|
||||
well_y = self.get_pin("vdd").cy() - 0.5 * self.nwell_width
|
||||
print(self.nwell_enclose_active)
|
||||
well_y = self.get_pin("vdd").cy() - 0.5 * self.tap.height - self.nwell_enclose_active
|
||||
well_ll = vector(0, well_y)
|
||||
height = self.get_pin("D").cy() + 0.5 * self.nwell_width - well_y
|
||||
height = self.get_pin("D").cy() + self.nwell_enclose_active - well_y
|
||||
self.add_rect("nwell", well_ll, self.width , height)
|
||||
|
||||
def place_tap(self):
|
||||
@@ -67,7 +70,7 @@ class rom_precharge_cell(rom_base_cell):
|
||||
self.tap_offset = abs(tap_y)
|
||||
pos = vector(source.cx(), tap_y )
|
||||
|
||||
self.add_via_center(layers=self.active_stack,
|
||||
self.tap = self.add_via_center(layers=self.active_stack,
|
||||
offset=pos,
|
||||
implant_type="n",
|
||||
well_type="n",
|
||||
|
||||
Reference in New Issue
Block a user