Change default delay modeling to analytical. Add command-line option characterization by simulation (-c).

This commit is contained in:
Matt Guthaus 2017-11-09 11:13:44 -08:00
parent 03c274c319
commit 95f1a24f72
29 changed files with 111 additions and 417 deletions

323
README
View File

@ -1,323 +0,0 @@
###############################################################################
BASIC SETUP
- Please look at the OpenRAM ICCAD paper and presentation in the repository:
https://github.com/mguthaus/OpenRAM/blob/master/OpenRAM_ICCAD_2016_paper.pdf
https://github.com/mguthaus/OpenRAM/blob/master/OpenRAM_ICCAD_2016_presentation.pdf
-The OpenRAM compiler has very few dependencies:
1) ngspice-26 or later or HSpice I-2013.12-1 or later
2) Python 2.7 and higher (currently excludes Python 3 and up)
3) a setup script for each technology
4) a technology directory for each technology with the base cells
- You must set two environment variables: OPENRAM_HOME should point to
the compiler source directory. OPENERAM_TECH should point to a root
technology directory that contains subdirs of all other technologies.
For example, in bash, add to your .bashrc:
export OPENRAM_HOME="$HOME/OpenRAM/compiler"
export OPENRAM_TECH="$HOME/OpenRAM/technology"
For example, in csh/tcsh, add to your .cshrc/.tcshrc:
setenv OPENRAM_HOME "$HOME/OpenRAM/compiler"
setenv OPENRAM_TECH "$HOME/OpenRAM/technology"
- If you are using FreePDK, you should also have that set up and have the
environment variable point to the PDK.
For example, in bash, add to your .bashrc:
export FREEPDK45="/bsoe/software/design-kits/FreePDK45"
For example, in csh/tcsh, add to your .tcshrc:
setenv FREEPDK45 "/bsoe/software/design-kits/FreePDK45"
We do not distribute the PDK, but you may get it from:
https://www.eda.ncsu.edu/wiki/FreePDK45:Contents
###############################################################################
DIRECTORY STRUCTURE
compiler - openram compiler itself (pointed to by OPENRAM_HOME)
compiler/characterizer - timing characterization code
compiler/gdsMill - GDSII reader/writer
compiler/router - detailed router
compiler/tests - unit tests
technology - openram technology directory (pointed to by OPENRAM_TECH)
technology/freepdk45 - example configuration library for freepdk45 technology node
technology/scn3me_subm - example configuration library SCMOS technology node
technology/setup_scripts - setup scripts to customize your PDKs and OpenRAM technologies
###############################################################################
UNIT TESTS
Regression testing performs a number of tests for all modules in OpenRAM.
Use the command:
python regress.py
To run a specific test:
python {unit test}.py
The unit tests take the same arguments as openram.py itself.
To increase the verbosity of the test, add one (or more) -v options:
python tests/00_code_format_check_test.py -v -t freepdk45
To specify a particular technology use "-t <techname>" such as
"-t scn3me_subm". The default for a unit test is freepdk45 whereas
the default for openram.py is specified in the configuration file.
A regression daemon script that can be used with cron is included:
regress_daemon.py
regress_daemon.sh
This updates a git repository, checks out code, and sends an email
report with status information.
###############################################################################
CREATING CUSTOM TECHNOLOGIES
-All setup scripts should be in the setup_scripts directory under the
$OPENRAM_TECH directory. Please look at the following file for an
example of what is needed for OpenRAM:
$OPENRAM_TECH/setup_scripts/setup_openram_freepdk45.py
Each setup script should be named as: setup_openram_{tech name}.py.
-Each specific technology (e.g., freepdk45) should be a subdirectory
(e.g., $OPENRAM_TECH/freepdk45) and include certain folders and files:
1) gds_lib folder with all the .gds (premade) library cells. At a
minimum this includes:
ms_flop.gds
sense_amp.gds
write_driver.gds
cell_6t.gds
replica_cell_6t.gds
tri_gate.gds
2) sp_lib folder with all the .sp (premade) library netlists for the above cells.
3) layers.map
4) A valid tech Python module (tech directory with __init__.py and tech.py) with:
References in tech.py to spice models
DRC/LVS rules needed for dynamic cells and routing
Layer information
etc.
###############################################################################
DEBUGGING
When OpenRAM runs, it puts files in a temporary directory that is
shown in the banner at the top. Like:
/tmp/openram_mrg_18128_temp/
This is where simulations and DRC/LVS get run so there is no network
traffic. The directory name is unique for each person and run of
OpenRAM to not clobber any files and allow simultaneous runs. If it
passes, the files are deleted. If it fails, you will see these files:
* _calibreDRC.rul_ is the DRC rule file.
* dc_runset is the command file for caliber.
* temp.gds is the layout
* test1.drc.err is the std err output of the command
* test1.drc.out is the standard output of the command
* test1.drc.db is the DRC results file
If DRC/LVS fails, the first thing is to check if it ran in the .out and
.err file. This shows the standard output and error output from
running DRC/LVS. If there is a setup problem it will be shown here.
If DRC/LVS runs, but doesn't pass, you then should look at the .db
file. If the DRC fails, it will typically show you the command that was used
to run caliber. It is something like this:
calibre -gui -drc /tmp/openram_mrg_28781_temp/drc_runset -batch 2>
/tmp/openram_mrg_28781_temp/test1.drc.err 1>
/tmp/openram_mrg_28781_temp/test1.drc.out
To debug, you will need a layout viewer. I prefer to use glade on my
Mac, but you can also use Calibre, Magic, etc.
1) Calibre
Start the Calibre DESIGNrev viewer in the temp directory and load your GDS file:
calibredrv temp.gds
Select Verification->Start RVE and select the results database file in
the new form (e.g., test1.drc.db). This will start the RVE (results
viewer). Scroll through the check pane and find the DRC check with an
error. Select it and it will open some numbers to the right. Double
click on any of the errors in the result browser. These will be
labelled as numbers "1 2 3 4" for example will be 4 DRC errors.
In the viewer ">" opens the layout down a level.
2) Glade
You can view errors in Glade as well. I like this because it is on my laptop.
You can get it from:
http://www.peardrop.co.uk/glade/
To remote display over X windows, you need to disable OpenGL acceleration or use vnc
or something. You can disable by adding this to your .bashrc in bash:
export GLADE_USE_OPENGL=no
or in .cshrc/.tcshrc in csh/tcsh:
setenv GLADE_USE_OPENGAL no
To use this with the FreePDK45 or SCMOS layer views you should use the
tech files. Then create a .glade.py file in your user directory with
these commands to load the technology layers:
ui().importCds("default",
"/Users/mrg/techfiles/freepdk45/display.drf",
"/Users/mrg/techfiles/freepdk45/FreePDK45.tf", 1000, 1,
"/Users/mrg/techfiles/freepdk45/layers.map")
Obviously, edit the paths to point to your directory. To switch
between processes, you have to change the importCds command (or you
can manually run the command each time you start glade).
To load the errors, you simply do:
Verify->Import Caliber Errors
select the .db file from calibre.
It is possible to use other viewers as well, such as:
LayoutEditor http://www.layouteditor.net/
Magic http://opencircuitdesign.com/magic/
###############################################################################
CONTRIBUTING TO OPENRAM
How to get the code and add contributions to OpenRAM.
0) One time, create a GitHub account.
1) Create a fork of the OpenRAM project on the github web page:
https://github.com/mguthaus/OpenRAM
It is on the upper right and says "Fork": This will make your own
OpenRAM repository on GitHub in your account.
2) Clone your repository (or use an existing cloned copy if you've
already done this once):
git clone https://github.com/<youruser>/OpenRAM.git
cd OpenRAM
3) Set up a new upstream that points to MY OpenRAM repository that you
forked (only first time):
git remote add upstream https://github.com/mguthaus/OpenRAM.git
You now have two remotes for this project:
origin which points to your GitHub fork of the project. You can read
and write to this remote.
upstream which points to the main project's GitHub repository. You can
only read from this remote.
You can remove remotes with
git remote remove upstream
if you previously added the one with the git@github that required
authentication.
4) Make your own branch. The number one rule is to put each piece of
work on its own branch:
git checkout -b useful-branch-name
Note that this is shorthand for:
git branch useful-branch-name
git checkout useful-branch-name
"master" is the name of the branch that is the release version of the
code (in your fork of the repository). You can check out the released
code with "git checkout master" or go back to your ranch with
"gitcheckout useful-branch-name".
5) Edit your code and make commits like normal:
git add <new files>
<edit files>
git commit -m "Useful comment" <files changed>
OR (sparingly, to commit all changes):
git status
<check that all the changed files are correct and should be commited>
git commit -a -m "Useful comment"
Run the unit tests entirely. Fix all bugs.
6) After you are done (or while you are editing and you see changes in
MY master branch) make sure you have the most recent from MY master
and merge any changes. Pull the updated copy from MY master branch in
MY repository:
git pull upstream master
This is important because we may have had other updates that conflict
with your changes and you must resolve them with current state of
master (the released, working code). You may have to merge changes if
they overlap your changes, so do this often to avoid the problem. You
now need to push this to the master of YOUR forked repository as well:
git push origin master
if you are on your master branch. Otherwise, just git push.
7) Push your branch to YOUR repository:
git push -u origin useful-branch-name
Remember origin is your copy on github and useful-branch-name is the
branch that you made to contain all your changes.
The -u flag links this branch with the remote one, so that in the
future, you can simply type git push origin.
8) When you are done, go to GitHub and you will see a button to notify
me. Press the button and it will notify me of your pushed branch.
This will have you fill in a form for the contribution that gets sent
to me.
9) I will review the request and may have you fix stuff if the tests
don't pass, you didn't merge all my changes in master from other
contributions, or your style of code is bad.
10) Go back to step 3 for your next contribution. Remember, you can
push/pull work to your repository all the time and can pull from my
master as well. Make sure to add large features so that You don't have
to add lots of pull requests.
###############################################################################
Example to output/input .gds layout files from/to Cadence
1) To create your component layouts, you should stream them to
individual gds files using our provided layermap and flatten
cells. For example,
strmout -layerMap layers.map -library sram -topCell $i -view layout -flattenVias -flattenPcells -strmFile ../gds_lib/$i.gds
2) To stream a layout back into Cadence, do this:
strmin -layerMap layers.map -attachTechFileOfLib NCSU_TechLib_FreePDK45 -library sram_4_32 -strmFile sram_4_32.gds
When you import a gds file, make sure to attach the correct tech lib
or you will get incorrect layers in the resulting library.

