mirror of https://github.com/VLSIDA/OpenRAM.git
Adding functional test to characterizer and unit tests in both single and multiport
This commit is contained in:
parent
fc5f163828
commit
938ded3dd6
|
|
@ -5,6 +5,7 @@ from globals import OPTS,find_exe,get_tool
|
||||||
from .lib import *
|
from .lib import *
|
||||||
from .delay import *
|
from .delay import *
|
||||||
from .setup_hold import *
|
from .setup_hold import *
|
||||||
|
from .functional import *
|
||||||
|
|
||||||
|
|
||||||
debug.info(1,"Initializing characterizer...")
|
debug.info(1,"Initializing characterizer...")
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,320 @@
|
||||||
|
import sys,re,shutil
|
||||||
|
import debug
|
||||||
|
import math
|
||||||
|
import tech
|
||||||
|
import random
|
||||||
|
from .stimuli import *
|
||||||
|
from .trim_spice import *
|
||||||
|
from .charutils import *
|
||||||
|
import utils
|
||||||
|
from globals import OPTS
|
||||||
|
|
||||||
|
|
||||||
|
class functional():
|
||||||
|
"""
|
||||||
|
Functions to write random data values to a random address then read them back and check
|
||||||
|
for successful SRAM operation.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, sram, spfile, corner):
|
||||||
|
self.sram = sram
|
||||||
|
self.name = sram.name
|
||||||
|
self.word_size = self.sram.word_size
|
||||||
|
self.addr_size = self.sram.addr_size
|
||||||
|
self.num_cols = self.sram.num_cols
|
||||||
|
self.num_rows = self.sram.num_rows
|
||||||
|
self.num_banks = self.sram.num_banks
|
||||||
|
self.sp_file = spfile
|
||||||
|
|
||||||
|
self.total_write = OPTS.num_rw_ports + OPTS.num_w_ports
|
||||||
|
self.total_read = OPTS.num_rw_ports + OPTS.num_r_ports
|
||||||
|
self.total_ports = OPTS.num_rw_ports + OPTS.num_w_ports + OPTS.num_r_ports
|
||||||
|
|
||||||
|
# These are the member variables for a simulation
|
||||||
|
self.set_corner(corner)
|
||||||
|
self.set_spice_constants()
|
||||||
|
self.set_stimulus_variables()
|
||||||
|
|
||||||
|
# Number of checks can be changed
|
||||||
|
self.num_checks = 1
|
||||||
|
|
||||||
|
def set_corner(self,corner):
|
||||||
|
""" Set the corner values """
|
||||||
|
self.corner = corner
|
||||||
|
(self.process, self.vdd_voltage, self.temperature) = corner
|
||||||
|
|
||||||
|
def set_spice_constants(self):
|
||||||
|
""" sets feasible timing parameters """
|
||||||
|
self.period = tech.spice["feasible_period"]
|
||||||
|
self.slew = tech.spice["rise_time"]*2
|
||||||
|
self.load = tech.spice["msflop_in_cap"]*4
|
||||||
|
self.gnd_voltage = 0
|
||||||
|
|
||||||
|
def set_stimulus_variables(self):
|
||||||
|
""" Variables relevant to functional test """
|
||||||
|
self.cycles = 0
|
||||||
|
self.written_words = []
|
||||||
|
|
||||||
|
# control signals: only one cs_b for entire multiported sram, one we_b for each write port
|
||||||
|
self.cs_b = []
|
||||||
|
self.we_b = [[] for port in range(self.total_write)]
|
||||||
|
|
||||||
|
# "end of period" signal used to keep track of when read output should be analyzed
|
||||||
|
self.eo_period = []
|
||||||
|
|
||||||
|
# Three dimensional list to handle each addr and data bits for wach port over the number of checks
|
||||||
|
self.addresses = [[[] for bit in range(self.addr_size)] for port in range(self.total_write)]
|
||||||
|
self.data = [[[] for bit in range(self.word_size)] for port in range(self.total_write)]
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
""" Main function to generate random writes/reads, run spice, and analyze results """
|
||||||
|
# Need a NOOP to enable the chip
|
||||||
|
# Old code. Is this still necessary?
|
||||||
|
self.first_run()
|
||||||
|
|
||||||
|
# Generate write and read signals for spice stimulus
|
||||||
|
for i in range(self.num_checks):
|
||||||
|
addr = self.gen_addr()
|
||||||
|
word = self.gen_data()
|
||||||
|
self.write(addr,word)
|
||||||
|
self.read(addr,word)
|
||||||
|
|
||||||
|
self.write_functional_stimulus()
|
||||||
|
self.stim.run_sim()
|
||||||
|
|
||||||
|
# Extrat DOUT values from spice timing.lis
|
||||||
|
read_value = parse_spice_list("timing", "vdout0[0]")
|
||||||
|
print("READ VALUE = {}".format(read_value))
|
||||||
|
|
||||||
|
def first_run(self):
|
||||||
|
""" First cycle as noop to enable chip """
|
||||||
|
self.cycles = self.cycles + 1
|
||||||
|
|
||||||
|
self.cs_b.append(1)
|
||||||
|
for port in range(self.total_write):
|
||||||
|
self.we_b[port].append(1)
|
||||||
|
|
||||||
|
for port in range(self.total_write):
|
||||||
|
for bit in range(self.addr_size):
|
||||||
|
self.addresses[port][bit].append(0)
|
||||||
|
|
||||||
|
for port in range(self.total_write):
|
||||||
|
for bit in range(self.word_size):
|
||||||
|
self.data[port][bit].append(0)
|
||||||
|
|
||||||
|
def write(self,addr,word,write_port=0):
|
||||||
|
""" Generates signals for a write cycle """
|
||||||
|
print("Writing {0} to {1}...".format(word,addr))
|
||||||
|
self.written_words.append(word)
|
||||||
|
self.cycles = self.cycles + 1
|
||||||
|
|
||||||
|
# Write control signals
|
||||||
|
self.cs_b.append(0)
|
||||||
|
self.we_b[write_port].append(0)
|
||||||
|
for port in range(self.total_write):
|
||||||
|
if port == write_port:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
self.we_b[port].append(1)
|
||||||
|
|
||||||
|
# Write address
|
||||||
|
for port in range(self.total_write):
|
||||||
|
for bit in range(self.addr_size):
|
||||||
|
current_address_bit = int(addr[bit])
|
||||||
|
self.addresses[port][bit].append(current_address_bit)
|
||||||
|
|
||||||
|
# Write data
|
||||||
|
for port in range(self.total_write):
|
||||||
|
for bit in range(self.word_size):
|
||||||
|
current_word_bit = int(word[bit])
|
||||||
|
self.data[port][bit].append(current_word_bit)
|
||||||
|
|
||||||
|
def read(self,addr,word):
|
||||||
|
""" Generates signals for a read cycle """
|
||||||
|
print("Reading {0} from {1}...".format(word,addr))
|
||||||
|
self.cycles = self.cycles + 2
|
||||||
|
|
||||||
|
# Read control signals
|
||||||
|
self.cs_b.append(0)
|
||||||
|
for port in range(self.total_write):
|
||||||
|
self.we_b[port].append(1)
|
||||||
|
|
||||||
|
# Read address
|
||||||
|
for port in range(self.total_write):
|
||||||
|
for bit in range(self.addr_size):
|
||||||
|
current_address_bit = int(addr[bit])
|
||||||
|
self.addresses[port][bit].append(current_address_bit)
|
||||||
|
|
||||||
|
# Data input doesn't matter during read cycle, so arbitrarily set to 0 for simulation
|
||||||
|
for port in range(self.total_write):
|
||||||
|
for bit in range(self.word_size):
|
||||||
|
self.data[port][bit].append(0)
|
||||||
|
|
||||||
|
|
||||||
|
# Add idle cycle since read may take more than 1 cycle
|
||||||
|
# Idle control signals
|
||||||
|
self.cs_b.append(1)
|
||||||
|
for port in range(self.total_write):
|
||||||
|
self.we_b[port].append(1)
|
||||||
|
|
||||||
|
# Address doesn't matter during idle cycle, but keep the same as read for easier debugging
|
||||||
|
for port in range(self.total_write):
|
||||||
|
for bit in range(self.addr_size):
|
||||||
|
current_address_bit = int(addr[bit])
|
||||||
|
self.addresses[port][bit].append(current_address_bit)
|
||||||
|
|
||||||
|
# Data input doesn't matter during idle cycle, so arbitrarily set to 0 for simulation
|
||||||
|
for port in range(self.total_write):
|
||||||
|
for bit in range(self.word_size):
|
||||||
|
self.data[port][bit].append(0)
|
||||||
|
|
||||||
|
|
||||||
|
# Record the end of the period that the read operation occured in
|
||||||
|
self.eo_period.append(self.cycles * self.period)
|
||||||
|
|
||||||
|
def gen_data(self):
|
||||||
|
""" Generates a random word to write """
|
||||||
|
rand = random.randint(0,(2**self.word_size)-1)
|
||||||
|
data_bits = self.convert_to_bin(rand,False)
|
||||||
|
return data_bits
|
||||||
|
|
||||||
|
def gen_addr(self):
|
||||||
|
""" Generates a random address value to write to """
|
||||||
|
rand = random.randint(0,(2**self.addr_size)-1)
|
||||||
|
addr_bits = self.convert_to_bin(rand,True)
|
||||||
|
return addr_bits
|
||||||
|
|
||||||
|
def get_data(self):
|
||||||
|
""" Gets an available address and corresponding word """
|
||||||
|
# Currently unused but may need later depending on how the functional test develops
|
||||||
|
addr = random.choice(self.stored_words.keys())
|
||||||
|
word = self.stored_words[addr]
|
||||||
|
return (addr,word)
|
||||||
|
|
||||||
|
def convert_to_bin(self,value,is_addr):
|
||||||
|
""" Converts addr & word to usable binary values """
|
||||||
|
new_value = str.replace(bin(value),"0b","")
|
||||||
|
if(is_addr):
|
||||||
|
expected_value = self.addr_size
|
||||||
|
else:
|
||||||
|
expected_value = self.word_size
|
||||||
|
for i in range (expected_value - len(new_value)):
|
||||||
|
new_value = "0" + new_value
|
||||||
|
|
||||||
|
print("Binary Conversion: {} to {}".format(value, new_value))
|
||||||
|
return new_value
|
||||||
|
|
||||||
|
def obtain_cycle_times(self,period):
|
||||||
|
""" Generate clock cycle times based on period and number of cycles """
|
||||||
|
t_current = 0
|
||||||
|
self.cycle_times = []
|
||||||
|
for i in range(self.cycles):
|
||||||
|
self.cycle_times.append(t_current)
|
||||||
|
t_current += period
|
||||||
|
|
||||||
|
def create_port_names(self):
|
||||||
|
"""Generates the port names to be used in characterization and sets default simulation target ports"""
|
||||||
|
self.write_ports = []
|
||||||
|
self.read_ports = []
|
||||||
|
self.total_port_num = OPTS.num_rw_ports + OPTS.num_w_ports + OPTS.num_r_ports
|
||||||
|
|
||||||
|
#save a member variable to avoid accessing global. readwrite ports have different control signals.
|
||||||
|
self.readwrite_port_num = OPTS.num_rw_ports
|
||||||
|
|
||||||
|
#Generate the port names. readwrite ports are required to be added first for this to work.
|
||||||
|
for readwrite_port_num in range(OPTS.num_rw_ports):
|
||||||
|
self.read_ports.append(readwrite_port_num)
|
||||||
|
self.write_ports.append(readwrite_port_num)
|
||||||
|
#This placement is intentional. It makes indexing input data easier. See self.data_values
|
||||||
|
for write_port_num in range(OPTS.num_rw_ports, OPTS.num_rw_ports+OPTS.num_w_ports):
|
||||||
|
self.write_ports.append(write_port_num)
|
||||||
|
for read_port_num in range(OPTS.num_rw_ports+OPTS.num_w_ports, OPTS.num_rw_ports+OPTS.num_w_ports+OPTS.num_r_ports):
|
||||||
|
self.read_ports.append(read_port_num)
|
||||||
|
|
||||||
|
self.read_index = []
|
||||||
|
port_number = 0
|
||||||
|
for port in range(OPTS.num_rw_ports):
|
||||||
|
self.read_index.append("{}".format(port_number))
|
||||||
|
port_number += 1
|
||||||
|
for port in range(OPTS.num_w_ports):
|
||||||
|
port_number += 1
|
||||||
|
for port in range(OPTS.num_r_ports):
|
||||||
|
self.read_index.append("{}".format(port_number))
|
||||||
|
port_number += 1
|
||||||
|
|
||||||
|
def write_functional_stimulus(self):
|
||||||
|
#Write Stimulus
|
||||||
|
|
||||||
|
self.obtain_cycle_times(self.period)
|
||||||
|
temp_stim = "{0}/stim.sp".format(OPTS.openram_temp)
|
||||||
|
self.sf = open(temp_stim,"w")
|
||||||
|
self.sf.write("* Functional test stimulus file for {}ns period\n\n".format(self.period))
|
||||||
|
self.stim = stimuli(self.sf,self.corner)
|
||||||
|
|
||||||
|
#Write include statements
|
||||||
|
self.sram_sp_file = "{}sram.sp".format(OPTS.openram_temp)
|
||||||
|
shutil.copy(self.sp_file, self.sram_sp_file)
|
||||||
|
self.stim.write_include(self.sram_sp_file)
|
||||||
|
|
||||||
|
#Write Vdd/Gnd statements
|
||||||
|
self.sf.write("\n* Global Power Supplies\n")
|
||||||
|
self.stim.write_supply()
|
||||||
|
|
||||||
|
self.create_port_names()
|
||||||
|
|
||||||
|
#Instantiate the SRAM
|
||||||
|
self.sf.write("\n* Instantiation of the SRAM\n")
|
||||||
|
self.stim.inst_sram(abits=self.addr_size,
|
||||||
|
dbits=self.word_size,
|
||||||
|
port_info=(self.total_port_num,self.readwrite_port_num,self.read_ports,self.write_ports),
|
||||||
|
sram_name=self.name)
|
||||||
|
|
||||||
|
# Add load capacitance to each of the read ports
|
||||||
|
self.sf.write("\n* SRAM output loads\n")
|
||||||
|
for port in range(self.total_read):
|
||||||
|
for bit in range(self.word_size):
|
||||||
|
self.sf.write("CD{0}{1} DOUT{0}[{1}] 0 {2}f\n".format(port, bit, self.load))
|
||||||
|
|
||||||
|
# Generate data input bits
|
||||||
|
self.sf.write("\n* Generation of data and address signals\n")
|
||||||
|
for port in range(self.total_write):
|
||||||
|
for bit in range(self.word_size):
|
||||||
|
sig_name = "DIN{0}[{1}]".format(port,bit)
|
||||||
|
self.stim.gen_pwl(sig_name, self.cycle_times, self.data[port][bit], self.period, self.slew, 0.05)
|
||||||
|
|
||||||
|
# Generate address bits
|
||||||
|
for port in range(self.total_write):
|
||||||
|
for bit in range(self.addr_size):
|
||||||
|
sig_name = "A{0}[{1}]".format(port,bit)
|
||||||
|
self.stim.gen_pwl(sig_name, self.cycle_times, self.addresses[port][bit], self.period, self.slew, 0.05)
|
||||||
|
|
||||||
|
# Generate control signals
|
||||||
|
self.sf.write("\n * Generation of control signals\n")
|
||||||
|
self.stim.gen_pwl("CSB0", self.cycle_times , self.cs_b, self.period, self.slew, 0.05)
|
||||||
|
for port in range(self.total_write):
|
||||||
|
self.stim.gen_pwl("WEB{}".format(port), self.cycle_times , self.we_b[port], self.period, self.slew, 0.05)
|
||||||
|
|
||||||
|
# Generate CLK
|
||||||
|
self.stim.gen_pulse(sig_name="CLK",
|
||||||
|
v1=self.gnd_voltage,
|
||||||
|
v2=self.vdd_voltage,
|
||||||
|
offset=self.period,
|
||||||
|
period=self.period,
|
||||||
|
t_rise=self.slew,
|
||||||
|
t_fall=self.slew)
|
||||||
|
|
||||||
|
# Generate DOUT value measurements
|
||||||
|
self.sf.write("\n * Generation of dout measurements\n")
|
||||||
|
for i in range(self.num_checks):
|
||||||
|
for port in range(self.total_read):
|
||||||
|
for bit in range(self.word_size):
|
||||||
|
self.stim.gen_meas_value(meas_name="VDOUT{0}[{1}]".format(port,bit),
|
||||||
|
dout="DOUT{0}[{1}]".format(port,bit),
|
||||||
|
eo_period=self.eo_period[i],
|
||||||
|
slew=self.slew,
|
||||||
|
setup=0.05)
|
||||||
|
|
||||||
|
self.stim.write_control(self.cycle_times[-1] + self.period)
|
||||||
|
self.sf.close()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -214,6 +214,12 @@ class stimuli():
|
||||||
t_initial,
|
t_initial,
|
||||||
t_final))
|
t_final))
|
||||||
|
|
||||||
|
def gen_meas_value(self, meas_name, dout, eo_period, setup, slew):
|
||||||
|
t0 = eo_period - setup - 2*slew
|
||||||
|
t1 = eo_period - setup - slew
|
||||||
|
measure_string=".meas tran {0} AVG v({1}) FROM={2}n TO={3}n\n\n".format(meas_name, dout, t0, t1)
|
||||||
|
self.sf.write(measure_string)
|
||||||
|
|
||||||
def write_control(self, end_time):
|
def write_control(self, end_time):
|
||||||
""" Write the control cards to run and end the simulation """
|
""" Write the control cards to run and end the simulation """
|
||||||
# UIC is needed for ngspice to converge
|
# UIC is needed for ngspice to converge
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,77 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Run a regression test on various srams
|
||||||
|
"""
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
#@unittest.skip("SKIPPING 22_psram_func_test")
|
||||||
|
class psram_func_test(openram_test):
|
||||||
|
|
||||||
|
def runTest(self):
|
||||||
|
globals.init_openram("config_20_{0}".format(OPTS.tech_name))
|
||||||
|
OPTS.spice_name="hspice"
|
||||||
|
OPTS.analytical_delay = False
|
||||||
|
OPTS.netlist_only = True
|
||||||
|
OPTS.bitcell = "pbitcell"
|
||||||
|
OPTS.replica_bitcell="replica_pbitcell"
|
||||||
|
|
||||||
|
# This is a hack to reload the characterizer __init__ with the spice version
|
||||||
|
from importlib import reload
|
||||||
|
import characterizer
|
||||||
|
reload(characterizer)
|
||||||
|
from characterizer import functional
|
||||||
|
if not OPTS.spice_exe:
|
||||||
|
debug.error("Could not find {} simulator.".format(OPTS.spice_name),-1)
|
||||||
|
|
||||||
|
from sram import sram
|
||||||
|
from sram_config import sram_config
|
||||||
|
c = sram_config(word_size=1,
|
||||||
|
num_words=16,
|
||||||
|
num_banks=1)
|
||||||
|
c.words_per_row=1
|
||||||
|
|
||||||
|
OPTS.num_rw_ports = 1
|
||||||
|
OPTS.num_w_ports = 0
|
||||||
|
OPTS.num_r_ports = 0
|
||||||
|
|
||||||
|
debug.info(1, "Functional test for 1bit, 16word SRAM, with 1 bank. Multiport with {}RW {}W {}R.".format(OPTS.num_rw_ports, OPTS.num_w_ports, OPTS.num_r_ports))
|
||||||
|
s = sram(c, name="sram1")
|
||||||
|
|
||||||
|
tempspice = OPTS.openram_temp + "temp.sp"
|
||||||
|
s.sp_write(tempspice)
|
||||||
|
|
||||||
|
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
|
||||||
|
f = functional(s.s, tempspice, corner)
|
||||||
|
f.run()
|
||||||
|
|
||||||
|
"""
|
||||||
|
OPTS.num_rw_ports = 1
|
||||||
|
OPTS.num_w_ports = 1
|
||||||
|
OPTS.num_r_ports = 1
|
||||||
|
|
||||||
|
debug.info(1, "Functional test for 1bit, 16word SRAM, with 1 bank. Multiport with {}RW {}W {}R.".format(OPTS.num_rw_ports, OPTS.num_w_ports, OPTS.num_r_ports))
|
||||||
|
s = sram(c, name="sram1")
|
||||||
|
|
||||||
|
tempspice = OPTS.openram_temp + "temp.sp"
|
||||||
|
s.sp_write(tempspice)
|
||||||
|
|
||||||
|
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
|
||||||
|
f = functional(s.s, tempspice, corner)
|
||||||
|
f.run
|
||||||
|
"""
|
||||||
|
|
||||||
|
#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()
|
||||||
|
|
@ -11,50 +11,39 @@ import globals
|
||||||
from globals import OPTS
|
from globals import OPTS
|
||||||
import debug
|
import debug
|
||||||
|
|
||||||
@unittest.skip("SKIPPING 22_sram_func_test")
|
#@unittest.skip("SKIPPING 22_sram_func_test")
|
||||||
class sram_func_test(openram_test):
|
class sram_func_test(openram_test):
|
||||||
|
|
||||||
def runTest(self):
|
def runTest(self):
|
||||||
globals.init_openram("config_20_{0}".format(OPTS.tech_name))
|
globals.init_openram("config_20_{0}".format(OPTS.tech_name))
|
||||||
|
OPTS.spice_name="hspice"
|
||||||
OPTS.analytical_delay = False
|
OPTS.analytical_delay = False
|
||||||
|
|
||||||
# This is a hack to reload the characterizer __init__ with the spice version
|
# This is a hack to reload the characterizer __init__ with the spice version
|
||||||
from importlib import reload
|
from importlib import reload
|
||||||
import characterizer
|
import characterizer
|
||||||
reload(characterizer)
|
reload(characterizer)
|
||||||
from characterizer import delay
|
from characterizer import functional
|
||||||
if not OPTS.spice_exe:
|
if not OPTS.spice_exe:
|
||||||
debug.error("Could not find {} simulator.".format(OPTS.spice_name),-1)
|
debug.error("Could not find {} simulator.".format(OPTS.spice_name),-1)
|
||||||
|
|
||||||
import sram
|
from sram import sram
|
||||||
|
from sram_config import sram_config
|
||||||
debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank")
|
c = sram_config(word_size=1,
|
||||||
s = sram.sram(word_size=1,
|
|
||||||
num_words=16,
|
num_words=16,
|
||||||
num_banks=1,
|
num_banks=1)
|
||||||
name="sram_func_test")
|
c.words_per_row=1
|
||||||
|
debug.info(1, "Functional test for 1bit, 16word SRAM, with 1 bank")
|
||||||
|
s = sram(c, name="sram1")
|
||||||
|
|
||||||
tempspice = OPTS.openram_temp + "temp.sp"
|
tempspice = OPTS.openram_temp + "temp.sp"
|
||||||
s.sp_write(tempspice)
|
s.sp_write(tempspice)
|
||||||
|
|
||||||
probe_address = "1" * s.addr_size
|
|
||||||
probe_data = s.word_size - 1
|
|
||||||
debug.info(1, "Probe address {0} probe data {1}".format(probe_address, probe_data))
|
|
||||||
|
|
||||||
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
|
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
|
||||||
d = delay(s,tempspice,corner)
|
f = functional(s.s, tempspice, corner)
|
||||||
d.set_probe(probe_address,probe_data)
|
f.run()
|
||||||
|
|
||||||
# This will exit if it doesn't find a feasible period
|
#globals.end_openram()
|
||||||
import tech
|
|
||||||
d.load = tech.spice["msflop_in_cap"]*4
|
|
||||||
d.slew = tech.spice["rise_time"]*2
|
|
||||||
feasible_period = d.find_feasible_period()
|
|
||||||
|
|
||||||
os.remove(tempspice)
|
|
||||||
|
|
||||||
reload(characterizer)
|
|
||||||
globals.end_openram()
|
|
||||||
|
|
||||||
# instantiate a copdsay of the class to actually run the test
|
# instantiate a copdsay of the class to actually run the test
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue