Updating functional test. Test can now run a spice simulation and read the dout values from the timing files.

This commit is contained in:
Michael Timothy Grimes 2018-09-28 23:38:48 -07:00
parent a71486e22f
commit 26c6232564
4 changed files with 72 additions and 42 deletions

View File

@ -35,6 +35,13 @@ class delay():
self.num_banks = self.sram.num_banks self.num_banks = self.sram.num_banks
self.sp_file = spfile self.sp_file = spfile
self.total_ports = self.sram.total_ports
self.total_write = self.sram.total_write
self.total_read = self.sram.total_read
self.read_index = self.sram.read_index
self.write_index = self.sram.write_index
self.port_id = self.sram.port_id
# These are the member variables for a simulation # These are the member variables for a simulation
self.period = 0 self.period = 0
self.set_load_slew(0,0) self.set_load_slew(0,0)

View File

@ -1,4 +1,5 @@
import sys,re,shutil import sys,re,shutil
from design import design
import debug import debug
import math import math
import tech import tech
@ -26,9 +27,12 @@ class functional():
self.num_banks = self.sram.num_banks self.num_banks = self.sram.num_banks
self.sp_file = spfile self.sp_file = spfile
self.total_write = OPTS.num_rw_ports + OPTS.num_w_ports self.total_ports = self.sram.total_ports
self.total_read = OPTS.num_rw_ports + OPTS.num_r_ports self.total_write = self.sram.total_write
self.total_ports = OPTS.num_rw_ports + OPTS.num_w_ports + OPTS.num_r_ports self.total_read = self.sram.total_read
self.read_index = self.sram.read_index
self.write_index = self.sram.write_index
self.port_id = self.sram.port_id
# These are the member variables for a simulation # These are the member variables for a simulation
self.set_corner(corner) self.set_corner(corner)
@ -38,6 +42,9 @@ class functional():
# Number of checks can be changed # Number of checks can be changed
self.num_checks = 1 self.num_checks = 1
# set to 1 if functional simulation fails during any check
self.functional_fail = 0
def set_corner(self,corner): def set_corner(self,corner):
""" Set the corner values """ """ Set the corner values """
self.corner = corner self.corner = corner
@ -66,6 +73,11 @@ class functional():
self.addresses = [[[] for bit in range(self.addr_size)] for port in range(self.total_write)] 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)] self.data = [[[] for bit in range(self.word_size)] for port in range(self.total_write)]
# stored written values and read values for functional check
#self.addr_keys = []
self.written_values = []
self.sp_read_value = ["" for port in range(self.total_read)]
def run(self): def run(self):
""" Main function to generate random writes/reads, run spice, and analyze results """ """ Main function to generate random writes/reads, run spice, and analyze results """
# Need a NOOP to enable the chip # Need a NOOP to enable the chip
@ -76,6 +88,9 @@ class functional():
for i in range(self.num_checks): for i in range(self.num_checks):
addr = self.gen_addr() addr = self.gen_addr()
word = self.gen_data() word = self.gen_data()
#self.addr_keys.append(addr)
#self.written_values[addr] = word
self.write(addr,word) self.write(addr,word)
self.read(addr,word) self.read(addr,word)
@ -83,8 +98,18 @@ class functional():
self.stim.run_sim() self.stim.run_sim()
# Extrat DOUT values from spice timing.lis # Extrat DOUT values from spice timing.lis
read_value = parse_spice_list("timing", "vdout0[0]") for port in range(self.total_read):
print("READ VALUE = {}".format(read_value)) for bit in range(self.word_size):
value = parse_spice_list("timing", "vdout{0}.{1}.".format(port,bit))
if value > 0.75 * self.vdd_voltage:
self.sp_read_value[port] = "1" + self.sp_read_value[port]
elif value < 0.25 * self.vdd_voltage:
self.sp_read_value[port] = "0" + self.sp_read_value[port]
else:
self.functional_fail = 1
print("READ VALUE dout{} = {}".format(port,self.sp_read_value[port]))
def first_run(self): def first_run(self):
""" First cycle as noop to enable chip """ """ First cycle as noop to enable chip """
@ -107,7 +132,6 @@ class functional():
def write(self,addr,word,write_port=0): def write(self,addr,word,write_port=0):
""" Generates signals for a write cycle """ """ Generates signals for a write cycle """
print("Writing {0} to {1}...".format(word,addr)) print("Writing {0} to {1}...".format(word,addr))
self.written_words.append(word)
self.cycles = self.cycles + 1 self.cycles = self.cycles + 1
# Write control signals # Write control signals
@ -126,13 +150,13 @@ class functional():
# Write address # Write address
for port in range(self.total_write): for port in range(self.total_write):
for bit in range(self.addr_size): for bit in range(self.addr_size):
current_address_bit = int(addr[bit]) current_address_bit = int(addr[self.addr_size-1-bit])
self.addresses[port][bit].append(current_address_bit) self.addresses[port][bit].append(current_address_bit)
# Write data # Write data
for port in range(self.total_write): for port in range(self.total_write):
for bit in range(self.word_size): for bit in range(self.word_size):
current_word_bit = int(word[bit]) current_word_bit = int(word[self.word_size-1-bit])
self.data[port][bit].append(current_word_bit) self.data[port][bit].append(current_word_bit)
def read(self,addr,word): def read(self,addr,word):
@ -150,7 +174,7 @@ class functional():
# Read address # Read address
for port in range(self.total_write): for port in range(self.total_write):
for bit in range(self.addr_size): for bit in range(self.addr_size):
current_address_bit = int(addr[bit]) current_address_bit = int(addr[self.addr_size-1-bit])
self.addresses[port][bit].append(current_address_bit) self.addresses[port][bit].append(current_address_bit)
# Data input doesn't matter during read cycle, so arbitrarily set to 0 for simulation # Data input doesn't matter during read cycle, so arbitrarily set to 0 for simulation
@ -167,10 +191,10 @@ class functional():
for port in range(self.total_write): for port in range(self.total_write):
self.we_b[port].append(1) self.we_b[port].append(1)
# Address doesn't matter during idle cycle, but keep the same as read for easier debugging # Address doesn't matter during idle cycle, but keep the same as read cycle for easier debugging
for port in range(self.total_write): for port in range(self.total_write):
for bit in range(self.addr_size): for bit in range(self.addr_size):
current_address_bit = int(addr[bit]) current_address_bit = int(addr[self.addr_size-1-bit])
self.addresses[port][bit].append(current_address_bit) self.addresses[port][bit].append(current_address_bit)
# Data input doesn't matter during idle cycle, so arbitrarily set to 0 for simulation # Data input doesn't matter during idle cycle, so arbitrarily set to 0 for simulation
@ -241,17 +265,6 @@ class functional():
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): 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_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): def write_functional_stimulus(self):
#Write Stimulus #Write Stimulus
@ -274,10 +287,8 @@ class functional():
#Instantiate the SRAM #Instantiate the SRAM
self.sf.write("\n* Instantiation of the SRAM\n") self.sf.write("\n* Instantiation of the SRAM\n")
self.stim.inst_sram(abits=self.addr_size, self.stim.inst_full_sram(sram=self.sram,
dbits=self.word_size, sram_name=self.name)
port_info=(self.total_port_num,self.total_write,self.read_ports,self.write_ports),
sram_name=self.name)
# Add load capacitance to each of the read ports # Add load capacitance to each of the read ports
self.sf.write("\n* SRAM output loads\n") self.sf.write("\n* SRAM output loads\n")
@ -306,14 +317,15 @@ class functional():
for port in range(self.total_write): 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) self.stim.gen_pwl("WEB{}".format(port), self.cycle_times , self.we_b[port], self.period, self.slew, 0.05)
# Generate CLK # Generate CLK signals
self.stim.gen_pulse(sig_name="CLK", for port in range(self.total_ports):
v1=self.gnd_voltage, self.stim.gen_pulse(sig_name="CLK{}".format(port),
v2=self.vdd_voltage, v1=self.gnd_voltage,
offset=self.period, v2=self.vdd_voltage,
period=self.period, offset=self.period,
t_rise=self.slew, period=self.period,
t_fall=self.slew) t_rise=self.slew,
t_fall=self.slew)
# Generate DOUT value measurements # Generate DOUT value measurements
self.sf.write("\n * Generation of dout measurements\n") self.sf.write("\n * Generation of dout measurements\n")