View File

@ -1243,21 +1243,21 @@ class bank(design.design):
offset=in_pin + self.m2m3_via_offset,
rotate=90)
def delay(self, slew, load):
def analytical_delay(self, slew, load):
""" return analytical delay of the bank"""
msf_addr_delay = self.msf_address.delay(slew, self.decoder.input_load())
msf_addr_delay = self.msf_address.analytical_delay(slew, self.decoder.input_load())
decoder_delay = self.decoder.delay(msf_addr_delay.slew, self.wordline_driver.input_load())
decoder_delay = self.decoder.analytical_delay(msf_addr_delay.slew, self.wordline_driver.input_load())
word_driver_delay = self.wordline_driver.delay(decoder_delay.slew, self.bitcell_array.input_load())
word_driver_delay = self.wordline_driver.analytical_delay(decoder_delay.slew, self.bitcell_array.input_load())
bitcell_array_delay = self.bitcell_array.delay(word_driver_delay.slew)
bitcell_array_delay = self.bitcell_array.analytical_delay(word_driver_delay.slew)
bl_t_data_out_delay = self.sense_amp_array.delay(bitcell_array_delay.slew,
self.bitcell_array.output_load())
bl_t_data_out_delay = self.sense_amp_array.analytical_delay(bitcell_array_delay.slew,
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.slew, load)
data_t_DATA_delay = self.tri_gate_array.analytical_delay(bl_t_data_out_delay.slew, load)
result = msf_addr_delay + decoder_delay + word_driver_delay \
+ bitcell_array_delay + bl_t_data_out_delay + data_t_DATA_delay

