From cbafd0fffe6f20fc85729ab765e06e062ef05754 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Tue, 28 Jan 2025 09:20:20 -0800 Subject: [PATCH] [membkdr] Provide a tile adapter to access internal rows Signed-off-by: Robert Schilling --- hw/dv/sv/mem_bkdr_util/mem_bkdr_util.core | 1 + hw/dv/sv/mem_bkdr_util/mem_bkdr_util.sv | 36 ++++++++++++---- hw/dv/sv/mem_bkdr_util/mem_bkdr_util_pkg.sv | 1 + .../mem_bkdr_util_row_adapter.sv | 41 +++++++++++++++++++ 4 files changed, 72 insertions(+), 7 deletions(-) create mode 100644 hw/dv/sv/mem_bkdr_util/mem_bkdr_util_row_adapter.sv diff --git a/hw/dv/sv/mem_bkdr_util/mem_bkdr_util.core b/hw/dv/sv/mem_bkdr_util/mem_bkdr_util.core index dcdb614771d8f..d57834c4c0741 100644 --- a/hw/dv/sv/mem_bkdr_util/mem_bkdr_util.core +++ b/hw/dv/sv/mem_bkdr_util/mem_bkdr_util.core @@ -21,6 +21,7 @@ filesets: files: - sram_scrambler_pkg.sv - mem_bkdr_util_pkg.sv + - mem_bkdr_util_row_adapter.sv: {is_include_file: true} - mem_bkdr_util.sv: {is_include_file: true} - mem_bkdr_util__rom.sv: {is_include_file: true} - mem_bkdr_util__sram.sv: {is_include_file: true} diff --git a/hw/dv/sv/mem_bkdr_util/mem_bkdr_util.sv b/hw/dv/sv/mem_bkdr_util/mem_bkdr_util.sv index 8eb704dce431d..4ee98f00ba1cb 100644 --- a/hw/dv/sv/mem_bkdr_util/mem_bkdr_util.sv +++ b/hw/dv/sv/mem_bkdr_util/mem_bkdr_util.sv @@ -35,6 +35,10 @@ class mem_bkdr_util extends uvm_object; // Indicates the error detection scheme implemented for this memory. protected err_detection_e err_detection_scheme = ErrDetectionNone; + // Adapter to access the underlying memory organization + // Integrators can provide a custom row adapter for their SRAM primitives + protected mem_bkdr_util_row_adapter row_adapter; + // Convenience macro to check if ECC / parity is enabled. `define HAS_ECC (!(err_detection_scheme inside {ErrDetectionNone, ParityEven, ParityOdd})) `define HAS_PARITY (err_detection_scheme inside {ParityEven, ParityOdd}) @@ -84,6 +88,9 @@ class mem_bkdr_util extends uvm_object; // // Optional arguments: // + // row_adapter Adapter to access the internal row of a memory. Integrators can + // provide a custom adapter for a different memory architecture. + // // num_prince_rounds_half The number of rounds of PRINCE used to scramble the memory. This is // used for scrambled memories. This defaults to 3. // @@ -104,18 +111,26 @@ class mem_bkdr_util extends uvm_object; // memory. function new(string name = "", string path, int unsigned depth, longint unsigned n_bits, err_detection_e err_detection_scheme, + mem_bkdr_util_row_adapter row_adapter = null, uint32_t num_prince_rounds_half = 3, uint32_t extra_bits_per_subword = 0, uint32_t system_base_addr = 0, string tiling_path = "", uint32_t tile_depth = depth); super.new(name); `DV_CHECK_FATAL(!(n_bits % depth), "n_bits must be divisible by depth.") - this.path = path; - this.tiling_path = tiling_path; - this.depth = depth; - this.tile_depth = tile_depth; - this.width = n_bits / depth; - this.err_detection_scheme = err_detection_scheme; + if (row_adapter) begin + this.row_adapter = row_adapter; + end else begin + this.row_adapter = new(); + end + + this.path = path; + this.tiling_path = tiling_path; + this.row_adapter = row_adapter; + this.depth = depth; + this.tile_depth = tile_depth; + this.width = (n_bits / depth) - this.row_adapter.get_num_extra_bits(); + this.err_detection_scheme = err_detection_scheme; this.num_prince_rounds_half = num_prince_rounds_half; // Check if the inferred path to each tile (or the whole memory) really exist @@ -290,6 +305,7 @@ class mem_bkdr_util extends uvm_object; index = addr >> addr_lsb; ram_tile = index / tile_depth; res = uvm_hdl_read($sformatf("%0s[%0d]", get_full_path(ram_tile), index), data); + data = row_adapter.read_row(data); `DV_CHECK_EQ(res, 1, $sformatf("uvm_hdl_read failed at index %0d", index)) return data; endfunction @@ -403,6 +419,7 @@ class mem_bkdr_util extends uvm_object; if (!check_addr_valid(addr)) return; index = addr >> addr_lsb; ram_tile = index / tile_depth; + data = row_adapter.write_row(data); res = uvm_hdl_deposit($sformatf("%0s[%0d]", get_full_path(ram_tile), index), data); `DV_CHECK_EQ(res, 1, $sformatf("uvm_hdl_deposit failed at index %0d", index)) endfunction @@ -455,9 +472,14 @@ class mem_bkdr_util extends uvm_object; // this is used to write 32bit of data plus 7 raw integrity bits. virtual function void write39integ(bit [bus_params_pkg::BUS_AW-1:0] addr, logic [38:0] data); + uvm_hdl_data_t rw_data; `_ACCESS_CHECKS(addr, 32) // this is essentially an aligned 32bit access. if (!check_addr_valid(addr)) return; - write(addr, data); + // Perform a read-modify-write to access the underlying memory architecture + rw_data = read(addr); + rw_data = row_adapter.access_row_data39(addr, data, rw_data); + // Note the write function takes care of interleaving, if used. + write(addr, rw_data); endfunction virtual function void write64(bit [bus_params_pkg::BUS_AW-1:0] addr, logic [63:0] data); diff --git a/hw/dv/sv/mem_bkdr_util/mem_bkdr_util_pkg.sv b/hw/dv/sv/mem_bkdr_util/mem_bkdr_util_pkg.sv index f13f186a50fac..2770cc76958fc 100644 --- a/hw/dv/sv/mem_bkdr_util/mem_bkdr_util_pkg.sv +++ b/hw/dv/sv/mem_bkdr_util/mem_bkdr_util_pkg.sv @@ -43,6 +43,7 @@ package mem_bkdr_util_pkg; `include "dv_macros.svh" // sources + `include "mem_bkdr_util_row_adapter.sv" `include "mem_bkdr_util.sv" endpackage diff --git a/hw/dv/sv/mem_bkdr_util/mem_bkdr_util_row_adapter.sv b/hw/dv/sv/mem_bkdr_util/mem_bkdr_util_row_adapter.sv new file mode 100644 index 0000000000000..ac0e8f46441ef --- /dev/null +++ b/hw/dv/sv/mem_bkdr_util/mem_bkdr_util_row_adapter.sv @@ -0,0 +1,41 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// Provide an abstract way to access the memory rows +// +// Integrators can subclass this to privide a specfic way of accessing a memory row +// and incorporate the phyical architecture. +// +class mem_bkdr_util_row_adapter; + + // A row might have additional extra bits + protected uint32_t num_extra_bits = 0; + + // Return the number of extra bits of this row architecture + function uint32_t get_num_extra_bits(); + return num_extra_bits; + endfunction + + // Translates a raw read UVM data raw from the memory in a contigious + // row of memory. + // + virtual function uvm_hdl_data_t read_row(uvm_hdl_data_t read_data); + return read_data; + endfunction + + // Translates a contigious UVM data row to the internal organzation of a row + // that can be written to the memory. + // + virtual function uvm_hdl_data_t write_row(uvm_hdl_data_t write_data); + return write_data; + endfunction + + // Writes a 39 bit word into the row data depending on the memory architecture + virtual function uvm_hdl_data_t access_row_data39(bit [bus_params_pkg::BUS_AW-1:0] addr, + logic [38:0] data, + uvm_hdl_data_t row_data); + row_data[38:0] = data; + return row_data; + endfunction +endclass