View File

@ -30,6 +30,17 @@ class stimuli():
self.device_models = tech.spice["fet_models"][self.process] self.device_models = tech.spice["fet_models"][self.process]
def inst_full_sram(self, sram, sram_name):
""" Function to instatiate an SRAM subckt. """
self.sf.write("Xsram ")
for pin in sram.pins:
if (pin=="vdd") or (pin=="gnd"):
self.sf.write("{0} ".format(pin))
else:
self.sf.write("{0} ".format(pin.upper()))
self.sf.write("{0}\n".format(sram_name))
def inst_sram(self, abits, dbits, port_info, sram_name): def inst_sram(self, abits, dbits, port_info, sram_name):
""" Function to instatiate an SRAM subckt. """ """ Function to instatiate an SRAM subckt. """
self.sf.write("Xsram ") self.sf.write("Xsram ")

View File

@ -29,7 +29,7 @@ class sram_func_test(openram_test):
from sram import sram from sram import sram
from sram_config import sram_config from sram_config import sram_config
c = sram_config(word_size=1, c = sram_config(word_size=4,
num_words=16, num_words=16,
num_banks=1) num_banks=1)
c.words_per_row=1 c.words_per_row=1
@ -43,7 +43,7 @@ class sram_func_test(openram_test):
f = functional(s.s, tempspice, corner) f = functional(s.s, tempspice, corner)
f.run() f.run()
#globals.end_openram() 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__":