View File

@ -23,7 +23,7 @@ class bitcell(design.design):
self.height = bitcell.height
self.pin_map = bitcell.pin_map
def delay(self, slew, load=0, swing = 0.5):
def analytical_delay(self, slew, load=0, swing = 0.5):
# delay of bit cell is not like a driver(from WL)
# so the slew used should be 0
# it should not be slew dependent?

View File

@ -160,7 +160,7 @@ class bitcell_array(design.design):
# increments to the next row height
offset.y += self.cell.height
def delay(self, slew, load=0):
def analytical_delay(self, slew, load=0):
from tech import drc
wl_wire = self.gen_wl_wire()
wl_wire.return_delay_over_wire(slew)
@ -171,7 +171,7 @@ class bitcell_array(design.design):
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.slew, cell_load, swing = bl_swing)
cell_delay = self.cell.analytical_delay(wl_to_cell_delay.slew, cell_load, swing = bl_swing)
#we do not consider the delay over the wire for now
return self.return_delay(cell_delay.delay+wl_to_cell_delay.delay,

View File

@ -424,3 +424,31 @@ class delay():
t_current += period
def analytical_model(self,sram, slews, loads):
""" Just return the analytical model results for the SRAM.
"""
LH_delay = []
HL_delay = []
LH_slew = []
HL_slew = []
for slew in slews:
for load in loads:
bank_delay = sram.analytical_delay(slew,load)
# Convert from ps to ns
LH_delay.append(bank_delay.delay/1e3)
HL_delay.append(bank_delay.delay/1e3)
LH_slew.append(bank_delay.slew/1e3)
HL_slew.append(bank_delay.slew/1e3)
data = {"min_period": 0,
"delay1": LH_delay,
"delay0": HL_delay,
"slew1": LH_slew,
"slew0": HL_slew,
"read0_power": 0,
"read1_power": 0,
"write0_power": 0,
"write1_power": 0
}
return data

View File

@ -379,12 +379,11 @@ class lib:
self.d
except AttributeError:
self.d = delay.delay(self.sram, self.spfile)
probe_address = "1" * self.addr_size
probe_data = self.word_size - 1
if self.use_model:
self.d = True
self.delay = self.sram.analytical_model(self.slews,self.loads)
self.delay = self.d.analytical_model(self.sram,self.slews,self.loads)
else:
probe_address = "1" * self.addr_size
probe_data = self.word_size - 1
self.delay = self.d.analyze(probe_address, probe_data, self.slews, self.loads)
def compute_setup_hold(self):

View File

@ -54,11 +54,12 @@ def parse_args():
help="Technology name"),
optparse.make_option("-s", "--spiceversion", dest="spice_version",
help="Spice simulator name"),
# TODO: Why is this -f?
optparse.make_option("-f", "--trim_noncritical", action="store_true", dest="trim_noncritical",
help="Trim noncritical memory cells during simulation"),
optparse.make_option("-r", "--reduce_netlist", action="store_true", dest="remove_noncritical",
help="Remove noncritical memory cells during characterization"),
optparse.make_option("-a", "--analytical", action="store_true", dest="analytical_delay",
help="Use analytical model to calculate delay")
help="Use analytical models to calculate delays (default)"),
optparse.make_option("-c", "--characterize", action="store_false", dest="analytical_delay",
help="Perform characterization to calculate delays (default is analytical models)")
}
# -h --help is implicit.
@ -238,6 +239,12 @@ def set_spice():
debug.info(2,"Finding spice...")
global OPTS
if OPTS.analytical_delay:
debug.info(1,"Using analytical delay models (no characterization)")
return
else:
debug.info(1,"Performing simulation-based characterization (may be slow!)")
OPTS.spice_exe = ""
# Check if the preferred spice option exists in the path

