mirror of https://github.com/VLSIDA/OpenRAM.git
Added ability to do partial writes to addresses that have already been written to.
This commit is contained in:
parent
a69d35b50a
commit
72e16f8fe6
|
|
@ -42,7 +42,7 @@ class functional(simulation):
|
||||||
#self.set_feasible_period(sram, spfile, corner)
|
#self.set_feasible_period(sram, spfile, corner)
|
||||||
self.set_stimulus_variables()
|
self.set_stimulus_variables()
|
||||||
self.create_signal_names()
|
self.create_signal_names()
|
||||||
self.initilize_wmask()
|
self.initialize_wmask()
|
||||||
|
|
||||||
# Number of checks can be changed
|
# Number of checks can be changed
|
||||||
self.num_cycles = 2
|
self.num_cycles = 2
|
||||||
|
|
@ -50,16 +50,13 @@ class functional(simulation):
|
||||||
self.write_check = []
|
self.write_check = []
|
||||||
self.read_check = []
|
self.read_check = []
|
||||||
|
|
||||||
def initilize_wmask(self):
|
def initialize_wmask(self):
|
||||||
self.wmask = [None]*self.num_wmasks
|
#self.wmask = [None]*self.num_wmasks
|
||||||
|
self.wmask = ""
|
||||||
if self.write_size is not None:
|
if self.write_size is not None:
|
||||||
# initialize wmask to 1
|
# initialize all wmask bits to 1
|
||||||
for bit in range(self.num_wmasks):
|
for bit in range(self.num_wmasks):
|
||||||
self.wmask[bit] = 1
|
self.wmask += "1"
|
||||||
# if bit == 0:
|
|
||||||
# self.wmask[self.num_wmask-1 - bit] = 1
|
|
||||||
# else:
|
|
||||||
# self.wmask[self.num_wmask-1 - bit] = 0
|
|
||||||
|
|
||||||
def run(self, feasible_period=None):
|
def run(self, feasible_period=None):
|
||||||
if feasible_period: #period defaults to tech.py feasible period otherwise.
|
if feasible_period: #period defaults to tech.py feasible period otherwise.
|
||||||
|
|
@ -80,8 +77,12 @@ class functional(simulation):
|
||||||
return self.check_stim_results()
|
return self.check_stim_results()
|
||||||
|
|
||||||
def write_random_memory_sequence(self):
|
def write_random_memory_sequence(self):
|
||||||
rw_ops = ["noop", "write", "read"]
|
if self.write_size is not None:
|
||||||
w_ops = ["noop", "write"]
|
rw_ops = ["noop", "write", "partial_write", "read"]
|
||||||
|
w_ops = ["noop", "write", "partial_write"]
|
||||||
|
else:
|
||||||
|
rw_ops = ["noop", "write", "read"]
|
||||||
|
w_ops = ["noop", "write"]
|
||||||
r_ops = ["noop", "read"]
|
r_ops = ["noop", "read"]
|
||||||
rw_read_din_data = "0"*self.word_size
|
rw_read_din_data = "0"*self.word_size
|
||||||
check = 0
|
check = 0
|
||||||
|
|
@ -129,16 +130,45 @@ class functional(simulation):
|
||||||
elif op == "write":
|
elif op == "write":
|
||||||
addr = self.gen_addr()
|
addr = self.gen_addr()
|
||||||
word = self.gen_data()
|
word = self.gen_data()
|
||||||
# wmask = self.gen_wmask()
|
|
||||||
# two ports cannot write to the same address
|
# two ports cannot write to the same address
|
||||||
if addr in w_addrs:
|
if addr in w_addrs:
|
||||||
self.add_noop_one_port("0"*self.addr_size, "0"*self.word_size, port)
|
self.add_noop_one_port("0"*self.addr_size, "0"*self.word_size, port)
|
||||||
else:
|
else:
|
||||||
# comment = self.gen_cycle_comment("write", word, addr, port, wmask, self.t_current)
|
|
||||||
comment = self.gen_cycle_comment("read", word, addr, port, self.wmask, self.t_current)
|
comment = self.gen_cycle_comment("read", word, addr, port, self.wmask, self.t_current)
|
||||||
self.add_write_one_port(comment, addr, word, port)
|
self.add_write_one_port(comment, addr, word, port)
|
||||||
self.stored_words[addr] = word
|
self.stored_words[addr] = word
|
||||||
w_addrs.append(addr)
|
w_addrs.append(addr)
|
||||||
|
elif op == "partial_write":
|
||||||
|
#write only to a word that's been written to
|
||||||
|
addr, old_word = self.get_data()
|
||||||
|
# rand = random.randint(0,len(w_addrs)-1)
|
||||||
|
# addr = w_addrs[rand]
|
||||||
|
word = self.gen_data()
|
||||||
|
wmask = self.gen_wmask()
|
||||||
|
new_word = word
|
||||||
|
for bit in range(len(wmask)):
|
||||||
|
# Remove the bits of the word that's been written to
|
||||||
|
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:]
|
||||||
|
# if bit == self.num_wmask - 1:
|
||||||
|
# new_word = new_word[0:lower] + old_word[lower:upper+1]
|
||||||
|
# elif bit == 0:
|
||||||
|
# new_word = old_word[lower:upper + 1] + new_word[upper + 1:self.word_size]
|
||||||
|
# else:
|
||||||
|
# new_word = new_word[0:lower] + old_word[lower:upper+1] + new_word[upper+1:self.word_size]
|
||||||
|
|
||||||
|
#wmask = wmask[:index] + "1" + wmask[index + 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, port)
|
||||||
|
else:
|
||||||
|
comment = self.gen_cycle_comment("partial_write", word, addr, port, wmask, self.t_current)
|
||||||
|
self.add_partial_write_one_port(comment, addr, word, wmask, port)
|
||||||
|
self.stored_words[addr] = new_word
|
||||||
|
w_addrs.append(addr)
|
||||||
else:
|
else:
|
||||||
(addr,word) = random.choice(list(self.stored_words.items()))
|
(addr,word) = random.choice(list(self.stored_words.items()))
|
||||||
# cannot read from an address that is currently being written to
|
# cannot read from an address that is currently being written to
|
||||||
|
|
@ -191,26 +221,48 @@ class functional(simulation):
|
||||||
return(1, "SUCCESS")
|
return(1, "SUCCESS")
|
||||||
|
|
||||||
def gen_wmask(self):
|
def gen_wmask(self):
|
||||||
wmask_bits = [None]*self.num_wmasks
|
# wmask_bits = [None]*self.num_wmasks
|
||||||
|
# for bit in range(self.num_wmasks):
|
||||||
|
# rand = random.randint(0,1)
|
||||||
|
# wmask_bits[bit] = rand
|
||||||
|
wmask = ""
|
||||||
for bit in range(self.num_wmasks):
|
for bit in range(self.num_wmasks):
|
||||||
rand = random.randint(0, 1)
|
rand = random.randint(0, 1)
|
||||||
wmask_bits[bit] = rand
|
wmask += str(rand)
|
||||||
return wmask_bits
|
# prevent the wmask from having all bits on
|
||||||
|
all_zeroes = True
|
||||||
|
all_ones = True
|
||||||
|
for bit in range(self.num_wmasks):
|
||||||
|
if wmask[bit]=="0":
|
||||||
|
all_ones = False
|
||||||
|
elif wmask[bit]=="1":
|
||||||
|
all_zeroes = False
|
||||||
|
if all_zeroes:
|
||||||
|
index = random.randint(0, self.num_wmasks - 1)
|
||||||
|
wmask = wmask[:index] + "1" + wmask[index + 1:]
|
||||||
|
elif all_ones:
|
||||||
|
index = random.randint(0, self.num_wmasks - 1)
|
||||||
|
wmask = wmask[:index] + "0" + wmask[index + 1:]
|
||||||
|
return wmask
|
||||||
|
|
||||||
|
|
||||||
|
# prevent the wmask from having all bits off
|
||||||
|
|
||||||
# def gen_data(self):
|
|
||||||
# """ Generates a random word to write. """
|
|
||||||
# rand = random.randint(0,(2**self.word_size)-1)
|
|
||||||
# data_bits = self.convert_to_bin(rand,False)
|
|
||||||
# return data_bits
|
|
||||||
|
|
||||||
def gen_data(self):
|
def gen_data(self):
|
||||||
""" Generates a random word, either all 0 or all 1's, to write. """
|
""" Generates a random word to write. """
|
||||||
rand = random.randint(0,1)
|
rand = random.randint(0,(2**self.word_size)-1)
|
||||||
bits = []
|
data_bits = self.convert_to_bin(rand,False)
|
||||||
for bit in range(self.word_size):
|
|
||||||
bits.append(rand)
|
|
||||||
data_bits = ''.join(map(str,bits))
|
|
||||||
return data_bits
|
return data_bits
|
||||||
|
|
||||||
|
# def gen_data(self):
|
||||||
|
# """ Generates a random word, either all 0 or all 1's, to write. """
|
||||||
|
# rand = random.randint(0,1)
|
||||||
|
# bits = []
|
||||||
|
# for bit in range(self.word_size):
|
||||||
|
# bits.append(rand)
|
||||||
|
# data_bits = ''.join(map(str,bits))
|
||||||
|
# return data_bits
|
||||||
|
|
||||||
def gen_addr(self):
|
def gen_addr(self):
|
||||||
""" Generates a random address value to write to. """
|
""" Generates a random address value to write to. """
|
||||||
|
|
@ -221,7 +273,7 @@ class functional(simulation):
|
||||||
def get_data(self):
|
def get_data(self):
|
||||||
""" Gets an available address and corresponding word. """
|
""" Gets an available address and corresponding word. """
|
||||||
# Currently unused but may need later depending on how the functional test develops
|
# Currently unused but may need later depending on how the functional test develops
|
||||||
addr = random.choice(self.stored_words.keys())
|
addr = random.choice(list(self.stored_words.keys()))
|
||||||
word = self.stored_words[addr]
|
word = self.stored_words[addr]
|
||||||
return (addr,word)
|
return (addr,word)
|
||||||
|
|
||||||
|
|
@ -294,8 +346,8 @@ class functional(simulation):
|
||||||
|
|
||||||
# Generate wmask bits
|
# Generate wmask bits
|
||||||
for port in self.write_ports:
|
for port in self.write_ports:
|
||||||
self.sf.write("\n* Generation of wmask sibfssgnals\n")
|
|
||||||
if self.write_size is not None:
|
if self.write_size is not None:
|
||||||
|
self.sf.write("\n* Generation of wmask signals\n")
|
||||||
for bit in range(self.num_wmasks):
|
for bit in range(self.num_wmasks):
|
||||||
sig_name = "WMASK{0}_{1} ".format(port, bit)
|
sig_name = "WMASK{0}_{1} ".format(port, bit)
|
||||||
self.stim.gen_pwl(sig_name, self.cycle_times, self.data_values[port][bit], self.period,
|
self.stim.gen_pwl(sig_name, self.cycle_times, self.data_values[port][bit], self.period,
|
||||||
|
|
|
||||||
|
|
@ -135,7 +135,7 @@ class simulation():
|
||||||
|
|
||||||
def add_wmask(self, wmask, port):
|
def add_wmask(self, wmask, port):
|
||||||
""" Add the array of address values """
|
""" Add the array of address values """
|
||||||
debug.check(len(wmask) == self.num_wmask, "Invalid wmask size.")
|
debug.check(len(wmask) == self.num_wmasks, "Invalid wmask size.")
|
||||||
|
|
||||||
bit = self.addr_size - 1
|
bit = self.addr_size - 1
|
||||||
for c in wmask:
|
for c in wmask:
|
||||||
|
|
@ -144,7 +144,8 @@ class simulation():
|
||||||
elif c == "1":
|
elif c == "1":
|
||||||
self.wmask_values[port][bit].append(1)
|
self.wmask_values[port][bit].append(1)
|
||||||
else:
|
else:
|
||||||
debug.error("Non-binary address string", 1)
|
print(c)
|
||||||
|
#debug.error("Non-binary wmask string", 1)
|
||||||
bit -= 1
|
bit -= 1
|
||||||
|
|
||||||
def add_write(self, comment, address, data, port):
|
def add_write(self, comment, address, data, port):
|
||||||
|
|
@ -208,10 +209,24 @@ class simulation():
|
||||||
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)
|
debug.info(2, comment)
|
||||||
self.fn_cycle_comments.append(comment)
|
self.fn_cycle_comments.append(comment)
|
||||||
|
|
||||||
self.add_control_one_port(port, "write")
|
self.add_control_one_port(port, "write")
|
||||||
self.add_data(data,port)
|
self.add_data(data,port)
|
||||||
self.add_address(address,port)
|
self.add_address(address,port)
|
||||||
|
|
||||||
|
def add_partial_write_one_port(self, comment, address, data, wmask, port):
|
||||||
|
""" Add the control values for a write cycle (partial). 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.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)
|
||||||
|
|
||||||
|
|
||||||
def add_read_one_port(self, comment, address, din_data, port):
|
def add_read_one_port(self, comment, address, din_data, port):
|
||||||
""" Add the control values for a read cycle. Does not increment the period. """
|
""" Add the control values for a read cycle. Does not increment the period. """
|
||||||
|
|
@ -249,22 +264,20 @@ class simulation():
|
||||||
t_current,
|
t_current,
|
||||||
t_current+self.period)
|
t_current+self.period)
|
||||||
elif op == "write":
|
elif op == "write":
|
||||||
if self.write_size is not None:
|
comment = "\tWriting {0} to address {1} (from port {2}) during cycle {3} ({4}ns - {5}ns)".format(word,
|
||||||
comment = "\tWriting {0} to address {1} with mask bit {2} (from port {3}) during cycle {4} ({5}ns - {6}ns)".format(word,
|
|
||||||
addr,
|
|
||||||
wmask,
|
|
||||||
port,
|
|
||||||
int(t_current / self.period),
|
|
||||||
t_current,
|
|
||||||
t_current + self.period)
|
|
||||||
|
|
||||||
else:
|
|
||||||
comment = "\tWriting {0} to address {1} (from port {2}) during cycle {3} ({4}ns - {5}ns)".format(word,
|
|
||||||
addr,
|
addr,
|
||||||
port,
|
port,
|
||||||
int(t_current/self.period),
|
int(t_current/self.period),
|
||||||
t_current,
|
t_current,
|
||||||
t_current+self.period)
|
t_current+self.period)
|
||||||
|
elif op == "partial_write":
|
||||||
|
comment = "\tWriting {0} to address {1} with mask bit {2} (from port {3}) during cycle {4} ({5}ns - {6}ns)".format(word,
|
||||||
|
addr,
|
||||||
|
wmask,
|
||||||
|
port,
|
||||||
|
int(t_current / self.period),
|
||||||
|
t_current,
|
||||||
|
t_current + self.period)
|
||||||
else:
|
else:
|
||||||
comment = "\tReading {0} from address {1} (from port {2}) during cycle {3} ({4}ns - {5}ns)".format(word,
|
comment = "\tReading {0} from address {1} (from port {2}) during cycle {3} ({4}ns - {5}ns)".format(word,
|
||||||
addr,
|
addr,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue