From c4aec6af8c933d1bf3919179c066bd4a6f509b51 Mon Sep 17 00:00:00 2001 From: mrg Date: Tue, 29 Jun 2021 09:33:44 -0700 Subject: [PATCH 1/7] Functional fixes. Off by one error of max address with redundant rows. Select reads 3x more during functional sim. --- compiler/characterizer/functional.py | 18 +++++++++--------- ...hys_test.py => 50_riscv_1rw1r_phys_test.py} | 0 2 files changed, 9 insertions(+), 9 deletions(-) rename compiler/tests/{50_riscv_phys_test.py => 50_riscv_1rw1r_phys_test.py} (100%) diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index db01708b..aa064e3e 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -32,13 +32,13 @@ class functional(simulation): if not spfile: # self.sp_file is assigned in base class sram.sp_write(self.sp_file, trim=OPTS.trim_netlist) - + if not corner: corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) if period: self.period = period - + if not output_path: self.output_path = OPTS.openram_temp else: @@ -63,11 +63,12 @@ class functional(simulation): self.addr_spare_index = self.addr_size # If trim is set, specify the valid addresses self.valid_addresses = set() - self.max_address = 2**self.addr_size - 1 + (self.num_spare_rows * self.words_per_row) + # Don't base off address with since we may have a couple spare columns + self.max_address = self.num_rows * self.words_per_row if OPTS.trim_netlist: for i in range(self.words_per_row): self.valid_addresses.add(i) - self.valid_addresses.add(self.max_address - i) + self.valid_addresses.add(self.max_address - i - 1) self.probe_address, self.probe_data = '0' * self.addr_size, 0 self.set_corner(corner) self.set_spice_constants() @@ -87,7 +88,7 @@ class functional(simulation): self.num_cycles = cycles # This is to have ordered keys for random selection self.stored_words = collections.OrderedDict() - self.stored_spares = collections.OrderedDict() + self.stored_spares = collections.OrderedDict() self.read_check = [] self.read_results = [] @@ -128,11 +129,12 @@ class functional(simulation): name)) def create_random_memory_sequence(self): + # Select randomly, but have 3x more reads to increase probability if self.write_size: - rw_ops = ["noop", "write", "partial_write", "read"] + rw_ops = ["noop", "write", "partial_write", "read", "read", "read"] w_ops = ["noop", "write", "partial_write"] else: - rw_ops = ["noop", "write", "read"] + rw_ops = ["noop", "write", "read", "read", "read"] w_ops = ["noop", "write"] r_ops = ["noop", "read"] @@ -483,5 +485,3 @@ class functional(simulation): qbar_name = cell_name + OPTS.hier_seperator + str(storage_names[1]) return (q_name, qbar_name) - - diff --git a/compiler/tests/50_riscv_phys_test.py b/compiler/tests/50_riscv_1rw1r_phys_test.py similarity index 100% rename from compiler/tests/50_riscv_phys_test.py rename to compiler/tests/50_riscv_1rw1r_phys_test.py From d2a1f6b6542e12a04da182239e9b24214bd0bde6 Mon Sep 17 00:00:00 2001 From: mrg Date: Tue, 29 Jun 2021 09:35:33 -0700 Subject: [PATCH 2/7] Add num_rows/cols to sim --- compiler/characterizer/simulation.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/characterizer/simulation.py b/compiler/characterizer/simulation.py index 9112e5eb..24f848c4 100644 --- a/compiler/characterizer/simulation.py +++ b/compiler/characterizer/simulation.py @@ -37,6 +37,8 @@ class simulation(): self.read_ports = self.sram.read_ports self.write_ports = self.sram.write_ports self.words_per_row = self.sram.words_per_row + self.num_rows = self.sram.num_rows + self.num_cols = self.sram.num_cols if self.write_size: self.num_wmasks = int(math.ceil(self.word_size / self.write_size)) else: @@ -536,7 +538,7 @@ class simulation(): if self.words_per_row > 1: self.sram.graph_clear_column_mux(port) self.sram.graph_exclude_column_mux(self.bitline_column, port) - + # Generate new graph every analysis as edges might change depending on test bit self.graph = graph_util.timing_graph() self.sram_instance_name = "X{}".format(self.sram.name) From 930cc48e168bd31783a032ffb7b7a586880a2aeb Mon Sep 17 00:00:00 2001 From: mrg Date: Tue, 29 Jun 2021 09:37:30 -0700 Subject: [PATCH 3/7] Add vdd/gnd for all bitcells --- compiler/modules/bitcell_base_array.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/modules/bitcell_base_array.py b/compiler/modules/bitcell_base_array.py index 495d7833..1f1a8a2d 100644 --- a/compiler/modules/bitcell_base_array.py +++ b/compiler/modules/bitcell_base_array.py @@ -161,9 +161,9 @@ class bitcell_base_array(design.design): for row in range(self.row_size): for col in range(self.column_size): inst = self.cell_inst[row, col] + for pin_name in ["vdd", "gnd"]: + self.copy_layout_pin(inst, pin_name) if row == 2: #add only 1 label per col - for pin_name in ["vdd", "gnd"]: - self.copy_layout_pin(inst, pin_name) if 'VPB' in self.cell_inst[row, col].mod.pins: self.add_label("gnd", inst.get_pin("vpb").layer, inst.get_pin("vpb").ll()) if 'VNB' in self.cell_inst[row, col].mod.pins: From ee1c2054d3011b792ca30fec18d9b6eb1a3e804e Mon Sep 17 00:00:00 2001 From: mrg Date: Tue, 29 Jun 2021 11:26:49 -0700 Subject: [PATCH 4/7] Add formatted debug output --- compiler/characterizer/functional.py | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index aa064e3e..e1222778 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -297,13 +297,37 @@ class functional(simulation): self.read_results.append([sp_read_value, dout_port, eo_period, check_count]) return (1, "SUCCESS") + def format_value(self, value): + """ Format in better readable manner """ + + def delineate(word): + # Create list of chars in reverse order + split_word = list(reversed([x for x in word])) + # Add underscore every 4th char + split_word2 = [x + '_' * (n != 0 and n % 4 == 0) for n, x in enumerate(split_word)] + # Join the word unreversed back together + new_word = ''.join(reversed(split_word2)) + return(new_word) + + # Split extra cols + vals = value[:-self.num_spare_cols] + spare_vals = value[-self.num_spare_cols:] + + # Insert underscores + vals = delineate(vals) + spare_vals = delineate(spare_vals) + + return vals + "+" + spare_vals + def check_stim_results(self): for i in range(len(self.read_check)): if self.read_check[i][0] != self.read_results[i][0]: + read_val = self.format_value(self.read_results[i][0]) + correct_val = self.format_value(self.read_check[i][0]) str = "FAILED: {0} read value {1} does not match written value {2} during cycle {3} at time {4}n" error = str.format(self.read_results[i][1], - self.read_results[i][0], - self.read_check[i][0], + read_val, + correct_val, int((self.read_results[i][2] - self.period) / self.period), self.read_results[i][2]) return(0, error) From 4a9f361ab9ea6e2f2983822e853fcaefa33048cd Mon Sep 17 00:00:00 2001 From: mrg Date: Tue, 29 Jun 2021 11:27:33 -0700 Subject: [PATCH 5/7] Save raw file by default for Xyce. Change command debug level. --- compiler/characterizer/stimuli.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/compiler/characterizer/stimuli.py b/compiler/characterizer/stimuli.py index b247a8fb..d4990eed 100644 --- a/compiler/characterizer/stimuli.py +++ b/compiler/characterizer/stimuli.py @@ -374,10 +374,11 @@ class stimuli(): else: mpi_cmd = "" - cmd = "{0} {1} -o {3}timing.lis {2}".format(mpi_cmd, - OPTS.spice_exe, - temp_stim, - OPTS.openram_temp) + # Xyce can save a raw file while doing timing, so keep it around + cmd = "{0} {1} -r {3}timing.raw -o {3}timing.lis {2}".format(mpi_cmd, + OPTS.spice_exe, + temp_stim, + OPTS.openram_temp) valid_retcode=0 else: @@ -399,7 +400,7 @@ class stimuli(): spice_stdout = open("{0}spice_stdout.log".format(OPTS.openram_temp), 'w') spice_stderr = open("{0}spice_stderr.log".format(OPTS.openram_temp), 'w') - debug.info(3, cmd) + debug.info(2, cmd) retcode = subprocess.call(cmd, stdout=spice_stdout, stderr=spice_stderr, shell=True) spice_stdout.close() From 833b7b98abb7a612b57dc2c434e652bf60728f8c Mon Sep 17 00:00:00 2001 From: mrg Date: Tue, 29 Jun 2021 11:27:54 -0700 Subject: [PATCH 6/7] Conditional import of array col/row multiple --- compiler/sram/sram_config.py | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/compiler/sram/sram_config.py b/compiler/sram/sram_config.py index 0916d0f4..2c81ba0f 100644 --- a/compiler/sram/sram_config.py +++ b/compiler/sram/sram_config.py @@ -9,8 +9,6 @@ import debug from math import log, sqrt, ceil from globals import OPTS from sram_factory import factory -from tech import array_row_multiple -from tech import array_col_multiple class sram_config: @@ -24,6 +22,18 @@ class sram_config: self.num_spare_rows = num_spare_rows self.num_spare_cols = num_spare_cols + try: + from tech import array_row_multiple + self.array_row_multiple = array_row_multiple + except ImportError: + self.array_row_multiple = 1 + try: + from tech import array_col_multiple + self.array_col_multiple = array_col_multiple + except ImportError: + self.array_col_multiple = 1 + + # This will get over-written when we determine the organization self.words_per_row = words_per_row @@ -69,7 +79,6 @@ class sram_config: OPTS.words_per_row = self.words_per_row debug.info(1, "Set SRAM Words Per Row={}".format(OPTS.words_per_row)) - def recompute_sizes(self): """ Calculate the auxiliary values assuming fixed number of words per row. @@ -100,11 +109,11 @@ class sram_config: num_ports = OPTS.num_rw_ports + OPTS.num_r_ports + OPTS.num_w_ports if num_ports == 1: - if ((self.num_cols + num_ports + self.num_spare_cols) % array_col_multiple != 0): - debug.error("Invalid number of cols including rbl(s): {}. Total cols must be divisible by {}".format(self.num_cols + num_ports + self.num_spare_cols, array_col_multiple), -1) + if ((self.num_cols + num_ports + self.num_spare_cols) % self.array_col_multiple != 0): + debug.error("Invalid number of cols including rbl(s): {}. Total cols must be divisible by {}".format(self.num_cols + num_ports + self.num_spare_cols, self.array_col_multiple), -1) - if ((self.num_rows + num_ports) % array_row_multiple != 0): - debug.error("invalid number of rows including dummy row(s): {}. Total cols must be divisible by {}".format(self.num_rows + num_ports, array_row_multiple), -1) + if ((self.num_rows + num_ports) % self.array_row_multiple != 0): + debug.error("invalid number of rows including dummy row(s): {}. Total cols must be divisible by {}".format(self.num_rows + num_ports, self.array_row_multiple), -1) def estimate_words_per_row(self, tentative_num_cols, word_size): """ From 9720e5af292418aec6a46e388cd3454a81009423 Mon Sep 17 00:00:00 2001 From: mrg Date: Tue, 29 Jun 2021 11:28:19 -0700 Subject: [PATCH 7/7] Remove default array row/col multiple --- technology/freepdk45/tech/tech.py | 3 --- technology/scn4m_subm/tech/tech.py | 3 --- 2 files changed, 6 deletions(-) diff --git a/technology/freepdk45/tech/tech.py b/technology/freepdk45/tech/tech.py index 46dc67fd..f5decd3c 100644 --- a/technology/freepdk45/tech/tech.py +++ b/technology/freepdk45/tech/tech.py @@ -465,6 +465,3 @@ lvs_name = "calibre" pex_name = "calibre" blackbox_bitcell = False - -array_row_multiple = 1 -array_col_multiple = 1 \ No newline at end of file diff --git a/technology/scn4m_subm/tech/tech.py b/technology/scn4m_subm/tech/tech.py index e5f50bd8..dc6cd866 100644 --- a/technology/scn4m_subm/tech/tech.py +++ b/technology/scn4m_subm/tech/tech.py @@ -412,6 +412,3 @@ lvs_name = "netgen" pex_name = "magic" blackbox_bitcell = False - -array_row_multiple = 1 -array_col_multiple = 1 \ No newline at end of file