View File

@ -531,7 +531,7 @@ class hierarchical_decoder(design.design):
offset=offset + vector(self.metal2_spacing,-self.via_shift),
rotate=90)
def delay(self, slew, load = 0.0):
def analytical_delay(self, slew, load = 0.0):
# A -> out
if self.determine_predecodes(self.num_inputs)[1]==0:
pre = self.pre2_4
@ -539,15 +539,15 @@ class hierarchical_decoder(design.design):
else:
pre = self.pre3_8
nand = self.nand3
a_t_out_delay = pre.delay(slew=slew,load = nand.input_load())
a_t_out_delay = pre.analytical_delay(slew=slew,load = nand.input_load())
# out -> z
out_t_z_delay = nand.delay(slew= a_t_out_delay.slew,
out_t_z_delay = nand.analytical_delay(slew= a_t_out_delay.slew,
load = self.inv.input_load())
result = a_t_out_delay + out_t_z_delay
# Z -> decode_out
z_t_decodeout_delay = self.inv.delay(slew = out_t_z_delay.slew , load = load)
z_t_decodeout_delay = self.inv.analytical_delay(slew = out_t_z_delay.slew , load = load)
result = result + z_t_decodeout_delay
return result

View File

@ -43,18 +43,17 @@ class hierarchical_predecode2x4(hierarchical_predecode):
return combination
def delay(self, slew, load = 0.0 ):
def analytical_delay(self, slew, load = 0.0 ):
# in -> inbar
a_t_b_delay = self.inv.delay(slew=slew,load = self.nand.input_load())
a_t_b_delay = self.inv.analytical_delay(slew=slew, load=self.nand.input_load())
# inbar -> z
b_t_z_delay = self.nand.delay(slew=a_t_b_delay.slew,load = self.inv.input_load())
result = a_t_b_delay + b_t_z_delay
b_t_z_delay = self.nand.analytical_delay(slew=a_t_b_delay.slew, load=self.inv.input_load())
# Z -> out
a_t_out_delay = self.inv.delay(slew=b_t_z_delay.slew,load = load)
result = result + a_t_out_delay
return result
a_t_out_delay = self.inv.analytical_delay(slew=b_t_z_delay.slew, load=load)
return a_t_b_delay + b_t_z_delay + a_t_out_delay
def input_load(self):
return self.nand.input_load()

View File

@ -51,18 +51,18 @@ class hierarchical_predecode3x8(hierarchical_predecode):
return combination
def delay(self, slew, load = 0.0 ):
def analytical_delay(self, slew, load = 0.0 ):
# A -> Abar
a_t_b_delay = self.inv.delay(slew=slew,load = self.nand.input_load())
a_t_b_delay = self.inv.analytical_delay(slew=slew, load=self.nand.input_load())
# Abar -> z
b_t_z_delay = self.nand.delay(slew=a_t_b_delay.slew,load = self.inv.input_load())
result = a_t_b_delay + b_t_z_delay
b_t_z_delay = self.nand.analytical_delay(slew=a_t_b_delay.slew, load=self.inv.input_load())
# Z -> out
a_t_out_delay = self.inv.delay(slew=b_t_z_delay.slew,load = load)
result = result + a_t_out_delay
return result
a_t_out_delay = self.inv.analytical_delay(slew=b_t_z_delay.slew, load=load)
return a_t_b_delay + b_t_z_delay + a_t_out_delay
def input_load(self):

View File

@ -148,7 +148,7 @@ class spice:
del usedMODS
spfile.close()
def delay(self, slew, load=0.0):
def analytical_delay(self, slew, 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__))

