mirror of https://github.com/VLSIDA/OpenRAM.git
Replaced delay measure statement with object implementation.
This commit is contained in:
parent
8eb4812e16
commit
b10ef3fb7e
|
|
@ -9,6 +9,7 @@ from .functional import *
|
|||
from .worst_case import *
|
||||
from .simulation import *
|
||||
from .bitline_delay import *
|
||||
from .measurements import *
|
||||
|
||||
debug.info(1,"Initializing characterizer...")
|
||||
OPTS.spice_exe = ""
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ from .charutils import *
|
|||
import utils
|
||||
from globals import OPTS
|
||||
from .simulation import simulation
|
||||
from .measurements import *
|
||||
|
||||
class delay(simulation):
|
||||
"""Functions to measure the delay and power of an SRAM at a given address and
|
||||
|
|
@ -46,6 +47,16 @@ class delay(simulation):
|
|||
self.delay_meas_names = ["delay_lh", "delay_hl", "slew_lh", "slew_hl"]
|
||||
self.power_meas_names = ["read0_power", "read1_power", "write0_power", "write1_power"]
|
||||
|
||||
def create_measurement_objects(self):
|
||||
self.meas_objs = []
|
||||
trig_delay_name = "clk{0}"
|
||||
targ_name = "{0}{1}_{2}".format(self.dout_name,"{}",self.probe_data) #Empty values are the port and probe data bit
|
||||
self.meas_objs.append(delay_measure("delay_lh{}", trig_delay_name, targ_name, "RISE", "RISE"))
|
||||
self.meas_objs.append(delay_measure("delay_hl{}", trig_delay_name, targ_name, "FALL", "FALL"))
|
||||
|
||||
self.meas_objs.append(slew_measure("slew_lh{}", targ_name, "RISE"))
|
||||
self.meas_objs.append(slew_measure("slew_hl{}", targ_name, "FALL"))
|
||||
|
||||
def create_signal_names(self):
|
||||
self.addr_name = "A"
|
||||
self.din_name = "DIN"
|
||||
|
|
@ -236,14 +247,27 @@ class delay(simulation):
|
|||
debug.error(1, "Measure command {0} not recognized".format(delay_name))
|
||||
return (meas_name,trig_name,targ_name,trig_val,targ_val,trig_dir,targ_dir,trig_td,targ_td)
|
||||
|
||||
def get_measure_variants(self, port, measure_obj):
|
||||
"""Get the measurement values that can either vary from simulation to simulation (vdd, address) or port to port (time delays)"""
|
||||
#Return value is intended to match the delay measure format: trig_td, targ_td, vdd, port
|
||||
#vdd is arguably constant as that is true for a single lib file.
|
||||
if measure_obj.targ_dir_str == "FALL":
|
||||
meas_cycle_delay = self.cycle_times[self.measure_cycles[port]["read0"]]
|
||||
elif measure_obj.targ_dir_str == "RISE":
|
||||
meas_cycle_delay = self.cycle_times[self.measure_cycles[port]["read1"]]
|
||||
else:
|
||||
debug.error("Unrecognised measurement direction={}".format(measure_obj.targ_dir_str),1)
|
||||
|
||||
return (meas_cycle_delay, meas_cycle_delay, self.vdd_voltage, port)
|
||||
|
||||
def write_delay_measures_read_port(self, port):
|
||||
"""
|
||||
Write the measure statements to quantify the delay and power results for a read port.
|
||||
"""
|
||||
# add measure statements for delays/slews
|
||||
for dname in self.delay_meas_names:
|
||||
meas_values = self.get_delay_meas_values(dname, port)
|
||||
self.stim.gen_meas_delay(*meas_values)
|
||||
for measure in self.meas_objs:
|
||||
measure_variant_tuple = self.get_measure_variants(port, measure)
|
||||
measure.write_measure(self.stim, measure_variant_tuple)
|
||||
|
||||
# add measure statements for power
|
||||
for pname in self.power_meas_names:
|
||||
|
|
@ -645,6 +669,7 @@ class delay(simulation):
|
|||
char_sram_data = {}
|
||||
|
||||
self.set_probe(probe_address, probe_data)
|
||||
self.create_measurement_objects()
|
||||
|
||||
self.load=max(loads)
|
||||
self.slew=max(slews)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,92 @@
|
|||
import debug
|
||||
from tech import drc, parameter, spice
|
||||
from abc import ABC, abstractmethod
|
||||
from .stimuli import *
|
||||
|
||||
class spice_measurement(ABC):
|
||||
"""Base class for spice stimulus measurements."""
|
||||
def __init__(self, measure_name):
|
||||
#Names must be unique for correct spice simulation, but not enforced here.
|
||||
self.name = measure_name
|
||||
|
||||
@abstractmethod
|
||||
def get_measure_function(self):
|
||||
return None
|
||||
|
||||
@abstractmethod
|
||||
def get_measure_values(self):
|
||||
return None
|
||||
|
||||
def write_measure(self, stim_obj, input_tuple):
|
||||
measure_func = self.get_measure_function()
|
||||
if measure_func == None:
|
||||
debug.error("Did not set measure function",1)
|
||||
measure_vals = self.get_measure_values(*input_tuple)
|
||||
measure_func(stim_obj, *measure_vals)
|
||||
|
||||
|
||||
class delay_measure(spice_measurement):
|
||||
"""Generates a spice measurement for the delay of 50%-to-50% points of two signals."""
|
||||
|
||||
def __init__(self, measure_name, trig_name, targ_name, trig_dir_str, targ_dir_str):
|
||||
spice_measurement.__init__(self, measure_name)
|
||||
self.set_meas_constants(trig_name, targ_name, trig_dir_str, targ_dir_str)
|
||||
|
||||
def get_measure_function(self):
|
||||
return stimuli.gen_meas_delay
|
||||
|
||||
def set_meas_constants(self, trig_name, targ_name, trig_dir_str, targ_dir_str):
|
||||
"""Set the values needed to generate a Spice measurement statement based on the name of the measurement."""
|
||||
self.trig_dir_str = trig_dir_str
|
||||
self.targ_dir_str = targ_dir_str
|
||||
|
||||
self.trig_val_of_vdd = 0.5
|
||||
self.targ_val_of_vdd = 0.5
|
||||
|
||||
self.trig_name_no_port = trig_name
|
||||
self.targ_name_no_port = targ_name
|
||||
|
||||
#Time delays and ports are variant and needed as inputs when writing the measurement
|
||||
|
||||
def get_measure_values(self, trig_td, targ_td, vdd_voltage, port=None):
|
||||
"""Constructs inputs to stimulus measurement function. Variant values are inputs here."""
|
||||
trig_val = self.trig_val_of_vdd * vdd_voltage
|
||||
targ_val = self.targ_val_of_vdd * vdd_voltage
|
||||
|
||||
if port != None:
|
||||
meas_name = self.name.format(port)
|
||||
trig_name = self.trig_name_no_port.format(port)
|
||||
targ_name = self.targ_name_no_port.format(port)
|
||||
else:
|
||||
meas_name = self.name
|
||||
trig_name = self.trig_name_no_port
|
||||
targ_name = self.targ_name_no_port
|
||||
|
||||
return (meas_name,trig_name,targ_name,trig_val,targ_val,self.trig_dir_str,self.targ_dir_str,trig_td,targ_td)
|
||||
|
||||
|
||||
class slew_measure(delay_measure):
|
||||
|
||||
def __init__(self, measure_name, signal_name, slew_dir_str):
|
||||
spice_measurement.__init__(self, measure_name)
|
||||
self.set_meas_constants(signal_name, slew_dir_str)
|
||||
|
||||
def set_meas_constants(self, signal_name, slew_dir_str):
|
||||
"""Set the values needed to generate a Spice measurement statement based on the name of the measurement."""
|
||||
self.trig_dir_str = slew_dir_str
|
||||
self.targ_dir_str = slew_dir_str
|
||||
|
||||
if slew_dir_str == "RISE":
|
||||
self.trig_val_of_vdd = 0.1
|
||||
self.targ_val_of_vdd = 0.9
|
||||
elif slew_dir_str == "FALL":
|
||||
self.trig_val_of_vdd = 0.9
|
||||
self.targ_val_of_vdd = 0.1
|
||||
else:
|
||||
debug.error("Unrecognised slew measurement direction={}".format(slew_dir_str),1)
|
||||
|
||||
self.trig_name_no_port = signal_name
|
||||
self.targ_name_no_port = signal_name
|
||||
|
||||
#Time delays and ports are variant and needed as inputs when writing the measurement
|
||||
|
||||
Loading…
Reference in New Issue