mirror of https://github.com/VLSIDA/OpenRAM.git
Add spice pruning for speed-up. Fix spice search bugs. Add time in stages to openram output.
This commit is contained in:
parent
e818cdc992
commit
29c5ab48f0
|
|
@ -17,7 +17,7 @@ class bitcell(design.design):
|
|||
|
||||
def __init__(self):
|
||||
design.design.__init__(self, "cell_6t")
|
||||
debug.info(2, "Create bitcell object")
|
||||
debug.info(2, "Create bitcell")
|
||||
|
||||
self.width = bitcell.width
|
||||
self.height = bitcell.height
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ class delay():
|
|||
self.word_size = sram.word_size
|
||||
self.addr_size = sram.addr_size
|
||||
self.sram_sp_file = spfile
|
||||
|
||||
|
||||
self.vdd = tech.spice["supply_voltage"]
|
||||
self.gnd = tech.spice["gnd_voltage"]
|
||||
|
||||
|
|
@ -326,6 +326,7 @@ class delay():
|
|||
self.probe_address = probe_address
|
||||
self.probe_data = probe_data
|
||||
|
||||
|
||||
def analyze(self,probe_address, probe_data, slews, loads):
|
||||
"""main function to calculate the min period for a low_to_high
|
||||
transistion and a high_to_low transistion returns a dictionary
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import delay
|
|||
import charutils as ch
|
||||
import tech
|
||||
import numpy as np
|
||||
from trim_spice import trim_spice
|
||||
|
||||
OPTS = globals.get_opts()
|
||||
|
||||
|
|
@ -18,13 +19,25 @@ class lib:
|
|||
|
||||
def __init__(self, libname, sram, spfile, use_model=OPTS.analytical_delay):
|
||||
self.sram = sram
|
||||
self.spfile = spfile
|
||||
self.sp_file = spfile
|
||||
self.use_model = use_model
|
||||
self.name = sram.name
|
||||
self.num_words = sram.num_words
|
||||
self.word_size = sram.word_size
|
||||
self.addr_size = sram.addr_size
|
||||
|
||||
# Set up to trim the netlist here if that is enabled
|
||||
if OPTS.trim_netlist:
|
||||
self.sim_sp_file = "{}reduced.sp".format(OPTS.openram_temp)
|
||||
self.trimsp=trim_spice(self.sp_file, self.sim_sp_file)
|
||||
self.trimsp.set_configuration(self.sram.num_banks,
|
||||
self.sram.num_rows,
|
||||
self.sram.num_cols,
|
||||
self.sram.word_size)
|
||||
else:
|
||||
# Else, use the non-reduced netlist file for simulation
|
||||
self.sim_sp_file = self.sp_file
|
||||
|
||||
# These are the parameters to determine the table sizes
|
||||
#self.load_scales = np.array([0.1, 0.25, 0.5, 1, 2, 4, 8])
|
||||
self.load_scales = np.array([0.25, 1, 8])
|
||||
|
|
@ -378,12 +391,15 @@ class lib:
|
|||
try:
|
||||
self.d
|
||||
except AttributeError:
|
||||
self.d = delay.delay(self.sram, self.spfile)
|
||||
self.d = delay.delay(self.sram, self.sim_sp_file)
|
||||
if self.use_model:
|
||||
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
|
||||
# We must trim based on a specific address and data bit
|
||||
if OPTS.trim_netlist:
|
||||
self.trimsp.trim(probe_address,probe_data)
|
||||
self.delay = self.d.analyze(probe_address, probe_data, self.slews, self.loads)
|
||||
|
||||
def compute_setup_hold(self):
|
||||
|
|
|
|||
|
|
@ -0,0 +1,117 @@
|
|||
import debug
|
||||
from math import log
|
||||
|
||||
class trim_spice():
|
||||
"""
|
||||
A utility to trim redundant parts of an SRAM spice netlist.
|
||||
Input is an SRAM spice file. Output is an equivalent netlist
|
||||
that works for a single address and range of data bits.
|
||||
"""
|
||||
|
||||
def __init__(self, spfile, reduced_spfile):
|
||||
self.sp_file = spfile
|
||||
self.reduced_spfile = reduced_spfile
|
||||
|
||||
debug.info(1,"Trimming non-critical cells to speed-up characterization: {}.".format(reduced_spfile))
|
||||
|
||||
# Load the file into a buffer for performance
|
||||
sp = open(self.sp_file, "r")
|
||||
self.spice = sp.readlines()
|
||||
for i in range(len(self.spice)):
|
||||
self.spice[i] = self.spice[i].rstrip(" \n")
|
||||
|
||||
|
||||
self.sp_buffer = self.spice
|
||||
|
||||
def set_configuration(self, banks, rows, columns, word_size):
|
||||
""" Set the configuration of SRAM sizes that we are simulating.
|
||||
Need the: number of banks, number of rows in each bank, number of
|
||||
columns in each bank, and data word size."""
|
||||
self.num_banks = banks
|
||||
self.num_rows = rows
|
||||
self.num_columns = columns
|
||||
self.word_size = word_size
|
||||
|
||||
self.words_per_row = self.num_columns / self.word_size
|
||||
self.row_addr_size = int(log(self.num_rows, 2))
|
||||
self.col_addr_size = int(log(self.words_per_row, 2))
|
||||
self.bank_addr_size = self.col_addr_size + self.row_addr_size
|
||||
self.addr_size = self.bank_addr_size + int(log(self.num_banks, 2))
|
||||
|
||||
|
||||
def trim(self, address, data_bit):
|
||||
""" Reduce the spice netlist but KEEP the given bits at the
|
||||
address (and things that will add capacitive load!)"""
|
||||
|
||||
# Always start fresh if we do multiple reductions
|
||||
self.sp_buffer = self.spice
|
||||
|
||||
# Find the row and column indices for the removals
|
||||
# Convert address froms tring to int
|
||||
address = int(address,2)
|
||||
array_row = address >> self.col_addr_size
|
||||
# Which word in the array (0 if only one word)
|
||||
if self.col_addr_size>0:
|
||||
lower_mask = int(self.col_addr_size-1)
|
||||
lower_address = address & lower_mask
|
||||
else:
|
||||
lower_address=0
|
||||
# Which bit in the array
|
||||
array_bit = lower_address*self.word_size + data_bit
|
||||
|
||||
# 1. Keep cells in the bitcell array based on WL and BL
|
||||
wl_name = "wl[{}]".format(array_row)
|
||||
bl_name = "bl[{}]".format(array_bit)
|
||||
self.remove_insts("bitcell_array",[wl_name,bl_name])
|
||||
|
||||
# 2. Keep sense amps basd on BL
|
||||
self.remove_insts("sense_amp_array",[bl_name])
|
||||
|
||||
# 3. Keep column muxes basd on BL
|
||||
self.remove_insts("column_mux_array",[bl_name])
|
||||
|
||||
# 4. Keep write driver based on DATA
|
||||
data_name = "data[{}]".format(data_bit)
|
||||
self.remove_insts("write_driver_array",[data_name])
|
||||
|
||||
# 5. Keep wordline driver based on WL
|
||||
# Need to keep the gater too
|
||||
#self.remove_insts("wordline_driver",wl_name)
|
||||
|
||||
# 6. Keep precharges based on BL
|
||||
self.remove_insts("precharge_array",[bl_name])
|
||||
|
||||
# Everything else isn't worth removing. :)
|
||||
|
||||
# Finally, write out the buffer as the new reduced file
|
||||
sp = open(self.reduced_spfile, "w")
|
||||
sp.write("\n".join(self.sp_buffer))
|
||||
|
||||
|
||||
def remove_insts(self, subckt_name, keep_inst_list):
|
||||
"""This will remove all of the instances in the list from the named
|
||||
subckt that DO NOT contain a term in the list. It just does a
|
||||
match of the line with a term so you can search for a single
|
||||
net connection, the instance name, anything..
|
||||
"""
|
||||
start_name = ".SUBCKT {}".format(subckt_name)
|
||||
end_name = ".ENDS {}".format(subckt_name)
|
||||
|
||||
in_subckt=False
|
||||
new_buffer=[]
|
||||
for line in self.sp_buffer:
|
||||
if start_name in line:
|
||||
new_buffer.append(line)
|
||||
in_subckt=True
|
||||
elif end_name in line:
|
||||
new_buffer.append(line)
|
||||
in_subckt=False
|
||||
elif in_subckt:
|
||||
for k in keep_inst_list:
|
||||
if k in line:
|
||||
new_buffer.append(line)
|
||||
break
|
||||
else:
|
||||
new_buffer.append(line)
|
||||
|
||||
self.sp_buffer = new_buffer
|
||||
|
|
@ -34,6 +34,9 @@ def info(lev, str):
|
|||
if (OPTS.debug_level >= lev):
|
||||
frm = inspect.stack()[1]
|
||||
mod = inspect.getmodule(frm[0])
|
||||
print("[{0}]: {1}".format(frm[0].f_code.co_name,str))
|
||||
# This sometimes gets a NoneType mod...
|
||||
# print "[" , mod.__name__ , "]: ", str
|
||||
#classname = frm.f_globals['__name__']
|
||||
if mod.__name__ == None:
|
||||
class_name=""
|
||||
else:
|
||||
class_name=mod.__name__
|
||||
print("[{0}/{1}]: {2}".format(class_name,frm[0].f_code.co_name,str))
|
||||
|
|
|
|||
|
|
@ -54,8 +54,8 @@ def parse_args():
|
|||
help="Technology name"),
|
||||
optparse.make_option("-s", "--spiceversion", dest="spice_version",
|
||||
help="Spice simulator name"),
|
||||
optparse.make_option("-r", "--reduce_netlist", action="store_true", dest="remove_noncritical",
|
||||
help="Remove noncritical memory cells during characterization"),
|
||||
optparse.make_option("-r", "--remove_netlist_trimming", action="store_false", dest="trim_netlist",
|
||||
help="Disable removal of noncritical memory cells during characterization"),
|
||||
optparse.make_option("-a", "--analytical", action="store_true", dest="analytical_delay",
|
||||
help="Use analytical models to calculate delays (default)"),
|
||||
optparse.make_option("-c", "--characterize", action="store_false", dest="analytical_delay",
|
||||
|
|
@ -163,7 +163,7 @@ def set_calibre():
|
|||
# everything.
|
||||
if not OPTS.check_lvsdrc:
|
||||
# over-ride the check LVS/DRC option
|
||||
debug.info(0,"Over-riding LVS/DRC. Not performing inline LVS/DRC.")
|
||||
debug.info(0,"Over-riding LVS/DRC. Not performing LVS/DRC.")
|
||||
else:
|
||||
# see if calibre is in the path (extend to other tools later)
|
||||
for path in os.environ["PATH"].split(os.pathsep):
|
||||
|
|
@ -175,7 +175,7 @@ def set_calibre():
|
|||
break
|
||||
else:
|
||||
# otherwise, give warning and procede
|
||||
debug.warning("Calibre not found. Not performing inline LVS/DRC.")
|
||||
debug.warning("Calibre not found. Not performing LVS/DRC.")
|
||||
OPTS.check_lvsdrc = False
|
||||
|
||||
def end_openram():
|
||||
|
|
@ -234,13 +234,12 @@ def setup_paths():
|
|||
|
||||
|
||||
|
||||
def find_spice(spice_exe):
|
||||
def find_spice(check_exe):
|
||||
# Check if the preferred spice option exists in the path
|
||||
for path in os.environ["PATH"].split(os.pathsep):
|
||||
spice_exe = os.path.join(path, OPTS.spice_version)
|
||||
spice_exe = os.path.join(path, check_exe)
|
||||
# if it is found, then break and use first version
|
||||
if is_exe(spice_exe):
|
||||
debug.info(1, "Using spice: " + spice_exe)
|
||||
OPTS.spice_exe = spice_exe
|
||||
return True
|
||||
return False
|
||||
|
|
@ -253,21 +252,18 @@ def set_spice():
|
|||
debug.info(1,"Using analytical delay models (no characterization)")
|
||||
return
|
||||
else:
|
||||
debug.info(1,"Performing simulation-based characterization (may be slow!)")
|
||||
|
||||
OPTS.spice_exe = ""
|
||||
|
||||
spice_preferences = ["xa", "hspice", "ngspice", "ngspice.exe"]
|
||||
|
||||
if OPTS.spice_version != "":
|
||||
if not find_spice(OPTS.spice_version):
|
||||
debug.error("{0} not found. Unable to perform characterization.".format(OPTS.spice_version),1)
|
||||
else:
|
||||
for spice_exe in spice_preferences:
|
||||
if find_spice(spice_exe):
|
||||
break
|
||||
else:
|
||||
debug.warning("Unable to find spice {0}, trying another.".format(spice_exe))
|
||||
spice_preferences = ["xa", "hspice", "ngspice", "ngspice.exe"]
|
||||
if OPTS.spice_version != "":
|
||||
if not find_spice(OPTS.spice_version):
|
||||
debug.error("{0} not found. Unable to perform characterization.".format(OPTS.spice_version),1)
|
||||
else:
|
||||
for spice_name in spice_preferences:
|
||||
if find_spice(spice_name):
|
||||
OPTS.spice_version=spice_name
|
||||
debug.info(1, "Using spice: " + OPTS.spice_exe)
|
||||
break
|
||||
else:
|
||||
debug.info(1, "Could not find {}, trying next spice simulator. ".format(spice_name))
|
||||
|
||||
# set the input dir for spice files if using ngspice
|
||||
if OPTS.spice_version == "ngspice":
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ class nand_2(design.design):
|
|||
|
||||
self.add_pins()
|
||||
self.create_layout()
|
||||
self.DRC_LVS()
|
||||
#self.DRC_LVS()
|
||||
|
||||
def add_pins(self):
|
||||
""" Add pins """
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ class nor_2(design.design):
|
|||
|
||||
self.add_pins()
|
||||
self.create_layout()
|
||||
self.DRC_LVS()
|
||||
#self.DRC_LVS()
|
||||
|
||||
def add_pins(self):
|
||||
self.add_pin_list(["A", "B", "Z", "vdd", "gnd"])
|
||||
|
|
|
|||
|
|
@ -26,6 +26,14 @@ global OPTS
|
|||
|
||||
(OPTS, args) = globals.parse_args()
|
||||
|
||||
def print_time(name, now_time, last_time=None):
|
||||
if last_time:
|
||||
time = round((now_time-last_time).total_seconds(),1)
|
||||
else:
|
||||
time = now_time
|
||||
print("** {0}: {1} seconds".format(name,time))
|
||||
return now_time
|
||||
|
||||
# These depend on arguments, so don't load them until now.
|
||||
import debug
|
||||
|
||||
|
|
@ -59,7 +67,7 @@ if (OPTS.output_name == ""):
|
|||
num_banks,
|
||||
OPTS.tech_name)
|
||||
|
||||
debug.info(1, "Output files are " + OPTS.output_name + ".(sp|gds|v|lib|lef)")
|
||||
print("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))
|
||||
|
|
@ -68,20 +76,25 @@ print("Word size: {0}\nWords: {1}\nBanks: {2}".format(word_size,num_words,num_ba
|
|||
if OPTS.analytical_delay:
|
||||
print("Using analytical delay models (no characterization)")
|
||||
else:
|
||||
print("Performing simulation-based characterization (may be slow!)")
|
||||
print("Performing simulation-based characterization with {}".format(OPTS.spice_version))
|
||||
|
||||
if OPTS.trim_netlist:
|
||||
print("Trimming netlist to speed up characterization (sacrificing some accuracy).")
|
||||
|
||||
# only start importing modules after we have the config file
|
||||
import calibre
|
||||
import sram
|
||||
|
||||
print("Start: {0}".format(datetime.datetime.now()))
|
||||
start_time = datetime.datetime.now()
|
||||
last_time = start_time
|
||||
print_time("Start",datetime.datetime.now())
|
||||
|
||||
# import SRAM test generation
|
||||
s = sram.sram(word_size=word_size,
|
||||
num_words=num_words,
|
||||
num_banks=num_banks,
|
||||
name=OPTS.output_name)
|
||||
|
||||
last_time=print_time("SRAM creation", datetime.datetime.now(), last_time)
|
||||
# Measure design area
|
||||
# Not working?
|
||||
#cell_size = s.gds.measureSize(s.name)
|
||||
|
|
@ -92,36 +105,40 @@ s = sram.sram(word_size=word_size,
|
|||
spname = OPTS.output_path + s.name + ".sp"
|
||||
print("SP: Writing to {0}".format(spname))
|
||||
s.sp_write(spname)
|
||||
last_time=print_time("Spice writing", datetime.datetime.now(), last_time)
|
||||
|
||||
gdsname = OPTS.output_path + s.name + ".gds"
|
||||
print("GDS: Writing to {0}".format(gdsname))
|
||||
s.gds_write(gdsname)
|
||||
|
||||
# Run Characterizer on the design
|
||||
# Output the extracted design
|
||||
sram_file = spname
|
||||
if OPTS.use_pex:
|
||||
sram_file = OPTS.output_path + "temp_pex.sp"
|
||||
calibre.run_pex(s.name, gdsname, spname, output=sram_file)
|
||||
|
||||
|
||||
# geenrate verilog
|
||||
import verilog
|
||||
vname = OPTS.output_path + s.name + ".v"
|
||||
print("Verilog: Writing to {0}".format(vname))
|
||||
verilog.verilog(vname,s)
|
||||
|
||||
# generate LEF
|
||||
import lef
|
||||
lefname = OPTS.output_path + s.name + ".lef"
|
||||
print("LEF: Writing to {0}".format(lefname))
|
||||
lef.lef(gdsname,lefname,s)
|
||||
|
||||
# generate lib
|
||||
# Characterize the design
|
||||
import lib
|
||||
libname = OPTS.output_path + s.name + ".lib"
|
||||
print("LIB: Writing to {0}".format(libname))
|
||||
lib.lib(libname,s,sram_file)
|
||||
last_time=print_time("Characterization", datetime.datetime.now(), last_time)
|
||||
|
||||
# Write the layout
|
||||
gdsname = OPTS.output_path + s.name + ".gds"
|
||||
print("GDS: Writing to {0}".format(gdsname))
|
||||
s.gds_write(gdsname)
|
||||
last_time=print_time("GDS", datetime.datetime.now(), last_time)
|
||||
|
||||
# Create a LEF physical model
|
||||
import lef
|
||||
lefname = OPTS.output_path + s.name + ".lef"
|
||||
print("LEF: Writing to {0}".format(lefname))
|
||||
lef.lef(gdsname,lefname,s)
|
||||
last_time=print_time("LEF writing", datetime.datetime.now(), last_time)
|
||||
|
||||
# Write a verilog model
|
||||
import verilog
|
||||
vname = OPTS.output_path + s.name + ".v"
|
||||
print("Verilog: Writing to {0}".format(vname))
|
||||
verilog.verilog(vname,s)
|
||||
last_time=print_time("Verilog writing", datetime.datetime.now(), last_time)
|
||||
|
||||
globals.end_openram()
|
||||
|
||||
print("End: {0}".format(datetime.datetime.now()))
|
||||
print_time("End",datetime.datetime.now(), start_time)
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ class options(optparse.Values):
|
|||
debug_level = 0
|
||||
# This determines whether LVS and DRC is checked for each submodule.
|
||||
check_lvsdrc = True
|
||||
# Variable to select the variant of spice (hspice or ngspice right now)
|
||||
spice_version = "hspice"
|
||||
# Variable to select the variant of spice
|
||||
spice_version = ""
|
||||
# Should we print out the banner at startup
|
||||
print_banner = True
|
||||
# The Calibre executable being used which is derived from the user PATH.
|
||||
|
|
@ -29,7 +29,7 @@ class options(optparse.Values):
|
|||
# Run with extracted parasitics
|
||||
use_pex = False
|
||||
# Remove noncritical memory cells for characterization speed-up
|
||||
remove_noncritical = False
|
||||
trim_netlist = True
|
||||
# Define the output file paths
|
||||
output_path = ""
|
||||
# Define the output file base name
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ class pinv(design.design):
|
|||
|
||||
self.add_pins()
|
||||
self.create_layout()
|
||||
self.DRC_LVS()
|
||||
#self.DRC_LVS()
|
||||
|
||||
def add_pins(self):
|
||||
"""Adds pins for spice netlist processing"""
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ class sense_amp(design.design):
|
|||
|
||||
def __init__(self, name):
|
||||
design.design.__init__(self, name)
|
||||
debug.info(2, "Create Sense Amp object")
|
||||
debug.info(2, "Create sense_amp")
|
||||
|
||||
self.width = sense_amp.width
|
||||
self.height = sense_amp.height
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import math
|
||||
import sys
|
||||
from tech import drc, spice
|
||||
import debug
|
||||
|
|
@ -11,6 +10,7 @@ import getpass
|
|||
from vector import vector
|
||||
from globals import OPTS
|
||||
|
||||
|
||||
class sram(design.design):
|
||||
"""
|
||||
Dynamically generated SRAM by connecting banks to control logic. The
|
||||
|
|
@ -88,7 +88,7 @@ class sram(design.design):
|
|||
|
||||
# Compute the area of the bitcells and estimate a square bank (excluding auxiliary circuitry)
|
||||
self.bank_area = self.bitcell.width*self.bitcell.height*self.num_bits_per_bank
|
||||
self.bank_side_length = math.sqrt(self.bank_area)
|
||||
self.bank_side_length = sqrt(self.bank_area)
|
||||
|
||||
# Estimate the words per row given the height of the bitcell and the square side length
|
||||
self.tentative_num_cols = int(self.bank_side_length/self.bitcell.width)
|
||||
|
|
@ -106,7 +106,7 @@ class sram(design.design):
|
|||
self.row_addr_size = int(log(self.num_rows, 2))
|
||||
self.col_addr_size = int(log(self.words_per_row, 2))
|
||||
self.bank_addr_size = self.col_addr_size + self.row_addr_size
|
||||
self.addr_size = self.bank_addr_size + int(math.log(self.num_banks, 2))
|
||||
self.addr_size = self.bank_addr_size + int(log(self.num_banks, 2))
|
||||
|
||||
|
||||
def estimate_words_per_row(self,tentative_num_cols, word_size):
|
||||
|
|
|
|||
|
|
@ -0,0 +1,62 @@
|
|||
#!/usr/bin/env python2.7
|
||||
"""
|
||||
Check the .lib file for an SRAM with pruning
|
||||
"""
|
||||
|
||||
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):
|
||||
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
|
||||
import lib
|
||||
|
||||
debug.info(1, "Testing timing for sample 2 bit, 16 words SRAM with 1 bank")
|
||||
s = sram.sram(word_size=2,
|
||||
num_words=OPTS.config.num_words,
|
||||
num_banks=OPTS.config.num_banks,
|
||||
name="sram_2_16_1_{0}".format(OPTS.tech_name))
|
||||
OPTS.check_lvsdrc = True
|
||||
|
||||
tempspice = OPTS.openram_temp + "temp.sp"
|
||||
s.sp_write(tempspice)
|
||||
|
||||
filename = s.name + ".lib"
|
||||
libname = OPTS.openram_temp + filename
|
||||
lib.lib(libname=libname,sram=s,spfile=tempspice,use_model=False)
|
||||
|
||||
# let's diff the result with a golden model
|
||||
golden = "{0}/golden/{1}".format(os.path.dirname(os.path.realpath(__file__)),filename)
|
||||
# From an experiment, a 15% difference between between pruned and not was found.
|
||||
self.assertEqual(isapproxdiff(libname,golden,0.15),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()
|
||||
del sys.argv[1:]
|
||||
header(__file__, OPTS.tech_name)
|
||||
unittest.main()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -18,6 +18,7 @@ class lib_test(unittest.TestCase):
|
|||
|
||||
def runTest(self):
|
||||
OPTS.analytical_delay = False
|
||||
OPTS.trim_netlist = False
|
||||
globals.init_openram("config_20_{0}".format(OPTS.tech_name))
|
||||
# we will manually run lvs/drc
|
||||
OPTS.check_lvsdrc = False
|
||||
|
|
@ -46,6 +47,7 @@ class lib_test(unittest.TestCase):
|
|||
|
||||
os.system("rm {0}".format(libname))
|
||||
OPTS.analytical_delay = True
|
||||
OPTS.trim_netlist = True
|
||||
globals.end_openram()
|
||||
|
||||
# instantiate a copdsay of the class to actually run the test
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ class tri_gate(design.design):
|
|||
name = "tri{0}".format(tri_gate.unique_id)
|
||||
tri_gate.unique_id += 1
|
||||
design.design.__init__(self, name)
|
||||
debug.info(2, "Create tri_gate object")
|
||||
debug.info(2, "Create tri_gate")
|
||||
|
||||
self.width = tri_gate.width
|
||||
self.height = tri_gate.height
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ class write_driver(design.design):
|
|||
|
||||
def __init__(self, name):
|
||||
design.design.__init__(self, name)
|
||||
debug.info(2, "Create write_driver object")
|
||||
debug.info(2, "Create write_driver")
|
||||
|
||||
self.width = write_driver.width
|
||||
self.height = write_driver.height
|
||||
|
|
|
|||
Loading…
Reference in New Issue