View File

@ -21,8 +21,9 @@ class ms_flop(design.design):
self.height = ms_flop.height
self.pin_map = ms_flop.pin_map
def delay(self, slew, load = 0.0):
def analytical_delay(self, slew, load = 0.0):
# dont know how to calculate this now, use constant in tech file
from tech import spice
result = self.return_delay(spice["msflop_delay"], spice["msflop_slew"])
return result

View File

@ -132,7 +132,5 @@ class ms_flop_array(design.design):
height=drc["minwidth_metal1"])
def delay(self, slew, load=0.0):
result = self.ms.delay(slew = slew,
load = load)
return result
def analytical_delay(self, slew, load=0.0):
return self.ms.analytical_delay(slew=slew, load=load)

View File

@ -419,7 +419,7 @@ class nand_2(design.design):
from tech import spice
return ((self.nmos_size+self.pmos_size)/parameter["min_tx_size"])*spice["min_tx_gate_c"]
def delay(self, slew, load=0.0):
def analytical_delay(self, slew, load=0.0):
r = spice["min_tx_r"]/(self.nmos_size/parameter["min_tx_size"])
c_para = spice["min_tx_drain_c"]*(self.nmos_size/parameter["min_tx_size"])#ff
return self.cal_delay_with_rc(r = r, c = c_para+load, slew = slew)

