mirror of https://github.com/VLSIDA/OpenRAM.git
Clean up Python comments and improve comments in stimulus file.
This commit is contained in:
parent
3820861ce8
commit
3e4ef36efe
|
|
@ -10,7 +10,7 @@ from globals import OPTS
|
||||||
|
|
||||||
class delay():
|
class delay():
|
||||||
"""
|
"""
|
||||||
Functions to measure the delay of the SRAM at a given address and
|
Functions to measure the delay of an SRAM at a given address and
|
||||||
data bit.
|
data bit.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
@ -52,7 +52,7 @@ class delay():
|
||||||
# creates and opens stimulus file for writing
|
# creates and opens stimulus file for writing
|
||||||
temp_stim = "{0}/stim.sp".format(OPTS.openram_temp)
|
temp_stim = "{0}/stim.sp".format(OPTS.openram_temp)
|
||||||
self.sf = open(temp_stim, "w")
|
self.sf = open(temp_stim, "w")
|
||||||
self.sf.write("* Stimulus for period of {0}n load={1}fF slew={2}ns\n\n".format(period,load,slew))
|
self.sf.write("\n* Stimulus for period of {0}n load={1}fF slew={2}ns\n\n".format(period,load,slew))
|
||||||
|
|
||||||
# include files in stimulus file
|
# include files in stimulus file
|
||||||
model_list = tech.spice["fet_models"] + [self.sram_sp_file]
|
model_list = tech.spice["fet_models"] + [self.sram_sp_file]
|
||||||
|
|
@ -60,26 +60,26 @@ class delay():
|
||||||
|
|
||||||
# add vdd/gnd statements
|
# add vdd/gnd statements
|
||||||
|
|
||||||
self.sf.write("* Global Power Supplies\n")
|
self.sf.write("\n* Global Power Supplies\n")
|
||||||
stimuli.write_supply(self.sf)
|
stimuli.write_supply(self.sf)
|
||||||
|
|
||||||
# instantiate the sram
|
# instantiate the sram
|
||||||
self.sf.write("* Instantiation of the SRAM\n")
|
self.sf.write("\n* Instantiation of the SRAM\n")
|
||||||
stimuli.inst_sram(stim_file=self.sf,
|
stimuli.inst_sram(stim_file=self.sf,
|
||||||
abits=self.addr_size,
|
abits=self.addr_size,
|
||||||
dbits=self.word_size,
|
dbits=self.word_size,
|
||||||
sram_name=self.name)
|
sram_name=self.name)
|
||||||
|
|
||||||
self.sf.write("* SRAM output loads\n")
|
self.sf.write("\n* SRAM output loads\n")
|
||||||
for i in range(self.word_size):
|
for i in range(self.word_size):
|
||||||
self.sf.write("CD{0} d[{0}] 0 {1}f\n".format(i,load))
|
self.sf.write("CD{0} d[{0}] 0 {1}f\n".format(i,load))
|
||||||
|
|
||||||
# add access transistors for data-bus
|
# add access transistors for data-bus
|
||||||
self.sf.write("* Transmission Gates for data-bus and control signals\n")
|
self.sf.write("\n* Transmission Gates for data-bus and control signals\n")
|
||||||
stimuli.inst_accesstx(stim_file=self.sf, dbits=self.word_size)
|
stimuli.inst_accesstx(stim_file=self.sf, dbits=self.word_size)
|
||||||
|
|
||||||
# generate data and addr signals
|
# generate data and addr signals
|
||||||
self.sf.write("* Generation of data and address signals\n")
|
self.sf.write("\n* Generation of data and address signals\n")
|
||||||
for i in range(self.word_size):
|
for i in range(self.word_size):
|
||||||
if i == self.probe_data:
|
if i == self.probe_data:
|
||||||
self.gen_data(clk_times=self.cycle_times,
|
self.gen_data(clk_times=self.cycle_times,
|
||||||
|
|
@ -97,20 +97,20 @@ class delay():
|
||||||
slew=slew)
|
slew=slew)
|
||||||
|
|
||||||
# generate control signals
|
# generate control signals
|
||||||
self.sf.write("* Generation of control signals\n")
|
self.sf.write("\n* Generation of control signals\n")
|
||||||
self.gen_csb(self.cycle_times, period, slew)
|
self.gen_csb(self.cycle_times, period, slew)
|
||||||
self.gen_web(self.cycle_times, period, slew)
|
self.gen_web(self.cycle_times, period, slew)
|
||||||
self.gen_oeb(self.cycle_times, period, slew)
|
self.gen_oeb(self.cycle_times, period, slew)
|
||||||
|
|
||||||
self.sf.write("* Generation of global clock signal\n")
|
self.sf.write("\n* Generation of global clock signal\n")
|
||||||
stimuli.gen_pulse(stim_file=self.sf,
|
stimuli.gen_pulse(stim_file=self.sf,
|
||||||
sig_name="CLK",
|
sig_name="CLK",
|
||||||
v1=self.gnd,
|
v1=self.gnd,
|
||||||
v2=self.vdd,
|
v2=self.vdd,
|
||||||
offset=period,
|
offset=period,
|
||||||
period=period,
|
period=period,
|
||||||
t_rise = slew,
|
t_rise=slew,
|
||||||
t_fall = slew)
|
t_fall=slew)
|
||||||
|
|
||||||
self.write_measures(period)
|
self.write_measures(period)
|
||||||
|
|
||||||
|
|
@ -120,17 +120,23 @@ class delay():
|
||||||
self.sf.close()
|
self.sf.close()
|
||||||
|
|
||||||
def write_measures(self,period):
|
def write_measures(self,period):
|
||||||
# meas statement for delay and power measurements
|
"""
|
||||||
self.sf.write("* Measure statements for delay and power\n")
|
Write the measure statements to quantify the delay and power results.
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.sf.write("\n* Measure statements for delay and power\n")
|
||||||
|
|
||||||
|
# Output some comments to aid where cycles start and
|
||||||
|
# what is happening
|
||||||
for comment in self.cycle_comments:
|
for comment in self.cycle_comments:
|
||||||
self.sf.write("* {}\n".format(comment))
|
self.sf.write("* {}\n".format(comment))
|
||||||
|
|
||||||
|
# Trigger on the clk of the appropriate cycle
|
||||||
trig_name = "clk"
|
trig_name = "clk"
|
||||||
targ_name = "{0}".format("d[{0}]".format(self.probe_data))
|
targ_name = "{0}".format("d[{0}]".format(self.probe_data))
|
||||||
trig_val = targ_val = 0.5 * self.vdd
|
trig_val = targ_val = 0.5 * self.vdd
|
||||||
# add measure statments for delay0
|
|
||||||
# delay the target to measure after the negative edge
|
# Delay the target to measure after the negative edge
|
||||||
stimuli.gen_meas_delay(stim_file=self.sf,
|
stimuli.gen_meas_delay(stim_file=self.sf,
|
||||||
meas_name="DELAY0",
|
meas_name="DELAY0",
|
||||||
trig_name=trig_name,
|
trig_name=trig_name,
|
||||||
|
|
@ -205,11 +211,13 @@ class delay():
|
||||||
t_final=t_final)
|
t_final=t_final)
|
||||||
|
|
||||||
def find_feasible_period(self, load, slew):
|
def find_feasible_period(self, load, slew):
|
||||||
"""Uses an initial period and finds a feasible period before we
|
"""
|
||||||
|
Uses an initial period and finds a feasible period before we
|
||||||
run the binary search algorithm to find min period. We check if
|
run the binary search algorithm to find min period. We check if
|
||||||
the given clock period is valid and if it's not, we continue to
|
the given clock period is valid and if it's not, we continue to
|
||||||
double the period until we find a valid period to use as a
|
double the period until we find a valid period to use as a
|
||||||
starting point. """
|
starting point.
|
||||||
|
"""
|
||||||
|
|
||||||
feasible_period = tech.spice["feasible_period"]
|
feasible_period = tech.spice["feasible_period"]
|
||||||
time_out = 8
|
time_out = 8
|
||||||
|
|
@ -225,13 +233,20 @@ class delay():
|
||||||
feasible_period = 2 * feasible_period
|
feasible_period = 2 * feasible_period
|
||||||
continue
|
continue
|
||||||
|
|
||||||
debug.info(1, "Found feasible_period: {0}ns feasible_delay1/0 {1}ns/{2}ns slew {3}ns/{4}ns".format(feasible_period,feasible_delay1,feasible_delay0,feasible_slew1,feasible_slew0))
|
debug.info(1, "Found feasible_period: {0}ns " +
|
||||||
|
"feasible_delay1/0 {1}ns/{2}ns slew {3}ns/{4}ns".format(feasible_period,
|
||||||
|
feasible_delay1,
|
||||||
|
feasible_delay0,
|
||||||
|
feasible_slew1,
|
||||||
|
feasible_slew0))
|
||||||
return (feasible_period, feasible_delay1, feasible_delay0)
|
return (feasible_period, feasible_delay1, feasible_delay0)
|
||||||
|
|
||||||
|
|
||||||
def run_simulation(self, period, load, slew):
|
def run_simulation(self, period, load, slew):
|
||||||
""" This tries to simulate a period and checks if the result
|
"""
|
||||||
works. If so, it returns True and the delays and slews."""
|
This tries to simulate a period and checks if the result
|
||||||
|
works. If so, it returns True and the delays and slews.
|
||||||
|
"""
|
||||||
|
|
||||||
# Checking from not data_value to data_value
|
# Checking from not data_value to data_value
|
||||||
self.write_stimulus(period, load, slew)
|
self.write_stimulus(period, load, slew)
|
||||||
|
|
@ -243,17 +258,40 @@ class delay():
|
||||||
|
|
||||||
# if it failed or the read was longer than a period
|
# if it failed or the read was longer than a period
|
||||||
if type(delay0)!=float or type(delay1)!=float or type(slew1)!=float or type(slew0)!=float:
|
if type(delay0)!=float or type(delay1)!=float or type(slew1)!=float or type(slew0)!=float:
|
||||||
debug.info(2,"Failed simulation: period {0} load {1} slew {2}, delay0={3}n delay1={4}ns slew0={5}n slew1={6}n".format(period,load,slew,delay0,delay1,slew0,slew1))
|
debug.info(2,"Failed simulation: period {0} load {1} slew {2}, " +
|
||||||
|
"delay0={3}n delay1={4}ns slew0={5}n slew1={6}n".format(period,
|
||||||
|
load,
|
||||||
|
slew,
|
||||||
|
delay0,
|
||||||
|
delay1,
|
||||||
|
slew0,
|
||||||
|
slew1))
|
||||||
return (False,0,0,0,0)
|
return (False,0,0,0,0)
|
||||||
|
# Scale delays to ns (they previously could have not been floats)
|
||||||
delay0 *= 1e9
|
delay0 *= 1e9
|
||||||
delay1 *= 1e9
|
delay1 *= 1e9
|
||||||
slew0 *= 1e9
|
slew0 *= 1e9
|
||||||
slew1 *= 1e9
|
slew1 *= 1e9
|
||||||
if delay0>period or delay1>period or slew0>period or slew1>period:
|
if delay0>period or delay1>period or slew0>period or slew1>period:
|
||||||
debug.info(2,"UNsuccessful simulation: period {0} load {1} slew {2}, delay0={3}n delay1={4}ns slew0={5}n slew1={6}n".format(period,load,slew,delay0,delay1,slew0,slew1))
|
debug.info(2,"UNsuccessful simulation: period {0} load {1} slew {2}, " +
|
||||||
|
"delay0={3}n delay1={4}ns slew0={5}n slew1={6}n".format(period,
|
||||||
|
load,
|
||||||
|
slew,
|
||||||
|
delay0,
|
||||||
|
delay1,
|
||||||
|
slew0,
|
||||||
|
slew1))
|
||||||
return (False,0,0,0,0)
|
return (False,0,0,0,0)
|
||||||
else:
|
else:
|
||||||
debug.info(2,"Successful simulation: period {0} load {1} slew {2}, delay0={3}n delay1={4}ns slew0={5}n slew1={6}n".format(period,load,slew,delay0,delay1,slew0,slew1))
|
debug.info(2,"Successful simulation: period {0} load {1} slew {2}, " +
|
||||||
|
"delay0={3}n delay1={4}ns slew0={5}n slew1={6}n".format(period,
|
||||||
|
load,
|
||||||
|
slew,
|
||||||
|
delay0,
|
||||||
|
delay1,
|
||||||
|
slew0,
|
||||||
|
slew1))
|
||||||
|
# For debug, you sometimes want to inspect each simulation.
|
||||||
#key=raw_input("press return to continue")
|
#key=raw_input("press return to continue")
|
||||||
|
|
||||||
# The delay is from the negative edge for our SRAM
|
# The delay is from the negative edge for our SRAM
|
||||||
|
|
@ -262,8 +300,10 @@ class delay():
|
||||||
|
|
||||||
|
|
||||||
def find_min_period(self,feasible_period, load, slew, feasible_delay1, feasible_delay0):
|
def find_min_period(self,feasible_period, load, slew, feasible_delay1, feasible_delay0):
|
||||||
"""Searches for the smallest period with output delays being within 5% of
|
"""
|
||||||
long period. """
|
Searches for the smallest period with output delays being within 5% of
|
||||||
|
long period.
|
||||||
|
"""
|
||||||
|
|
||||||
previous_period = ub_period = feasible_period
|
previous_period = ub_period = feasible_period
|
||||||
lb_period = 0.0
|
lb_period = 0.0
|
||||||
|
|
@ -291,8 +331,10 @@ class delay():
|
||||||
|
|
||||||
|
|
||||||
def try_period(self, period, load, slew, feasible_delay1, feasible_delay0):
|
def try_period(self, period, load, slew, feasible_delay1, feasible_delay0):
|
||||||
""" This tries to simulate a period and checks if the result
|
"""
|
||||||
works. If it does and the delay is within 5% still, it returns True."""
|
This tries to simulate a period and checks if the result
|
||||||
|
works. If it does and the delay is within 5% still, it returns True.
|
||||||
|
"""
|
||||||
|
|
||||||
# Checking from not data_value to data_value
|
# Checking from not data_value to data_value
|
||||||
self.write_stimulus(period,load,slew)
|
self.write_stimulus(period,load,slew)
|
||||||
|
|
@ -303,14 +345,16 @@ class delay():
|
||||||
slew1 = ch.convert_to_float(ch.parse_output("timing", "slew1"))
|
slew1 = ch.convert_to_float(ch.parse_output("timing", "slew1"))
|
||||||
# if it failed or the read was longer than a period
|
# if it failed or the read was longer than a period
|
||||||
if type(delay0)!=float or type(delay1)!=float or type(slew1)!=float or type(slew0)!=float:
|
if type(delay0)!=float or type(delay1)!=float or type(slew1)!=float or type(slew0)!=float:
|
||||||
debug.info(2,"Invalid measures: Period {0}, delay0={1}ns, delay1={2}ns slew0={3}ns slew1={4}ns".format(period, delay0, delay1, slew0, slew1))
|
debug.info(2,"Invalid measures: Period {0}, " +
|
||||||
|
"delay0={1}ns, delay1={2}ns slew0={3}ns slew1={4}ns".format(period, delay0, delay1, slew0, slew1))
|
||||||
return False
|
return False
|
||||||
delay0 *= 1e9
|
delay0 *= 1e9
|
||||||
delay1 *= 1e9
|
delay1 *= 1e9
|
||||||
slew0 *= 1e9
|
slew0 *= 1e9
|
||||||
slew1 *= 1e9
|
slew1 *= 1e9
|
||||||
if delay0>period or delay1>period or slew0>period or slew1>period:
|
if delay0>period or delay1>period or slew0>period or slew1>period:
|
||||||
debug.info(2,"Too long delay/slew: Period {0}, delay0={1}ns, delay1={2}ns slew0={3}ns slew1={4}ns".format(period, delay0, delay1, slew0, slew1))
|
debug.info(2,"Too long delay/slew: Period {0}, " +
|
||||||
|
"delay0={1}ns, delay1={2}ns slew0={3}ns slew1={4}ns".format(period, delay0, delay1, slew0, slew1))
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
if not ch.relative_compare(delay1,feasible_delay1,error_tolerance=0.05):
|
if not ch.relative_compare(delay1,feasible_delay1,error_tolerance=0.05):
|
||||||
|
|
@ -323,7 +367,8 @@ class delay():
|
||||||
|
|
||||||
#key=raw_input("press return to continue")
|
#key=raw_input("press return to continue")
|
||||||
|
|
||||||
debug.info(2,"Successful period {0}, delay0={1}ns, delay1={2}ns slew0={3}ns slew1={4}ns".format(period, delay0, delay1, slew0, slew1))
|
debug.info(2,"Successful period {0}, " +
|
||||||
|
"delay0={1}ns, delay1={2}ns slew0={3}ns slew1={4}ns".format(period, delay0, delay1, slew0, slew1))
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def set_probe(self,probe_address, probe_data):
|
def set_probe(self,probe_address, probe_data):
|
||||||
|
|
@ -520,7 +565,7 @@ class delay():
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def gen_data(self, clk_times, sig_name, period, slew):
|
def gen_data(self, clk_times, sig_name, period, slew):
|
||||||
"""Generates the PWL data inputs for a simulation timing test."""
|
""" Generates the PWL data inputs for a simulation timing test. """
|
||||||
# values for NOP, W1, W0, W1, R0, NOP, W1, W0, R1, NOP
|
# values for NOP, W1, W0, W1, R0, NOP, W1, W0, R1, NOP
|
||||||
# we are asserting the opposite value on the other side of the tx gate during
|
# we are asserting the opposite value on the other side of the tx gate during
|
||||||
# the read to be "worst case". Otherwise, it can actually assist the read.
|
# the read to be "worst case". Otherwise, it can actually assist the read.
|
||||||
|
|
@ -528,8 +573,9 @@ class delay():
|
||||||
stimuli.gen_pwl(self.sf, sig_name, clk_times, values, period, slew, 0.05)
|
stimuli.gen_pwl(self.sf, sig_name, clk_times, values, period, slew, 0.05)
|
||||||
|
|
||||||
def gen_addr(self, clk_times, addr, period, slew):
|
def gen_addr(self, clk_times, addr, period, slew):
|
||||||
"""Generates the address inputs for a simulation timing test.
|
"""
|
||||||
One cycle is different to clear the bus
|
Generates the address inputs for a simulation timing test.
|
||||||
|
This alternates between all 1's and all 0's for the address.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
zero_values = [0, 0, 0, 1, 0, 0, 0, 1, 0, 0 ]
|
zero_values = [0, 0, 0, 1, 0, 0, 0, 1, 0, 0 ]
|
||||||
|
|
@ -544,14 +590,14 @@ class delay():
|
||||||
|
|
||||||
|
|
||||||
def gen_csb(self, clk_times, period, slew):
|
def gen_csb(self, clk_times, period, slew):
|
||||||
""" Generates the PWL CSb signal"""
|
""" Generates the PWL CSb signal """
|
||||||
# values for NOP, W1, W0, W1, R0, NOP, W1, W0, R1, NOP
|
# values for NOP, W1, W0, W1, R0, NOP, W1, W0, R1, NOP
|
||||||
# Keep CSb asserted in NOP for measuring >1 period
|
# Keep CSb asserted in NOP for measuring >1 period
|
||||||
values = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
values = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||||
stimuli.gen_pwl(self.sf, "csb", clk_times, values, period, slew, 0.05)
|
stimuli.gen_pwl(self.sf, "csb", clk_times, values, period, slew, 0.05)
|
||||||
|
|
||||||
def gen_web(self, clk_times, period, slew):
|
def gen_web(self, clk_times, period, slew):
|
||||||
""" Generates the PWL WEb signal"""
|
""" Generates the PWL WEb signal """
|
||||||
# values for NOP, W1, W0, W1, R0, NOP, W1, W0, R1, NOP
|
# values for NOP, W1, W0, W1, R0, NOP, W1, W0, R1, NOP
|
||||||
# Keep WEb deasserted in NOP for measuring >1 period
|
# Keep WEb deasserted in NOP for measuring >1 period
|
||||||
values = [1, 0, 0, 0, 1, 1, 0, 0, 1, 1]
|
values = [1, 0, 0, 0, 1, 1, 0, 0, 1, 1]
|
||||||
|
|
@ -564,7 +610,7 @@ class delay():
|
||||||
stimuli.gen_pwl(self.sf, "acc_en_inv", clk_times, values, period, slew, 0)
|
stimuli.gen_pwl(self.sf, "acc_en_inv", clk_times, values, period, slew, 0)
|
||||||
|
|
||||||
def gen_oeb(self, clk_times, period, slew):
|
def gen_oeb(self, clk_times, period, slew):
|
||||||
""" Generates the PWL WEb signal"""
|
""" Generates the PWL WEb signal """
|
||||||
# values for NOP, W1, W0, W1, R0, W1, W0, R1, NOP
|
# values for NOP, W1, W0, W1, R0, W1, W0, R1, NOP
|
||||||
# Keep OEb asserted in NOP for measuring >1 period
|
# Keep OEb asserted in NOP for measuring >1 period
|
||||||
values = [1, 1, 1, 1, 0, 0, 1, 1, 0, 0]
|
values = [1, 1, 1, 1, 0, 0, 1, 1, 0, 0]
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
"""
|
"""
|
||||||
This file generates the test structure and stimulus for an sram
|
This file generates simple spice cards for simulation. There are
|
||||||
simulation. There are various functions that can be be used to
|
various functions that can be be used to generate stimulus for other
|
||||||
generate stimulus for other simulations as well.
|
simulations as well.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import tech
|
import tech
|
||||||
|
|
@ -22,7 +22,7 @@ tx_width = tech.spice["minwidth_tx"]
|
||||||
tx_length = tech.spice["channel"]
|
tx_length = tech.spice["channel"]
|
||||||
|
|
||||||
def inst_sram(stim_file, abits, dbits, sram_name):
|
def inst_sram(stim_file, abits, dbits, sram_name):
|
||||||
"""function to instatiate the sram subckt"""
|
""" Function to instatiate an SRAM subckt. """
|
||||||
stim_file.write("Xsram ")
|
stim_file.write("Xsram ")
|
||||||
for i in range(dbits):
|
for i in range(dbits):
|
||||||
stim_file.write("D[{0}] ".format(i))
|
stim_file.write("D[{0}] ".format(i))
|
||||||
|
|
@ -32,11 +32,11 @@ def inst_sram(stim_file, abits, dbits, sram_name):
|
||||||
stim_file.write("{0} ".format(i))
|
stim_file.write("{0} ".format(i))
|
||||||
stim_file.write("{0} ".format(tech.spice["clk"]))
|
stim_file.write("{0} ".format(tech.spice["clk"]))
|
||||||
stim_file.write("{0} {1} ".format(vdd_name, gnd_name))
|
stim_file.write("{0} {1} ".format(vdd_name, gnd_name))
|
||||||
stim_file.write("{0}\n\n".format(sram_name))
|
stim_file.write("{0}\n".format(sram_name))
|
||||||
|
|
||||||
|
|
||||||
def inst_model(stim_file, pins, model_name):
|
def inst_model(stim_file, pins, model_name):
|
||||||
"""function to instantiate a model"""
|
""" Function to instantiate a generic model with a set of pins """
|
||||||
stim_file.write("X{0} ".format(model_name))
|
stim_file.write("X{0} ".format(model_name))
|
||||||
for pin in pins:
|
for pin in pins:
|
||||||
stim_file.write("{0} ".format(pin))
|
stim_file.write("{0} ".format(pin))
|
||||||
|
|
@ -44,7 +44,7 @@ def inst_model(stim_file, pins, model_name):
|
||||||
|
|
||||||
|
|
||||||
def create_inverter(stim_file, size=1, beta=2.5):
|
def create_inverter(stim_file, size=1, beta=2.5):
|
||||||
"""Generates inverter for the top level signals (only for sim purposes)"""
|
""" Generates inverter for the top level signals (only for sim purposes) """
|
||||||
stim_file.write(".SUBCKT test_inv in out {0} {1}\n".format(vdd_name, gnd_name))
|
stim_file.write(".SUBCKT test_inv in out {0} {1}\n".format(vdd_name, gnd_name))
|
||||||
stim_file.write("mpinv out in {0} {0} {1} w={2}u l={3}u\n".format(vdd_name,
|
stim_file.write("mpinv out in {0} {0} {1} w={2}u l={3}u\n".format(vdd_name,
|
||||||
pmos_name,
|
pmos_name,
|
||||||
|
|
@ -58,9 +58,10 @@ def create_inverter(stim_file, size=1, beta=2.5):
|
||||||
|
|
||||||
|
|
||||||
def create_buffer(stim_file, buffer_name, size=[1,3], beta=2.5):
|
def create_buffer(stim_file, buffer_name, size=[1,3], beta=2.5):
|
||||||
"""Generates buffer for top level signals (only for sim
|
"""
|
||||||
purposes). Size is pair for PMOS, NMOS width multiple. It includes
|
Generates buffer for top level signals (only for sim
|
||||||
a beta of 3."""
|
purposes). Size is pair for PMOS, NMOS width multiple.
|
||||||
|
"""
|
||||||
|
|
||||||
stim_file.write(".SUBCKT test_{2} in out {0} {1}\n".format(vdd_name,
|
stim_file.write(".SUBCKT test_{2} in out {0} {1}\n".format(vdd_name,
|
||||||
gnd_name,
|
gnd_name,
|
||||||
|
|
@ -85,7 +86,7 @@ def create_buffer(stim_file, buffer_name, size=[1,3], beta=2.5):
|
||||||
|
|
||||||
|
|
||||||
def inst_buffer(stim_file, buffer_name, signal_list):
|
def inst_buffer(stim_file, buffer_name, signal_list):
|
||||||
"""Adds buffers to each top level signal that is in signal_list (only for sim purposes)"""
|
""" Adds buffers to each top level signal that is in signal_list (only for sim purposes) """
|
||||||
for signal in signal_list:
|
for signal in signal_list:
|
||||||
stim_file.write("X{0}_buffer {0} {0}_buf {1} {2} test_{3}\n".format(signal,
|
stim_file.write("X{0}_buffer {0} {0}_buf {1} {2} test_{3}\n".format(signal,
|
||||||
"test"+vdd_name,
|
"test"+vdd_name,
|
||||||
|
|
@ -94,7 +95,7 @@ def inst_buffer(stim_file, buffer_name, signal_list):
|
||||||
|
|
||||||
|
|
||||||
def inst_inverter(stim_file, signal_list):
|
def inst_inverter(stim_file, signal_list):
|
||||||
"""Adds inv for each signal that needs its inverted version (only for sim purposes)"""
|
""" Adds inv for each signal that needs its inverted version (only for sim purposes) """
|
||||||
for signal in signal_list:
|
for signal in signal_list:
|
||||||
stim_file.write("X{0}_inv {0} {0}_inv {1} {2} test_inv\n".format(signal,
|
stim_file.write("X{0}_inv {0} {0}_inv {1} {2} test_inv\n".format(signal,
|
||||||
"test"+vdd_name,
|
"test"+vdd_name,
|
||||||
|
|
@ -102,7 +103,7 @@ def inst_inverter(stim_file, signal_list):
|
||||||
|
|
||||||
|
|
||||||
def inst_accesstx(stim_file, dbits):
|
def inst_accesstx(stim_file, dbits):
|
||||||
"""Adds transmission gate for inputs to data-bus (only for sim purposes)"""
|
""" Adds transmission gate for inputs to data-bus (only for sim purposes) """
|
||||||
stim_file.write("* Tx Pin-list: Drain Gate Source Body\n")
|
stim_file.write("* Tx Pin-list: Drain Gate Source Body\n")
|
||||||
for i in range(dbits):
|
for i in range(dbits):
|
||||||
pmos_access_string="mp{0} DATA[{0}] acc_en D[{0}] {1} {2} w={3}u l={4}u\n"
|
pmos_access_string="mp{0} DATA[{0}] acc_en D[{0}] {1} {2} w={3}u l={4}u\n"
|
||||||
|
|
@ -119,8 +120,11 @@ def inst_accesstx(stim_file, dbits):
|
||||||
tx_length))
|
tx_length))
|
||||||
|
|
||||||
def gen_pulse(stim_file, sig_name, v1=gnd_voltage, v2=vdd_voltage, offset=0, period=1, t_rise=0, t_fall=0):
|
def gen_pulse(stim_file, sig_name, v1=gnd_voltage, v2=vdd_voltage, offset=0, period=1, t_rise=0, t_fall=0):
|
||||||
"""Generates a periodic signal with 50% duty cycle and slew rates. Period is measured
|
"""
|
||||||
from 50% to 50%."""
|
Generates a periodic signal with 50% duty cycle and slew rates. Period is measured
|
||||||
|
from 50% to 50%.
|
||||||
|
"""
|
||||||
|
stim_file.write("* PULSE: period={0}\n".format(period))
|
||||||
pulse_string="V{0} {0} 0 PULSE ({1} {2} {3}n {4}n {5}n {6}n {7}n)\n"
|
pulse_string="V{0} {0} 0 PULSE ({1} {2} {3}n {4}n {5}n {6}n {7}n)\n"
|
||||||
stim_file.write(pulse_string.format(sig_name,
|
stim_file.write(pulse_string.format(sig_name,
|
||||||
v1,
|
v1,
|
||||||
|
|
@ -133,6 +137,11 @@ def gen_pulse(stim_file, sig_name, v1=gnd_voltage, v2=vdd_voltage, offset=0, per
|
||||||
|
|
||||||
|
|
||||||
def gen_pwl(stim_file, sig_name, clk_times, data_values, period, slew, setup):
|
def gen_pwl(stim_file, sig_name, clk_times, data_values, period, slew, setup):
|
||||||
|
"""
|
||||||
|
Generate a PWL stimulus given a signal name and data values at each period.
|
||||||
|
Automatically creates slews and ensures each data occurs a setup before the clock
|
||||||
|
edge.
|
||||||
|
"""
|
||||||
# the initial value is not a clock time
|
# the initial value is not a clock time
|
||||||
debug.check(len(clk_times)==len(data_values),"Clock and data value lengths don't match.")
|
debug.check(len(clk_times)==len(data_values),"Clock and data value lengths don't match.")
|
||||||
|
|
||||||
|
|
@ -140,6 +149,7 @@ def gen_pwl(stim_file, sig_name, clk_times, data_values, period, slew, setup):
|
||||||
times = np.array(clk_times) - setup*period
|
times = np.array(clk_times) - setup*period
|
||||||
values = np.array(data_values) * vdd_voltage
|
values = np.array(data_values) * vdd_voltage
|
||||||
half_slew = 0.5 * slew
|
half_slew = 0.5 * slew
|
||||||
|
stim_file.write("* (time, data): {}\n".format(zip(clk_times, data_values)))
|
||||||
stim_file.write("V{0} {0} 0 PWL (0n {1}v ".format(sig_name, values[0]))
|
stim_file.write("V{0} {0} 0 PWL (0n {1}v ".format(sig_name, values[0]))
|
||||||
for i in range(1,len(times)-1):
|
for i in range(1,len(times)-1):
|
||||||
stim_file.write("{0}n {1}v {2}n {3}v ".format(times[i]-half_slew,
|
stim_file.write("{0}n {1}v {2}n {3}v ".format(times[i]-half_slew,
|
||||||
|
|
@ -148,13 +158,10 @@ def gen_pwl(stim_file, sig_name, clk_times, data_values, period, slew, setup):
|
||||||
values[i]))
|
values[i]))
|
||||||
stim_file.write(")\n")
|
stim_file.write(")\n")
|
||||||
|
|
||||||
|
|
||||||
def gen_constant(stim_file, sig_name, v_val):
|
def gen_constant(stim_file, sig_name, v_val):
|
||||||
"""Generates a constant signal with reference voltage and the voltage value"""
|
""" Generates a constant signal with reference voltage and the voltage value """
|
||||||
stim_file.write("V{0} {0} 0 DC {1}\n".format(sig_name, v_val))
|
stim_file.write("V{0} {0} 0 DC {1}\n".format(sig_name, v_val))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_inverse_voltage(value):
|
def get_inverse_voltage(value):
|
||||||
if value > 0.5*vdd_voltage:
|
if value > 0.5*vdd_voltage:
|
||||||
return gnd_voltage
|
return gnd_voltage
|
||||||
|
|
@ -173,7 +180,7 @@ def get_inverse_value(value):
|
||||||
|
|
||||||
|
|
||||||
def gen_meas_delay(stim_file, meas_name, trig_name, targ_name, trig_val, targ_val, trig_dir, targ_dir, trig_td, targ_td):
|
def gen_meas_delay(stim_file, meas_name, trig_name, targ_name, trig_val, targ_val, trig_dir, targ_dir, trig_td, targ_td):
|
||||||
"""Creates the .meas statement for the measurement of delay"""
|
""" Creates the .meas statement for the measurement of delay """
|
||||||
measure_string=".meas tran {0} TRIG v({1}) VAL={2} {3}=1 TD={4}n TARG v({5}) VAL={6} {7}=1 TD={8}n\n\n"
|
measure_string=".meas tran {0} TRIG v({1}) VAL={2} {3}=1 TD={4}n TARG v({5}) VAL={6} {7}=1 TD={8}n\n\n"
|
||||||
stim_file.write(measure_string.format(meas_name,
|
stim_file.write(measure_string.format(meas_name,
|
||||||
trig_name,
|
trig_name,
|
||||||
|
|
@ -186,7 +193,7 @@ def gen_meas_delay(stim_file, meas_name, trig_name, targ_name, trig_val, targ_va
|
||||||
targ_td))
|
targ_td))
|
||||||
|
|
||||||
def gen_meas_power(stim_file, meas_name, t_initial, t_final):
|
def gen_meas_power(stim_file, meas_name, t_initial, t_final):
|
||||||
"""Creates the .meas statement for the measurement of avg power"""
|
""" Creates the .meas statement for the measurement of avg power """
|
||||||
# power mea cmd is different in different spice:
|
# power mea cmd is different in different spice:
|
||||||
if OPTS.spice_name == "hspice":
|
if OPTS.spice_name == "hspice":
|
||||||
power_exp = "power"
|
power_exp = "power"
|
||||||
|
|
@ -196,9 +203,9 @@ def gen_meas_power(stim_file, meas_name, t_initial, t_final):
|
||||||
power_exp,
|
power_exp,
|
||||||
t_initial,
|
t_initial,
|
||||||
t_final))
|
t_final))
|
||||||
stim_file.write("\n")
|
|
||||||
|
|
||||||
def write_control(stim_file, end_time):
|
def write_control(stim_file, end_time):
|
||||||
|
""" Write the control cards to run and end the simulation """
|
||||||
# UIC is needed for ngspice to converge
|
# UIC is needed for ngspice to converge
|
||||||
stim_file.write(".TRAN 5p {0}n UIC\n".format(end_time))
|
stim_file.write(".TRAN 5p {0}n UIC\n".format(end_time))
|
||||||
if OPTS.spice_name == "ngspice":
|
if OPTS.spice_name == "ngspice":
|
||||||
|
|
@ -227,22 +234,22 @@ def write_include(stim_file, models):
|
||||||
"""Writes include statements, inputs are lists of model files"""
|
"""Writes include statements, inputs are lists of model files"""
|
||||||
for item in list(models):
|
for item in list(models):
|
||||||
if os.path.isfile(item):
|
if os.path.isfile(item):
|
||||||
stim_file.write(".include \"{0}\"\n\n".format(item))
|
stim_file.write(".include \"{0}\"\n".format(item))
|
||||||
else:
|
else:
|
||||||
debug.error("Could not find spice model: {0}\nSet SPICE_MODEL_DIR to over-ride path.\n".format(item))
|
debug.error("Could not find spice model: {0}\nSet SPICE_MODEL_DIR to over-ride path.\n".format(item))
|
||||||
|
|
||||||
|
|
||||||
def write_supply(stim_file):
|
def write_supply(stim_file):
|
||||||
"""Writes supply voltage statements"""
|
""" Writes supply voltage statements """
|
||||||
stim_file.write("V{0} {0} 0.0 {1}\n".format(vdd_name, vdd_voltage))
|
stim_file.write("V{0} {0} 0.0 {1}\n".format(vdd_name, vdd_voltage))
|
||||||
stim_file.write("V{0} {0} 0.0 {1}\n".format(gnd_name, gnd_voltage))
|
stim_file.write("V{0} {0} 0.0 {1}\n".format(gnd_name, gnd_voltage))
|
||||||
# This is for the test power supply
|
# This is for the test power supply
|
||||||
stim_file.write("V{0} {0} 0.0 {1}\n".format("test"+vdd_name, vdd_voltage))
|
stim_file.write("V{0} {0} 0.0 {1}\n".format("test"+vdd_name, vdd_voltage))
|
||||||
stim_file.write("V{0} {0} 0.0 {1}\n\n".format("test"+gnd_name, gnd_voltage))
|
stim_file.write("V{0} {0} 0.0 {1}\n".format("test"+gnd_name, gnd_voltage))
|
||||||
|
|
||||||
|
|
||||||
def run_sim():
|
def run_sim():
|
||||||
"""Run hspice in batch mode and output rawfile to parse."""
|
""" Run hspice in batch mode and output rawfile to parse. """
|
||||||
temp_stim = "{0}stim.sp".format(OPTS.openram_temp)
|
temp_stim = "{0}stim.sp".format(OPTS.openram_temp)
|
||||||
import datetime
|
import datetime
|
||||||
start_time = datetime.datetime.now()
|
start_time = datetime.datetime.now()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue