From ceab1a5daf1ff867f93aac718188204d8255d289 Mon Sep 17 00:00:00 2001 From: Michael Timothy Grimes Date: Wed, 24 Oct 2018 23:29:09 -0700 Subject: [PATCH] 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. --- compiler/characterizer/functional.py | 33 ++++++------ compiler/characterizer/simulation.py | 54 ++++++++++---------- compiler/tests/22_psram_func_test.py | 75 +++++++++++++++++++++++++--- compiler/tests/22_sram_func_test.py | 64 +++++++++++++++++++++--- 4 files changed, 168 insertions(+), 58 deletions(-) mode change 100755 => 100644 compiler/tests/22_psram_func_test.py mode change 100755 => 100644 compiler/tests/22_sram_func_test.py diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index 2fc7dcc4..b2c88d08 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -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): diff --git a/compiler/characterizer/simulation.py b/compiler/characterizer/simulation.py index 64b85bbb..d568e112 100644 --- a/compiler/characterizer/simulation.py +++ b/compiler/characterizer/simulation.py @@ -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, diff --git a/compiler/tests/22_psram_func_test.py b/compiler/tests/22_psram_func_test.py old mode 100755 new mode 100644 index 6a527754..647df849 --- a/compiler/tests/22_psram_func_test.py +++ b/compiler/tests/22_psram_func_test.py @@ -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 diff --git a/compiler/tests/22_sram_func_test.py b/compiler/tests/22_sram_func_test.py old mode 100755 new mode 100644 index de55c2ce..4c2ec58c --- a/compiler/tests/22_sram_func_test.py +++ b/compiler/tests/22_sram_func_test.py @@ -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