View File

@ -435,7 +435,7 @@ class nand_3(design.design):
def input_load(self):
return ((self.nmos_size+self.pmos_size)/parameter["min_tx_size"])*spice["min_tx_gate_c"]
def delay(self, slew, load=0.0):
def analytical_delay(self, slew, load=0.0):
r = spice["min_tx_r"]/(self.nmos_size/parameter["min_tx_size"])
c_para = spice["min_tx_drain_c"]*(self.nmos_size/parameter["min_tx_size"])#ff
return self.cal_delay_with_rc(r = r, c = c_para+load, slew = slew)

View File

@ -59,11 +59,17 @@ if (OPTS.output_name == ""):
num_banks,
OPTS.tech_name)
debug.info(1, "Output file is " + OPTS.output_name + ".(sp|gds|v|lib|lef)")
debug.info(1, "Output files are " + OPTS.output_name + ".(sp|gds|v|lib|lef)")
print("Technology: {0}".format(OPTS.tech_name))
print("Word size: {0}\nWords: {1}\nBanks: {2}".format(word_size,num_words,num_banks))
if OPTS.analytical_delay:
print("Using analytical delay models (no characterization)")
else:
print("Performing simulation-based characterization (may be slow!)")
# only start importing modules after we have the config file
import calibre
import sram

View File

@ -30,10 +30,11 @@ class options(optparse.Values):
spice_exe = ""
# Run with extracted parasitics
use_pex = False
# Trim noncritical memory cells for simulation speed-up
trim_noncritical = False
# Remove noncritical memory cells for characterization speed-up
remove_noncritical = False
# Define the output file paths
output_path = ""
# Define the output file base name
output_name = ""
analytical_delay = False
# Use analytical delay models by default rather than (slow) characterization
analytical_delay = True

View File

@ -406,7 +406,7 @@ class pinv(design.design):
def input_load(self):
return ((self.nmos_size+self.pmos_size)/parameter["min_tx_size"])*spice["min_tx_gate_c"]
def delay(self, slew, load=0.0):
def analytical_delay(self, slew, load=0.0):
from tech import spice
r = spice["min_tx_r"]/(self.nmos_size/parameter["min_tx_size"])
c_para = spice["min_tx_drain_c"]*(self.nmos_size/parameter["min_tx_size"])#ff

View File

@ -23,7 +23,7 @@ class sense_amp(design.design):
self.height = sense_amp.height
self.pin_map = sense_amp.pin_map
def delay(self, slew, load=0.0):
def analytical_delay(self, slew, load=0.0):
from tech import spice
r = spice["min_tx_r"]/(10)
c_para = spice["min_tx_drain_c"]

View File

@ -117,6 +117,5 @@ class sense_amp_array(design.design):
width=self.width,
height=drc["minwidth_metal1"])
def delay(self, slew, load=0.0):
result = self.amp.delay(slew=slew, load=load)
return result
def analytical_delay(self, slew, load=0.0):
return self.amp.analytical_delay(slew=slew, load=load)

View File

@ -998,28 +998,6 @@ class sram(design.design):
del usedMODS
sp.close()
def analytical_model(self,slews,loads):
LH_delay = []
HL_delay = []
LH_slew = []
HL_slew = []
for slew in slews:
for load in loads:
bank_delay = self.bank.delay(slew,load)
# Convert from ps to ns
LH_delay.append(bank_delay.delay/1e3)
HL_delay.append(bank_delay.delay/1e3)
LH_slew.append(bank_delay.slew/1e3)
HL_slew.append(bank_delay.slew/1e3)
data = {"min_period": 0,
"delay1": LH_delay,
"delay0": HL_delay,
"slew1": LH_slew,
"slew0": HL_slew,
"read0_power": 0,
"read1_power": 0,
"write0_power": 0,
"write1_power": 0
}
return data
def analytical_delay(self,slew,load):
""" LH and HL are the same in analytical model. """
return self.bank.analytical_delay(slew,load)

View File

