Move delay-specific stimulus commands to delay.py. Keep stimuli.py generic.

This commit is contained in:
Matt Guthaus 2018-02-07 12:58:47 -08:00
parent ed194ad47b
commit 5c4999d4cc
4 changed files with 132 additions and 89 deletions

View File

@ -82,27 +82,25 @@ class delay():
self.sf.write("* Generation of data and address signals\n")
for i in range(self.word_size):
if i == self.probe_data:
stimuli.gen_data(stim_file=self.sf,
clk_times=self.cycle_times,
sig_name="data[{0}]".format(i),
period=period,
slew=slew)
self.gen_data(clk_times=self.cycle_times,
sig_name="data[{0}]".format(i),
period=period,
slew=slew)
else:
stimuli.gen_constant(stim_file=self.sf,
sig_name="d[{0}]".format(i),
v_val=self.gnd)
stimuli.gen_addr(self.sf,
clk_times=self.cycle_times,
self.gen_addr(clk_times=self.cycle_times,
addr=self.probe_address,
period=period,
slew=slew)
# generate control signals
self.sf.write("* Generation of control signals\n")
stimuli.gen_csb(self.sf, self.cycle_times, period, slew)
stimuli.gen_web(self.sf, self.cycle_times, period, slew)
stimuli.gen_oeb(self.sf, self.cycle_times, period, slew)
self.gen_csb(self.cycle_times, period, slew)
self.gen_web(self.cycle_times, period, slew)
self.gen_oeb(self.cycle_times, period, slew)
self.sf.write("* Generation of global clock signal\n")
stimuli.gen_pulse(stim_file=self.sf,
@ -404,54 +402,95 @@ class delay():
and does not need a rising edge."""
self.cycle_comments = []
# idle cycle, no operation
t_current = period
self.cycle_times = []
# cycle0: W data 1 address 1111 to initialize cell to a value
t_current = 0
# idle cycle, no operation
msg = "Idle cycle (no clock)"
self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(0,
t_current,
msg))
self.cycle_times.append(t_current)
self.cycle_comments.append("Cycle0 {}ns: W data 1 address 11..11 to initialize cell".format(t_current))
t_current += period
# cycle1: W data 0 address 1111 (to ensure a write of value works)
# One period
msg = "W data 1 address 11..11 to initialize cell"
self.cycle_times.append(t_current)
self.write0_cycle=1
self.cycle_comments.append("Cycle1 {}ns: W data 0 address 11..11 (to ensure a write of value works)".format(t_current))
self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1,
t_current,
msg))
t_current += period
# One period
msg = "W data 0 address 11..11 (to ensure a write of value works)"
self.cycle_times.append(t_current)
self.write0_cycle=len(self.cycle_times)-1
self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1,
t_current,
msg))
t_current += period
# cycle2: W data 1 address 0000 (to clear the data bus cap)
# One period
msg = "W data 1 address 00..00 (to clear bus caps)"
self.cycle_times.append(t_current)
self.cycle_comments.append("Cycle2 {}ns: W data 1 address 00..00 (to clear bus caps)".format(t_current))
self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1,
t_current,
msg))
t_current += period
# cycle3: R data 0 address 1111 to check W0 works
# One period
msg = "R data 0 address 11..11 to check W0 worked"
self.cycle_times.append(t_current)
self.read0_cycle=3
self.cycle_comments.append("Cycle3 {}ns: R data 0 address 11..11 to check W0 worked".format(t_current))
self.read0_cycle=len(self.cycle_times)-1
self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1,
t_current,
msg))
t_current += period
# cycle4: W data 1 address 1111 (to ensure a write of value works)
# One period
msg = "Idle cycle"
self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1,
t_current,
msg))
self.cycle_times.append(t_current)
self.write1_cycle=4
self.cycle_comments.append("Cycle4 {}ns: W data 1 address 11..11 (to ensure a write of value worked)".format(t_current))
t_current += period
# cycle5: W data 0 address 0000 (to clear the data bus cap)
# One period
msg = "W data 1 address 11..11 (to ensure a write of value worked)"
self.cycle_times.append(t_current)
self.cycle_comments.append("Cycle5 {}ns: W data 0 address 00..00 (to clear bus caps)".format(t_current))
self.write1_cycle=len(self.cycle_times)-1
self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1,
t_current,
msg))
t_current += period
# One period
msg = "W data 0 address 00..00 (to clear bus caps)"
self.cycle_times.append(t_current)
self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1,
t_current,
msg))
t_current += period
# cycle6: R data 1 address 1111 to check W1 works
# One period
msg = "R data 1 address 11..11 to check W1 worked"
self.cycle_times.append(t_current)
self.read1_cycle=6
self.cycle_comments.append("Cycle6 {}ns: R data 1 address 11..11 to check W1 worked".format(t_current))
self.read1_cycle=len(self.cycle_times)-1
self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1,
t_current,
msg))
t_current += period
# cycle7: wait a clock period to end the simulation
# One period
msg = "Idle cycle"
self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1,
t_current,
msg))
self.cycle_times.append(t_current)
self.cycle_comments.append("Cycle7 {}ns: Idle period to end simulation".format(t_current))
t_current += period
def analytical_model(self,sram, slews, loads):
""" Just return the analytical model results for the SRAM.
"""
@ -480,3 +519,53 @@ class delay():
}
return data
def gen_data(self, clk_times, sig_name, period, slew):
"""Generates the PWL data inputs for a simulation timing test."""
# 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
# the read to be "worst case". Otherwise, it can actually assist the read.
values = [0, 1, 0, 1, 1, 1, 1, 0, 0, 0 ]
stimuli.gen_pwl(self.sf, sig_name, clk_times, values, period, slew, 0.05)
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
"""
zero_values = [0, 0, 0, 1, 0, 0, 0, 1, 0, 0 ]
ones_values = [1, 1, 1, 0, 1, 0, 1, 0, 1, 1 ]
for i in range(len(addr)):
sig_name = "A[{0}]".format(i)
if addr[i]=="1":
stimuli.gen_pwl(self.sf, sig_name, clk_times, ones_values, period, slew, 0.05)
else:
stimuli.gen_pwl(self.sf, sig_name, clk_times, zero_values, period, slew, 0.05)
def gen_csb(self, clk_times, period, slew):
""" Generates the PWL CSb signal"""
# values for NOP, W1, W0, W1, R0, NOP, W1, W0, R1, NOP
# Keep CSb asserted in NOP for measuring >1 period
values = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
stimuli.gen_pwl(self.sf, "csb", clk_times, values, period, slew, 0.05)
def gen_web(self, clk_times, period, slew):
""" Generates the PWL WEb signal"""
# values for NOP, W1, W0, W1, R0, NOP, W1, W0, R1, NOP
# Keep WEb deasserted in NOP for measuring >1 period
values = [1, 0, 0, 0, 1, 1, 0, 0, 1, 1]
stimuli.gen_pwl(self.sf, "web", clk_times, values, period, slew, 0.05)
# Keep acc_en deasserted in NOP for measuring >1 period
values = [1, 0, 0, 0, 1, 1, 0, 0, 1, 1]
stimuli.gen_pwl(self.sf, "acc_en", clk_times, values, period, slew, 0)
values = [0, 1, 1, 1, 0, 0, 1, 1, 0, 0]
stimuli.gen_pwl(self.sf, "acc_en_inv", clk_times, values, period, slew, 0)
def gen_oeb(self, clk_times, period, slew):
""" Generates the PWL WEb signal"""
# values for NOP, W1, W0, W1, R0, W1, W0, R1, NOP
# Keep OEb asserted in NOP for measuring >1 period
values = [1, 1, 1, 1, 0, 0, 1, 1, 0, 0]
stimuli.gen_pwl(self.sf, "oeb", clk_times, values, period, slew, 0.05)

View File

@ -1,8 +1,5 @@
import os
import sys
import re
import os,sys,re,shutil
import debug
import tech
import math
import setup_hold
import delay
@ -34,7 +31,9 @@ class lib:
self.sram.word_size)
else:
# Else, use the non-reduced netlist file for simulation
self.sim_sp_file = self.sp_file
self.sim_sp_file = "{}sram.sp".format(OPTS.openram_temp)
# Make a copy in temp for debugging
shutil.copy(self.sp_file, self.sim_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])

