OpenRAM/compiler/tri_gate_array.py

137 lines
5.2 KiB
Python

import debug
from tech import drc
import design
from vector import vector
from globals import OPTS
class tri_gate_array(design.design):
"""
Dynamically generated tri gate array of all bitlines. words_per_row
"""
def __init__(self, columns, word_size):
"""Intial function of tri gate array """
design.design.__init__(self, "tri_gate_array")
debug.info(1, "Creating {0}".format(self.name))
c = reload(__import__(OPTS.config.tri_gate))
self.mod_tri_gate = getattr(c, OPTS.config.tri_gate)
self.tri_gate_chars = self.mod_tri_gate.chars
self.columns = columns
self.word_size = word_size
self.create_layout()
self.DRC_LVS()
def create_layout(self):
"""generate layout """
self.add_modules()
self.setup_layout_constants()
self.add_pins()
self.create_write_array()
self.add_metal_rails()
self.add_labels()
def add_pins(self):
"""create the name of pins depend on the word size"""
for i in range(self.word_size):
self.add_pin("tri_in[{0}]".format(i))
for i in range(self.word_size):
self.add_pin("DATA[{0}]".format(i))
for pin in ["en", "en_bar", "vdd", "gnd"]:
self.add_pin(pin)
def setup_layout_constants(self):
"""caculate the size of tri gate array"""
self.words_per_row = self.columns / self.word_size
self.width = (self.columns / self.words_per_row) * self.tri.width
self.height = self.tri.height
self.tri_gate_positions = []
self.vdd_positions = []
self.gnd_positions = []
self.tri_in_positions = []
self.DATA_positions = []
def add_modules(self):
"""instantiation of a tri gate"""
self.tri = self.mod_tri_gate("tri_gate")
self.add_mod(self.tri)
def create_write_array(self):
"""add tri gate to the array """
for i in range(self.word_size):
mirror = "R0"
if (i % 2 == 0):
name = "Xtri_gate{0}".format(i)
x_off = i * self.tri.width * self.words_per_row
else:
name = "Xtri_gate{0}".format(i)
if (self.words_per_row == 1):
x_off = (i + 1) * self.tri.width * self.words_per_row
mirror = "MY"
else:
x_off = i * self.tri.width * self.words_per_row
self.add_inst(name=name,
mod=self.tri,
offset=[x_off, 0],
mirror = mirror)
self.connect_inst(["tri_in[{0}]".format(i),
"DATA[{0}]".format(i),
"en", "en_bar", "vdd", "gnd"])
def add_metal_rails(self):
"""Connect en en_bar and vdd together """
correct = vector(0, 0.5 * drc["minwidth_metal1"])
width = (self.tri.width * self.columns
- (self.words_per_row - 1) * self.tri.width)
self.add_rect(layer="metal1",
offset=(self.tri_gate_chars["en"] - correct).scale(0, 1),
width=width,
height=drc['minwidth_metal1'])
self.add_rect(layer="metal1",
offset=(self.tri_gate_chars["en_bar"] - correct).scale(0, 1),
width=width,
height=drc['minwidth_metal1'])
self.add_rect(layer="metal1",
offset=(self.tri_gate_chars["vdd"] - correct).scale(0, 1),
width=width,
height=drc['minwidth_metal1'])
def add_labels(self):
"""add label for pins"""
for i in range(self.word_size):
if (i % 2 == 0 or self.words_per_row > 1):
x_off = i * self.tri.width * self.words_per_row
dir_vector = vector(1,1)
else:
x_off = (i + 1) * self.tri.width * self.words_per_row
dir_vector = vector(-1,1)
pin_offset={}
for pin in ["en", "en_bar", "vdd", "gnd", "in", "out"]:
pin_offset[pin] = vector(x_off, 0) + dir_vector.scale(self.tri_gate_chars[pin])
for pin in ["en", "en_bar", "vdd"]:
self.add_label(text=pin,
layer="metal1",
offset=pin_offset[pin])
self.add_label(text="gnd",
layer="metal2",
offset=pin_offset["gnd"])
self.add_label(text="tri_in[{0}]".format(i),
layer="metal2",
offset=pin_offset["in"])
self.add_label(text="DATA[{0}]".format(i),
layer="metal2",
offset=pin_offset["out"])
self.vdd_positions.append(pin_offset["vdd"])
self.gnd_positions.append(pin_offset["gnd"])
self.tri_in_positions.append(pin_offset["in"])
self.DATA_positions.append(pin_offset["out"])
self.add_label(text="tri gate",
layer="text",
offset=[self.width / 2.0,
self.height / 2.0])