@ -24,6 +24,7 @@ class timing_sram_test(unittest.TestCase):
OPTS.check_lvsdrc = False
OPTS.spice_version="hspice"
OPTS.force_spice = True
OPTS.analytical_delay = False
globals.set_spice()
import sram
@ -88,6 +89,7 @@ class timing_sram_test(unittest.TestCase):
OPTS.check_lvsdrc = True
OPTS.spice_version="hspice"
OPTS.force_spice = False
OPTS.analytical_delay = True
globals.set_spice()
os.remove(tempspice)

View File

@ -22,6 +22,7 @@ class timing_sram_test(unittest.TestCase):
OPTS.check_lvsdrc = False
OPTS.spice_version="ngspice"
OPTS.force_spice = True
OPTS.analytical_delay = False
globals.set_spice()
import sram
@ -84,6 +85,7 @@ class timing_sram_test(unittest.TestCase):
OPTS.check_lvsdrc = True
OPTS.spice_version="hspice"
OPTS.force_spice = False
OPTS.analytical_delay = True
globals.set_spice()
os.remove(tempspice)

View File

@ -19,10 +19,10 @@ OPTS = globals.get_opts()
class sram_func_test(unittest.TestCase):
def runTest(self):
OPTS.analytical_delay = False
globals.init_openram("config_20_{0}".format(OPTS.tech_name))
# we will manually run lvs/drc
OPTS.check_lvsdrc = False
import sram
debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank")
@ -32,7 +32,6 @@ class sram_func_test(unittest.TestCase):
name="sram_func_test")
OPTS.check_lvsdrc = True
import delay
tempspice = OPTS.openram_temp + "temp.sp"
@ -52,7 +51,7 @@ class sram_func_test(unittest.TestCase):
feasible_period = d.find_feasible_period(load,slew)
os.remove(tempspice)
OPTS.analytical_delay = True
globals.end_openram()
# instantiate a copdsay of the class to actually run the test

View File

@ -17,6 +17,7 @@ OPTS = globals.get_opts()
class lib_test(unittest.TestCase):
def runTest(self):
OPTS.analytical_delay = False
globals.init_openram("config_20_{0}".format(OPTS.tech_name))
# we will manually run lvs/drc
OPTS.check_lvsdrc = False
@ -44,9 +45,9 @@ class lib_test(unittest.TestCase):
self.assertEqual(isapproxdiff(libname,golden,0.10),True)
os.system("rm {0}".format(libname))
OPTS.analytical_delay = True
globals.end_openram()
# instantiate a copdsay of the class to actually run the test
if __name__ == "__main__":
(OPTS, args) = globals.parse_args()

View File

@ -27,7 +27,7 @@ class tri_gate(design.design):
self.height = tri_gate.height
self.pin_map = tri_gate.pin_map
def delay(self, slew, load=0.0):
def analytical_delay(self, slew, load=0.0):
from tech import spice
r = spice["min_tx_r"]
c_para = spice["min_tx_drain_c"]

View File

@ -109,6 +109,5 @@ class tri_gate_array(design.design):
height=drc["minwidth_metal1"])
def delay(self, slew, load=0.0):
result = self.tri.delay(slew = slew, load = load)
return result
def analytical_delay(self, slew, load=0.0):
return self.tri.analytical_delay(slew = slew, load = load)

View File

@ -9,7 +9,6 @@ class verilog:
self.word_size = sram.word_size
self.addr_size = sram.addr_size
debug.info(1,"Writing to {0}".format(verilog_name))
self.vf = open(verilog_name, "w")
self.create()

View File

@ -191,15 +191,14 @@ class wordline_driver(design.design):
end=wl_offset-vector(drc["minwidth_metal1"],0))
def delay(self, slew, load=0):
def analytical_delay(self, slew, load=0):
# decode -> net
decode_t_net = self.nand2.delay(slew, self.inv.input_load())
decode_t_net = self.nand2.analytical_delay(slew, self.inv.input_load())
# net -> wl
net_t_wl = self.inv.delay(decode_t_net.slew, load)
net_t_wl = self.inv.analytical_delay(decode_t_net.slew, load)
result = decode_t_net + net_t_wl
return result
return decode_t_net + net_t_wl
def input_load(self):
return self.nand2.input_load()