View File

@ -134,71 +134,25 @@ 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):
# the initial value is not a clock time
debug.check(len(clk_times)+1==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.")
# shift signal times earlier for setup time
times = np.array(clk_times) - setup*period
values = np.array(data_values) * vdd_voltage
half_slew = 0.5 * slew
stim_file.write("V{0} {0} 0 PWL (0n {1}v ".format(sig_name, values[0]))
for i in range(len(times)):
for i in range(1,len(times)-1):
stim_file.write("{0}n {1}v {2}n {3}v ".format(times[i]-half_slew,
values[i],
values[i-1],
times[i]+half_slew,
values[i+1]))
values[i]))
stim_file.write(")\n")
def gen_data(stim_file, clk_times, sig_name, period, slew):
"""Generates the PWL data inputs for a simulation timing test."""
# values for NOP, W1, W0, W1, R0, W1, W0, R1, NOP
# 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.
values = [0, 1, 0, 1, 1, 1, 0, 0, 0 ]
gen_pwl(stim_file, sig_name, clk_times, values, period, slew, 0.05)
def gen_addr(stim_file, clk_times, addr, period, slew):
"""Generates the address inputs for a simulation timing test.
One cycle is different to clear the bus
"""
zero_values = [0, 0, 0, 1, 0, 0, 1, 0, 0 ]
ones_values = [1, 1, 1, 0, 1, 1, 0, 1, 1 ]
for i in range(len(addr)):
sig_name = "A[{0}]".format(i)
if addr[i]=="1":
gen_pwl(stim_file, sig_name, clk_times, ones_values, period, slew, 0.05)
else:
gen_pwl(stim_file, sig_name, clk_times, zero_values, period, slew, 0.05)
def gen_constant(stim_file, sig_name, v_val):
"""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))
def gen_csb(stim_file, clk_times, period, slew):
""" Generates the PWL CSb signal"""
# values for NOP, W1, W0, W1, R0, W1, W0, R1, NOP
values = [1, 0, 0, 0, 0, 0, 0, 0, 1]
gen_pwl(stim_file, "csb", clk_times, values, period, slew, 0.05)
def gen_web(stim_file, clk_times, period, slew):
""" Generates the PWL WEb signal"""
# values for NOP, W1, W0, W1, R0, W1, W0, R1, NOP
values = [1, 0, 0, 0, 1, 0, 0, 1, 1]
gen_pwl(stim_file, "web", clk_times, values, period, slew, 0.05)
values = [1, 0, 0, 0, 1, 0, 0, 1, 1]
gen_pwl(stim_file, "acc_en", clk_times, values, period, slew, 0)
values = [0, 1, 1, 1, 0, 1, 1, 0, 0]
gen_pwl(stim_file, "acc_en_inv", clk_times, values, period, slew, 0)
def gen_oeb(stim_file, clk_times, period, slew):
""" Generates the PWL WEb signal"""
# values for NOP, W1, W0, W1, R0, W1, W0, R1, NOP
values = [1, 1, 1, 1, 0, 1, 1, 0, 1]
gen_pwl(stim_file, "oeb", clk_times, values, period, slew, 0.05)
def get_inverse_voltage(value):

View File

@ -75,7 +75,8 @@ class trim_spice():
self.remove_insts("bitcell_array",[wl_name,bl_name])
# 2. Keep sense amps basd on BL
self.remove_insts("sense_amp_array",[bl_name])
# FIXME: The bit lines are not indexed the same in sense_amp_array
#self.remove_insts("sense_amp_array",[bl_name])
# 3. Keep column muxes basd on BL
self.remove_insts("column_mux_array",[bl_name])