From 01493aab3ecc8b6088e6a632e91d321d101ed866 Mon Sep 17 00:00:00 2001 From: jsowash Date: Tue, 23 Jul 2019 15:58:54 -0700 Subject: [PATCH] Added wmask valuesto functional test through add_wmask() --- compiler/characterizer/delay.py | 28 ++++++++------ compiler/characterizer/functional.py | 58 ++++++++++++++++------------ compiler/characterizer/simulation.py | 57 ++++++++++++++------------- 3 files changed, 81 insertions(+), 62 deletions(-) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 59f5dcf5..41ab7993 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -44,6 +44,10 @@ class delay(simulation): self.targ_read_ports = [] self.targ_write_ports = [] self.period = 0 + if self.write_size is not None: + self.num_wmasks = int(self.word_size / self.write_size) + else: + self.num_wmasks = 0 self.set_load_slew(0,0) self.set_corner(corner) self.create_signal_names() @@ -1078,46 +1082,48 @@ class delay(simulation): # For now, ignore data patterns and write ones or zeros data_ones = "1"*self.word_size data_zeros = "0"*self.word_size + wmask_ones = "1"*self.num_wmasks + 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) + inverse_address, data_zeros,wmask_zeroes) self.add_write("W data 1 address {}".format(inverse_address), - inverse_address,data_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,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,read_port) + inverse_address,data_zeros,wmask_ones,read_port) self.add_read("R data 0 address {} to check W0 worked".format(self.probe_address), - self.probe_address,data_zeros,read_port) + self.probe_address,data_zeros,wmask_ones,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) + inverse_address,data_zeros,wmask_zeroes) self.add_write("W data 1 address {} to write value".format(self.probe_address), - self.probe_address,data_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,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,read_port) + inverse_address,data_zeros,wmask_ones,read_port) self.add_read("R data 1 address {} to check W1 worked".format(self.probe_address), - self.probe_address,data_zeros,read_port) + self.probe_address,data_zeros,wmask_ones,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) + self.probe_address,data_zeros,wmask_zeroes) def get_available_port(self,get_read_port): """Returns the first accessible read or write port. """ diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index db455e38..ffb5f70d 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -30,7 +30,10 @@ class functional(simulation): # Seed the characterizer with a constant seed for unit tests if OPTS.is_unit_test: - random.seed(12345) + random.seed(91218) + #12364? + #12365 + #91218 if self.write_size is not None: self.num_wmasks = int(self.word_size / self.write_size) @@ -88,24 +91,26 @@ class functional(simulation): check = 0 # First cycle idle - comment = self.gen_cycle_comment("noop", "0"*self.word_size, "0"*self.addr_size, 0, self.wmask, self.t_current) - self.add_noop_all_ports(comment, "0"*self.addr_size, "0"*self.word_size) + 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 addr = self.gen_addr() word = self.gen_data() - comment = self.gen_cycle_comment("write", word, addr, 0, self.wmask, self.t_current) - self.add_write(comment, addr, word, 0) + # print("write", self.t_current, addr, word) + comment = self.gen_cycle_comment("write", word, addr, self.wmask, 0, self.t_current) + self.add_write(comment, addr, word, self.wmask, 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. # 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, port) + 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, port, self.wmask, self.t_current) - self.add_read_one_port(comment, addr, rw_read_din_data, port) + # print("read", self.t_current, addr, word) + 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, "1"*self.num_wmasks, 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) @@ -126,21 +131,23 @@ class functional(simulation): if op == "noop": addr = "0"*self.addr_size word = "0"*self.word_size - self.add_noop_one_port(addr, word, port) + wmask = "0" * self.num_wmasks + self.add_noop_one_port(addr, word, wmask, port) elif op == "write": addr = self.gen_addr() word = self.gen_data() + # print("w",self.t_current,addr,word) # 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) + 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, port, self.wmask, self.t_current) - self.add_write_one_port(comment, addr, word, port) + 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) 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() + (addr,old_word) = self.get_data() # rand = random.randint(0,len(w_addrs)-1) # addr = w_addrs[rand] word = self.gen_data() @@ -152,23 +159,24 @@ class functional(simulation): 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:] - + # print("partial_w",self.t_current,addr,wmask,word, "new", new_word) # 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) + self.add_noop_one_port("0"*self.addr_size, "0"*self.word_size, "0"*self.num_wmasks, 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) + 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())) + # print("read",self.t_current,addr,word) # 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, port) + 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, port, self.wmask, self.t_current) - self.add_read_one_port(comment, addr, rw_read_din_data, port) + 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, "1"*self.num_wmasks, port) self.write_check.append([word, "{0}{1}".format(self.dout_name,port), self.t_current+self.period, check]) check += 1 @@ -176,8 +184,8 @@ class functional(simulation): 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, 0, self.wmask, self.t_current) - self.add_noop_all_ports(comment, "0"*self.addr_size, "0"*self.word_size) + 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) def read_stim_results(self): # Extrat DOUT values from spice timing.lis @@ -337,10 +345,10 @@ class functional(simulation): self.sf.write("\n* Generation of wmask signals\n") for bit in range(self.num_wmasks): 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.slew, 0.05) - # self.stim.gen_pwl(sig_name, self.cycle_times, self.wmask_values[port][bit], self.period, + # self.stim.gen_pwl(sig_name, self.cycle_times, self.data_values[port][bit], self.period, # self.slew, 0.05) + self.stim.gen_pwl(sig_name, self.cycle_times, self.wmask_values[port][bit], self.period, + self.slew, 0.05) # Generate CLK signals for port in self.all_ports: diff --git a/compiler/characterizer/simulation.py b/compiler/characterizer/simulation.py index 84ec925d..52070a35 100644 --- a/compiler/characterizer/simulation.py +++ b/compiler/characterizer/simulation.py @@ -137,18 +137,17 @@ class simulation(): """ Add the array of address values """ debug.check(len(wmask) == self.num_wmasks, "Invalid wmask size.") - bit = self.addr_size - 1 + bit = self.num_wmasks - 1 for c in wmask: if c == "0": self.wmask_values[port][bit].append(0) elif c == "1": self.wmask_values[port][bit].append(1) else: - print(c) - #debug.error("Non-binary wmask string", 1) + debug.error("Non-binary wmask string", 1) bit -= 1 - def add_write(self, comment, address, data, port): + 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.info(2, comment) @@ -161,15 +160,16 @@ class simulation(): self.add_control_one_port(port, "write") self.add_data(data,port) 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, unselected_port) + self.add_noop_one_port(address, noop_data, wmask, unselected_port) - def add_read(self, comment, address, din_data, port): + def add_read(self, comment, address, din_data, wmask, 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.info(2, comment) @@ -183,6 +183,7 @@ class simulation(): #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 @@ -190,9 +191,9 @@ class simulation(): #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, unselected_port) + self.add_noop_one_port(address, noop_data, wmask, unselected_port) - def add_noop_all_ports(self, comment, address, data): + def add_noop_all_ports(self, comment, address, data, wmask): """ Add the control values for a noop to all ports. """ debug.info(2, comment) self.fn_cycle_comments.append(comment) @@ -202,9 +203,9 @@ class simulation(): self.t_current += self.period for port in self.all_ports: - self.add_noop_one_port(address, data, port) - - def add_write_one_port(self, comment, address, data, port): + self.add_noop_one_port(address, data, wmask, 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.info(2, comment) @@ -213,22 +214,24 @@ class simulation(): self.add_control_one_port(port, "write") self.add_data(data,port) self.add_address(address,port) + self.add_wmask(wmask,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_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, wmask, 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.info(2, comment) @@ -238,13 +241,15 @@ class simulation(): #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) - def add_noop_one_port(self, address, data, port): + def add_noop_one_port(self, address, data, wmask, port): """ Add the control values for a noop to a single port. Does not increment the period. """ self.add_control_one_port(port, "noop") if port in self.write_ports: self.add_data(data,port) + self.add_wmask(wmask,port) self.add_address(address, port) def append_cycle_comment(self, port, comment): @@ -258,7 +263,7 @@ class simulation(): time_spacing, comment)) - def gen_cycle_comment(self, op, word, addr, port, wmask, t_current): + 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,