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
|
|
|
|
|
"""
|
|
|
|
|
|
2017-08-24 00:02:15 +02:00
|
|
|
def __init__(self, columns, word_size, name=""):
|
2016-11-08 18:57:35 +01:00
|
|
|
self.columns = columns
|
|
|
|
|
self.word_size = word_size
|
2017-08-24 00:02:15 +02:00
|
|
|
if name=="":
|
|
|
|
|
name = "flop_array_c{0}_w{1}".format(columns,word_size)
|
2016-11-08 18:57:35 +01:00
|
|
|
design.design.__init__(self, name)
|
2017-08-24 00:02:15 +02:00
|
|
|
debug.info(1, "Creating {}".format(self.name))
|
2016-11-08 18:57:35 +01:00
|
|
|
|
|
|
|
|
c = reload(__import__(OPTS.config.ms_flop))
|
|
|
|
|
self.mod_ms_flop = getattr(c, OPTS.config.ms_flop)
|
2017-08-24 00:02:15 +02:00
|
|
|
self.ms = self.mod_ms_flop("ms_flop")
|
|
|
|
|
self.add_mod(self.ms)
|
|
|
|
|
|
|
|
|
|
self.width = self.columns * self.ms.width
|
|
|
|
|
self.height = self.ms.height
|
|
|
|
|
self.words_per_row = self.columns / self.word_size
|
2016-11-08 18:57:35 +01:00
|
|
|
|
|
|
|
|
self.create_layout()
|
|
|
|
|
|
|
|
|
|
def create_layout(self):
|
|
|
|
|
self.add_pins()
|
|
|
|
|
self.create_ms_flop_array()
|
2017-08-24 00:02:15 +02:00
|
|
|
self.add_layout_pins()
|
2016-11-08 18:57:35 +01:00
|
|
|
self.DRC_LVS()
|
|
|
|
|
|
|
|
|
|
def add_pins(self):
|
|
|
|
|
for i in range(self.word_size):
|
2017-07-03 21:08:50 +02:00
|
|
|
self.add_pin("din[{0}]".format(i))
|
2017-09-11 23:30:52 +02:00
|
|
|
for i in range(self.word_size):
|
2017-07-03 21:08:50 +02:00
|
|
|
self.add_pin("dout[{0}]".format(i))
|
|
|
|
|
self.add_pin("dout_bar[{0}]".format(i))
|
|
|
|
|
self.add_pin("clk")
|
2016-11-08 18:57:35 +01:00
|
|
|
self.add_pin("vdd")
|
|
|
|
|
self.add_pin("gnd")
|
|
|
|
|
|
|
|
|
|
def create_ms_flop_array(self):
|
2017-08-24 00:02:15 +02:00
|
|
|
self.ms_inst={}
|
|
|
|
|
for i in range(0,self.columns,self.words_per_row):
|
|
|
|
|
name = "Xdff{0}".format(i)
|
|
|
|
|
if (i % 2 == 0 or self.words_per_row>1):
|
|
|
|
|
base = vector(i*self.ms.width,0)
|
|
|
|
|
mirror = "R0"
|
2016-11-08 18:57:35 +01:00
|
|
|
else:
|
2017-08-24 00:02:15 +02:00
|
|
|
base = vector((i+1)*self.ms.width,0)
|
|
|
|
|
mirror = "MY"
|
2017-08-25 01:22:14 +02:00
|
|
|
self.ms_inst[i/self.words_per_row]=self.add_inst(name=name,
|
|
|
|
|
mod=self.ms,
|
|
|
|
|
offset=base,
|
|
|
|
|
mirror=mirror)
|
2017-08-24 00:02:15 +02:00
|
|
|
self.connect_inst(["din[{0}]".format(i/self.words_per_row),
|
|
|
|
|
"dout[{0}]".format(i/self.words_per_row),
|
|
|
|
|
"dout_bar[{0}]".format(i/self.words_per_row),
|
2017-07-03 21:08:50 +02:00
|
|
|
"clk",
|
2016-11-08 18:57:35 +01:00
|
|
|
"vdd", "gnd"])
|
|
|
|
|
|
2017-08-24 00:02:15 +02:00
|
|
|
def add_layout_pins(self):
|
|
|
|
|
|
2017-08-25 01:22:14 +02:00
|
|
|
for i in range(self.word_size):
|
2016-11-08 18:57:35 +01:00
|
|
|
|
2017-08-24 00:02:15 +02:00
|
|
|
for gnd_pin in self.ms_inst[i].get_pins("gnd"):
|
|
|
|
|
if gnd_pin.layer!="metal2":
|
|
|
|
|
continue
|
2017-08-25 01:22:14 +02:00
|
|
|
self.add_layout_pin(text="gnd",
|
|
|
|
|
layer="metal2",
|
|
|
|
|
offset=gnd_pin.ll(),
|
|
|
|
|
width=gnd_pin.width(),
|
|
|
|
|
height=gnd_pin.height())
|
2017-08-24 00:02:15 +02:00
|
|
|
|
2017-09-30 01:22:13 +02:00
|
|
|
din_pins = self.ms_inst[i].get_pins("din")
|
|
|
|
|
for din_pin in din_pins:
|
|
|
|
|
self.add_layout_pin(text="din[{}]".format(i),
|
|
|
|
|
layer=din_pin.layer,
|
|
|
|
|
offset=din_pin.ll(),
|
|
|
|
|
width=din_pin.width(),
|
|
|
|
|
height=din_pin.height())
|
2017-08-24 00:02:15 +02:00
|
|
|
|
|
|
|
|
dout_pin = self.ms_inst[i].get_pin("dout")
|
2017-08-25 01:22:14 +02:00
|
|
|
self.add_layout_pin(text="dout[{}]".format(i),
|
2017-08-24 00:02:15 +02:00
|
|
|
layer="metal2",
|
|
|
|
|
offset=dout_pin.ll(),
|
|
|
|
|
width=dout_pin.width(),
|
|
|
|
|
height=dout_pin.height())
|
|
|
|
|
|
|
|
|
|
doutbar_pin = self.ms_inst[i].get_pin("dout_bar")
|
2017-08-25 01:22:14 +02:00
|
|
|
self.add_layout_pin(text="dout_bar[{}]".format(i),
|
2017-08-24 00:02:15 +02:00
|
|
|
layer="metal2",
|
|
|
|
|
offset=doutbar_pin.ll(),
|
|
|
|
|
width=doutbar_pin.width(),
|
|
|
|
|
height=doutbar_pin.height())
|
|
|
|
|
|
|
|
|
|
|
2017-08-25 01:22:14 +02:00
|
|
|
# Continous clk rail along with label.
|
2017-08-24 00:02:15 +02:00
|
|
|
self.add_layout_pin(text="clk",
|
|
|
|
|
layer="metal1",
|
|
|
|
|
offset=self.ms_inst[0].get_pin("clk").ll().scale(0,1),
|
|
|
|
|
width=self.width,
|
|
|
|
|
height=drc["minwidth_metal1"])
|
2016-11-08 18:57:35 +01:00
|
|
|
|
2017-08-24 00:02:15 +02:00
|
|
|
|
2017-08-25 01:22:14 +02:00
|
|
|
# Continous vdd rail along with label.
|
2017-08-24 00:02:15 +02:00
|
|
|
for vdd_pin in self.ms_inst[i].get_pins("vdd"):
|
|
|
|
|
if vdd_pin.layer!="metal1":
|
|
|
|
|
continue
|
|
|
|
|
self.add_layout_pin(text="vdd",
|
|
|
|
|
layer="metal1",
|
|
|
|
|
offset=vdd_pin.ll().scale(0,1),
|
|
|
|
|
width=self.width,
|
|
|
|
|
height=drc["minwidth_metal1"])
|
2016-11-08 18:57:35 +01:00
|
|
|
|
2017-08-25 01:22:14 +02:00
|
|
|
# Continous gnd rail along with label.
|
|
|
|
|
for gnd_pin in self.ms_inst[i].get_pins("gnd"):
|
|
|
|
|
if gnd_pin.layer!="metal1":
|
|
|
|
|
continue
|
|
|
|
|
self.add_layout_pin(text="gnd",
|
|
|
|
|
layer="metal1",
|
|
|
|
|
offset=gnd_pin.ll().scale(0,1),
|
|
|
|
|
width=self.width,
|
|
|
|
|
height=drc["minwidth_metal1"])
|
|
|
|
|
|
2017-05-30 21:50:07 +02:00
|
|
|
|
2017-11-09 20:13:44 +01:00
|
|
|
def analytical_delay(self, slew, load=0.0):
|
|
|
|
|
return self.ms.analytical_delay(slew=slew, load=load)
|