mirror of https://github.com/VLSIDA/OpenRAM.git
pdriver.py passes resgression tests. Size and number of inverters has been added.
This commit is contained in:
parent
da631618b6
commit
2534a32e20
|
|
@ -12,8 +12,10 @@ class pdriver(design.design):
|
|||
This instantiates an even or odd number of inverters sized for driving a load.
|
||||
"""
|
||||
unique_id = 1
|
||||
inv_list = []
|
||||
inv_inst_list = []
|
||||
|
||||
def __init__(self, driver_size=4, height=None, name="", neg_polarity=False, c_load=8, electrical_effort=1, size_list):
|
||||
def __init__(self, driver_size=4, height=None, name="", neg_polarity=False, c_load=8, size_list = []):
|
||||
|
||||
self.stage_effort = 4
|
||||
self.row_height = height
|
||||
|
|
@ -24,26 +26,26 @@ class pdriver(design.design):
|
|||
self.neg_polarity = neg_polarity
|
||||
self.size_list = size_list
|
||||
self.c_load = c_load
|
||||
self.electrical_effort = electrical_effort
|
||||
|
||||
if length(self.size_list) > 0 and (self.c_load != 8 or self.neg_polarity):
|
||||
raise Exception("Cannot specify both neg_polarity or c_load and size_list.")
|
||||
if len(self.size_list) > 0 and (self.c_load != 8 or self.neg_polarity):
|
||||
raise Exception("Cannot specify both size_list and neg_polarity or c_load.")
|
||||
|
||||
# size_list specified
|
||||
if length(self.size_list) > 0:
|
||||
if not length(self.size_list) % 2:
|
||||
if len(self.size_list) > 0:
|
||||
if not len(self.size_list) % 2:
|
||||
neg_polarity = True
|
||||
self.inv_num = length(self.size_list)
|
||||
self.inv_num = len(self.size_list)
|
||||
else:
|
||||
c_in = c_load/electrical_effort
|
||||
N = max(1, math.loglp(electrical_effort) / math.loglp(3.6))
|
||||
# with pinv = i
|
||||
rho = 3.59
|
||||
N = max(1, int(math.log1p(self.stage_effort)/math.log1p(rho)))
|
||||
if self.neg_polarity:
|
||||
if (int(N) % 2 == 0): # if N is even
|
||||
if (N % 2 == 0): # if N is even
|
||||
self.inv_num = int(N)+1
|
||||
else: # if N is odd
|
||||
self.inv_num = int(N)
|
||||
else: # positive polarity
|
||||
if (int(N) % 2 == 0): # if N is even
|
||||
else: # positive polarity
|
||||
if (N % 2 == 0):
|
||||
self.inv_num = int(N)
|
||||
else:
|
||||
self.inv_num = int(N)+1
|
||||
|
|
@ -84,62 +86,64 @@ class pdriver(design.design):
|
|||
self.add_pin("gnd")
|
||||
|
||||
def add_modules(self):
|
||||
inv_list = []
|
||||
|
||||
if length(self.size_list) > 0: # size list specified
|
||||
for x in length(self.size_list):
|
||||
inv_list.append.=(pinv(size=size_list[x], height=self.row_height))
|
||||
self.add_mod(inv_list[x])
|
||||
else:
|
||||
# Shield the cap, but have at least a stage effort of 4
|
||||
if len(self.size_list) > 0: # size list specified
|
||||
for x in range(len(self.size_list)):
|
||||
self.inv_list.append(pinv(size=self.size_list[x], height=self.row_height))
|
||||
self.add_mod(self.inv_list[x])
|
||||
else: # find inv sizes
|
||||
# shield the cap, but have at least a stage effort of 4
|
||||
input_size = max(1,int(self.driver_size/self.stage_effort))
|
||||
for x in inv_num:
|
||||
inv_list.append(pinv(size=input_size, height=self.row_height))
|
||||
self.add_mod(inv_list[x])
|
||||
self.inv_list.append(pinv(size=input_size, height=self.row_height))
|
||||
self.add_mod(self.inv_list[0])
|
||||
|
||||
# work backwards
|
||||
for x in range(self.inv_num-1, 0, -1):
|
||||
c_in = max(input_size, int(round(self.c_load/self.stage_effort ,0)))
|
||||
self.c_load = c_in
|
||||
self.inv_list.append(pinv(size=c_in, height=self.row_height))
|
||||
self.add_mod(self.inv_list[x])
|
||||
|
||||
def create_insts(self):
|
||||
inv_inst_list = []
|
||||
|
||||
for x in range(1,self.inv_num+1):
|
||||
# Create first inverter
|
||||
if x == 1:
|
||||
zbx_int = "Zb{}_int".format(x);
|
||||
inv_inst_list.append(self.add_inst(name="buf_inv{}".format(x),
|
||||
mod=self.inv_list[x]))
|
||||
self.inv_inst_list.append(self.add_inst(name="buf_inv{}".format(x),
|
||||
mod=self.inv_list[x-1]))
|
||||
if self.inv_num == 1:
|
||||
self.connect_inst(["A", "Z", "vdd", "gnd"])
|
||||
else:
|
||||
self.connect_inst(["A", zbx_int, "vdd", "gnd"])
|
||||
# Create last inverter
|
||||
else if x == inv_num:
|
||||
elif x == self.inv_num:
|
||||
zbn_int = "Zb{}_int".format(x-1);
|
||||
inv_inst_list.append(self.add_inst(name="buf_inv{}".format(x),
|
||||
mod=self.inv_list[x]))
|
||||
self.inv_inst_list.append(self.add_inst(name="buf_inv{}".format(x),
|
||||
mod=self.inv_list[x-1]))
|
||||
self.connect_inst([zbn_int, "Z", "vdd", "gnd"])
|
||||
|
||||
# Create middle inverters
|
||||
else:
|
||||
zbx_int = "Zb{}_int".format(x-1);
|
||||
zbn_int = "Zb{}_int".format(x);
|
||||
inv_inst_list.append(self.add_inst(name="buf_inv{}".format(x),
|
||||
mod=self.inv_list[x]))
|
||||
self.inv_inst_list.append(self.add_inst(name="buf_inv{}".format(x),
|
||||
mod=self.inv_list[x-1]))
|
||||
self.connect_inst([zbx_int, zbn_int, "vdd", "gnd"])
|
||||
|
||||
|
||||
def place_modules(self):
|
||||
# Add INV1 to the left
|
||||
inv_inst_list[0].place(vector(0,0))
|
||||
self.inv_inst_list[0].place(vector(0,0))
|
||||
|
||||
# Add inverters to the right of INV1
|
||||
for x in range(1,len(inv_inst_list)):
|
||||
inv_inst_list[x].place(vector(inv_inst_list[x-1].rx(),0))
|
||||
for x in range(1,len(self.inv_inst_list)):
|
||||
self.inv_inst_list[x].place(vector(self.inv_inst_list[x-1].rx(),0))
|
||||
|
||||
|
||||
def route_wires(self):
|
||||
z_inst_list = []
|
||||
a_inst_list = []
|
||||
# inv_current Z to inv_next A
|
||||
for x in range(0,len(inv_inst_list)-1):
|
||||
for x in range(0,len(self.inv_inst_list)-1):
|
||||
z_inst_list.append(self.inv_inst_list[x].get_pin("Z"))
|
||||
a_inst_list.append(self.inv_inst_list[x+1].get_pin("A"))
|
||||
mid_point = vector(z_inst_list[x].cx(), a_inst_list[x].cy())
|
||||
|
|
@ -148,7 +152,7 @@ class pdriver(design.design):
|
|||
|
||||
def add_layout_pins(self):
|
||||
# Continous vdd rail along with label.
|
||||
vdd_pin=inv_inst_list[0].get_pin("vdd")
|
||||
vdd_pin=self.inv_inst_list[0].get_pin("vdd")
|
||||
self.add_layout_pin(text="vdd",
|
||||
layer="metal1",
|
||||
offset=vdd_pin.ll().scale(0,1),
|
||||
|
|
@ -156,25 +160,43 @@ class pdriver(design.design):
|
|||
height=vdd_pin.height())
|
||||
|
||||
# Continous gnd rail along with label.
|
||||
gnd_pin=inv_inst_list[0].get_pin("gnd")
|
||||
gnd_pin=self.inv_inst_list[0].get_pin("gnd")
|
||||
self.add_layout_pin(text="gnd",
|
||||
layer="metal1",
|
||||
offset=gnd_pin.ll().scale(0,1),
|
||||
width=self.width,
|
||||
height=vdd_pin.height())
|
||||
|
||||
z_pin = inv_inst_list[len(inv_inst_list)-1].get_pin("Z")
|
||||
z_pin = self.inv_inst_list[len(self.inv_inst_list)-1].get_pin("Z")
|
||||
self.add_layout_pin_rect_center(text="Z",
|
||||
layer="metal2",
|
||||
offset=z_pin.center())
|
||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
||||
offset=z_pin.center())
|
||||
layer=z_pin.layer,
|
||||
offset=z_pin.center(),
|
||||
width = z_pin.width(),
|
||||
height = z_pin.height())
|
||||
|
||||
a_pin = inv_inst_list[0].get_pin("A")
|
||||
a_pin = self.inv_inst_list[0].get_pin("A")
|
||||
self.add_layout_pin_rect_center(text="A",
|
||||
layer="metal2",
|
||||
offset=a_pin.center())
|
||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
||||
offset=a_pin.center())
|
||||
layer=a_pin.layer,
|
||||
offset=a_pin.center(),
|
||||
width = a_pin.width(),
|
||||
height = a_pin.height())
|
||||
|
||||
|
||||
def analytical_delay(self, slew, load=0.0):
|
||||
"""Calculate the analytical delay of DFF -> INV -> ... -> INV"""
|
||||
delay = 0;
|
||||
if len(self.inv_inst_list) == 1:
|
||||
delay = self.inv_inst_list[x].analytical_delay(slew=slew);
|
||||
else:
|
||||
for x in range(len(self.inv_inst_list-1)):
|
||||
load_next = 0.0
|
||||
for n in range(x,len(self.inv_inst_list+1)):
|
||||
load_next += self.inv_inst_list[x+1]
|
||||
if x == 1:
|
||||
delay += self.inv_inst_list[x].analytical_delay(slew=slew,
|
||||
load=load_next)
|
||||
else:
|
||||
delay += self.inv_inst_list[x+1].analytical_delay(slew=delay.slew,
|
||||
load=load_next)
|
||||
return delay
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Run a regression test on a 2-row buffer cell
|
||||
"""
|
||||
|
||||
import unittest
|
||||
from testutils import header,openram_test
|
||||
import sys,os
|
||||
sys.path.append(os.path.join(sys.path[0],".."))
|
||||
import globals
|
||||
from globals import OPTS
|
||||
import debug
|
||||
|
||||
class pdriver_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
globals.init_openram("config_20_{0}".format(OPTS.tech_name))
|
||||
global verify
|
||||
import verify
|
||||
|
||||
import pdriver
|
||||
|
||||
debug.info(2, "Testing inverter/buffer 4x 8x")
|
||||
#a = pdriver.pdriver(c_load = 4,size_list = [1,2,4,8])
|
||||
#a = pdriver.pdriver(size_list = [1,2,4,8])
|
||||
a = pdriver.pdriver(c_load = 4)
|
||||
#a = pdriver.pdriver(c_load = 4, neg_polarity = True)
|
||||
self.local_check(a)
|
||||
|
||||
globals.end_openram()
|
||||
|
||||
# instantiate a copdsay of the class to actually run the test
|
||||
if __name__ == "__main__":
|
||||
(OPTS, args) = globals.parse_args()
|
||||
del sys.argv[1:]
|
||||
header(__file__, OPTS.tech_name)
|
||||
unittest.main()
|
||||
Loading…
Reference in New Issue