OpenRAM/compiler/modules/wordline_buffer_array.py

125 lines
4.1 KiB
Python
Raw Normal View History

# See LICENSE for licensing information.
#
2024-01-03 23:32:44 +01:00
# Copyright (c) 2016-2024 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
2022-11-27 22:01:20 +01:00
from openram import debug
from openram.base import design
from openram.base import vector
from openram.sram_factory import factory
from openram.tech import layer
from openram.tech import layer_properties as layer_props
from openram import OPTS
class wordline_buffer_array(design):
"""
Creates a Wordline Buffer/Inverter array
"""
def __init__(self, name, rows, cols):
design.__init__(self, name)
debug.info(1, "Creating {0}".format(self.name))
self.add_comment("rows: {0} cols: {1}".format(rows, cols))
2020-11-03 15:29:17 +01:00
self.rows = rows
self.cols = cols
self.create_netlist()
if not OPTS.netlist_only:
self.create_layout()
def create_netlist(self):
self.add_modules()
self.add_pins()
self.create_drivers()
2020-11-03 15:29:17 +01:00
def create_layout(self):
if "li" in layer:
self.route_layer = "li"
else:
self.route_layer = "m1"
self.place_drivers()
self.route_layout()
self.route_supplies()
2022-05-13 19:46:00 +02:00
# Don't offset these because some cells use standard cell style drivers
#self.offset_all_coordinates()
self.add_boundary()
self.DRC_LVS()
2020-11-03 15:29:17 +01:00
def add_pins(self):
# inputs to wordline_driver.
for i in range(self.rows):
self.add_pin("in_{0}".format(i), "INPUT")
# Outputs from wordline_driver.
for i in range(self.rows):
2020-07-24 02:15:39 +02:00
self.add_pin("out_{0}".format(i), "OUTPUT")
self.add_pin("vdd", "POWER")
self.add_pin("gnd", "GROUND")
def add_modules(self):
2020-11-06 01:55:08 +01:00
b = factory.create(module_type=OPTS.bitcell)
2020-11-03 15:29:17 +01:00
self.wl_driver = factory.create(module_type="inv_dec",
2020-08-12 00:00:29 +02:00
size=self.cols,
height=b.height)
2020-11-03 15:29:17 +01:00
def route_supplies(self):
"""
Add a pin for each row of vdd/gnd which
are must-connects next level up.
"""
2020-10-28 17:54:15 +01:00
if layer_props.wordline_driver.vertical_supply:
2022-05-13 19:46:00 +02:00
self.route_vertical_pins("vdd", self.wld_inst)
self.route_vertical_pins("gnd", self.wld_inst)
else:
2022-05-13 19:46:00 +02:00
self.route_vertical_pins("vdd", self.wld_inst, xside="rx",)
self.route_vertical_pins("gnd", self.wld_inst, xside="lx",)
2020-11-03 15:29:17 +01:00
def create_drivers(self):
self.wld_inst = []
for row in range(self.rows):
self.wld_inst.append(self.add_inst(name="wld{0}".format(row),
mod=self.wl_driver))
self.connect_inst(["in_{0}".format(row),
2020-07-24 02:15:39 +02:00
"out_{0}".format(row),
"vdd", "gnd"])
def place_drivers(self):
for row in range(self.rows):
# These are flipped since we always start with an RBL on the bottom
if (row % 2):
y_offset = self.wl_driver.height * row
inst_mirror = "R0"
else:
y_offset = self.wl_driver.height * (row + 1)
inst_mirror = "MX"
offset = [0, y_offset]
2020-11-03 15:29:17 +01:00
self.wld_inst[row].place(offset=offset,
mirror=inst_mirror)
self.width = self.wl_driver.width
self.height = self.wl_driver.height * self.rows
def route_layout(self):
""" Route all of the signals """
for row in range(self.rows):
inst = self.wld_inst[row]
self.copy_layout_pin(inst, "A", "in_{0}".format(row))
# output each WL on the right
wl_offset = inst.get_pin("Z").rc()
2020-07-24 02:15:39 +02:00
self.add_layout_pin_segment_center(text="out_{0}".format(row),
layer=self.route_layer,
start=wl_offset,
end=wl_offset - vector(self.m1_width, 0))