OpenRAM/compiler/ms_flop_array.py

171 lines
7.4 KiB
Python
Raw Normal View History

2016-11-08 18:57:35 +01:00
import debug
import design
from tech import drc
from math import log
from vector import vector
from globals import OPTS
class ms_flop_array(design.design):
"""
An Array of D-Flipflops used for to store Data_in & Data_out of
Write_driver & Sense_amp, address inputs of column_mux &
hierdecoder
"""
def __init__(self, name, array_type, columns, word_size):
self.array_type = array_type
self.columns = columns
self.word_size = word_size
design.design.__init__(self, name)
debug.info(1, "Creating %s" % self.name)
c = reload(__import__(OPTS.config.ms_flop))
self.mod_ms_flop = getattr(c, OPTS.config.ms_flop)
self.ms_flop_chars = self.mod_ms_flop.chars
self.create_layout()
def create_layout(self):
self.add_modules()
self.setup_layout_constants()
self.add_pins()
self.create_ms_flop_array()
self.add_labels()
self.DRC_LVS()
def add_modules(self):
self.ms_flop = self.mod_ms_flop("ms_flop")
self.add_mod(self.ms_flop)
def setup_layout_constants(self):
self.width = self.columns * self.ms_flop.width
self.height = self.ms_flop.height
self.words_per_row = self.columns / self.word_size
self.flop_positions = []
self.vdd_positions = []
self.gnd_positions = []
self.clk_positions = []
self.dout_positions = []
self.dout_bar_positions = []
self.din_positions = []
def add_pins(self):
if (self.array_type == "data_in"):
pins = {"data_in": 1, "din": "DATA", "dout": "data_in", "dout_bar": "data_in_bar", "clk": "clk"}
elif (self.array_type == "data_out"):
pins = {"data_out": 1, "din": "data_out", "dout": "tri_in", "dout_bar": "tri_in_bar", "clk": "sclk"}
elif (self.array_type == "address"):
pins = {"address": 1, "din": "ADDR", "dout": "A", "dout_bar": "A_bar", "clk": "addr_clk"}
self.input_output_pins = pins
assert(self.array_type in pins), "Invalid input for array_type"
for i in range(self.word_size):
self.add_pin(self.input_output_pins["din"] + "[{0}]".format(i))
for i in range(self.word_size):
self.add_pin(self.input_output_pins["dout"] + "[{0}]".format(i))
self.add_pin(self.input_output_pins["dout_bar"] + "[{0}]".format(i))
self.add_pin(self.input_output_pins["clk"])
self.add_pin("vdd")
self.add_pin("gnd")
def create_ms_flop_array(self):
for i in range(self.word_size):
name = "Xdff%d" % i
if (i % 2 == 0):
x_off = i * self.ms_flop.width * self.words_per_row
mirror = "None"
else:
if (self.words_per_row == 1):
x_off = (i + 1) * self.ms_flop.width
mirror="MY"
else:
x_off = i * self.ms_flop.width * self.words_per_row
self.add_inst(name=name,
mod=self.ms_flop,
offset=[x_off, 0],
mirror=mirror)
self.connect_inst([self.input_output_pins["din"] + "[{0}]".format(i),
self.input_output_pins["dout"] + "[{0}]".format(i),
self.input_output_pins["dout_bar"] + "[{0}]".format(i),
self.input_output_pins["clk"],
"vdd", "gnd"])
self.flop_positions.append(vector(x_off, 0))
def add_labels(self):
for i in range(self.word_size):
i_str = "[{0}]".format(i)
if (i % 2 == 0 or self.words_per_row > 1):
base = vector(i * self.ms_flop.width * self.words_per_row, 0)
self.add_label(text="gnd",
layer="metal2",
offset=base + self.ms_flop_chars["gnd"])
self.add_label(text=self.input_output_pins["din"] + i_str,
layer="metal2",
offset=base + self.ms_flop_chars["din"])
self.add_label(text=self.input_output_pins["dout"] + i_str,
layer="metal2",
offset=base + self.ms_flop_chars["dout"])
self.add_label(text=self.input_output_pins["dout_bar"] + i_str,
layer="metal2",
offset=base + self.ms_flop_chars["dout_bar"])
self.din_positions.append(base + self.ms_flop_chars["din"])
self.dout_positions.append(base + self.ms_flop_chars["dout"])
self.dout_bar_positions.append(base + self.ms_flop_chars["dout_bar"])
self.gnd_positions.append(base + self.ms_flop_chars["gnd"])
else:
base = vector((i + 1) * self.ms_flop.width, 0)
gnd_offset = base + vector(self.ms_flop_chars["gnd"]).scale(-1,1)
din_offset = base + vector(self.ms_flop_chars["din"]).scale(-1,1)
dout_offset = base + vector(self.ms_flop_chars["dout"]).scale(-1,1)
dout_bar_offset = base + vector(self.ms_flop_chars["dout_bar"]).scale(-1,1)
self.add_label(text="gnd",
layer="metal2",
offset=gnd_offset)
self.add_label(text=self.input_output_pins["din"] + i_str,
layer="metal2",
offset=din_offset)
self.add_label(text=self.input_output_pins["dout"] + i_str,
layer="metal2",
offset=dout_offset)
self.add_label(text=self.input_output_pins["dout_bar"] + i_str,
layer="metal2",
offset=dout_bar_offset)
self.gnd_positions.append(gnd_offset)
self.din_positions.append(din_offset)
self.dout_positions.append(dout_offset)
self.dout_bar_positions.append(dout_bar_offset)
# Continous "clk" rail along with label.
self.add_rect(layer="metal1",
offset=[0, self.ms_flop_chars["clk"][1]],
width=self.width,
height=-drc["minwidth_metal1"])
self.add_label(text=self.input_output_pins["clk"],
layer="metal1",
offset=self.ms_flop_chars["clk"])
self.clk_positions.append(vector(self.ms_flop_chars["clk"]))
# Continous "Vdd" rail along with label.
self.add_rect(layer="metal1",
offset=[0, self.ms_flop_chars["vdd"][1] - 0.5 * drc["minwidth_metal1"]],
width=self.width,
height=drc["minwidth_metal1"])
self.add_label(text="vdd",
layer="metal1",
offset=vector(self.ms_flop_chars["vdd"]).scale(0, 1))
self.vdd_positions.append(vector(self.ms_flop_chars["vdd"]).scale(0, 1))
self.add_label(text=self.array_type + "ms_flop",
layer="text",
offset=[self.width / 2.0,
self.height / 2.0])
def delay(self, slope, load=0.0):
result = self.ms_flop.delay(slope = slope,
load = load)
return result