mirror of https://github.com/VLSIDA/OpenRAM.git
Merge branch 'master' into router
This commit is contained in:
commit
8cc63560f8
|
|
@ -38,3 +38,17 @@ timing code too.
|
|||
|
||||
Convert characterizer into a Python package
|
||||
|
||||
cal_delay_over_path functions in hierarchy_spice
|
||||
can wire as output(it only take capcitance now).
|
||||
maybe consider make rc_net a class
|
||||
|
||||
dont use dictionary in analytical model make it like vector class
|
||||
|
||||
add wire delay model for bank connection
|
||||
|
||||
#may 15
|
||||
-explain why nand_2 fail lef
|
||||
-add bank seg for delay
|
||||
-build better sense amp
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -228,6 +228,7 @@ class bank(design.design):
|
|||
|
||||
self.wordline_driver = self.mod_wordline_driver(name="wordline_driver",
|
||||
rows=self.num_rows)
|
||||
#self.wordline_driver.logic_effort_sizing(self.num_cols)
|
||||
self.add_mod(self.wordline_driver)
|
||||
|
||||
self.inv = pinv(name="pinv",
|
||||
|
|
@ -1516,3 +1517,26 @@ class bank(design.design):
|
|||
offset=[x_offset + drc["minwidth_metal1"],
|
||||
y_offset],
|
||||
mirror="R90")
|
||||
|
||||
def delay(self, slope):
|
||||
""" return analytical delay of the bank"""
|
||||
msf_addr_delay = self.msf_address.delay(slope,
|
||||
self.decoder.input_load())
|
||||
|
||||
decoder_delay = self.decoder.delay(msf_addr_delay.slope,
|
||||
self.wordline_driver.input_load())
|
||||
|
||||
word_driver_delay = self.wordline_driver.delay(decoder_delay.slope,
|
||||
self.bitcell_array.input_load())
|
||||
|
||||
bitcell_array_delay = self.bitcell_array.delay(word_driver_delay.slope)
|
||||
|
||||
bl_t_data_out_delay = self.sens_amp_array.delay(bitcell_array_delay.slope,
|
||||
self.bitcell_array.output_load())
|
||||
# output load of bitcell_array is set to be only small part of bl for sense amp.
|
||||
|
||||
data_t_DATA_delay = self.tri_gate_array.delay(bl_t_data_out_delay.slope)
|
||||
|
||||
result = msf_addr_delay + decoder_delay + word_driver_delay \
|
||||
+ bitcell_array_delay + bl_t_data_out_delay + data_t_DATA_delay
|
||||
return result
|
||||
|
|
|
|||
|
|
@ -21,3 +21,14 @@ class bitcell(design.design):
|
|||
self.width = bitcell.chars["width"]
|
||||
self.height = bitcell.chars["height"]
|
||||
|
||||
def delay(self, slope, load=0, swing = 0.5):
|
||||
# delay of bit cell is not like a driver(from WL)
|
||||
# so the slope used should be 0
|
||||
# it should not be slope dependent?
|
||||
# because the value is there
|
||||
# the delay is only over half transsmission gate
|
||||
from tech import spice
|
||||
r = spice["min_tx_r"]*3
|
||||
c_para = spice["min_tx_c_para"]#ff
|
||||
result = self.cal_delay_with_rc(r = r, c = c_para+load, slope = slope, swing = swing)
|
||||
return result
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
import debug
|
||||
import design
|
||||
from tech import drc, spice
|
||||
from vector import vector
|
||||
from globals import OPTS
|
||||
|
||||
|
||||
|
||||
class bitcell_array(design.design):
|
||||
"""
|
||||
Creates a rows x cols array of memory cells. Assumes bit-lines
|
||||
|
|
@ -140,3 +142,44 @@ class bitcell_array(design.design):
|
|||
offset.y += self.cell.height
|
||||
# increments to the next column width
|
||||
offset.x += self.cell.width
|
||||
|
||||
def delay(self, slope, load=0):
|
||||
from tech import drc
|
||||
wl_wire = self.gen_wl_wire()
|
||||
wl_wire.return_delay_over_wire(slope)
|
||||
|
||||
wl_to_cell_delay = wl_wire.return_delay_over_wire(slope)
|
||||
# hypothetical delay from cell to bl end without sense amp
|
||||
bl_wire = self.gen_bl_wire()
|
||||
cell_load = 2 * bl_wire.return_input_cap() # we ingore the wire r
|
||||
# hence just use the whole c
|
||||
bl_swing = 0.1
|
||||
cell_delay = self.cell.delay(wl_to_cell_delay.slope, cell_load, swing = bl_swing)
|
||||
|
||||
#we do not consider the delay over the wire for now
|
||||
#bl_wire_delay = bl_wire.return_delay_over_wire(cell_delay.slope, swing = bl_swing)
|
||||
#return [wl_to_cell_delay, cell_delay, bl_wire_delay]
|
||||
#return self.return_delay(cell_delay.delay+wl_to_cell_delay.delay+bl_wire_delay.delay,
|
||||
# bl_wire_delay.slope)
|
||||
return self.return_delay(cell_delay.delay+wl_to_cell_delay.delay,
|
||||
wl_to_cell_delay.slope)
|
||||
|
||||
def gen_wl_wire(self):
|
||||
wl_wire = self.generate_rc_net(int(self.column_size), self.width, drc["minwidth_metal1"])
|
||||
wl_wire.wire_c = 2*spice["min_tx_gate_c"] + wl_wire.wire_c # 2 access tx gate per cell
|
||||
return wl_wire
|
||||
|
||||
def gen_bl_wire(self):
|
||||
bl_pos = 0
|
||||
bl_wire = self.generate_rc_net(int(self.row_size-bl_pos), self.height, drc["minwidth_metal1"])
|
||||
bl_wire.wire_c =spice["min_tx_c_para"] + bl_wire.wire_c # 1 access tx d/s per cell
|
||||
return bl_wire
|
||||
|
||||
def output_load(self, bl_pos=0):
|
||||
bl_wire = self.gen_bl_wire()
|
||||
return bl_wire.wire_c # sense amp only need to charge small portion of the bl
|
||||
# set as one segment for now
|
||||
|
||||
def input_load(self):
|
||||
wl_wire = self.gen_wl_wire()
|
||||
return wl_wire.return_input_cap()
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ OPTS = globals.get_opts()
|
|||
class lib:
|
||||
""" lib file generation."""
|
||||
|
||||
def __init__(self, libname, sram, spfile):
|
||||
def __init__(self, libname, sram, spfile, use_model=OPTS.analytical_delay):
|
||||
self.name = sram.name
|
||||
self.num_words = sram.num_words
|
||||
self.word_size = sram.word_size
|
||||
|
|
@ -61,7 +61,11 @@ class lib:
|
|||
probe_address = "1" * self.addr_size
|
||||
probe_data = self.word_size - 1
|
||||
|
||||
data = self.d.analyze(probe_address, probe_data)
|
||||
if use_model:
|
||||
data = sram.analytical_model(slope=0.001)
|
||||
else:
|
||||
data = self.d.analyze(probe_address, probe_data)
|
||||
|
||||
for i in data.keys():
|
||||
if i == "read_power" or i == "write_power":
|
||||
continue
|
||||
|
|
|
|||
|
|
@ -51,7 +51,9 @@ def parse_args():
|
|||
help="Spice simulator name"),
|
||||
# TODO: Why is this -f?
|
||||
optparse.make_option("-f", "--trim_noncritical", dest="trim_noncritical",
|
||||
help="Trim noncritical memory cells during simulation")
|
||||
help="Trim noncritical memory cells during simulation"),
|
||||
optparse.make_option("-a", "--analyticaldelay", dest="analytical_delay",
|
||||
help="Use analytical model to calculate delay or not")
|
||||
}
|
||||
# -h --help is implicit.
|
||||
|
||||
|
|
|
|||
|
|
@ -601,3 +601,30 @@ class hierarchical_decoder(design.design):
|
|||
offset=[xoffset + self.gap_between_rails,
|
||||
yoffset - self.via_shift],
|
||||
rotate=90)
|
||||
|
||||
def delay(self, slope, load = 0.0):
|
||||
# A -> out
|
||||
if self.determine_predecodes(self.num_inputs)[1]==0:
|
||||
pre = self.pre2_4
|
||||
nand = self.nand2
|
||||
else:
|
||||
pre = self.pre3_8
|
||||
nand = self.nand3
|
||||
a_t_out_delay = pre.delay(slope=slope,load = nand.input_load())
|
||||
|
||||
# out -> z
|
||||
out_t_z_delay = nand.delay(slope= a_t_out_delay.slope,
|
||||
load = self.inv.input_load())
|
||||
result = a_t_out_delay + out_t_z_delay
|
||||
|
||||
# Z -> decode_out
|
||||
z_t_decodeout_delay = self.inv.delay(slope = out_t_z_delay.slope , load = load)
|
||||
result = result + z_t_decodeout_delay
|
||||
return result
|
||||
|
||||
def input_load(self):
|
||||
if self.determine_predecodes(self.num_inputs)[1]==0:
|
||||
pre = self.pre2_4
|
||||
else:
|
||||
pre = self.pre3_8
|
||||
return pre.input_load()
|
||||
|
|
|
|||
|
|
@ -108,3 +108,21 @@ class hierarchical_predecode2x4(hierarchical_predecode):
|
|||
|
||||
def get_via_y(self):
|
||||
return self.rail_height
|
||||
|
||||
def delay(self, slope, load = 0.0 ):
|
||||
#print "pre2x4 consist:"
|
||||
# A -> B
|
||||
a_t_b_delay = self.inv.delay(slope=slope,load = self.nand.input_load())
|
||||
|
||||
# out -> z
|
||||
b_t_z_delay = self.nand.delay(slope=a_t_b_delay.slope,load = self.inv.input_load())
|
||||
result = a_t_b_delay + b_t_z_delay
|
||||
|
||||
# Z -> out
|
||||
a_t_out_delay = self.inv.delay(slope=b_t_z_delay.slope,load = load)
|
||||
result = result + a_t_out_delay
|
||||
#print "end of pre2x4"
|
||||
return result
|
||||
|
||||
def input_load(self):
|
||||
return self.inv.input_load()
|
||||
|
|
|
|||
|
|
@ -90,3 +90,17 @@ class hierarchical_predecode3x8(hierarchical_predecode):
|
|||
yoffset = (self.number_of_outputs * self.inv.height
|
||||
- 0.5 * drc["minwidth_metal1"])
|
||||
return yoffset
|
||||
|
||||
def delay(self, slope, load = 0.0 ):
|
||||
# A -> z
|
||||
b_t_z_delay = self.nand.delay(slope=slope,
|
||||
load = self.input_load())
|
||||
|
||||
# Z -> out
|
||||
a_t_out_delay = self.inv.delay(slope=b_t_z_delay.slope,
|
||||
load = load)
|
||||
result = b_t_z_delay + a_t_out_delay
|
||||
return result
|
||||
|
||||
def input_load(self):
|
||||
return self.nand.input_load()
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import debug
|
||||
import re
|
||||
import os
|
||||
import math
|
||||
|
||||
|
||||
class spice:
|
||||
|
|
@ -146,3 +147,108 @@ class spice:
|
|||
self.sp_write_file(spfile, usedMODS)
|
||||
del usedMODS
|
||||
spfile.close()
|
||||
|
||||
def delay(self, slope, load=0.0):
|
||||
"""Inform users undefined delay module while building new modules"""
|
||||
debug.warning("Design Class {0} delay function needs to be defined"
|
||||
.format(self.__class__.__name__))
|
||||
debug.warning("Class {0} name {1}"
|
||||
.format(self.__class__.__name__,
|
||||
self.name))
|
||||
# return 0 to keep code running while building
|
||||
return delay_data(0.0, 0.0)
|
||||
|
||||
def cal_delay_with_rc(self, r, c ,slope, swing = 0.5):
|
||||
"""
|
||||
Calculate the delay of a mosfet by
|
||||
modeling it as a resistance driving a capacitance
|
||||
"""
|
||||
swing_factor = abs(math.log(1-swing)) # time constant based on swing
|
||||
delay = swing_factor * r * c #c is in ff and delay is in fs
|
||||
delay = delay * 0.001 #make the unit to ps
|
||||
|
||||
# Output slope should be linear to input slope which is described
|
||||
# as 0.005* slope.
|
||||
|
||||
# The slope will be also influenced by the delay.
|
||||
# If no input slope(or too small to make impact)
|
||||
# The mimum slope should be the time to charge RC.
|
||||
# Delay * 2 is from 0 to 100% swing. 0.6*2*delay is from 20%-80%.
|
||||
slope = delay * 0.6 * 2 + 0.005 * slope
|
||||
return delay_data(delay = delay, slope = slope)
|
||||
|
||||
|
||||
def return_delay(self, delay, slope):
|
||||
return delay_data(delay, slope)
|
||||
|
||||
def generate_rc_net(self,lump_num, wire_length, wire_width):
|
||||
return wire_spice_model(lump_num, wire_length, wire_width)
|
||||
|
||||
class delay_data:
|
||||
"""
|
||||
This is the delay class to represent the delay information
|
||||
Time is 50% of the signal to 50% of reference signal delay.
|
||||
Slope is the 20% of the signal to 80% of signal
|
||||
"""
|
||||
def __init__(self, delay=0.0, slope=0.0):
|
||||
""" init function support two init method"""
|
||||
# will take single input as a coordinate
|
||||
self.delay = delay
|
||||
self.slope = slope
|
||||
|
||||
def __str__(self):
|
||||
""" override print function output """
|
||||
return "Delay Data: Delay "+str(self.delay)+", Slope "+str(self.slope)+""
|
||||
|
||||
def __add__(self, other):
|
||||
"""
|
||||
Override - function (left), for delay_data: a+b != b+a
|
||||
"""
|
||||
assert isinstance(other,delay_data)
|
||||
return delay_data(other.delay + self.delay,
|
||||
other.slope)
|
||||
|
||||
def __radd__(self, other):
|
||||
"""
|
||||
Override - function (right), for delay_data: a+b != b+a
|
||||
"""
|
||||
assert isinstance(other,delay_data)
|
||||
return delay_data(other.delay + self.delay,
|
||||
self.slope)
|
||||
|
||||
|
||||
class wire_spice_model:
|
||||
"""
|
||||
This is the spice class to represent a wire
|
||||
"""
|
||||
def __init__(self, lump_num, wire_length, wire_width):
|
||||
self.lump_num = lump_num # the number of segment the wire delay has
|
||||
self.wire_c = self.cal_wire_c(wire_length, wire_width) # c in each segment
|
||||
self.wire_r = self.cal_wire_r(wire_length, wire_width) # r in each segment
|
||||
|
||||
def cal_wire_c(self, wire_length, wire_width):
|
||||
from tech import spice
|
||||
total_c = spice["wire_unit_c"] * wire_length * wire_width
|
||||
wire_c = total_c / self.lump_num
|
||||
return wire_c
|
||||
|
||||
def cal_wire_r(self, wire_length, wire_width):
|
||||
from tech import spice
|
||||
total_r = spice["wire_unit_r"] * wire_length / wire_width
|
||||
wire_r = total_r / self.lump_num
|
||||
return wire_r
|
||||
|
||||
def return_input_cap(self):
|
||||
return 0.5 * self.wire_c * self.lump_num
|
||||
|
||||
def return_delay_over_wire(self, slope, swing = 0.5):
|
||||
# delay will be sum of arithmetic sequence start from
|
||||
# rc to self.lump_num*rc with step of rc
|
||||
|
||||
swing_factor = abs(math.log(1-swing)) # time constant based on swing
|
||||
sum_factor = (1+self.lump_num) * self.lump_num * 0.5 # sum of the arithmetic sequence
|
||||
delay = sum_factor * swing_factor * self.wire_r * self.wire_c
|
||||
slope = delay * 2 + slope
|
||||
result= delay_data(delay, slope)
|
||||
return result
|
||||
|
||||
|
|
|
|||
|
|
@ -23,3 +23,20 @@ class ms_flop(design.design):
|
|||
self.din_offset = ms_flop.chars["din"]
|
||||
self.dout_offset = ms_flop.chars["dout"]
|
||||
self.dout_bar_offset = ms_flop.chars["dout_bar"]
|
||||
|
||||
def delay(self, slope, load = 0.0):
|
||||
#import pinv
|
||||
# use inv to mimic the delay
|
||||
# din -> mout
|
||||
#ref = pinv.pinv("reference_inv")
|
||||
#mid_load = ref.input_load()
|
||||
#din_t_mout_delay = ref.delay(slope = slope, load = mid_load)
|
||||
|
||||
# mout -> out
|
||||
#mout_t_out_delay = ref.delay(slope = slope, load = load)
|
||||
#result = din_t_mout_delay + mout_t_out_delay
|
||||
|
||||
# dont k how to calculate this now, use constant in tech file
|
||||
from tech import spice
|
||||
result = self.return_delay(spice["msflop_delay"], spice["msflop_slope"])
|
||||
return result
|
||||
|
|
|
|||
|
|
@ -163,3 +163,8 @@ class ms_flop_array(design.design):
|
|||
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
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import contact
|
||||
import design
|
||||
import debug
|
||||
from tech import drc
|
||||
from tech import drc, parameter, spice
|
||||
from ptx import ptx
|
||||
from vector import vector
|
||||
from globals import OPTS
|
||||
|
|
@ -438,3 +438,12 @@ class nand_2(design.design):
|
|||
self.Z_position = self.Z_position = self.output_position
|
||||
self.vdd_position = self.vdd_position
|
||||
self.gnd_position = self.gnd_position
|
||||
|
||||
def input_load(self):
|
||||
from tech import spice
|
||||
return ((self.nmos_size+self.pmos_size)/parameter["min_tx_size"])*spice["min_tx_gate_c"]
|
||||
|
||||
def delay(self, slope, load=0.0):
|
||||
r = spice["min_tx_r"]/(self.nmos_size/parameter["min_tx_size"])
|
||||
c_para = spice["min_tx_c_para"]*(self.nmos_size/parameter["min_tx_size"])#ff
|
||||
return self.cal_delay_with_rc(r = r, c = c_para+load, slope =slope)
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import debug
|
|||
from tech import drc
|
||||
from ptx import ptx
|
||||
from vector import vector
|
||||
from tech import parameter, spice
|
||||
from globals import OPTS
|
||||
|
||||
class nand_3(design.design):
|
||||
|
|
@ -525,3 +526,11 @@ class nand_3(design.design):
|
|||
self.Z_position = self.Z_position
|
||||
self.vdd_position = self.vdd_position
|
||||
self.gnd_position = self.gnd_position
|
||||
|
||||
def input_load(self):
|
||||
return ((self.nmos_size+self.pmos_size)/parameter["min_tx_size"])*spice["min_tx_gate_c"]
|
||||
|
||||
def delay(self, slope, load=0.0):
|
||||
r = spice["min_tx_r"]/(self.nmos_size/parameter["min_tx_size"])
|
||||
c_para = spice["min_tx_c_para"]*(self.nmos_size/parameter["min_tx_size"])#ff
|
||||
return self.cal_delay_with_rc(r = r, c = c_para+load, slope =slope)
|
||||
|
|
|
|||
|
|
@ -36,3 +36,4 @@ class options(optparse.Values):
|
|||
out_path = ""
|
||||
# Define the output file base name
|
||||
out_name = ""
|
||||
analytical_delay = True
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import contact
|
||||
import design
|
||||
import debug
|
||||
from tech import drc, parameter
|
||||
from tech import drc, parameter, spice
|
||||
from ptx import ptx
|
||||
from vector import vector
|
||||
from math import ceil
|
||||
|
|
@ -401,3 +401,12 @@ class pinv(design.design):
|
|||
def setup_layout_offsets(self):
|
||||
self.A_position = self.input_position
|
||||
self.Z_position = self.output_position
|
||||
|
||||
def input_load(self):
|
||||
return ((self.nmos_size+self.pmos_size)/parameter["min_tx_size"])*spice["min_tx_gate_c"]
|
||||
|
||||
def delay(self, slope, load=0.0):
|
||||
from tech import spice
|
||||
r = spice["min_tx_r"]/(self.nmos_size/parameter["min_tx_size"])
|
||||
c_para = spice["min_tx_c_para"]*(self.nmos_size/parameter["min_tx_size"])#ff
|
||||
return self.cal_delay_with_rc(r = r, c = c_para+load, slope =slope)
|
||||
|
|
|
|||
|
|
@ -21,3 +21,10 @@ class sense_amp(design.design):
|
|||
self.width = sense_amp.chars["width"]
|
||||
self.height = sense_amp.chars["height"]
|
||||
|
||||
def delay(self, slope, load=0.0):
|
||||
from tech import spice
|
||||
r = spice["min_tx_r"]/(10)
|
||||
c_para = spice["min_tx_c_para"]#ff
|
||||
result = self.cal_delay_with_rc(r = r, c = c_para+load, slope =slope)
|
||||
return self.return_delay(result.delay , result.slope)
|
||||
|
||||
|
|
|
|||
|
|
@ -131,3 +131,7 @@ class sense_amp_array(design.design):
|
|||
width=self.width,
|
||||
height=drc["minwidth_metal1"])
|
||||
self.SCLK_positions.append(sclk_offset)
|
||||
|
||||
def delay(self, slope, load =0.0):
|
||||
result = self.amp.delay(slope=slope, load =load)
|
||||
return result
|
||||
|
|
|
|||
|
|
@ -1170,3 +1170,13 @@ class sram(design.design):
|
|||
self.sp_write_file(sp, usedMODS)
|
||||
del usedMODS
|
||||
sp.close()
|
||||
|
||||
def analytical_model(self,slope):
|
||||
#control_delay = self.control.delay(slope=slope)
|
||||
bank_delay = self.bank.delay(slope = slope)
|
||||
data ={'delay1': bank_delay.delay, 'delay0': bank_delay.delay,
|
||||
'min_period1': 0,
|
||||
'min_period0': 0,
|
||||
'read_power': 0,
|
||||
'write_power': 0}
|
||||
return data
|
||||
|
|
|
|||
|
|
@ -0,0 +1,70 @@
|
|||
#!/usr/bin/env python2.7
|
||||
"""
|
||||
Check the .lib file for an SRAM
|
||||
"""
|
||||
|
||||
import unittest
|
||||
from testutils import header,isapproxdiff
|
||||
import sys,os
|
||||
sys.path.append(os.path.join(sys.path[0],".."))
|
||||
import globals
|
||||
import debug
|
||||
import calibre
|
||||
|
||||
OPTS = globals.get_opts()
|
||||
|
||||
|
||||
class lib_test(unittest.TestCase):
|
||||
|
||||
def runTest(self):
|
||||
globals.init_openram("config_20_{0}".format(OPTS.tech_name))
|
||||
# we will manually run lvs/drc
|
||||
OPTS.check_lvsdrc = False
|
||||
|
||||
import sram
|
||||
import lib
|
||||
|
||||
debug.info(1, "Testing timing for sample 2 bit, 16 words SRAM with 1 bank")
|
||||
total_size = 1024
|
||||
for word_size in [1,2,4,8,16,32,64]:
|
||||
num_words = total_size/word_size# OPTS.config.num_words
|
||||
s = sram.sram(word_size=word_size,
|
||||
num_words=num_words,
|
||||
num_banks=OPTS.config.num_banks,
|
||||
name="sram_2_16_1_{0}".format(OPTS.tech_name))
|
||||
delay = s.analytical_model(0.1)
|
||||
|
||||
|
||||
OPTS.check_lvsdrc = True
|
||||
|
||||
tempspice = OPTS.openram_temp + "temp.sp"
|
||||
s.sp_write(tempspice)
|
||||
|
||||
filename = s.name + ".lib"
|
||||
libname = OPTS.openram_temp + filename
|
||||
use_model = True
|
||||
lib.lib(libname,s,tempspice,use_model)
|
||||
|
||||
|
||||
# let's diff the result with a golden model
|
||||
golden = "{0}/golden/{1}".format(os.path.dirname(os.path.realpath(__file__)),filename)
|
||||
# Randomly decided 10% difference between spice simulators is ok.
|
||||
if use_model != True:
|
||||
self.assertEqual(isapproxdiff(libname,golden,0.10),True)
|
||||
|
||||
os.system("rm {0}".format(libname))
|
||||
|
||||
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()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -34,7 +34,10 @@ class lib_test(unittest.TestCase):
|
|||
tempspice = OPTS.openram_temp + "temp.sp"
|
||||
s.sp_write(tempspice)
|
||||
|
||||
filename = s.name + ".lib"
|
||||
if OPTS.analytical_delay == True:
|
||||
filename = s.name + "_analytical.lib"
|
||||
else:
|
||||
filename = s.name + ".lib"
|
||||
libname = OPTS.openram_temp + filename
|
||||
lib.lib(libname,s,tempspice)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,315 @@
|
|||
library (sram_2_16_1_freepdk45_lib){
|
||||
delay_model : "table_lookup";
|
||||
time_unit : "1ns" ;
|
||||
voltage_unit : "1v" ;
|
||||
current_unit : "1mA" ;
|
||||
resistance_unit : "1kohm" ;
|
||||
capacitive_load_unit(1 ,fF) ;
|
||||
leakage_power_unit : "1mW" ;
|
||||
pulling_resistance_unit :"1kohm" ;
|
||||
operating_conditions(TT){
|
||||
voltage : 1.0 ;
|
||||
temperature : 25.000 ;
|
||||
}
|
||||
|
||||
input_threshold_pct_fall : 50.0 ;
|
||||
output_threshold_pct_fall : 50.0 ;
|
||||
input_threshold_pct_rise : 50.0 ;
|
||||
output_threshold_pct_rise : 50.0 ;
|
||||
slew_lower_threshold_pct_fall : 10.0 ;
|
||||
slew_upper_threshold_pct_fall : 90.0 ;
|
||||
slew_lower_threshold_pct_rise : 10.0 ;
|
||||
slew_upper_threshold_pct_rise : 90.0 ;
|
||||
|
||||
default_cell_leakage_power : 0.0 ;
|
||||
default_leakage_power_density : 0.0 ;
|
||||
default_input_pin_cap : 1.0 ;
|
||||
default_inout_pin_cap : 1.0 ;
|
||||
default_output_pin_cap : 0.0 ;
|
||||
default_max_transition : 0.5 ;
|
||||
default_fanout_load : 1.0 ;
|
||||
default_max_fanout : 4.0 ;
|
||||
default_connection_class : universal ;
|
||||
|
||||
lu_table_template(CELL_UP_FOR_CLOCK){
|
||||
variable_1 : input_net_transition;
|
||||
variable_2 : total_output_net_capacitance;
|
||||
index_1 ("0.5");
|
||||
index_2 ("0.5");
|
||||
}
|
||||
|
||||
lu_table_template(CELL_DN_FOR_CLOCK){
|
||||
variable_1 : input_net_transition;
|
||||
variable_2 : total_output_net_capacitance;
|
||||
index_1 ("0.5");
|
||||
index_2 ("0.5");
|
||||
}
|
||||
|
||||
lu_table_template(CONSTRAINT_HIGH_POS){
|
||||
variable_1 : related_pin_transition;
|
||||
variable_2 : constrained_pin_transition;
|
||||
index_1 ("0.5");
|
||||
index_2 ("0.5");
|
||||
}
|
||||
|
||||
lu_table_template(CONSTRAINT_LOW_POS){
|
||||
variable_1 : related_pin_transition;
|
||||
variable_2 : constrained_pin_transition;
|
||||
index_1 ("0.5");
|
||||
index_2 ("0.5");
|
||||
}
|
||||
|
||||
lu_table_template(CLK_TRAN) {
|
||||
variable_1 : constrained_pin_transition;
|
||||
index_1 ("0.5");
|
||||
}
|
||||
|
||||
lu_table_template(TRAN) {
|
||||
variable_1 : total_output_net_capacitance;
|
||||
index_1 ("0.5");
|
||||
}
|
||||
|
||||
power_lut_template(INPUT_BY_TRANS_FOR_CLOCK){
|
||||
variable_1 : input_transition_time;
|
||||
index_1 ("0.5");
|
||||
}
|
||||
|
||||
power_lut_template(INPUT_BY_TRANS_FOR_SIGNAL){
|
||||
variable_1 : input_transition_time;
|
||||
index_1 ("0.5");
|
||||
}
|
||||
|
||||
default_operating_conditions : TT;
|
||||
|
||||
|
||||
type (DATA){
|
||||
base_type : array;
|
||||
data_type : bit;
|
||||
bit_width : 2;
|
||||
bit_from : 0;
|
||||
bit_to : 1;
|
||||
}
|
||||
|
||||
type (ADDR){
|
||||
base_type : array;
|
||||
data_type : bit;
|
||||
bit_width : 4;
|
||||
bit_from : 0;
|
||||
bit_to : 3;
|
||||
}
|
||||
|
||||
cell (sram_2_16_1_freepdk45){
|
||||
memory(){
|
||||
type : ram;
|
||||
address_width : 4;
|
||||
word_width : 2;
|
||||
}
|
||||
interface_timing : true;
|
||||
dont_use : true;
|
||||
map_only : true;
|
||||
dont_touch : true;
|
||||
area : 799.659625;
|
||||
|
||||
bus(DATA){
|
||||
bus_type : DATA;
|
||||
direction : inout;
|
||||
max_capacitance : 0.62166;
|
||||
pin(DATA[1:0]){
|
||||
}
|
||||
three_state : "!OEb & !clk";
|
||||
memory_write(){
|
||||
address : ADDR;
|
||||
clocked_on : clk;
|
||||
}
|
||||
internal_power(){
|
||||
when : "OEb & !clk";
|
||||
rise_power(INPUT_BY_TRANS_FOR_SIGNAL){
|
||||
values("0.0");
|
||||
}
|
||||
fall_power(INPUT_BY_TRANS_FOR_SIGNAL){
|
||||
values("0.0");
|
||||
}
|
||||
}
|
||||
timing(){
|
||||
timing_type : setup_rising;
|
||||
related_pin : "clk";
|
||||
rise_constraint(CONSTRAINT_HIGH_POS) {
|
||||
values("0.015");
|
||||
}
|
||||
fall_constraint(CONSTRAINT_LOW_POS) {
|
||||
values("0.009");
|
||||
}
|
||||
}
|
||||
timing(){
|
||||
timing_type : hold_rising;
|
||||
related_pin : "clk";
|
||||
rise_constraint(CONSTRAINT_HIGH_POS) {
|
||||
values("-0.005");
|
||||
}
|
||||
fall_constraint(CONSTRAINT_LOW_POS) {
|
||||
values("-0.011");
|
||||
}
|
||||
}
|
||||
memory_read(){
|
||||
address : ADDR;
|
||||
}
|
||||
internal_power(){
|
||||
when : "!OEb & !clk";
|
||||
rise_power(INPUT_BY_TRANS_FOR_SIGNAL){
|
||||
values("0.0");
|
||||
}
|
||||
fall_power(INPUT_BY_TRANS_FOR_SIGNAL){
|
||||
values("0.0");
|
||||
}
|
||||
}
|
||||
timing(){
|
||||
timing_sense : non_unate;
|
||||
related_pin : "clk";
|
||||
timing_type : rising_edge;
|
||||
cell_rise(CELL_UP_FOR_CLOCK) {
|
||||
values("120.044");
|
||||
}
|
||||
cell_fall(CELL_DN_FOR_CLOCK) {
|
||||
values("120.044");
|
||||
}
|
||||
rise_transition(TRAN) {
|
||||
values("120.044");
|
||||
}
|
||||
fall_transition(TRAN) {
|
||||
values("120.044");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bus(ADDR){
|
||||
bus_type : ADDR;
|
||||
direction : input;
|
||||
capacitance : 0.2091;
|
||||
max_transition : 0.5;
|
||||
fanout_load : 1.000000;
|
||||
pin(ADDR[3:0]){
|
||||
}
|
||||
timing(){
|
||||
timing_type : setup_rising;
|
||||
related_pin : "clk";
|
||||
rise_constraint(CONSTRAINT_HIGH_POS) {
|
||||
values("0.015");
|
||||
}
|
||||
fall_constraint(CONSTRAINT_LOW_POS) {
|
||||
values("0.009");
|
||||
}
|
||||
}
|
||||
timing(){
|
||||
timing_type : hold_rising;
|
||||
related_pin : "clk";
|
||||
rise_constraint(CONSTRAINT_HIGH_POS) {
|
||||
values("-0.005");
|
||||
}
|
||||
fall_constraint(CONSTRAINT_LOW_POS) {
|
||||
values("-0.011");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pin(CSb){
|
||||
direction : input;
|
||||
capacitance : 0.2091;
|
||||
timing(){
|
||||
timing_type : setup_rising;
|
||||
related_pin : "clk";
|
||||
rise_constraint(CONSTRAINT_HIGH_POS) {
|
||||
values("0.015");
|
||||
}
|
||||
fall_constraint(CONSTRAINT_LOW_POS) {
|
||||
values("0.009");
|
||||
}
|
||||
}
|
||||
timing(){
|
||||
timing_type : hold_rising;
|
||||
related_pin : "clk";
|
||||
rise_constraint(CONSTRAINT_HIGH_POS) {
|
||||
values("-0.005");
|
||||
}
|
||||
fall_constraint(CONSTRAINT_LOW_POS) {
|
||||
values("-0.011");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pin(OEb){
|
||||
direction : input;
|
||||
capacitance : 0.2091;
|
||||
timing(){
|
||||
timing_type : setup_rising;
|
||||
related_pin : "clk";
|
||||
rise_constraint(CONSTRAINT_HIGH_POS) {
|
||||
values("0.015");
|
||||
}
|
||||
fall_constraint(CONSTRAINT_LOW_POS) {
|
||||
values("0.009");
|
||||
}
|
||||
}
|
||||
timing(){
|
||||
timing_type : hold_rising;
|
||||
related_pin : "clk";
|
||||
rise_constraint(CONSTRAINT_HIGH_POS) {
|
||||
values("-0.005");
|
||||
}
|
||||
fall_constraint(CONSTRAINT_LOW_POS) {
|
||||
values("-0.011");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pin(WEb){
|
||||
direction : input;
|
||||
capacitance : 0.2091;
|
||||
timing(){
|
||||
timing_type : setup_rising;
|
||||
related_pin : "clk";
|
||||
rise_constraint(CONSTRAINT_HIGH_POS) {
|
||||
values("0.015");
|
||||
}
|
||||
fall_constraint(CONSTRAINT_LOW_POS) {
|
||||
values("0.009");
|
||||
}
|
||||
}
|
||||
timing(){
|
||||
timing_type : hold_rising;
|
||||
related_pin : "clk";
|
||||
rise_constraint(CONSTRAINT_HIGH_POS) {
|
||||
values("-0.005");
|
||||
}
|
||||
fall_constraint(CONSTRAINT_LOW_POS) {
|
||||
values("-0.011");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pin(clk){
|
||||
clock : true;
|
||||
direction : input;
|
||||
capacitance : 0.2091;
|
||||
timing(){
|
||||
timing_type :"min_pulse_width";
|
||||
related_pin : clk;
|
||||
rise_constraint(CLK_TRAN) {
|
||||
values("0.0");
|
||||
}
|
||||
fall_constraint(CLK_TRAN) {
|
||||
values("0.0");
|
||||
}
|
||||
}
|
||||
timing(){
|
||||
timing_type :"minimum_period";
|
||||
related_pin : clk;
|
||||
rise_constraint(CLK_TRAN) {
|
||||
values("0.0");
|
||||
}
|
||||
fall_constraint(CLK_TRAN) {
|
||||
values("0.0");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,315 @@
|
|||
library (sram_2_16_1_scn3me_subm_lib){
|
||||
delay_model : "table_lookup";
|
||||
time_unit : "1ns" ;
|
||||
voltage_unit : "1v" ;
|
||||
current_unit : "1mA" ;
|
||||
resistance_unit : "1kohm" ;
|
||||
capacitive_load_unit(1 ,fF) ;
|
||||
leakage_power_unit : "1mW" ;
|
||||
pulling_resistance_unit :"1kohm" ;
|
||||
operating_conditions(TT){
|
||||
voltage : 5.0 ;
|
||||
temperature : 25.000 ;
|
||||
}
|
||||
|
||||
input_threshold_pct_fall : 50.0 ;
|
||||
output_threshold_pct_fall : 50.0 ;
|
||||
input_threshold_pct_rise : 50.0 ;
|
||||
output_threshold_pct_rise : 50.0 ;
|
||||
slew_lower_threshold_pct_fall : 10.0 ;
|
||||
slew_upper_threshold_pct_fall : 90.0 ;
|
||||
slew_lower_threshold_pct_rise : 10.0 ;
|
||||
slew_upper_threshold_pct_rise : 90.0 ;
|
||||
|
||||
default_cell_leakage_power : 0.0 ;
|
||||
default_leakage_power_density : 0.0 ;
|
||||
default_input_pin_cap : 1.0 ;
|
||||
default_inout_pin_cap : 1.0 ;
|
||||
default_output_pin_cap : 0.0 ;
|
||||
default_max_transition : 0.5 ;
|
||||
default_fanout_load : 1.0 ;
|
||||
default_max_fanout : 4.0 ;
|
||||
default_connection_class : universal ;
|
||||
|
||||
lu_table_template(CELL_UP_FOR_CLOCK){
|
||||
variable_1 : input_net_transition;
|
||||
variable_2 : total_output_net_capacitance;
|
||||
index_1 ("0.5");
|
||||
index_2 ("0.5");
|
||||
}
|
||||
|
||||
lu_table_template(CELL_DN_FOR_CLOCK){
|
||||
variable_1 : input_net_transition;
|
||||
variable_2 : total_output_net_capacitance;
|
||||
index_1 ("0.5");
|
||||
index_2 ("0.5");
|
||||
}
|
||||
|
||||
lu_table_template(CONSTRAINT_HIGH_POS){
|
||||
variable_1 : related_pin_transition;
|
||||
variable_2 : constrained_pin_transition;
|
||||
index_1 ("0.5");
|
||||
index_2 ("0.5");
|
||||
}
|
||||
|
||||
lu_table_template(CONSTRAINT_LOW_POS){
|
||||
variable_1 : related_pin_transition;
|
||||
variable_2 : constrained_pin_transition;
|
||||
index_1 ("0.5");
|
||||
index_2 ("0.5");
|
||||
}
|
||||
|
||||
lu_table_template(CLK_TRAN) {
|
||||
variable_1 : constrained_pin_transition;
|
||||
index_1 ("0.5");
|
||||
}
|
||||
|
||||
lu_table_template(TRAN) {
|
||||
variable_1 : total_output_net_capacitance;
|
||||
index_1 ("0.5");
|
||||
}
|
||||
|
||||
power_lut_template(INPUT_BY_TRANS_FOR_CLOCK){
|
||||
variable_1 : input_transition_time;
|
||||
index_1 ("0.5");
|
||||
}
|
||||
|
||||
power_lut_template(INPUT_BY_TRANS_FOR_SIGNAL){
|
||||
variable_1 : input_transition_time;
|
||||
index_1 ("0.5");
|
||||
}
|
||||
|
||||
default_operating_conditions : TT;
|
||||
|
||||
|
||||
type (DATA){
|
||||
base_type : array;
|
||||
data_type : bit;
|
||||
bit_width : 2;
|
||||
bit_from : 0;
|
||||
bit_to : 1;
|
||||
}
|
||||
|
||||
type (ADDR){
|
||||
base_type : array;
|
||||
data_type : bit;
|
||||
bit_width : 4;
|
||||
bit_from : 0;
|
||||
bit_to : 3;
|
||||
}
|
||||
|
||||
cell (sram_2_16_1_scn3me_subm){
|
||||
memory(){
|
||||
type : ram;
|
||||
address_width : 4;
|
||||
word_width : 2;
|
||||
}
|
||||
interface_timing : true;
|
||||
dont_use : true;
|
||||
map_only : true;
|
||||
dont_touch : true;
|
||||
area : 102102.39;
|
||||
|
||||
bus(DATA){
|
||||
bus_type : DATA;
|
||||
direction : inout;
|
||||
max_capacitance : 11.3222;
|
||||
pin(DATA[1:0]){
|
||||
}
|
||||
three_state : "!OEb & !clk";
|
||||
memory_write(){
|
||||
address : ADDR;
|
||||
clocked_on : clk;
|
||||
}
|
||||
internal_power(){
|
||||
when : "OEb & !clk";
|
||||
rise_power(INPUT_BY_TRANS_FOR_SIGNAL){
|
||||
values("0.0");
|
||||
}
|
||||
fall_power(INPUT_BY_TRANS_FOR_SIGNAL){
|
||||
values("0.0");
|
||||
}
|
||||
}
|
||||
timing(){
|
||||
timing_type : setup_rising;
|
||||
related_pin : "clk";
|
||||
rise_constraint(CONSTRAINT_HIGH_POS) {
|
||||
values("0.093");
|
||||
}
|
||||
fall_constraint(CONSTRAINT_LOW_POS) {
|
||||
values("-0.024");
|
||||
}
|
||||
}
|
||||
timing(){
|
||||
timing_type : hold_rising;
|
||||
related_pin : "clk";
|
||||
rise_constraint(CONSTRAINT_HIGH_POS) {
|
||||
values("0.046");
|
||||
}
|
||||
fall_constraint(CONSTRAINT_LOW_POS) {
|
||||
values("-0.083");
|
||||
}
|
||||
}
|
||||
memory_read(){
|
||||
address : ADDR;
|
||||
}
|
||||
internal_power(){
|
||||
when : "!OEb & !clk";
|
||||
rise_power(INPUT_BY_TRANS_FOR_SIGNAL){
|
||||
values("0.0");
|
||||
}
|
||||
fall_power(INPUT_BY_TRANS_FOR_SIGNAL){
|
||||
values("0.0");
|
||||
}
|
||||
}
|
||||
timing(){
|
||||
timing_sense : non_unate;
|
||||
related_pin : "clk";
|
||||
timing_type : rising_edge;
|
||||
cell_rise(CELL_UP_FOR_CLOCK) {
|
||||
values("553.907");
|
||||
}
|
||||
cell_fall(CELL_DN_FOR_CLOCK) {
|
||||
values("553.907");
|
||||
}
|
||||
rise_transition(TRAN) {
|
||||
values("553.907");
|
||||
}
|
||||
fall_transition(TRAN) {
|
||||
values("553.907");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bus(ADDR){
|
||||
bus_type : ADDR;
|
||||
direction : input;
|
||||
capacitance : 9.8242;
|
||||
max_transition : 0.5;
|
||||
fanout_load : 1.000000;
|
||||
pin(ADDR[3:0]){
|
||||
}
|
||||
timing(){
|
||||
timing_type : setup_rising;
|
||||
related_pin : "clk";
|
||||
rise_constraint(CONSTRAINT_HIGH_POS) {
|
||||
values("0.093");
|
||||
}
|
||||
fall_constraint(CONSTRAINT_LOW_POS) {
|
||||
values("-0.024");
|
||||
}
|
||||
}
|
||||
timing(){
|
||||
timing_type : hold_rising;
|
||||
related_pin : "clk";
|
||||
rise_constraint(CONSTRAINT_HIGH_POS) {
|
||||
values("0.046");
|
||||
}
|
||||
fall_constraint(CONSTRAINT_LOW_POS) {
|
||||
values("-0.083");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pin(CSb){
|
||||
direction : input;
|
||||
capacitance : 9.8242;
|
||||
timing(){
|
||||
timing_type : setup_rising;
|
||||
related_pin : "clk";
|
||||
rise_constraint(CONSTRAINT_HIGH_POS) {
|
||||
values("0.093");
|
||||
}
|
||||
fall_constraint(CONSTRAINT_LOW_POS) {
|
||||
values("-0.024");
|
||||
}
|
||||
}
|
||||
timing(){
|
||||
timing_type : hold_rising;
|
||||
related_pin : "clk";
|
||||
rise_constraint(CONSTRAINT_HIGH_POS) {
|
||||
values("0.046");
|
||||
}
|
||||
fall_constraint(CONSTRAINT_LOW_POS) {
|
||||
values("-0.083");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pin(OEb){
|
||||
direction : input;
|
||||
capacitance : 9.8242;
|
||||
timing(){
|
||||
timing_type : setup_rising;
|
||||
related_pin : "clk";
|
||||
rise_constraint(CONSTRAINT_HIGH_POS) {
|
||||
values("0.093");
|
||||
}
|
||||
fall_constraint(CONSTRAINT_LOW_POS) {
|
||||
values("-0.024");
|
||||
}
|
||||
}
|
||||
timing(){
|
||||
timing_type : hold_rising;
|
||||
related_pin : "clk";
|
||||
rise_constraint(CONSTRAINT_HIGH_POS) {
|
||||
values("0.046");
|
||||
}
|
||||
fall_constraint(CONSTRAINT_LOW_POS) {
|
||||
values("-0.083");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pin(WEb){
|
||||
direction : input;
|
||||
capacitance : 9.8242;
|
||||
timing(){
|
||||
timing_type : setup_rising;
|
||||
related_pin : "clk";
|
||||
rise_constraint(CONSTRAINT_HIGH_POS) {
|
||||
values("0.093");
|
||||
}
|
||||
fall_constraint(CONSTRAINT_LOW_POS) {
|
||||
values("-0.024");
|
||||
}
|
||||
}
|
||||
timing(){
|
||||
timing_type : hold_rising;
|
||||
related_pin : "clk";
|
||||
rise_constraint(CONSTRAINT_HIGH_POS) {
|
||||
values("0.046");
|
||||
}
|
||||
fall_constraint(CONSTRAINT_LOW_POS) {
|
||||
values("-0.083");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pin(clk){
|
||||
clock : true;
|
||||
direction : input;
|
||||
capacitance : 9.8242;
|
||||
timing(){
|
||||
timing_type :"min_pulse_width";
|
||||
related_pin : clk;
|
||||
rise_constraint(CLK_TRAN) {
|
||||
values("0.0");
|
||||
}
|
||||
fall_constraint(CLK_TRAN) {
|
||||
values("0.0");
|
||||
}
|
||||
}
|
||||
timing(){
|
||||
timing_type :"minimum_period";
|
||||
related_pin : clk;
|
||||
rise_constraint(CLK_TRAN) {
|
||||
values("0.0");
|
||||
}
|
||||
fall_constraint(CLK_TRAN) {
|
||||
values("0.0");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -20,3 +20,14 @@ class tri_gate(design.design):
|
|||
|
||||
self.width = tri_gate.chars["width"]
|
||||
self.height = tri_gate.chars["height"]
|
||||
|
||||
def delay(self, slope, load=0.0):
|
||||
from tech import spice
|
||||
r = spice["min_tx_r"]
|
||||
c_para = spice["min_tx_c_para"]#ff
|
||||
return self.cal_delay_with_rc(r = r, c = c_para+load, slope =slope)
|
||||
|
||||
|
||||
def input_load(self):
|
||||
return 9*spice["min_tx_gate_c"]
|
||||
|
||||
|
|
|
|||
|
|
@ -134,3 +134,8 @@ class tri_gate_array(design.design):
|
|||
layer="text",
|
||||
offset=[self.width / 2.0,
|
||||
self.height / 2.0])
|
||||
|
||||
def delay(self, slope, load=0.0):
|
||||
result = self.tri.delay(slope = slope,
|
||||
load = load)
|
||||
return result
|
||||
|
|
|
|||
|
|
@ -211,3 +211,16 @@ class wordline_driver(design.design):
|
|||
self.WL_positions.append(wl_offset)
|
||||
self.vdd_positions.append(vdd_offset)
|
||||
self.gnd_positions.append(gnd_offset)
|
||||
|
||||
def delay(self, slope, load=0):
|
||||
# decode_out -> net
|
||||
decode_t_net = self.NAND2.delay(slope = slope, load = self.inv.input_load())
|
||||
|
||||
# net -> wl
|
||||
net_t_wl = self.inv.delay(slope = decode_t_net.slope, load = load)
|
||||
|
||||
result = decode_t_net + net_t_wl
|
||||
return result
|
||||
|
||||
def input_load(self):
|
||||
return self.NAND2.input_load()
|
||||
|
|
|
|||
|
|
@ -291,3 +291,11 @@ spice["clk"] = "clk"
|
|||
# estimated feasible period in ns
|
||||
spice["feasible_period"] = 5
|
||||
|
||||
# analytical delay parameter
|
||||
spice["wire_unit_r"] = 0.075 #ohm
|
||||
spice["wire_unit_c"] = 0.64 #ff/um^2
|
||||
spice["min_tx_r"] = 9250.0
|
||||
spice["min_tx_c_para"] = 0.7 #ff
|
||||
spice["min_tx_gate_c"] = 0.2
|
||||
spice["msflop_delay"] = 20.5171565446#ps
|
||||
spice["msflop_slope"] = 13.0801872972#ps
|
||||
|
|
|
|||
|
|
@ -208,3 +208,14 @@ spice["clk"] = "clk"
|
|||
|
||||
# estimated feasible period in ns
|
||||
spice["feasible_period"] = 5
|
||||
|
||||
# analytical delay parameter
|
||||
# these numbers are copied from freepdk
|
||||
# need to measure them in scn cmos
|
||||
spice["wire_unit_r"] = 0.075 #ohm
|
||||
spice["wire_unit_c"] = 0.64 #ff/um^2
|
||||
spice["min_tx_r"] = 9250.0
|
||||
spice["min_tx_c_para"] = 0.7 #ff
|
||||
spice["min_tx_gate_c"] = 0.1
|
||||
spice["msflop_delay"] = 20.5171565446#ps
|
||||
spice["msflop_slope"] = 13.0801872972#ps
|
||||
|
|
|
|||
Loading…
Reference in New Issue