Adding debug comments to stim file for functional test and cleaning up comment code in simulation.py. Adding multiple tests for different mux configurations to functional unit tests.

This commit is contained in:
Michael Timothy Grimes 2018-10-24 23:29:09 -07:00
parent 6716aac1a6
commit ceab1a5daf
4 changed files with 168 additions and 58 deletions

View File

@ -52,18 +52,16 @@ class functional(simulation):
rw_ops = ["noop", "write", "read"]
w_ops = ["noop", "write"]
r_ops = ["noop", "read"]
rw_read_data = "0"*self.word_size
rw_read_din_data = "0"*self.word_size
check = 0
# First cycle idle
debug_comment = self.cycle_comment("noop", "0"*self.word_size, "0"*self.addr_size, 0, self.t_current)
self.add_noop_all_ports(debug_comment, "0"*self.addr_size, "0"*self.word_size)
self.add_noop_all_ports("0"*self.addr_size, "0"*self.word_size)
# Write at least once
addr = self.gen_addr()
word = self.gen_data()
debug_comment = self.cycle_comment("write", word, addr, 0, self.t_current)
self.add_write(debug_comment, addr, word, 0)
self.add_write(addr, word, 0)
self.stored_words[addr] = word
# Read at least once. For multiport, it is important that one read cycle uses all RW and R port to read from the same address simultaniously.
@ -72,8 +70,7 @@ class functional(simulation):
if self.port_id[port] == "w":
self.add_noop_one_port("0"*self.addr_size, "0"*self.word_size, port)
else:
debug_comment = self.cycle_comment("read", word, addr, port, self.t_current)
self.add_read_one_port(debug_comment, addr, rw_read_data, port)
self.add_read_one_port(addr, rw_read_din_data, word, port)
self.write_check.append([word, "{0}{1}".format(self.dout_name,port), self.t_current+self.period, check])
check += 1
self.cycle_times.append(self.t_current)
@ -101,8 +98,7 @@ class functional(simulation):
if addr in w_addrs:
self.add_noop_one_port("0"*self.addr_size, "0"*self.word_size, port)
else:
debug_comment = self.cycle_comment("write", word, addr, port, self.t_current)
self.add_write_one_port(debug_comment, addr, word, port)
self.add_write_one_port(addr, word, port)
self.stored_words[addr] = word
w_addrs.append(addr)
else:
@ -111,8 +107,7 @@ class functional(simulation):
if addr in w_addrs:
self.add_noop_one_port("0"*self.addr_size, "0"*self.word_size, port)
else:
debug_comment = self.cycle_comment("read", word, addr, port, self.t_current)
self.add_read_one_port(debug_comment, addr, rw_read_data, port)
self.add_read_one_port(addr, rw_read_din_data, word, port)
self.write_check.append([word, "{0}{1}".format(self.dout_name,port), self.t_current+self.period, check])
check += 1
@ -120,8 +115,7 @@ class functional(simulation):
self.t_current += self.period
# Last cycle idle needed to correctly measure the value on the second to last clock edge
debug_comment = self.cycle_comment("noop", "0"*self.word_size, "0"*self.addr_size, 0, self.t_current)
self.add_noop_all_ports(debug_comment, "0"*self.addr_size, "0"*self.word_size)
self.add_noop_all_ports("0"*self.addr_size, "0"*self.word_size)
def read_stim_results(self):
# Extrat DOUT values from spice timing.lis
@ -129,17 +123,17 @@ class functional(simulation):
sp_read_value = ""
for bit in range(self.word_size):
value = parse_spice_list("timing", "v{0}.{1}ck{2}".format(dout_port.lower(),bit,check))
if value > 0.9 * self.vdd_voltage:
if value > 0.88 * self.vdd_voltage:
sp_read_value = "1" + sp_read_value
elif value < 0.1 * self.vdd_voltage:
elif value < 0.12 * self.vdd_voltage:
sp_read_value = "0" + sp_read_value
else:
error ="FAILED: {0}_{1} value {2} at time {3}n does not fall within noise margins <{4} or >{5}.".format(dout_port,
bit,
value,
eo_period,
0.1*self.vdd_voltage,
0.9*self.vdd_voltage)
0.12*self.vdd_voltage,
0.88*self.vdd_voltage)
return (0, error)
self.read_check.append([sp_read_value, dout_port, eo_period, check])
@ -225,6 +219,11 @@ class functional(simulation):
sig_name="{0}{1}_{2} ".format(self.dout_name, self.read_index[port], bit)
self.sf.write("CD{0}{1} {2} 0 {3}f\n".format(self.read_index[port], bit, sig_name, self.load))
# Write debug comments to stim file
self.sf.write("\n\n * Sequence of operations\n")
for comment in self.cycle_comments:
self.sf.write("*{}\n".format(comment))
# Generate data input bits
self.sf.write("\n* Generation of data and address signals\n")
for port in range(self.total_write):

View File

