mirror of https://github.com/VLSIDA/OpenRAM.git
Move delay-specific stimulus commands to delay.py. Keep stimuli.py generic.
This commit is contained in:
parent
ed194ad47b
commit
5c4999d4cc
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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])
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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])
|
||||
|
|
|
|||
Loading…
Reference in New Issue