mirror of https://github.com/VLSIDA/OpenRAM.git
Clean and simplify simulation code. Feedthru check added.
This commit is contained in:
parent
6bee66f9dc
commit
86c22c8904
|
|
@ -1180,44 +1180,57 @@ class delay(simulation):
|
|||
wmask_zeroes = "0"*self.num_wmasks
|
||||
|
||||
if self.t_current == 0:
|
||||
self.add_noop_all_ports("Idle cycle (no positive clock edge)",
|
||||
inverse_address, data_zeros,wmask_zeroes)
|
||||
self.add_noop_all_ports("Idle cycle (no positive clock edge)")
|
||||
|
||||
self.add_write("W data 1 address {}".format(inverse_address),
|
||||
inverse_address,data_ones,wmask_ones,write_port)
|
||||
inverse_address,
|
||||
data_ones,
|
||||
wmask_ones,
|
||||
write_port)
|
||||
|
||||
self.add_write("W data 0 address {} to write value".format(self.probe_address),
|
||||
self.probe_address,data_zeros,wmask_ones,write_port)
|
||||
self.probe_address,
|
||||
data_zeros,
|
||||
wmask_ones,
|
||||
write_port)
|
||||
self.measure_cycles[write_port][sram_op.WRITE_ZERO] = len(self.cycle_times)-1
|
||||
|
||||
# This also ensures we will have a H->L transition on the next read
|
||||
self.add_read("R data 1 address {} to set dout caps".format(inverse_address),
|
||||
inverse_address,data_zeros,wmask_ones,read_port)
|
||||
inverse_address,
|
||||
read_port)
|
||||
|
||||
self.add_read("R data 0 address {} to check W0 worked".format(self.probe_address),
|
||||
self.probe_address,data_zeros,wmask_ones,read_port)
|
||||
self.probe_address,
|
||||
read_port)
|
||||
self.measure_cycles[read_port][sram_op.READ_ZERO] = len(self.cycle_times)-1
|
||||
|
||||
self.add_noop_all_ports("Idle cycle (if read takes >1 cycle)",
|
||||
inverse_address,data_zeros,wmask_zeroes)
|
||||
self.add_noop_all_ports("Idle cycle (if read takes >1 cycle)")
|
||||
|
||||
self.add_write("W data 1 address {} to write value".format(self.probe_address),
|
||||
self.probe_address,data_ones,wmask_ones,write_port)
|
||||
self.probe_address,
|
||||
data_ones,
|
||||
wmask_ones,
|
||||
write_port)
|
||||
self.measure_cycles[write_port][sram_op.WRITE_ONE] = len(self.cycle_times)-1
|
||||
|
||||
self.add_write("W data 0 address {} to clear din caps".format(inverse_address),
|
||||
inverse_address,data_zeros,wmask_ones,write_port)
|
||||
inverse_address,
|
||||
data_zeros,
|
||||
wmask_ones,
|
||||
write_port)
|
||||
|
||||
# This also ensures we will have a L->H transition on the next read
|
||||
self.add_read("R data 0 address {} to clear dout caps".format(inverse_address),
|
||||
inverse_address,data_zeros,wmask_ones,read_port)
|
||||
inverse_address,
|
||||
read_port)
|
||||
|
||||
self.add_read("R data 1 address {} to check W1 worked".format(self.probe_address),
|
||||
self.probe_address,data_zeros,wmask_ones,read_port)
|
||||
self.probe_address,
|
||||
read_port)
|
||||
self.measure_cycles[read_port][sram_op.READ_ONE] = len(self.cycle_times)-1
|
||||
|
||||
self.add_noop_all_ports("Idle cycle (if read takes >1 cycle))",
|
||||
self.probe_address,data_zeros,wmask_zeroes)
|
||||
self.add_noop_all_ports("Idle cycle (if read takes >1 cycle))")
|
||||
|
||||
def get_available_port(self,get_read_port):
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
# All rights reserved.
|
||||
#
|
||||
import sys,re,shutil
|
||||
import copy
|
||||
import collections
|
||||
from design import design
|
||||
import debug
|
||||
|
|
@ -49,23 +50,14 @@ class functional(simulation):
|
|||
self.create_graph()
|
||||
self.set_internal_spice_names()
|
||||
|
||||
self.initialize_wmask()
|
||||
|
||||
# Number of checks can be changed
|
||||
self.num_cycles = 15
|
||||
# This is to have ordered keys for random selection
|
||||
self.stored_words = collections.OrderedDict()
|
||||
self.write_check = []
|
||||
self.read_check = []
|
||||
self.read_results = []
|
||||
|
||||
|
||||
def initialize_wmask(self):
|
||||
self.wmask = ""
|
||||
if self.write_size:
|
||||
# initialize all wmask bits to 1
|
||||
for bit in range(self.num_wmasks):
|
||||
self.wmask += "1"
|
||||
|
||||
def run(self, feasible_period=None):
|
||||
if feasible_period: #period defaults to tech.py feasible period otherwise.
|
||||
self.period = feasible_period
|
||||
|
|
@ -83,7 +75,25 @@ class functional(simulation):
|
|||
|
||||
# Check read values with written values. If the values do not match, return an error.
|
||||
return self.check_stim_results()
|
||||
|
||||
|
||||
def check_lengths(self):
|
||||
""" Do a bunch of assertions. """
|
||||
|
||||
for port in self.all_ports:
|
||||
checks = []
|
||||
if port in self.read_ports:
|
||||
checks.append((self.addr_value[port],"addr"))
|
||||
if port in self.write_ports:
|
||||
checks.append((self.data_value[port],"data"))
|
||||
checks.append((self.wmask_value[port],"wmask"))
|
||||
|
||||
for (val, name) in checks:
|
||||
debug.check(len(self.cycle_times)==len(val),
|
||||
"Port {2} lengths don't match. {0} clock values, {1} {3} values".format(len(self.cycle_times),
|
||||
len(val),
|
||||
port,
|
||||
name))
|
||||
|
||||
def create_random_memory_sequence(self):
|
||||
if self.write_size:
|
||||
rw_ops = ["noop", "write", "partial_write", "read"]
|
||||
|
|
@ -92,35 +102,61 @@ class functional(simulation):
|
|||
rw_ops = ["noop", "write", "read"]
|
||||
w_ops = ["noop", "write"]
|
||||
r_ops = ["noop", "read"]
|
||||
rw_read_din_data = "0"*self.word_size
|
||||
check = 0
|
||||
|
||||
# First cycle idle
|
||||
comment = self.gen_cycle_comment("noop", "0"*self.word_size, "0"*self.addr_size, self.wmask, 0, self.t_current)
|
||||
self.add_noop_all_ports(comment, "0"*self.addr_size, "0"*self.word_size, "0"*self.num_wmasks)
|
||||
|
||||
# Write at least once
|
||||
# First cycle idle is always an idle cycle
|
||||
comment = self.gen_cycle_comment("noop", "0"*self.word_size, "0"*self.addr_size, "0"*self.num_wmasks, 0, self.t_current)
|
||||
self.add_noop_all_ports(comment)
|
||||
|
||||
# 1. Write at least once. For multiport, it ensures that
|
||||
# feedthru reads also work.
|
||||
|
||||
# Port 0 may not be a write port, so find the first write
|
||||
# port.
|
||||
first_write_port = self.write_ports[0]
|
||||
addr = self.gen_addr()
|
||||
word = self.gen_data()
|
||||
comment = self.gen_cycle_comment("write", word, addr, self.wmask, 0, self.t_current)
|
||||
self.add_write(comment, addr, word, self.wmask, 0)
|
||||
comment = self.gen_cycle_comment("write", word, addr, "1"*self.num_wmasks, first_write_port, self.t_current)
|
||||
self.add_write_one_port(comment, addr, word, "1"*self.num_wmasks, first_write_port)
|
||||
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.
|
||||
# This will test the viablilty of the transistor sizing in the bitcell.
|
||||
for port in self.all_ports:
|
||||
if port in self.write_ports:
|
||||
self.add_noop_one_port("0"*self.addr_size, "0"*self.word_size, "0"*self.num_wmasks, port)
|
||||
else:
|
||||
comment = self.gen_cycle_comment("read", word, addr, self.wmask, port, self.t_current)
|
||||
self.add_read_one_port(comment, addr, rw_read_din_data, "0"*self.num_wmasks, port)
|
||||
self.write_check.append([word, "{0}{1}".format(self.dout_name,port), self.t_current+self.period, check])
|
||||
check += 1
|
||||
# The read port should not be the same as the write port being written.
|
||||
other_read_ports = copy.copy(self.read_ports)
|
||||
other_read_ports.remove(first_write_port)
|
||||
# If we have one, check the feedthru read worked.
|
||||
if len(other_read_ports)>0:
|
||||
first_read_port = other_read_ports[0]
|
||||
comment = self.gen_cycle_comment("read (feedthru)", word, addr, "0"*self.num_wmasks, first_read_port, self.t_current)
|
||||
self.add_read_one_port(comment, addr, first_read_port)
|
||||
self.add_read_check(word, first_read_port)
|
||||
|
||||
# All other ports are noops.
|
||||
other_ports = copy.copy(self.all_ports)
|
||||
other_ports.remove(first_write_port)
|
||||
other_ports.remove(first_read_port)
|
||||
for port in other_ports:
|
||||
self.add_nop_one_port(port)
|
||||
self.cycle_times.append(self.t_current)
|
||||
self.t_current += self.period
|
||||
self.check_lengths()
|
||||
|
||||
# Perform a random sequence of writes and reads on random ports, using random addresses and random words
|
||||
# and random write masks (if applicable)
|
||||
# 2. 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. This will test the viablilty of the
|
||||
# transistor sizing in the bitcell.
|
||||
for port in self.all_ports:
|
||||
if port in self.write_ports:
|
||||
self.add_noop_one_port(port)
|
||||
else:
|
||||
comment = self.gen_cycle_comment("read", word, addr, "0"*self.num_wmasks, port, self.t_current)
|
||||
self.add_read_one_port(comment, addr, port)
|
||||
self.add_read_check(word, port)
|
||||
self.cycle_times.append(self.t_current)
|
||||
self.t_current += self.period
|
||||
self.check_lengths()
|
||||
|
||||
# 3. Perform a random sequence of writes and reads on random
|
||||
# ports, using random addresses and random words and random
|
||||
# write masks (if applicable)
|
||||
for i in range(self.num_cycles):
|
||||
w_addrs = []
|
||||
for port in self.all_ports:
|
||||
|
|
@ -132,63 +168,69 @@ class functional(simulation):
|
|||
op = random.choice(r_ops)
|
||||
|
||||
if op == "noop":
|
||||
addr = "0"*self.addr_size
|
||||
word = "0"*self.word_size
|
||||
wmask = "0" * self.num_wmasks
|
||||
self.add_noop_one_port(addr, word, wmask, port)
|
||||
self.add_noop_one_port(port)
|
||||
elif op == "write":
|
||||
addr = self.gen_addr()
|
||||
word = self.gen_data()
|
||||
# two ports cannot write to the same address
|
||||
if addr in w_addrs:
|
||||
self.add_noop_one_port("0"*self.addr_size, "0"*self.word_size, "0"*self.num_wmasks, port)
|
||||
self.add_noop_one_port(port)
|
||||
else:
|
||||
comment = self.gen_cycle_comment("write", word, addr, self.wmask, port, self.t_current)
|
||||
self.add_write_one_port(comment, addr, word, self.wmask, port)
|
||||
word = self.gen_data()
|
||||
comment = self.gen_cycle_comment("write", word, addr, "1"*self.num_wmasks, port, self.t_current)
|
||||
self.add_write_one_port(comment, addr, word, "1"*self.num_wmasks, port)
|
||||
self.stored_words[addr] = word
|
||||
w_addrs.append(addr)
|
||||
elif op == "partial_write":
|
||||
# write only to a word that's been written to
|
||||
(addr,old_word) = self.get_data()
|
||||
word = self.gen_data()
|
||||
wmask = self.gen_wmask()
|
||||
new_word = word
|
||||
for bit in range(len(wmask)):
|
||||
# When the write mask's bits are 0, the old data values should appear in the new word
|
||||
# as to not overwrite the old values
|
||||
if wmask[bit] == "0":
|
||||
lower = bit * self.write_size
|
||||
upper = lower + self.write_size - 1
|
||||
new_word = new_word[:lower] + old_word[lower:upper+1] + new_word[upper + 1:]
|
||||
# two ports cannot write to the same address
|
||||
if addr in w_addrs:
|
||||
self.add_noop_one_port("0"*self.addr_size, "0"*self.word_size, "0"*self.num_wmasks, port)
|
||||
self.add_noop_one_port(port)
|
||||
else:
|
||||
word = self.gen_data()
|
||||
wmask = self.gen_wmask()
|
||||
new_word = word
|
||||
for bit in range(len(wmask)):
|
||||
# When the write mask's bits are 0, the old data values should appear in the new word
|
||||
# as to not overwrite the old values
|
||||
if wmask[bit] == "0":
|
||||
lower = bit * self.write_size
|
||||
upper = lower + self.write_size - 1
|
||||
new_word = new_word[:lower] + old_word[lower:upper+1] + new_word[upper + 1:]
|
||||
comment = self.gen_cycle_comment("partial_write", word, addr, wmask, port, self.t_current)
|
||||
self.add_write_one_port(comment, addr, word, wmask, port)
|
||||
self.stored_words[addr] = new_word
|
||||
w_addrs.append(addr)
|
||||
else:
|
||||
(addr,word) = random.choice(list(self.stored_words.items()))
|
||||
# cannot read from an address that is currently being written to
|
||||
if addr in w_addrs:
|
||||
self.add_noop_one_port("0"*self.addr_size, "0"*self.word_size, "0"*self.num_wmasks, port)
|
||||
else:
|
||||
comment = self.gen_cycle_comment("read", word, addr, self.wmask, port, self.t_current)
|
||||
self.add_read_one_port(comment, addr, rw_read_din_data, "0"*self.num_wmasks, port)
|
||||
self.write_check.append([word, "{0}{1}".format(self.dout_name,port), self.t_current+self.period, check])
|
||||
check += 1
|
||||
## cannot read from an address that is currently being written to
|
||||
# Yes, you can!!
|
||||
#if addr in w_addrs:
|
||||
# self.add_noop_one_port(port)
|
||||
#else:
|
||||
comment = self.gen_cycle_comment("read", word, addr, "0"*self.num_wmasks, port, self.t_current)
|
||||
self.add_read_one_port(comment, addr, port)
|
||||
self.add_read_check(word, port)
|
||||
|
||||
self.cycle_times.append(self.t_current)
|
||||
self.t_current += self.period
|
||||
|
||||
# Last cycle idle needed to correctly measure the value on the second to last clock edge
|
||||
comment = self.gen_cycle_comment("noop", "0"*self.word_size, "0"*self.addr_size, self.wmask, 0, self.t_current)
|
||||
self.add_noop_all_ports(comment, "0"*self.addr_size, "0"*self.word_size, "0"*self.num_wmasks)
|
||||
|
||||
comment = self.gen_cycle_comment("noop", "0"*self.word_size, "0"*self.addr_size, "0"*self.num_wmasks, 0, self.t_current)
|
||||
self.add_noop_all_ports(comment)
|
||||
|
||||
def add_read_check(self, word, port):
|
||||
""" Add to the check array to ensure a read works. """
|
||||
try:
|
||||
self.check
|
||||
except:
|
||||
self.check = 0
|
||||
self.read_check.append([word, "{0}{1}".format(self.dout_name,port), self.t_current+self.period, self.check])
|
||||
self.check += 1
|
||||
|
||||
def read_stim_results(self):
|
||||
# Extract dout values from spice timing.lis
|
||||
for (word, dout_port, eo_period, check) in self.write_check:
|
||||
for (word, dout_port, eo_period, check) in self.read_check:
|
||||
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))
|
||||
|
|
@ -205,17 +247,17 @@ class functional(simulation):
|
|||
self.v_high)
|
||||
return (0, error)
|
||||
|
||||
self.read_check.append([sp_read_value, dout_port, eo_period, check])
|
||||
self.read_results.append([sp_read_value, dout_port, eo_period, check])
|
||||
return (1, "SUCCESS")
|
||||
|
||||
def check_stim_results(self):
|
||||
for i in range(len(self.write_check)):
|
||||
if self.write_check[i][0] != self.read_check[i][0]:
|
||||
error = "FAILED: {0} value {1} does not match written value {2} read during cycle {3} at time {4}n".format(self.read_check[i][1],
|
||||
for i in range(len(self.read_check)):
|
||||
if self.read_check[i][0] != self.read_results[i][0]:
|
||||
error = "FAILED: {0} value {1} does not match written value {2} read during cycle {3} at time {4}n".format(self.read_results[i][1],
|
||||
self.read_results[i][0],
|
||||
self.read_check[i][0],
|
||||
self.write_check[i][0],
|
||||
int((self.read_check[i][2]-self.period)/self.period),
|
||||
self.read_check[i][2])
|
||||
int((self.read_results[i][2]-self.period)/self.period),
|
||||
self.read_results[i][2])
|
||||
return(0, error)
|
||||
return(1, "SUCCESS")
|
||||
|
||||
|
|
@ -359,7 +401,7 @@ class functional(simulation):
|
|||
|
||||
# Generate dout value measurements
|
||||
self.sf.write("\n * Generation of dout measurements\n")
|
||||
for (word, dout_port, eo_period, check) in self.write_check:
|
||||
for (word, dout_port, eo_period, check) in self.read_check:
|
||||
t_intital = eo_period - 0.01*self.period
|
||||
t_final = eo_period + 0.01*self.period
|
||||
for bit in range(self.word_size):
|
||||
|
|
|
|||
|
|
@ -60,8 +60,10 @@ class simulation():
|
|||
port_info=(len(self.all_ports),self.write_ports,self.read_ports),
|
||||
abits=self.addr_size,
|
||||
dbits=self.word_size)
|
||||
debug.check(len(self.sram.pins) == len(self.pins), "Number of pins generated for characterization \
|
||||
do match pins of SRAM\nsram.pins = {0}\npin_names = {1}".format(self.sram.pins,self.pins))
|
||||
debug.check(len(self.sram.pins) == len(self.pins),
|
||||
"Number of pins generated for characterization \
|
||||
do match pins of SRAM\nsram.pins = {0}\npin_names = {1}".format(self.sram.pins,
|
||||
self.pins))
|
||||
#This is TODO once multiport control has been finalized.
|
||||
#self.control_name = "CSB"
|
||||
|
||||
|
|
@ -71,13 +73,18 @@ class simulation():
|
|||
self.t_current = 0
|
||||
|
||||
# control signals: only one cs_b for entire multiported sram, one we_b for each write port
|
||||
self.csb_values = [[] for port in self.all_ports]
|
||||
self.web_values = [[] for port in self.readwrite_ports]
|
||||
|
||||
# Three dimensional list to handle each addr and data bits for wach port over the number of checks
|
||||
self.addr_values = [[[] for bit in range(self.addr_size)] for port in self.all_ports]
|
||||
self.data_values = [[[] for bit in range(self.word_size)] for port in self.write_ports]
|
||||
self.wmask_values = [[[] for bit in range(self.num_wmasks)] for port in self.write_ports]
|
||||
self.csb_values = {port:[] for port in self.all_ports}
|
||||
self.web_values = {port:[] for port in self.readwrite_ports}
|
||||
|
||||
# Raw values added as a bit vector
|
||||
self.addr_value = {port:[] for port in self.all_ports}
|
||||
self.data_value = {port:[] for port in self.write_ports}
|
||||
self.wmask_value = {port:[] for port in self.write_ports}
|
||||
|
||||
# Three dimensional list to handle each addr and data bits for each port over the number of checks
|
||||
self.addr_values = {port:[[] for bit in range(self.addr_size)] for port in self.all_ports}
|
||||
self.data_values = {port:[[] for bit in range(self.word_size)] for port in self.write_ports}
|
||||
self.wmask_values = {port:[[] for bit in range(self.num_wmasks)] for port in self.write_ports}
|
||||
|
||||
# For generating comments in SPICE stimulus
|
||||
self.cycle_comments = []
|
||||
|
|
@ -105,7 +112,8 @@ class simulation():
|
|||
def add_data(self, data, port):
|
||||
""" Add the array of data values """
|
||||
debug.check(len(data)==self.word_size, "Invalid data word size.")
|
||||
|
||||
|
||||
self.data_value[port].append(data)
|
||||
bit = self.word_size - 1
|
||||
for c in data:
|
||||
if c=="0":
|
||||
|
|
@ -116,10 +124,12 @@ class simulation():
|
|||
debug.error("Non-binary data string",1)
|
||||
bit -= 1
|
||||
|
||||
|
||||
def add_address(self, address, port):
|
||||
""" Add the array of address values """
|
||||
debug.check(len(address)==self.addr_size, "Invalid address size.")
|
||||
|
||||
self.addr_value[port].append(address)
|
||||
bit = self.addr_size - 1
|
||||
for c in address:
|
||||
if c=="0":
|
||||
|
|
@ -130,10 +140,12 @@ class simulation():
|
|||
debug.error("Non-binary address string",1)
|
||||
bit -= 1
|
||||
|
||||
|
||||
def add_wmask(self, wmask, port):
|
||||
""" Add the array of address values """
|
||||
debug.check(len(wmask) == self.num_wmasks, "Invalid wmask size.")
|
||||
|
||||
self.wmask_value[port].append(wmask)
|
||||
bit = self.num_wmasks - 1
|
||||
for c in wmask:
|
||||
if c == "0":
|
||||
|
|
@ -143,10 +155,13 @@ class simulation():
|
|||
else:
|
||||
debug.error("Non-binary wmask string", 1)
|
||||
bit -= 1
|
||||
|
||||
|
||||
|
||||
def add_write(self, comment, address, data, wmask, port):
|
||||
""" Add the control values for a write cycle. """
|
||||
debug.check(port in self.write_ports, "Cannot add write cycle to a read port. Port {0}, Write Ports {1}".format(port, self.write_ports))
|
||||
debug.check(port in self.write_ports,
|
||||
"Cannot add write cycle to a read port. Port {0}, Write Ports {1}".format(port,
|
||||
self.write_ports))
|
||||
debug.info(2, comment)
|
||||
self.fn_cycle_comments.append(comment)
|
||||
self.append_cycle_comment(port, comment)
|
||||
|
|
@ -159,16 +174,16 @@ class simulation():
|
|||
self.add_address(address,port)
|
||||
self.add_wmask(wmask,port)
|
||||
|
||||
#This value is hard coded here. Possibly change to member variable or set in add_noop_one_port
|
||||
noop_data = "0"*self.word_size
|
||||
#Add noops to all other ports.
|
||||
for unselected_port in self.all_ports:
|
||||
if unselected_port != port:
|
||||
self.add_noop_one_port(address, noop_data, wmask, unselected_port)
|
||||
self.add_noop_one_port(unselected_port)
|
||||
|
||||
def add_read(self, comment, address, din_data, wmask, port):
|
||||
def add_read(self, comment, address, port):
|
||||
""" Add the control values for a read cycle. """
|
||||
debug.check(port in self.read_ports, "Cannot add read cycle to a write port. Port {0}, Read Ports {1}".format(port, self.read_ports))
|
||||
debug.check(port in self.read_ports,
|
||||
"Cannot add read cycle to a write port. Port {0}, Read Ports {1}".format(port,
|
||||
self.read_ports))
|
||||
debug.info(2, comment)
|
||||
self.fn_cycle_comments.append(comment)
|
||||
self.append_cycle_comment(port, comment)
|
||||
|
|
@ -176,21 +191,26 @@ class simulation():
|
|||
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_ports:
|
||||
self.add_data(din_data,port)
|
||||
self.add_wmask(wmask,port)
|
||||
self.add_address(address, port)
|
||||
|
||||
#This value is hard coded here. Possibly change to member variable or set in add_noop_one_port
|
||||
noop_data = "0"*self.word_size
|
||||
# If the port is also a readwrite then add
|
||||
# the same value as previous cycle
|
||||
if port in self.write_ports:
|
||||
try:
|
||||
self.add_data(self.data_value[port][-1], port)
|
||||
except:
|
||||
self.add_data("0"*self.word_size, port)
|
||||
try:
|
||||
self.add_wmask(self.wmask_value[port][-1], port)
|
||||
except:
|
||||
self.add_wmask("0"*self.num_wmasks, port)
|
||||
|
||||
#Add noops to all other ports.
|
||||
for unselected_port in self.all_ports:
|
||||
if unselected_port != port:
|
||||
self.add_noop_one_port(address, noop_data, wmask, unselected_port)
|
||||
self.add_noop_one_port(unselected_port)
|
||||
|
||||
def add_noop_all_ports(self, comment, address, data, wmask):
|
||||
def add_noop_all_ports(self, comment):
|
||||
""" Add the control values for a noop to all ports. """
|
||||
debug.info(2, comment)
|
||||
self.fn_cycle_comments.append(comment)
|
||||
|
|
@ -200,39 +220,64 @@ class simulation():
|
|||
self.t_current += self.period
|
||||
|
||||
for port in self.all_ports:
|
||||
self.add_noop_one_port(address, data, wmask, port)
|
||||
self.add_noop_one_port(port)
|
||||
|
||||
def add_write_one_port(self, comment, address, data, wmask, port):
|
||||
""" Add the control values for a write cycle. Does not increment the period. """
|
||||
debug.check(port in self.write_ports, "Cannot add write cycle to a read port. Port {0}, Write Ports {1}".format(port, self.write_ports))
|
||||
debug.check(port in self.write_ports,
|
||||
"Cannot add write cycle to a read port. Port {0}, Write Ports {1}".format(port,
|
||||
self.write_ports))
|
||||
debug.info(2, comment)
|
||||
self.fn_cycle_comments.append(comment)
|
||||
|
||||
self.add_control_one_port(port, "write")
|
||||
self.add_data(data,port)
|
||||
self.add_address(address,port)
|
||||
self.add_wmask(wmask,port)
|
||||
self.add_data(data, port)
|
||||
self.add_address(address, port)
|
||||
self.add_wmask(wmask, port)
|
||||
|
||||
def add_read_one_port(self, comment, address, din_data, wmask, port):
|
||||
def add_read_one_port(self, comment, address, port):
|
||||
""" Add the control values for a read cycle. Does not increment the period. """
|
||||
debug.check(port in self.read_ports, "Cannot add read cycle to a write port. Port {0}, Read Ports {1}".format(port, self.read_ports))
|
||||
debug.check(port in self.read_ports,
|
||||
"Cannot add read cycle to a write port. Port {0}, Read Ports {1}".format(port,
|
||||
self.read_ports))
|
||||
debug.info(2, comment)
|
||||
self.fn_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_ports:
|
||||
self.add_data(din_data,port)
|
||||
self.add_wmask(wmask,port)
|
||||
self.add_address(address, port)
|
||||
# If the port is also a readwrite then add
|
||||
# the same value as previous cycle
|
||||
if port in self.write_ports:
|
||||
try:
|
||||
self.add_data(self.data_value[port][-1], port)
|
||||
except:
|
||||
self.add_data("0"*self.word_size, port)
|
||||
try:
|
||||
self.add_wmask(self.wmask_value[port][-1], port)
|
||||
except:
|
||||
self.add_wmask("0"*self.num_wmasks, port)
|
||||
|
||||
|
||||
def add_noop_one_port(self, address, data, wmask, port):
|
||||
def add_noop_one_port(self, port):
|
||||
""" Add the control values for a noop to a single port. Does not increment the period. """
|
||||
self.add_control_one_port(port, "noop")
|
||||
|
||||
try:
|
||||
self.add_address(self.addr_value[port][-1], port)
|
||||
except:
|
||||
self.add_address("0"*self.addr_size, port)
|
||||
|
||||
# If the port is also a readwrite then add
|
||||
# the same value as previous cycle
|
||||
if port in self.write_ports:
|
||||
self.add_data(data,port)
|
||||
self.add_wmask(wmask,port)
|
||||
self.add_address(address, port)
|
||||
try:
|
||||
self.add_data(self.data_value[port][-1], port)
|
||||
except:
|
||||
self.add_data("0"*self.word_size, port)
|
||||
try:
|
||||
self.add_wmask(self.wmask_value[port][-1], port)
|
||||
except:
|
||||
self.add_wmask("0"*self.num_wmasks, port)
|
||||
|
||||
def append_cycle_comment(self, port, comment):
|
||||
"""Add comment to list to be printed in stimulus file"""
|
||||
|
|
@ -240,16 +285,16 @@ class simulation():
|
|||
time = "{0:.2f} ns:".format(self.t_current)
|
||||
time_spacing = len(time)+6
|
||||
self.cycle_comments.append("Cycle {0:<6d} Port {1:<6} {2:<{3}}: {4}".format(len(self.cycle_times),
|
||||
port,
|
||||
time,
|
||||
time_spacing,
|
||||
comment))
|
||||
port,
|
||||
time,
|
||||
time_spacing,
|
||||
comment))
|
||||
|
||||
def gen_cycle_comment(self, op, word, addr, wmask, port, t_current):
|
||||
if op == "noop":
|
||||
comment = "\tIdle during cycle {0} ({1}ns - {2}ns)".format(int(t_current/self.period),
|
||||
t_current,
|
||||
t_current+self.period)
|
||||
t_current,
|
||||
t_current+self.period)
|
||||
elif op == "write":
|
||||
comment = "\tWriting {0} to address {1} (from port {2}) during cycle {3} ({4}ns - {5}ns)".format(word,
|
||||
addr,
|
||||
|
|
|
|||
Loading…
Reference in New Issue