[dv/kmac] initial covergroup implementation
this PR adds the initial implementation of covergroups to KMAC.
Signed-off-by: Udi Jonnalagadda <udij@google.com>
diff --git a/hw/ip/kmac/dv/env/kmac_env_cov.sv b/hw/ip/kmac/dv/env/kmac_env_cov.sv
index bebab8d..e56da96 100644
--- a/hw/ip/kmac/dv/env/kmac_env_cov.sv
+++ b/hw/ip/kmac/dv/env/kmac_env_cov.sv
@@ -8,6 +8,185 @@
* Covergroups may also be wrapped inside helper classes if needed.
*/
+// Covers various configuration combinations for the masked version of KMAC.
+//
+// Declare this outside of `kmac_env_cov` so that we can conditionally instantiate this in the
+// `build_phase` depending on a value in the env_cfg object.
+
+// macro for the common KMAC configuration fields
+`define COMMON_CFG_CGS \
+ kmac_en: coverpoint kmac; \
+ xof_en: coverpoint xof; \
+ strength: coverpoint kstrength; \
+ mode: coverpoint kmode; \
+ key_len: coverpoint key; \
+ msg_endian: coverpoint msg_endianness; \
+ state_endian: coverpoint state_endianness; \
+ sideload: coverpoint en_sideload;
+
+// creates the cross bins for all XOF functions
+`define XOF_CROSS_CG(strength_cg, valid_mode_expr) \
+ bins valid = ``valid_mode_expr`` && binsof(``strength_cg``) intersect {sha3_pkg::L128, sha3_pkg::L256}; \
+ ignore_bins invalid_mode = !``valid_mode_expr``; \
+ ignore_bins invalid_strength = !binsof(``strength_cg``) intersect {sha3_pkg::L128, sha3_pkg::L256};
+
+// creates the cross bins for SHA3 functions
+`define SHA3_CROSS_CG(mode_cg, strength_cg) \
+ bins valid = binsof(``mode_cg``) intersect {sha3_pkg::Sha3}; \
+ ignore_bins invalid_mode = !binsof(``mode_cg``) intersect {sha3_pkg::Sha3}; \
+ ignore_bins invalid_strength = binsof(``strength_cg``) intersect {sha3_pkg::L128};
+
+// creates a coverpoint to cover different TLUL access granularities
+`define MASK_CP(name, mask) \
+ ``name``: coverpoint ``mask`` { \
+ bins byte_access = {'b0001, 'b0010, 'b0100, 'b1000}; \
+ bins halfword_access = {'b0011, 'b0110, 'b1100}; \
+ bins triple_byte_access = {'b0111, 'b1110}; \
+ bins word_access = {'b1111}; \
+ }
+
+
+covergroup config_masked_cg with function sample(bit kmac, bit xof,
+ sha3_pkg::keccak_strength_e kstrength,
+ sha3_pkg::sha3_mode_e kmode,
+ kmac_pkg::key_len_e key,
+ bit msg_endianness,
+ bit state_endianness,
+ bit en_sideload,
+ kmac_pkg::entropy_mode_e entr_mode,
+ bit fast_entropy);
+ `COMMON_CFG_CGS
+
+ entropy_mode: coverpoint entr_mode;
+
+ entropy_fast_process: coverpoint fast_entropy;
+
+ // cross the various configuration settings
+
+ kmac_cross: cross kmac_en, xof_en, strength, key_len, msg_endian,
+ state_endian, entropy_mode, entropy_fast_process {
+ `XOF_CROSS_CG(strength, binsof(kmac_en) intersect {1})
+ }
+
+ cshake_cross: cross mode, strength, msg_endian, state_endian,
+ entropy_mode, entropy_fast_process {
+ `XOF_CROSS_CG(strength, binsof(mode) intersect {sha3_pkg::CShake})
+ }
+
+ shake_cross: cross mode, strength, msg_endian, state_endian,
+ entropy_mode, entropy_fast_process {
+ `XOF_CROSS_CG(strength, binsof(mode) intersect {sha3_pkg::Shake})
+ }
+
+ sha3_cross: cross mode, strength, msg_endian, state_endian,
+ entropy_mode, entropy_fast_process {
+ `SHA3_CROSS_CG(mode, strength)
+ }
+endgroup
+
+
+// Covers various configuration combinations for the unmasked version of KMAC.
+//
+// Declare this outside of `kmac_env_cov` so that we can conditionally instantiate this in the
+// `build_phase` depending on a value in the env_cfg object.
+covergroup config_unmasked_cg with function sample(bit kmac, bit xof,
+ sha3_pkg::keccak_strength_e kstrength,
+ sha3_pkg::sha3_mode_e kmode,
+ kmac_pkg::key_len_e key,
+ bit msg_endianness,
+ bit state_endianness,
+ bit en_sideload);
+ `COMMON_CFG_CGS
+
+ // cross the various configuration settings
+
+ kmac_cross: cross kmac_en, xof_en, strength, key_len, msg_endian, state_endian {
+ `XOF_CROSS_CG(strength, binsof(kmac_en) intersect {1})
+ }
+
+ cshake_cross: cross mode, strength, msg_endian, state_endian {
+ `XOF_CROSS_CG(strength, binsof(mode) intersect {sha3_pkg::CShake})
+ }
+
+ shake_cross: cross mode, strength, msg_endian, state_endian {
+ `XOF_CROSS_CG(strength, binsof(mode) intersect {sha3_pkg::Shake})
+ }
+
+ sha3_cross: cross mode, strength, msg_endian, state_endian {
+ `SHA3_CROSS_CG(mode, strength)
+ }
+
+endgroup
+
+// Wrapper class for the covergroup for the application interface.
+//
+// We do this so that we can create an array of these covergroups for each app interface
+// present in the testbench environment.
+class app_cg_wrap;
+ // done signal is sent while kecak rounds are running
+ covergroup app_cg(string name) with function sample(bit single_beat,
+ bit [keymgr_pkg::KmacDataIfWidth/8-1:0] strb,
+ bit err,
+ bit is_done,
+ bit in_keccak);
+ option.per_instance = 1;
+ option.name = name;
+
+ single_data_beat: coverpoint single_beat;
+
+ data_strb: coverpoint strb {
+ bins one_byte = {'b0000_0001};
+ bins two_bytes = {'b0000_0011};
+ bins three_bytes = {'b0000_0111};
+ bins four_bytes = {'b0000_1111};
+ bins five_bytes = {'b0001_1111};
+ bins six_bytes = {'b0011_1111};
+ bins seven_bytes = {'b0111_1111};
+ bins full_data_beat = {'1};
+ illegal_bins invalid = default;
+ }
+
+ app_err: coverpoint err;
+
+ done: coverpoint is_done;
+
+ in_keccak_rounds: coverpoint in_keccak;
+
+ partial_data_on_last_beat: cross done, data_strb {
+ bins valid = binsof(done) intersect {1};
+
+ ignore_bins invalid = !binsof(done) intersect {1};
+ }
+
+ done_in_keccak_rounds: cross done, in_keccak_rounds {
+ bins valid = binsof(done) intersect {1};
+
+ ignore_bins invalid = !binsof(done) intersect {1};
+ }
+ endgroup
+
+ function new(string name = "app_cg");
+ app_cg = new(name);
+ endfunction
+
+ function void sample(bit single_beat,
+ bit [keymgr_pkg::KmacDataIfWidth/8-1:0] strb,
+ bit err,
+ bit is_done,
+ bit in_keccak);
+ app_cg.sample(single_beat, strb, err, is_done, in_keccak);
+ endfunction
+endclass
+
+
+// Covers whether we see an EDN response while keccak rounds are active/inactive.
+// Create this covergroup outside of the class as its instantiation relies on a field in the
+// env.cfg.
+covergroup edn_cg with function sample(bit in_keccak_rounds);
+ edn_in_keccak: coverpoint in_keccak_rounds;
+endgroup
+
+
class kmac_env_cov extends cip_base_env_cov #(.CFG_T(kmac_env_cfg));
`uvm_component_utils(kmac_env_cov)
@@ -15,11 +194,176 @@
// kmac_env_cfg: cfg
// covergroups
- // [add covergroups here]
+
+ config_masked_cg config_masked_cg;
+ config_unmasked_cg config_unmasked_cg;
+
+ edn_cg edn_cg;
+
+ app_cg_wrap app_cg_wrappers[kmac_pkg::NumAppIntf];
+
+ covergroup msg_len_cg with function sample(int len);
+ msg_len: coverpoint len {
+ bins len_0 = {0};
+ bins len_1 = {1};
+ bins len_keccak_block_sizes[] = {72, 104, 136, 144, 168};
+ bins len_0_256 = {[0 : 256]};
+ bins len_257_512 = {[257 : 512]};
+ bins len_513_768 = {[513 : 768]};
+ bins len_769_1024 = {[769 : 1024]};
+ bins len_1025_2500 = {[1025 : 2500]};
+ bins len_2501_5000 = {[2501 : 5000]};
+ bins len_5001_7500 = {[5001 : 7500]};
+ bins len_7501_10000 = {[7501 : 10_000]};
+ bins remainder = default;
+ }
+ endgroup
+
+ covergroup output_digest_len_cg with function sample(int len);
+ output_digest_len: coverpoint len {
+ bins len_1 = {1};
+ bins len_2_63 = {[2 : 63]};
+ bins len_datapath_width = {64};
+ bins len_keccak_block_sizes[] = {72, 104, 136, 144, 168};
+ bins len_min_for_xof_require_squeeze = {137, 169};
+ bins len_65_200 = {[65 : 200]};
+ bins len_201_400 = {[201 : 400]};
+ bins len_401_600 = {[401 : 600]};
+ bins len_601_800 = {[601 : 800]};
+ bins len_801_1000 = {[801 : 1_000]};
+ bins remainder = default;
+ }
+ endgroup
+
+ covergroup prefix_range_cg with function sample(byte b);
+ prefix_range: coverpoint b {
+ bins space = {32};
+ bins capital_letters = {[65 : 90]};
+ bins lowercase_letters = {[97 : 122]};
+ bins rest = default;
+ }
+ endgroup
+
+ covergroup msgfifo_write_mask_cg with function sample(bit [TL_DBW-1:0] mask);
+ `MASK_CP(msgfifo_write_mask, mask)
+ endgroup
+
+ covergroup msgfifo_level_cg with function sample(bit fifo_empty, bit fifo_full, bit [4:0] fifo_depth,
+ sha3_pkg::sha3_mode_e mode, bit kmac_en);
+ kmac_mode: coverpoint kmac_en;
+ hash_mode: coverpoint mode {
+ bins sha3 = {sha3_pkg::Sha3};
+ bins shake = {sha3_pkg::Shake};
+ bins cshake = {sha3_pkg::CShake};
+ }
+ msgfifo_empty: coverpoint fifo_empty;
+ msgfifo_full: coverpoint fifo_full;
+ msgfifo_depth: coverpoint fifo_depth {
+ bins depth[] = {[0 : KMAC_FIFO_DEPTH]};
+ bins invalid = default;
+ }
+ endgroup
+
+ covergroup sha3_status_cg with function sample(bit sha3_idle, bit sha3_absorb, bit sha3_squeeze);
+ idle: coverpoint sha3_idle;
+ absorb: coverpoint sha3_absorb;
+ squeeze: coverpoint sha3_squeeze;
+ endgroup
+
+ covergroup state_read_mask_cg with function sample(bit [TL_DBW-1:0] mask, bit share_num);
+ share: coverpoint share_num;
+ `MASK_CP(state_read_mask, mask)
+ state_mask_share_cross: cross share, state_read_mask;
+ endgroup
+
+ covergroup cmd_process_cg with function sample(bit in_keccak_rounds, bit keccak_complete_cycle);
+ in_keccak: coverpoint in_keccak_rounds;
+
+ in_keccak_complete_cycle: coverpoint keccak_complete_cycle;
+ endgroup
+
+ covergroup sideload_cg with function sample(bit en_sideload, bit in_kmac, bit app_keymgr);
+ sideload: coverpoint en_sideload;
+ kmac_mode: coverpoint in_kmac;
+ in_app_keymgr: coverpoint app_keymgr;
+
+ sideload_cross: cross sideload, kmac_mode, in_app_keymgr {
+ bins sw_kmac_valid_sideload = binsof(sideload) intersect {1} && binsof(kmac_mode);
+ bins sw_kmac_invalid_sideload = binsof(sideload) intersect {1} && binsof(kmac_mode);
+ bins app_valid_sideload = binsof(sideload) intersect {1} && binsof(in_app_keymgr);
+ bins app_invalid_sideload = binsof(sideload) intersect {1} && binsof(in_app_keymgr);
+
+ ignore_bins invalid = !binsof(sideload) intersect {1};
+ }
+ endgroup
+
+ covergroup app_cg with function sample();
+
+ endgroup
+
+ covergroup error_cg with function sample(kmac_pkg::err_code_e kmac_err,
+ sha3_pkg::err_code_e sha3_err);
+ // placeholder comment
+ kmac_err_code: coverpoint kmac_err {
+ bins err_none = {kmac_pkg::ErrNone};
+ bins err_key_not_valid = {kmac_pkg::ErrKeyNotValid};
+ bins err_sw_pushed_msg_fifo = {kmac_pkg::ErrSwPushedMsgFifo};
+ bins err_sw_pushed_wrong_cmd = {kmac_pkg::ErrSwPushedWrongCmd};
+ bins err_wait_timer_expired = {kmac_pkg::ErrWaitTimerExpired};
+ bins err_incorrect_entropy_mode = {kmac_pkg::ErrIncorrectEntropyMode};
+
+ bins invalid = default;
+ }
+
+ sha3_err_code: coverpoint sha3_err {
+ bins err_none = {sha3_pkg::ErrNone};
+ bins err_sha3_sw_control = {sha3_pkg::ErrSha3SwControl};
+
+ bins invalid = default;
+ }
+ endgroup
+
+ function sample_cfg(bit kmac,
+ bit xof,
+ sha3_pkg::keccak_strength_e kstrength,
+ sha3_pkg::sha3_mode_e kmode,
+ kmac_pkg::key_len_e key_len,
+ bit msg_endianness,
+ bit state_endianness,
+ bit en_sideload,
+ kmac_pkg::entropy_mode_e entropy_mode,
+ bit fast_entropy);
+
+ if (cfg.enable_masking) begin
+ config_masked_cg.sample(kmac, xof, kstrength, kmode, key_len, msg_endianness,
+ state_endianness, en_sideload, entropy_mode,
+ fast_entropy);
+ end else begin
+ config_unmasked_cg.sample(kmac, xof, kstrength, kmode, key_len,
+ msg_endianness, state_endianness,
+ en_sideload);
+ end
+ endfunction
+
function new(string name, uvm_component parent);
+ kmac_app_e app_name = app_name.first;
super.new(name, parent);
// [instantiate covergroups here]
+ msg_len_cg = new();
+ output_digest_len_cg = new();
+ prefix_range_cg = new();
+ msgfifo_write_mask_cg = new();
+ msgfifo_level_cg = new();
+ sha3_status_cg = new();
+ state_read_mask_cg = new();
+ cmd_process_cg = new();
+ sideload_cg = new();
+ error_cg = new(); // TODO sample this in scb
+ do begin
+ app_cg_wrappers[app_name] = new({app_name.name(), "_cg"});
+ app_name = app_name.next;
+ end while (app_name != app_name.first);
endfunction : new
virtual function void build_phase(uvm_phase phase);
@@ -27,6 +371,17 @@
// [or instantiate covergroups here]
// Please instantiate sticky_intr_cov array of objects for all interrupts that are sticky
// See cip_base_env_cov for details
+ if (cfg.enable_masking) begin
+ config_masked_cg = new();
+ edn_cg = new();
+ end else begin
+ config_unmasked_cg = new();
+ end
endfunction
endclass
+
+`undef MASK_CP
+`undef SHA3_CROSS_CG
+`undef XOF_CROSS_CG
+`undef COMMON_CFG_CGS
diff --git a/hw/ip/kmac/dv/env/kmac_scoreboard.sv b/hw/ip/kmac/dv/env/kmac_scoreboard.sv
index 1b90529..5fa4db5 100644
--- a/hw/ip/kmac/dv/env/kmac_scoreboard.sv
+++ b/hw/ip/kmac/dv/env/kmac_scoreboard.sv
@@ -24,6 +24,9 @@
// Represents the number of blocks that have been filled in sha3pad
int num_blocks_filled = 0;
+ // used solely for coverage sampling, indicates that keccak rounds are currently running
+ bit in_keccak_rounds = 0;
+
// Whenever the keccak rounds are running, the `complete` signal is raised at the end
// for a single cycle to signal to sha3 control logic that the keccak engine is completed.
//
@@ -192,6 +195,7 @@
process_sha3_idle();
process_sha3_absorb();
process_sha3_squeeze();
+ if (cfg.en_cov) sample_sha3_status();
process_initial_digest();
process_manual_digest_squeeze();
process_intr_kmac_done();
@@ -303,6 +307,25 @@
end else if (`KMAC_APP_VALID_TRANS(AppRom)) begin
app_mode = AppRom;
end
+
+ // sample sideload-related coverage
+ if (cfg.en_cov) begin
+ // Note that all arguments to the covergroup sample() function are the same,
+ // this is due to the nature of the arguments that this function takes:
+ //
+ // - `en_sideload`: this bit indicates whether sideloading mode is active
+ // - `in_kmac` : this bit indicates whether we are operating in KMAC mode
+ // - `app_keymgr` : this bit indicates whether we are using the Keymgr-specific App
+ // interface
+ //
+ // Checking whether the current application mode is the AppKeymgr mode gives us
+ // sufficient information for all three of these arguments due to the nature of this
+ // particular interface.
+ cov.sideload_cg.sample(app_mode == AppKeymgr,
+ app_mode == AppKeymgr,
+ app_mode == AppKeymgr);
+ end
+
@(posedge sha3_idle);
end
,
@@ -311,6 +334,7 @@
if (cfg.under_reset) begin
@(negedge cfg.under_reset);
end
+
end
endtask
@@ -333,6 +357,16 @@
UVM_HIGH)
{kmac_app_block_data, kmac_app_block_strb, kmac_app_last} = kmac_app_block_item.h_data;
kmac_app_block_strb_size = $countones(kmac_app_block_strb);
+
+ // sample coverage
+ if (cfg.en_cov) begin
+ cov.app_cg_wrappers[app_mode].sample(0,
+ kmac_app_block_strb,
+ 0,
+ kmac_app_last,
+ in_keccak_rounds);
+ end
+
got_data_from_kmac_app = 1;
while (kmac_app_block_strb > 0) begin
if (kmac_app_block_strb[0]) begin
@@ -382,6 +416,17 @@
kmac_app_rsp.sprint()),
UVM_HIGH)
+ // sample coverage
+ if (cfg.en_cov) begin
+ cov.app_cg_wrappers[app_mode].sample(
+ kmac_app_rsp.byte_data_q.size() <= keymgr_pkg::KmacDataIfWidth/8,
+ '0,
+ kmac_app_rsp.rsp_error,
+ 1,
+ 0
+ );
+ end
+
// safety check that things are working properly and
// no random KMAC_APP operations are seen
`DV_CHECK_FATAL(in_kmac_app == 1,
@@ -514,6 +559,22 @@
end
endtask
+ // This is a simple task that just polls for any changes in the SHA3 status bits and samples them
+ virtual task sample_sha3_status();
+ forever begin
+ @(negedge cfg.under_reset);
+ `DV_SPINWAIT_EXIT(
+ forever begin
+ @(sha3_idle or sha3_absorb or sha3_squeeze);
+ #0;
+ cov.sha3_status_cg.sample(sha3_idle, sha3_absorb, sha3_squeeze);
+ end
+ ,
+ @(posedge cfg.under_reset);
+ )
+ end
+ endtask
+
// This task handles asserting the `kmac_done` interrupt bit
virtual task process_intr_kmac_done();
@(negedge cfg.under_reset);
@@ -686,6 +747,8 @@
// processing is enabled).
bit full_entropy_expansion = 0;
+ in_keccak_rounds = 1;
+
// insert zero delay to ensure all entropy-related updates have settled
//
// this also helps catch an edge case where EDN returns valid entropy
@@ -790,6 +853,8 @@
cfg.clk_rst_vif.wait_clks(1);
keccak_complete_cycle = 0;
+ in_keccak_rounds = 0;
+
`uvm_info(`gfn, "finished waiting for keccak", UVM_HIGH)
endtask
@@ -1569,6 +1634,12 @@
fifo_empty = (fifo_depth == 0);
fifo_full = fifo_depth == KMAC_FIFO_DEPTH;
+ // sample coverage on the fifo status
+ if (cfg.en_cov) begin
+ cov.msgfifo_level_cg.sample(fifo_empty, fifo_full, fifo_depth,
+ hash_mode, kmac_en);
+ end
+
`uvm_info(`gfn, $sformatf("fifo_depth: %0d", fifo_depth), UVM_HIGH)
`uvm_info(`gfn, $sformatf("fifo_empty: %0d", fifo_empty), UVM_HIGH)
`uvm_info(`gfn, $sformatf("fifo_full: %0d", fifo_full), UVM_HIGH)
@@ -1739,6 +1810,11 @@
entropy_mode = entropy_mode_e'(item.a_data[KmacEntropyModeMSB:KmacEntropyModeLSB]);
+ // sample sideload-related coverage
+ if (cfg.en_cov) begin
+ cov.sideload_cg.sample(item.a_data[KmacSideload], kmac_en, 0);
+ end
+
if (entropy_mode == EntropyModeEdn &&
item.a_data[KmacEntropyReady] &&
first_op_after_rst) begin
@@ -1751,8 +1827,6 @@
in_edn_fetch = 1;
`uvm_info(`gfn, "raised in_edn_fetch after reset", UVM_HIGH)
end
-
- // TODO - sample coverage
end
end
"cmd": begin
@@ -1769,6 +1843,10 @@
// kmac will now compute the digest
kmac_cmd = CmdProcess;
+ if (cfg.en_cov) begin
+ cov.cmd_process_cg.sample(in_keccak_rounds, keccak_complete_cycle);
+ end
+
// Raise this bit after a small delay to handle an edge case where
// fifo_wr_ptr and fifo_rd_ptr both increment on same cycle that CmdProcess
// is latched by internal scoreboard logic
@@ -1784,6 +1862,11 @@
CmdDone: begin
kmac_cmd = CmdDone;
+ // sample coverage of message length
+ if (cfg.en_cov) begin
+ cov.msg_len_cg.sample(msg.size());
+ end
+
// Calculate the digest using DPI and check for correctness
check_digest();
@@ -1912,6 +1995,11 @@
`uvm_info(`gfn, $sformatf("item.a_mask: 0b%0b", item.a_mask), UVM_HIGH)
`uvm_info(`gfn, $sformatf("full_data: %0p", full_data), UVM_HIGH)
+ // sample coverage on the write mask
+ if (cfg.en_cov) begin
+ cov.msgfifo_write_mask_cg.sample(item.a_mask);
+ end
+
// All writes in big-endian order will be full-word,
// so we can generalize this to a for-loop that reverses the byte order of each word.
// This way we can also preserve little-endian ordering.
@@ -1947,6 +2035,11 @@
state_mask = item.a_mask;
digest_word = item.d_data;
+ // sample coverage on state read mask
+ if (cfg.en_cov) begin
+ cov.state_read_mask_cg.sample(state_mask, share1_access);
+ end
+
`uvm_info(`gfn, $sformatf("state read mask: 0b%0b", state_mask), UVM_HIGH)
`uvm_info(`gfn, $sformatf("digest_word: 0x%0x", digest_word), UVM_HIGH)
@@ -2127,6 +2220,20 @@
$sformatf("Calculated output length doesn't match actual output length!"))
end
+ if (cfg.en_cov) begin
+ // sample configuration coverage, as only now do we know which KMAC variant is used
+ // (xof/non-xof)
+ cov.sample_cfg(kmac_en, xof_en, strength, hash_mode, key_len,
+ `gmv(ral.cfg.msg_endianness), `gmv(ral.cfg.state_endianness),
+ `gmv(ral.cfg.sideload), entropy_mode, entropy_fast_process);
+
+ // sample coverage on the digest length
+ if (cfg.en_cov) begin
+ cov.output_digest_len_cg.sample(output_len_bytes);
+ end
+ end
+
+
`uvm_info(`gfn, $sformatf("output_len_bytes: %0d", output_len_bytes), UVM_HIGH)
`uvm_info(`gfn, $sformatf("xof_en: %0d", xof_en), UVM_HIGH)
@@ -2376,6 +2483,13 @@
prefix_bytes = {<< byte {prefix_bytes}};
end
+ // sample coverage
+ if (cfg.en_cov) begin
+ foreach (prefix_bytes[i]) begin
+ cov.prefix_range_cg.sample(byte'(prefix_bytes[i]));
+ end
+ end
+
`uvm_info(`gfn, $sformatf("prefix: %0p", prefix), UVM_HIGH)
`uvm_info(`gfn, $sformatf("prefix_bytes: %0p", prefix_bytes), UVM_HIGH)