@ -107,14 +107,13 @@ class simulation():
debug.error("Non-binary address string",1)
bit -= 1
def add_write(self, comment, address, data, port):
def add_write(self, address, data, port):
""" Add the control values for a write cycle. """
debug.info(1, comment)
debug.check(port in self.write_index, "Cannot add write cycle to a read port. Port {0}, Write Ports {1}".format(port, self.write_index))
self.cycle_comments.append("Cycle {0:2d}\tPort {3}\t{1:5.2f}ns:\t{2}".format(len(self.cycle_comments),
self.t_current,
comment,
port))
comment = self.gen_cycle_comment("write", data, address, port, self.t_current)
debug.info(1, comment)
self.cycle_comments.append(comment)
self.cycle_times.append(self.t_current)
self.t_current += self.period
@ -129,21 +128,20 @@ class simulation():
if unselected_port != port:
self.add_noop_one_port(address, noop_data, unselected_port)
def add_read(self, comment, address, data, port):
def add_read(self, address, din_data, dout_data, port):
""" Add the control values for a read cycle. """
debug.info(1, comment)
debug.check(port in self.read_index, "Cannot add read cycle to a write port. Port {0}, Read Ports {1}".format(port, self.read_index))
self.cycle_comments.append("Cycle {0:2d}\tPort {3}\t{1:5.2f}ns:\t{2}".format(len(self.cycle_comments),
self.t_current,
comment,
port))
comment = self.gen_cycle_comment("read", dout_data, address, port, self.t_current)
debug.info(1, comment)
self.cycle_comments.append(comment)
self.cycle_times.append(self.t_current)
self.t_current += self.period
self.add_control_one_port(port, "read")
#If the port is also a readwrite then add data.
if port in self.write_index:
self.add_data(data,port)
self.add_data(din_data,port)
self.add_address(address, port)
#This value is hard coded here. Possibly change to member variable or set in add_noop_one_port
@ -153,42 +151,40 @@ class simulation():
if unselected_port != port:
self.add_noop_one_port(address, noop_data, unselected_port)
def add_noop_all_ports(self, comment, address, data):
def add_noop_all_ports(self, address, data):
""" Add the control values for a noop to all ports. """
comment = self.gen_cycle_comment("noop", "0"*self.word_size, "0"*self.addr_size, 0, self.t_current)
debug.info(1, comment)
self.cycle_comments.append("Cycle {0:2d}\tPort All\t{1:5.2f}ns:\t{2}".format(len(self.cycle_times),
self.t_current,
comment))
self.cycle_comments.append(comment)
self.cycle_times.append(self.t_current)
self.t_current += self.period
for port in range(self.total_ports):
self.add_noop_one_port(address, data, port)
def add_write_one_port(self, comment, address, data, port):
def add_write_one_port(self, address, data, port):
""" Add the control values for a write cycle. Does not increment the period. """
debug.check(port in self.write_index, "Cannot add write cycle to a read port. Port {0}, Write Ports {1}".format(port, self.write_index))
comment = self.gen_cycle_comment("write", data, address, port, self.t_current)
debug.info(1, comment)
self.cycle_comments.append("Cycle {0:2d}\tPort {3}\t{1:5.2f}ns:\t{2}".format(len(self.cycle_comments),
self.t_current,
comment,
port))
self.cycle_comments.append(comment)
self.add_control_one_port(port, "write")
self.add_data(data,port)
self.add_address(address,port)
def add_read_one_port(self, comment, address, data, port):
def add_read_one_port(self, address, din_data, dout_data, port):
""" Add the control values for a read cycle. Does not increment the period. """
debug.check(port in self.read_index, "Cannot add read cycle to a write port. Port {0}, Read Ports {1}".format(port, self.read_index))
comment = self.gen_cycle_comment("read", dout_data, address, port, self.t_current)
debug.info(1, comment)
self.cycle_comments.append("Cycle {0:2d}\tPort {3}\t{1:5.2f}ns:\t{2}".format(len(self.cycle_comments),
self.t_current,
comment,
port))
self.cycle_comments.append(comment)
self.add_control_one_port(port, "read")
#If the port is also a readwrite then add data.
if port in self.write_index:
self.add_data(data,port)
self.add_data(din_data,port)
self.add_address(address, port)
def add_noop_one_port(self, address, data, port):
@ -198,7 +194,7 @@ class simulation():
self.add_data(data,port)
self.add_address(address, port)
def cycle_comment(self, op, word, addr, port, t_current):
def gen_cycle_comment(self, op, word, addr, port, t_current):
if op == "noop":
comment = "\tIdle during cycle {0} ({1}ns - {2}ns)".format(int(t_current/self.period),
t_current,

75
compiler/tests/22_psram_func_test.py Executable file → Normal file
View File

@ -32,27 +32,90 @@ class psram_func_test(openram_test):
from sram import sram
from sram_config import sram_config
c = sram_config(word_size=4,
num_words=64,
num_words=32,
num_banks=1)
c.words_per_row=2
c.words_per_row=1
OPTS.num_rw_ports = 1
OPTS.num_w_ports = 1
OPTS.num_r_ports = 1
debug.info(1, "Functional test for 1bit, 16word SRAM, with 1 bank. Multiport with {}RW {}W {}R.".format(OPTS.num_rw_ports, OPTS.num_w_ports, OPTS.num_r_ports))
# no column mux
debug.info(1, "Functional test for multi-port ({0}RW {1}W {2}R) sram with {3}bit words, {4}words, {5}words per row, {6}banks".format(OPTS.num_rw_ports,
OPTS.num_w_ports,
OPTS.num_r_ports,
c.word_size,
c.num_words,
c.words_per_row,
c.num_banks))
s = sram(c, name="sram1")
tempspice = OPTS.openram_temp + "temp.sp"
s.sp_write(tempspice)
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
f = functional(s.s, tempspice, corner)
f.num_cycles = 10
(fail,error) = f.run()
self.assertTrue(fail,error)
self.reset()
# 2-way column mux
c.num_words = 64
c.words_per_row = 2
debug.info(1, "Functional test for multi-port ({0}RW {1}W {2}R) sram with {3}bit words, {4}words, {5}words per row, {6}banks".format(OPTS.num_rw_ports,
OPTS.num_w_ports,
OPTS.num_r_ports,
c.word_size,
c.num_words,
c.words_per_row,
c.num_banks))
s = sram(c, name="sram2")
s.sp_write(tempspice)
f = functional(s.s, tempspice, corner)
f.num_cycles = 10
(fail,error) = f.run()
self.assertTrue(fail,error)
self.reset()
"""
# 4-way column mux
c.num_words = 256
c.words_per_row = 4
debug.info(1, "Functional test for multi-port ({0}RW {1}W {2}R) sram with {3}bit words, {4}words, {5}words per row, {6}banks".format(OPTS.num_rw_ports,
OPTS.num_w_ports,
OPTS.num_r_ports,
c.word_size,
c.num_words,
c.words_per_row,
c.num_banks))
s = sram(c, name="sram1")
s.sp_write(tempspice)
f = functional(s.s, tempspice, corner)
f.num_cycles = 10
(fail,error) = f.run()
self.assertTrue(fail,error)
self.reset()
# 8-way column mux
c.num_words = 512
c.words_per_row = 8
debug.info(1, "Functional test for multi-port ({0}RW {1}W {2}R) sram with {3}bit words, {4}words, {5}words per row, {6}banks".format(OPTS.num_rw_ports,
OPTS.num_w_ports,
OPTS.num_r_ports,
c.word_size,
c.num_words,
c.words_per_row,
c.num_banks))
s = sram(c, name="sram1")
s.sp_write(tempspice)
f = functional(s.s, tempspice, corner)
f.num_cycles = 10
(fail,error) = f.run()
self.assertTrue(fail,error)
self.reset()
"""
globals.end_openram()
# instantiate a copdsay of the class to actually run the test

64
compiler/tests/22_sram_func_test.py Executable file → Normal file
View File

@ -30,22 +30,74 @@ class sram_func_test(openram_test):
from sram import sram
from sram_config import sram_config
c = sram_config(word_size=4,
num_words=64,
num_words=32,
num_banks=1)
c.words_per_row=2
debug.info(1, "Functional test for 1bit, 16word SRAM, with 1 bank")
c.words_per_row=1
# no column mux
debug.info(1, "Functional test for sram with {} bit words, {} words, {} words per row, {} banks".format(c.word_size,
c.num_words,
c.words_per_row,
c.num_banks))
s = sram(c, name="sram1")
tempspice = OPTS.openram_temp + "temp.sp"
s.sp_write(tempspice)
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
f = functional(s.s, tempspice, corner)
f.num_cycles = 10
(fail, error) = f.run()
self.assertTrue(fail,error)
self.reset()
# 2-way column mux
c.num_words=64
c.words_per_row=2
debug.info(1, "Functional test for sram with {} bit words, {} words, {} words per row, {} banks".format(c.word_size,
c.num_words,
c.words_per_row,
c.num_banks))
s = sram(c, name="sram2")
s.sp_write(tempspice)
f = functional(s.s, tempspice, corner)
f.num_cycles = 10
(fail, error) = f.run()
self.assertTrue(fail,error)
self.reset()
"""
# 4-way column mux
c.num_words=256
c.words_per_row=4
debug.info(1, "Functional test for sram with {} bit words, {} words, {} words per row, {} banks".format(c.word_size,
c.num_words,
c.words_per_row,
c.num_banks))
s = sram(c, name="sram3")
s.sp_write(tempspice)
f = functional(s.s, tempspice, corner)
f.num_cycles = 10
(fail, error) = f.run()
self.assertTrue(fail,error)
self.reset()
# 8-way column mux
c.num_words=512
c.words_per_row=8
debug.info(1, "Functional test for sram with {} bit words, {} words, {} words per row, {} banks".format(c.word_size,
c.num_words,
c.words_per_row,
c.num_banks))
s = sram(c, name="sram4")
s.sp_write(tempspice)
f = functional(s.s, tempspice, corner)
f.num_cycles = 10
(fail, error) = f.run()
self.assertTrue(fail,error)
self.reset()
"""
globals.end_openram()
# instantiate a copdsay of the class to actually run the test