2022-08-13 04:51:08 +02:00
|
|
|
# See LICENSE for licensing information.
|
|
|
|
|
#
|
2023-02-28 00:56:24 +01:00
|
|
|
# Copyright (c) 2016-2023 Regents of the University of California and The Board
|
2022-08-13 04:51:08 +02:00
|
|
|
# of Regents for the Oklahoma Agricultural and Mechanical College
|
|
|
|
|
# (acting for and on behalf of Oklahoma State University)
|
|
|
|
|
# All rights reserved.
|
|
|
|
|
#
|
|
|
|
|
|
2023-01-17 01:15:03 +01:00
|
|
|
from openram.base import design
|
2022-12-13 01:35:23 +01:00
|
|
|
from openram.base import vector
|
|
|
|
|
from openram import OPTS
|
|
|
|
|
from openram.sram_factory import factory
|
|
|
|
|
from openram.tech import drc
|
2022-08-13 04:51:08 +02:00
|
|
|
|
|
|
|
|
|
2023-01-17 01:15:03 +01:00
|
|
|
class rom_base_cell(design):
|
2022-12-30 09:35:15 +01:00
|
|
|
|
2023-05-18 01:07:44 +02:00
|
|
|
def __init__(self, name="", bitline_layer=None, bit_value=1, add_well=False):
|
2023-01-17 01:15:03 +01:00
|
|
|
super().__init__(name)
|
|
|
|
|
self.bit_value = bit_value
|
2023-05-18 01:07:44 +02:00
|
|
|
|
|
|
|
|
if bitline_layer is None and OPTS.tech_name == "sky130":
|
|
|
|
|
self.bitline_layer = "li"
|
|
|
|
|
elif bitline_layer is None:
|
|
|
|
|
self.bitline_layer = "m1"
|
|
|
|
|
else:
|
|
|
|
|
self.bitline_layer = bitline_layer
|
2023-01-23 03:34:11 +01:00
|
|
|
self.add_well=add_well
|
2023-01-17 01:15:03 +01:00
|
|
|
self.create_netlist()
|
|
|
|
|
self.create_layout()
|
2022-08-13 04:51:08 +02:00
|
|
|
|
2023-03-01 06:10:52 +01:00
|
|
|
def create_netlist(self):
|
2022-08-13 04:51:08 +02:00
|
|
|
self.add_pins()
|
2023-01-17 01:15:03 +01:00
|
|
|
self.add_modules()
|
2023-03-01 06:10:52 +01:00
|
|
|
|
2022-08-13 04:51:08 +02:00
|
|
|
def create_layout(self):
|
2023-03-01 06:10:52 +01:00
|
|
|
|
2023-01-17 01:15:03 +01:00
|
|
|
self.create_tx()
|
2022-08-13 04:51:08 +02:00
|
|
|
self.setup_drc_offsets()
|
|
|
|
|
self.add_boundary()
|
2023-01-17 01:15:03 +01:00
|
|
|
self.place_tx()
|
|
|
|
|
self.place_bitline()
|
|
|
|
|
self.place_poly()
|
|
|
|
|
if self.bit_value == 0:
|
|
|
|
|
self.short_gate()
|
2023-01-23 03:34:11 +01:00
|
|
|
|
2023-01-17 01:15:03 +01:00
|
|
|
# Calculates offsets of cell width and height so that tiling of cells does not violate any drc rules
|
|
|
|
|
def setup_drc_offsets(self):
|
|
|
|
|
|
2023-05-18 01:07:44 +02:00
|
|
|
self.bitline_width = drc(f"minwidth_{self.bitline_layer}")
|
2023-01-17 01:15:03 +01:00
|
|
|
self.poly_size = (self.cell_inst.width + self.active_space) - (self.cell_inst.height + 2 * self.poly_extend_active)
|
2022-08-13 04:51:08 +02:00
|
|
|
|
2023-01-17 01:15:03 +01:00
|
|
|
def add_boundary(self):
|
2022-08-13 04:51:08 +02:00
|
|
|
|
2023-01-17 01:15:03 +01:00
|
|
|
height = self.cell_inst.width + self.active_space
|
|
|
|
|
|
2023-03-01 06:10:52 +01:00
|
|
|
#cell width with offsets applied, height becomes width when the cells are rotated
|
2023-01-17 01:15:03 +01:00
|
|
|
width = self.cell_inst.height + 2 * self.poly_extend_active
|
2023-03-02 00:49:43 +01:00
|
|
|
|
2023-01-17 01:15:03 +01:00
|
|
|
# make the cells square so the pitch of wordlines will match bitlines
|
|
|
|
|
if width > height:
|
|
|
|
|
self.width = width
|
|
|
|
|
self.height = width
|
|
|
|
|
else:
|
|
|
|
|
self.width = height
|
|
|
|
|
self.height = height
|
2023-03-01 06:10:52 +01:00
|
|
|
|
2023-01-17 01:15:03 +01:00
|
|
|
super().add_boundary()
|
|
|
|
|
|
|
|
|
|
def add_modules(self):
|
|
|
|
|
|
|
|
|
|
self.nmos = factory.create(module_type="ptx",
|
|
|
|
|
module_name="nmos_rom_mod",
|
|
|
|
|
tx_type="nmos",
|
|
|
|
|
add_source_contact=self.bitline_layer,
|
|
|
|
|
add_drain_contact=self.bitline_layer
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def create_tx(self):
|
2022-10-07 23:40:28 +02:00
|
|
|
self.cell_inst = self.add_inst( name=self.name + "_nmos",
|
2023-03-01 06:10:52 +01:00
|
|
|
mod=self.nmos,
|
2022-09-02 05:06:48 +02:00
|
|
|
)
|
2023-07-25 23:45:14 +02:00
|
|
|
print("bitmos", self.cell_inst.height, self.cell_inst.width)
|
|
|
|
|
|
2023-01-17 01:15:03 +01:00
|
|
|
if self.bit_value == 0:
|
|
|
|
|
self.connect_inst(["bl", "wl", "bl", "gnd"])
|
|
|
|
|
else:
|
|
|
|
|
self.connect_inst(["bl_h", "wl", "bl_l", "gnd"])
|
2022-08-13 04:51:08 +02:00
|
|
|
|
2023-01-17 01:15:03 +01:00
|
|
|
def add_pins(self):
|
|
|
|
|
if self.bit_value == 0 :
|
|
|
|
|
pin_list = ["bl", "wl", "gnd"]
|
|
|
|
|
dir_list = ["INOUT", "INPUT", "GROUND"]
|
|
|
|
|
else:
|
|
|
|
|
pin_list = ["bl_h", "bl_l", "wl", "gnd"]
|
|
|
|
|
dir_list = ["INOUT", "INOUT", "INPUT", "GROUND"]
|
2022-10-07 23:40:28 +02:00
|
|
|
|
2023-03-01 06:10:52 +01:00
|
|
|
self.add_pin_list(pin_list, dir_list)
|
2022-08-13 04:51:08 +02:00
|
|
|
|
2023-01-17 01:15:03 +01:00
|
|
|
def place_tx(self):
|
2022-08-13 04:51:08 +02:00
|
|
|
|
2023-02-04 02:21:35 +01:00
|
|
|
tx_offset = vector(self.poly_extend_active + self.cell_inst.height + self.poly_size,- 0.5 * self.contact_width - self.active_enclose_contact)
|
2023-03-01 06:10:52 +01:00
|
|
|
|
2023-01-17 01:15:03 +01:00
|
|
|
self.cell_inst.place(tx_offset, rotate=90)
|
2023-03-02 01:44:48 +01:00
|
|
|
|
2022-12-09 23:25:11 +01:00
|
|
|
self.copy_layout_pin(self.cell_inst, "S", "S")
|
|
|
|
|
self.copy_layout_pin(self.cell_inst, "D", "D")
|
2023-07-25 23:45:14 +02:00
|
|
|
self.copy_layout_pin(self.cell_inst, "G", "G")
|
|
|
|
|
|
2022-12-09 23:25:11 +01:00
|
|
|
self.source_pos = self.cell_inst.get_pin("S").center()
|
2022-12-30 09:35:15 +01:00
|
|
|
|
2023-01-17 01:15:03 +01:00
|
|
|
def place_poly(self):
|
|
|
|
|
poly_offset = vector(0, self.cell_inst.width * 0.5 - 0.5 * self.contact_width - self.active_enclose_contact)
|
|
|
|
|
|
|
|
|
|
start = poly_offset
|
|
|
|
|
end = poly_offset + vector(self.poly_size, 0)
|
|
|
|
|
self.add_segment_center("poly", start, end)
|
|
|
|
|
|
|
|
|
|
def place_bitline(self):
|
|
|
|
|
start = self.get_pin("D").center()
|
2023-05-18 01:07:44 +02:00
|
|
|
end = start + vector(0, 2 * self.active_enclose_contact + self.contact_width + self.active_space)
|
|
|
|
|
self.add_segment_center(self.bitline_layer, start, end, self.bitline_width * 2)
|
2023-01-17 01:15:03 +01:00
|
|
|
|
|
|
|
|
def short_gate(self):
|
2023-02-28 00:56:24 +01:00
|
|
|
self.add_segment_center(self.bitline_layer, self.get_pin("D").center(), self.get_pin("S").center())
|