profile
viewpoint
Henrik Fegran silabs-hfegran Silicon Laboratories Inc. Oslo, Norway www.silabs.com

silabs-hfegran/core-v-verif 0

Functional verification project for the CORE-V family of RISC-V cores.

silabs-hfegran/cv32e40x 0

4 stage, in-order, compute RISC-V core based on the CV32E40P

silabs-hfegran/force-riscv 0

Instruction Set Generator initially contributed by Futurewei

silabs-hfegran/riscv-dv 0

Random instruction generator for RISC-V processor verification

silabs-hfegran/tinyusb 0

An open source cross-platform USB stack for embedded system

issue commentopenhwgroup/cv32e40x

Complete, correct and extend rvfi_trap description

There is a small issue with the current table as well.

The values in the table under bits [8:3] are prefixed with 0x indicating a base 16 number, while the value matches the implementation in base 10. e.g. 0x48 should be 48 (or 0x30).

Silabs-ArjanB

comment created time in 5 hours

pull request commentgoogle/riscv-dv

Bitmanip v1.0.0 support

Thanks for the feedback! I think supporting both 0.94 and 1.0.0 should be fairly easy to accomplish - I opted not to do any changes to the existing infrastructure to avoid breaking backwards compatibility for those who depend on it. If support for 0.92 is no longer needed then the change would largely just involve removing the duplicate instructions from the old B-extension and updating the ones that are outdated or missing. I do feel however, that those also would benefit from being split into their own submodules.

silabs-hfegran

comment created time in 6 days

Pull request review commentopenhwgroup/core-v-verif

Create bus errors (obi/rvfi) scoreboard for 40x

+// Copyright 2021 OpenHW Group+// Copyright 2021 Silicon Labs, Inc.+//+// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");+// you may not use this file except in compliance with the License.+// You may obtain a copy of the License at+//+//     https://solderpad.org/licenses/+//+// Unless required by applicable law or agreed to in writing, software+// distributed under the License is distributed on an "AS IS" BASIS,+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+// See the License for the specific language governing permissions and+// limitations under the License.+//+// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0+++`ifndef __UVME_CV32E40X_BUSERR_SB_SV__+`define __UVME_CV32E40X_BUSERR_SB_SV__+++`uvm_analysis_imp_decl(_obid)  // D-side OBI+`uvm_analysis_imp_decl(_obii)  // I-side OBI+`uvm_analysis_imp_decl(_rvfi)+++// Class: uvme_cv32e40x_buserr_sb_c+// A scoreboard to check that OBI "err" bus faults arrive at the RVFI.+// For I-side "err"s, the main mode of checking is to store every err-flagged+//   OBI transaction in a queue, and then compare the PC addresses of RVFI+//   retires to see that they have the expected impact.+// For D-side "err"s, the main mode of checking is to watch for the first "err"+//   (in, potentially, a series of "err"s) and demand that no more than two+//   RVFI retires (non-debug/step) happen before we must enter the NMI handler.+// There are also a couple of other checks to see if all counts are as expected.+class uvme_cv32e40x_buserr_sb_c extends uvm_scoreboard;++  string info_tag = "BUSERRSB";++  uvm_analysis_imp_obid#(uvma_obi_memory_mon_trn_c, uvme_cv32e40x_buserr_sb_c)  obid;+  uvm_analysis_imp_obii#(uvma_obi_memory_mon_trn_c, uvme_cv32e40x_buserr_sb_c)  obii;+  uvm_analysis_imp_rvfi#(uvma_rvfi_instr_seq_item_c#(ILEN,XLEN), uvme_cv32e40x_buserr_sb_c)  rvfi;++  // OBI D-side variables:+  int cnt_obid_trn;      // Count of all obi d-side transactions+  int cnt_obid_err;      // Count of all d-side "err" transactions+  int cnt_obid_firsterr; // Count of all first d-side "err", in case of multiple "err" before handler "taken"+  // OBI I-side variables:+  int cnt_obii_trn;  // Count of all obi i-side transactions+  int cnt_obii_err;  // Count of all i-side "err" transactions+  // RVFI variables:+  int cnt_rvfi_trn;         // Count of all rvfi transactions+  int cnt_rvfi_nmihandl;    // Count of all nmi handler entries+  int cnt_rvfi_ifaulthandl; // Count of all instr bus fault handler entries+  int cnt_rvfi_errmatch;    // Count of all retires matched with expected I-side "err"+  // Expectations variables:+  bit                       pending_nmi;       // Whether nmi happened and handler is expected+  int                       late_retires;      // Number of non-debug/step/handler retires since "pending_nmi"+  uvma_obi_memory_mon_trn_c obii_err_queue[$]; // All I-side OBI trns last seen with "err"++  `uvm_component_utils(uvme_cv32e40x_buserr_sb_c)++  extern function              new(string name="uvme_cv32e40x_buserr_sb", uvm_component parent=null);+  extern virtual function void write_obid(uvma_obi_memory_mon_trn_c trn);+  extern virtual function void write_obii(uvma_obi_memory_mon_trn_c trn);+  extern virtual function void write_rvfi(uvma_rvfi_instr_seq_item_c#(ILEN,XLEN) trn);+  extern virtual function void build_phase(uvm_phase phase);+  extern virtual function void check_phase(uvm_phase phase);+  extern function bit          should_instr_err(uvma_rvfi_instr_seq_item_c#(ILEN,XLEN) rvfi_trn);+  extern function void         remove_from_err_queue(uvma_obi_memory_mon_trn_c  trn);+  extern function void         add_to_err_queue(uvma_obi_memory_mon_trn_c  trn);++endclass : uvme_cv32e40x_buserr_sb_c+++function uvme_cv32e40x_buserr_sb_c::new(string name="uvme_cv32e40x_buserr_sb", uvm_component parent=null);++  super.new(name, parent);++endfunction : new+++function void uvme_cv32e40x_buserr_sb_c::write_obid(uvma_obi_memory_mon_trn_c trn);++  cnt_obid_trn++;++  if (trn.err) begin+    cnt_obid_err++;++    if (!pending_nmi) begin+      cnt_obid_firsterr++;+      pending_nmi = 1;+    end+  end++endfunction : write_obid+++function void uvme_cv32e40x_buserr_sb_c::write_obii(uvma_obi_memory_mon_trn_c trn);++  cnt_obii_trn++;++  if (trn.err) begin+    cnt_obii_err++;+    add_to_err_queue(trn);+  end else begin+    // Acquit this address, as it was (re)fetched wo/ err+    remove_from_err_queue(trn);+  end++endfunction : write_obii+++function void uvme_cv32e40x_buserr_sb_c::write_rvfi(uvma_rvfi_instr_seq_item_c#(ILEN,XLEN) trn);++  bit [31:0] mcause = trn.csrs["mcause"].get_csr_retirement_data;+  bit [31:0] dcsr = trn.csrs["dcsr"].get_csr_retirement_data;+  bit step = dcsr[2];+  bit stepie = dcsr[11];++  cnt_rvfi_trn++;++  // Expected ifault retires+  if (should_instr_err(trn)) begin+    cnt_rvfi_errmatch++;++    assert (trn.trap)+      else `uvm_error(info_tag, $sformatf("retire at 0x%08x (expected 'err') lacks 'rvfi_trap'", trn.pc_rdata));+    assert (cnt_rvfi_errmatch - cnt_rvfi_ifaulthandl <= 1)+      else `uvm_error(info_tag, "too many err retires without ifault handling");+  end++  // D-side NMI handler+  if (trn.intr && mcause[31] && (mcause[30:0] inside {128, 129})) begin+    cnt_rvfi_nmihandl++;++    assert (pending_nmi)+      else `uvm_error(info_tag, "nmi handlered entered without sb having seen an 'err' on d-bus");+    pending_nmi = 0;++    assert (cnt_obid_firsterr == cnt_rvfi_nmihandl)+      else `uvm_error(info_tag, "expected D-bus 'err' count equal to handler entry count");+  end++  // I-side exception handler+  if (trn.intr && !mcause[31] && (mcause[31:0] == 48)) begin+    cnt_rvfi_ifaulthandl++;++    assert (cnt_rvfi_errmatch == cnt_rvfi_ifaulthandl)+      else `uvm_error(info_tag, "ifault handler entered without matching an ifault retirement");+  end++  // Retires after D-side "first err"+  if (pending_nmi && !trn.dbg_mode && !(step && !stepie)) begin+    late_retires++;+    assert (late_retires <= 2 + 1)  // "+1" is for the "rvfi_valid" that belongs to before the nmi+      else `uvm_error(info_tag, "more than 2 instructions retired before the nmi was taken");+  end+  if (!pending_nmi) begin+    late_retires = 0;+  end++endfunction : write_rvfi+++function void uvme_cv32e40x_buserr_sb_c::build_phase(uvm_phase phase);++  super.build_phase(phase);++  obid = new("obid", this);+  obii = new("obii", this);+  rvfi = new("rvfi", this);++endfunction : build_phase+++function void uvme_cv32e40x_buserr_sb_c::check_phase(uvm_phase phase);++  super.check_phase(phase);++  // Check OBI D-side+  assert (cnt_obid_trn > 0)+    else `uvm_warning(info_tag, "zero D-side OBI transactions received");+  assert (cnt_obid_trn >= cnt_obid_err)+    else `uvm_error(info_tag, "obid 'err' transactions counted wrong");+  assert (cnt_obid_trn != cnt_obid_err)+    else `uvm_warning(info_tag, "all the D-side OBI transactions were errs");

my bad - I misinterpreted things here; disregard this comment

silabs-robin

comment created time in 10 days

PullRequestReviewEvent

create barnchsilabs-hfegran/riscv-dv

branch : priv_1_12

created branch time in 13 days

Pull request review commentopenhwgroup/core-v-verif

Create bus errors (obi/rvfi) scoreboard for 40x

+// Copyright 2021 OpenHW Group+// Copyright 2021 Silicon Labs, Inc.+//+// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");+// you may not use this file except in compliance with the License.+// You may obtain a copy of the License at+//+//     https://solderpad.org/licenses/+//+// Unless required by applicable law or agreed to in writing, software+// distributed under the License is distributed on an "AS IS" BASIS,+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+// See the License for the specific language governing permissions and+// limitations under the License.+//+// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0+++`ifndef __UVME_CV32E40X_BUSERR_SB_SV__+`define __UVME_CV32E40X_BUSERR_SB_SV__+++`uvm_analysis_imp_decl(_obid)  // D-side OBI+`uvm_analysis_imp_decl(_obii)  // I-side OBI+`uvm_analysis_imp_decl(_rvfi)+++// Class: uvme_cv32e40x_buserr_sb_c+// A scoreboard to check that OBI "err" bus faults arrive at the RVFI.+// For I-side "err"s, the main mode of checking is to store every err-flagged+//   OBI transaction in a queue, and then compare the PC addresses of RVFI+//   retires to see that they have the expected impact.+// For D-side "err"s, the main mode of checking is to watch for the first "err"+//   (in, potentially, a series of "err"s) and demand that no more than two+//   RVFI retires (non-debug/step) happen before we must enter the NMI handler.+// There are also a couple of other checks to see if all counts are as expected.+class uvme_cv32e40x_buserr_sb_c extends uvm_scoreboard;++  string info_tag = "BUSERRSB";++  uvm_analysis_imp_obid#(uvma_obi_memory_mon_trn_c, uvme_cv32e40x_buserr_sb_c)  obid;+  uvm_analysis_imp_obii#(uvma_obi_memory_mon_trn_c, uvme_cv32e40x_buserr_sb_c)  obii;+  uvm_analysis_imp_rvfi#(uvma_rvfi_instr_seq_item_c#(ILEN,XLEN), uvme_cv32e40x_buserr_sb_c)  rvfi;++  // OBI D-side variables:+  int cnt_obid_trn;      // Count of all obi d-side transactions+  int cnt_obid_err;      // Count of all d-side "err" transactions+  int cnt_obid_firsterr; // Count of all first d-side "err", in case of multiple "err" before handler "taken"+  // OBI I-side variables:+  int cnt_obii_trn;  // Count of all obi i-side transactions+  int cnt_obii_err;  // Count of all i-side "err" transactions+  // RVFI variables:+  int cnt_rvfi_trn;         // Count of all rvfi transactions+  int cnt_rvfi_nmihandl;    // Count of all nmi handler entries+  int cnt_rvfi_ifaulthandl; // Count of all instr bus fault handler entries+  int cnt_rvfi_errmatch;    // Count of all retires matched with expected I-side "err"+  // Expectations variables:+  bit                       pending_nmi;       // Whether nmi happened and handler is expected+  int                       late_retires;      // Number of non-debug/step/handler retires since "pending_nmi"+  uvma_obi_memory_mon_trn_c obii_err_queue[$]; // All I-side OBI trns last seen with "err"++  `uvm_component_utils(uvme_cv32e40x_buserr_sb_c)++  extern function              new(string name="uvme_cv32e40x_buserr_sb", uvm_component parent=null);+  extern virtual function void write_obid(uvma_obi_memory_mon_trn_c trn);+  extern virtual function void write_obii(uvma_obi_memory_mon_trn_c trn);+  extern virtual function void write_rvfi(uvma_rvfi_instr_seq_item_c#(ILEN,XLEN) trn);+  extern virtual function void build_phase(uvm_phase phase);+  extern virtual function void check_phase(uvm_phase phase);+  extern function bit          should_instr_err(uvma_rvfi_instr_seq_item_c#(ILEN,XLEN) rvfi_trn);+  extern function void         remove_from_err_queue(uvma_obi_memory_mon_trn_c  trn);+  extern function void         add_to_err_queue(uvma_obi_memory_mon_trn_c  trn);++endclass : uvme_cv32e40x_buserr_sb_c+++function uvme_cv32e40x_buserr_sb_c::new(string name="uvme_cv32e40x_buserr_sb", uvm_component parent=null);++  super.new(name, parent);++endfunction : new+++function void uvme_cv32e40x_buserr_sb_c::write_obid(uvma_obi_memory_mon_trn_c trn);++  cnt_obid_trn++;++  if (trn.err) begin+    cnt_obid_err++;++    if (!pending_nmi) begin+      cnt_obid_firsterr++;+      pending_nmi = 1;+    end+  end++endfunction : write_obid+++function void uvme_cv32e40x_buserr_sb_c::write_obii(uvma_obi_memory_mon_trn_c trn);++  cnt_obii_trn++;++  if (trn.err) begin+    cnt_obii_err++;+    add_to_err_queue(trn);+  end else begin+    // Acquit this address, as it was (re)fetched wo/ err+    remove_from_err_queue(trn);+  end++endfunction : write_obii+++function void uvme_cv32e40x_buserr_sb_c::write_rvfi(uvma_rvfi_instr_seq_item_c#(ILEN,XLEN) trn);++  bit [31:0] mcause = trn.csrs["mcause"].get_csr_retirement_data;+  bit [31:0] dcsr = trn.csrs["dcsr"].get_csr_retirement_data;+  bit step = dcsr[2];+  bit stepie = dcsr[11];++  cnt_rvfi_trn++;++  // Expected ifault retires+  if (should_instr_err(trn)) begin+    cnt_rvfi_errmatch++;++    assert (trn.trap)+      else `uvm_error(info_tag, $sformatf("retire at 0x%08x (expected 'err') lacks 'rvfi_trap'", trn.pc_rdata));+    assert (cnt_rvfi_errmatch - cnt_rvfi_ifaulthandl <= 1)+      else `uvm_error(info_tag, "too many err retires without ifault handling");+  end++  // D-side NMI handler+  if (trn.intr && mcause[31] && (mcause[30:0] inside {128, 129})) begin+    cnt_rvfi_nmihandl++;++    assert (pending_nmi)+      else `uvm_error(info_tag, "nmi handlered entered without sb having seen an 'err' on d-bus");+    pending_nmi = 0;++    assert (cnt_obid_firsterr == cnt_rvfi_nmihandl)+      else `uvm_error(info_tag, "expected D-bus 'err' count equal to handler entry count");+  end++  // I-side exception handler+  if (trn.intr && !mcause[31] && (mcause[31:0] == 48)) begin+    cnt_rvfi_ifaulthandl++;++    assert (cnt_rvfi_errmatch == cnt_rvfi_ifaulthandl)+      else `uvm_error(info_tag, "ifault handler entered without matching an ifault retirement");+  end++  // Retires after D-side "first err"+  if (pending_nmi && !trn.dbg_mode && !(step && !stepie)) begin+    late_retires++;+    assert (late_retires <= 2 + 1)  // "+1" is for the "rvfi_valid" that belongs to before the nmi+      else `uvm_error(info_tag, "more than 2 instructions retired before the nmi was taken");+  end+  if (!pending_nmi) begin+    late_retires = 0;+  end++endfunction : write_rvfi+++function void uvme_cv32e40x_buserr_sb_c::build_phase(uvm_phase phase);++  super.build_phase(phase);++  obid = new("obid", this);+  obii = new("obii", this);+  rvfi = new("rvfi", this);++endfunction : build_phase+++function void uvme_cv32e40x_buserr_sb_c::check_phase(uvm_phase phase);++  super.check_phase(phase);++  // Check OBI D-side+  assert (cnt_obid_trn > 0)+    else `uvm_warning(info_tag, "zero D-side OBI transactions received");+  assert (cnt_obid_trn >= cnt_obid_err)+    else `uvm_error(info_tag, "obid 'err' transactions counted wrong");+  assert (cnt_obid_trn != cnt_obid_err)+    else `uvm_warning(info_tag, "all the D-side OBI transactions were errs");+  assert (cnt_obid_err >= cnt_obid_firsterr)+    else `uvm_error(info_tag, "obid 'first' transactions counted wrong");+  assert (!(cnt_obid_err && !cnt_obid_firsterr))+    else `uvm_error(info_tag, "'first' errs counted wrong");++  // Check RVFI D-side+  assert (cnt_rvfi_trn >= cnt_rvfi_nmihandl)+    else `uvm_error(info_tag, "rvfi 'nmi' transactions counted wrong");+  assert (cnt_rvfi_trn != cnt_rvfi_nmihandl)+    else `uvm_error(info_tag, "all the rvfi transactions where nmi entries");++  // Check OBI D-side vs RVFI+  assert (cnt_obid_firsterr inside {cnt_rvfi_nmihandl, cnt_rvfi_nmihandl + 1})+    else `uvm_error(info_tag, $sformatf("more/less 'err' (%0d) than nmi handling (%0d)", cnt_obid_firsterr, cnt_rvfi_nmihandl));++  // Check OBI I-side+  assert (cnt_obii_trn > 0)+    else `uvm_warning(info_tag, "zero I-side OBI transactions received");+  assert (cnt_obii_trn >= cnt_obii_err)+    else `uvm_error(info_tag, "obii 'err' transactions counted wrong");+  assert (cnt_obii_trn != cnt_obii_err)+    else `uvm_warning(info_tag, "all the I-side OBI transactions were errs");++  // Check RVFI I-side+  assert (cnt_rvfi_errmatch >= cnt_rvfi_ifaulthandl)+    else `uvm_error(info_tag, "more instr fault handler than actual err retirements");+  assert (cnt_rvfi_errmatch == cnt_rvfi_ifaulthandl)+    else `uvm_warning(info_tag, $sformatf("err retires (%0d) != handler entries (%0d)", cnt_rvfi_errmatch, cnt_rvfi_ifaulthandl));++  // Check OBI I-side vs RVFI+  assert (cnt_obii_err >= cnt_rvfi_ifaulthandl)+    else `uvm_error(info_tag, $sformatf("less I-side err (%0d) than exception handling (%0d)", cnt_obii_err, cnt_rvfi_ifaulthandl));+  assert (cnt_obii_err >= cnt_rvfi_errmatch)+    else `uvm_warning(info_tag, "more retired errs than fetches");++  // Check RVFI (just a sanity check)+  assert (cnt_rvfi_trn > 0)+    else `uvm_warning(info_tag, "zero rvfi transactions received");++  // Inform about the end state+  `uvm_info(info_tag, $sformatf("received %0d D-side 'err' transactions", cnt_obid_err), UVM_NONE)+  `uvm_info(info_tag, $sformatf("received %0d D-side 'first err' transactions", cnt_obid_firsterr), UVM_NONE)+  `uvm_info(info_tag, $sformatf("observed %0d rvfi nmi handler entries", cnt_rvfi_nmihandl), UVM_NONE)+  `uvm_info(info_tag, $sformatf("received %0d I-side 'err' transactions", cnt_obii_err), UVM_NONE)+  `uvm_info(info_tag, $sformatf("retired %0d expectedly ifault instructions", cnt_rvfi_errmatch), UVM_NONE)+  `uvm_info(info_tag, $sformatf("observed %0d rvfi ifault handler entries", cnt_rvfi_ifaulthandl), UVM_NONE)++endfunction : check_phase+++function bit uvme_cv32e40x_buserr_sb_c::should_instr_err(uvma_rvfi_instr_seq_item_c#(ILEN,XLEN) rvfi_trn);++  uvma_obi_memory_addr_l_t  err_addrs[$];+  bit [31:0]                rvfi_addr = rvfi_trn.pc_rdata;++  // Extract all addrs from queue of I-side OBI "err" transactions+  foreach (obii_err_queue[i]) err_addrs[i] = obii_err_queue[i].address;++  foreach (err_addrs[i]) begin+    bit compressed =+      (rvfi_trn.insn[1:0] != 2'b 11)+      && !({rvfi_addr[31:2], 2'b 00} inside {err_addrs});+    bit [31:0] hi_addr = err_addrs[i] + 4;+    bit [31:0] lo_addr = err_addrs[i] - (compressed ? 2 : 4);+

This is a matter of preference, logic is not wrong - for readability I would suggest perhaps changing it to something like the following snippet. The non-inclusive range is not as intuitive to read and the "inside lo:hi" construction makes the intention obvious: bit [31:0] err_addr_range_hi = err_addrs[i] + 4 + 1; bit [31:0] err_addr_range_lo = err_addrs[i] - (compressed ? 2 : 4) - 1; if (rvfi_addr inside {[err_addr_range_lo:err_addr_range_hi]})

silabs-robin

comment created time in 13 days

PullRequestReviewEvent

Pull request review commentopenhwgroup/core-v-verif

Create bus errors (obi/rvfi) scoreboard for 40x

+// Copyright 2021 OpenHW Group+// Copyright 2021 Silicon Labs, Inc.+//+// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");+// you may not use this file except in compliance with the License.+// You may obtain a copy of the License at+//+//     https://solderpad.org/licenses/+//+// Unless required by applicable law or agreed to in writing, software+// distributed under the License is distributed on an "AS IS" BASIS,+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+// See the License for the specific language governing permissions and+// limitations under the License.+//+// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0+++`ifndef __UVME_CV32E40X_BUSERR_SB_SV__+`define __UVME_CV32E40X_BUSERR_SB_SV__+++`uvm_analysis_imp_decl(_obid)  // D-side OBI+`uvm_analysis_imp_decl(_obii)  // I-side OBI+`uvm_analysis_imp_decl(_rvfi)+++// Class: uvme_cv32e40x_buserr_sb_c+// A scoreboard to check that OBI "err" bus faults arrive at the RVFI.+// For I-side "err"s, the main mode of checking is to store every err-flagged+//   OBI transaction in a queue, and then compare the PC addresses of RVFI+//   retires to see that they have the expected impact.+// For D-side "err"s, the main mode of checking is to watch for the first "err"+//   (in, potentially, a series of "err"s) and demand that no more than two+//   RVFI retires (non-debug/step) happen before we must enter the NMI handler.+// There are also a couple of other checks to see if all counts are as expected.+class uvme_cv32e40x_buserr_sb_c extends uvm_scoreboard;++  string info_tag = "BUSERRSB";++  uvm_analysis_imp_obid#(uvma_obi_memory_mon_trn_c, uvme_cv32e40x_buserr_sb_c)  obid;+  uvm_analysis_imp_obii#(uvma_obi_memory_mon_trn_c, uvme_cv32e40x_buserr_sb_c)  obii;+  uvm_analysis_imp_rvfi#(uvma_rvfi_instr_seq_item_c#(ILEN,XLEN), uvme_cv32e40x_buserr_sb_c)  rvfi;++  // OBI D-side variables:+  int cnt_obid_trn;      // Count of all obi d-side transactions+  int cnt_obid_err;      // Count of all d-side "err" transactions+  int cnt_obid_firsterr; // Count of all first d-side "err", in case of multiple "err" before handler "taken"+  // OBI I-side variables:+  int cnt_obii_trn;  // Count of all obi i-side transactions+  int cnt_obii_err;  // Count of all i-side "err" transactions+  // RVFI variables:+  int cnt_rvfi_trn;         // Count of all rvfi transactions+  int cnt_rvfi_nmihandl;    // Count of all nmi handler entries+  int cnt_rvfi_ifaulthandl; // Count of all instr bus fault handler entries+  int cnt_rvfi_errmatch;    // Count of all retires matched with expected I-side "err"+  // Expectations variables:+  bit                       pending_nmi;       // Whether nmi happened and handler is expected+  int                       late_retires;      // Number of non-debug/step/handler retires since "pending_nmi"+  uvma_obi_memory_mon_trn_c obii_err_queue[$]; // All I-side OBI trns last seen with "err"++  `uvm_component_utils(uvme_cv32e40x_buserr_sb_c)++  extern function              new(string name="uvme_cv32e40x_buserr_sb", uvm_component parent=null);+  extern virtual function void write_obid(uvma_obi_memory_mon_trn_c trn);+  extern virtual function void write_obii(uvma_obi_memory_mon_trn_c trn);+  extern virtual function void write_rvfi(uvma_rvfi_instr_seq_item_c#(ILEN,XLEN) trn);+  extern virtual function void build_phase(uvm_phase phase);+  extern virtual function void check_phase(uvm_phase phase);+  extern function bit          should_instr_err(uvma_rvfi_instr_seq_item_c#(ILEN,XLEN) rvfi_trn);+  extern function void         remove_from_err_queue(uvma_obi_memory_mon_trn_c  trn);+  extern function void         add_to_err_queue(uvma_obi_memory_mon_trn_c  trn);++endclass : uvme_cv32e40x_buserr_sb_c+++function uvme_cv32e40x_buserr_sb_c::new(string name="uvme_cv32e40x_buserr_sb", uvm_component parent=null);++  super.new(name, parent);++endfunction : new+++function void uvme_cv32e40x_buserr_sb_c::write_obid(uvma_obi_memory_mon_trn_c trn);++  cnt_obid_trn++;++  if (trn.err) begin+    cnt_obid_err++;++    if (!pending_nmi) begin+      cnt_obid_firsterr++;+      pending_nmi = 1;+    end+  end++endfunction : write_obid+++function void uvme_cv32e40x_buserr_sb_c::write_obii(uvma_obi_memory_mon_trn_c trn);++  cnt_obii_trn++;++  if (trn.err) begin+    cnt_obii_err++;+    add_to_err_queue(trn);+  end else begin+    // Acquit this address, as it was (re)fetched wo/ err+    remove_from_err_queue(trn);+  end++endfunction : write_obii+++function void uvme_cv32e40x_buserr_sb_c::write_rvfi(uvma_rvfi_instr_seq_item_c#(ILEN,XLEN) trn);++  bit [31:0] mcause = trn.csrs["mcause"].get_csr_retirement_data;+  bit [31:0] dcsr = trn.csrs["dcsr"].get_csr_retirement_data;+  bit step = dcsr[2];+  bit stepie = dcsr[11];++  cnt_rvfi_trn++;++  // Expected ifault retires+  if (should_instr_err(trn)) begin+    cnt_rvfi_errmatch++;++    assert (trn.trap)+      else `uvm_error(info_tag, $sformatf("retire at 0x%08x (expected 'err') lacks 'rvfi_trap'", trn.pc_rdata));+    assert (cnt_rvfi_errmatch - cnt_rvfi_ifaulthandl <= 1)+      else `uvm_error(info_tag, "too many err retires without ifault handling");+  end++  // D-side NMI handler+  if (trn.intr && mcause[31] && (mcause[30:0] inside {128, 129})) begin+    cnt_rvfi_nmihandl++;++    assert (pending_nmi)+      else `uvm_error(info_tag, "nmi handlered entered without sb having seen an 'err' on d-bus");+    pending_nmi = 0;++    assert (cnt_obid_firsterr == cnt_rvfi_nmihandl)+      else `uvm_error(info_tag, "expected D-bus 'err' count equal to handler entry count");+  end++  // I-side exception handler+  if (trn.intr && !mcause[31] && (mcause[31:0] == 48)) begin+    cnt_rvfi_ifaulthandl++;++    assert (cnt_rvfi_errmatch == cnt_rvfi_ifaulthandl)+      else `uvm_error(info_tag, "ifault handler entered without matching an ifault retirement");+  end++  // Retires after D-side "first err"+  if (pending_nmi && !trn.dbg_mode && !(step && !stepie)) begin+    late_retires++;+    assert (late_retires <= 2 + 1)  // "+1" is for the "rvfi_valid" that belongs to before the nmi+      else `uvm_error(info_tag, "more than 2 instructions retired before the nmi was taken");+  end+  if (!pending_nmi) begin+    late_retires = 0;+  end++endfunction : write_rvfi+++function void uvme_cv32e40x_buserr_sb_c::build_phase(uvm_phase phase);++  super.build_phase(phase);++  obid = new("obid", this);+  obii = new("obii", this);+  rvfi = new("rvfi", this);++endfunction : build_phase+++function void uvme_cv32e40x_buserr_sb_c::check_phase(uvm_phase phase);++  super.check_phase(phase);++  // Check OBI D-side+  assert (cnt_obid_trn > 0)+    else `uvm_warning(info_tag, "zero D-side OBI transactions received");+  assert (cnt_obid_trn >= cnt_obid_err)+    else `uvm_error(info_tag, "obid 'err' transactions counted wrong");+  assert (cnt_obid_trn != cnt_obid_err)+    else `uvm_warning(info_tag, "all the D-side OBI transactions were errs");+  assert (cnt_obid_err >= cnt_obid_firsterr)+    else `uvm_error(info_tag, "obid 'first' transactions counted wrong");+  assert (!(cnt_obid_err && !cnt_obid_firsterr))+    else `uvm_error(info_tag, "'first' errs counted wrong");++  // Check RVFI D-side+  assert (cnt_rvfi_trn >= cnt_rvfi_nmihandl)+    else `uvm_error(info_tag, "rvfi 'nmi' transactions counted wrong");+  assert (cnt_rvfi_trn != cnt_rvfi_nmihandl)+    else `uvm_error(info_tag, "all the rvfi transactions where nmi entries");++  // Check OBI D-side vs RVFI+  assert (cnt_obid_firsterr inside {cnt_rvfi_nmihandl, cnt_rvfi_nmihandl + 1})+    else `uvm_error(info_tag, $sformatf("more/less 'err' (%0d) than nmi handling (%0d)", cnt_obid_firsterr, cnt_rvfi_nmihandl));++  // Check OBI I-side+  assert (cnt_obii_trn > 0)+    else `uvm_warning(info_tag, "zero I-side OBI transactions received");+  assert (cnt_obii_trn >= cnt_obii_err)+    else `uvm_error(info_tag, "obii 'err' transactions counted wrong");+  assert (cnt_obii_trn != cnt_obii_err)+    else `uvm_warning(info_tag, "all the I-side OBI transactions were errs");++  // Check RVFI I-side+  assert (cnt_rvfi_errmatch >= cnt_rvfi_ifaulthandl)+    else `uvm_error(info_tag, "more instr fault handler than actual err retirements");+  assert (cnt_rvfi_errmatch == cnt_rvfi_ifaulthandl)+    else `uvm_warning(info_tag, $sformatf("err retires (%0d) != handler entries (%0d)", cnt_rvfi_errmatch, cnt_rvfi_ifaulthandl));++  // Check OBI I-side vs RVFI+  assert (cnt_obii_err >= cnt_rvfi_ifaulthandl)+    else `uvm_error(info_tag, $sformatf("less I-side err (%0d) than exception handling (%0d)", cnt_obii_err, cnt_rvfi_ifaulthandl));+  assert (cnt_obii_err >= cnt_rvfi_errmatch)+    else `uvm_warning(info_tag, "more retired errs than fetches");++  // Check RVFI (just a sanity check)+  assert (cnt_rvfi_trn > 0)+    else `uvm_warning(info_tag, "zero rvfi transactions received");++  // Inform about the end state+  `uvm_info(info_tag, $sformatf("received %0d D-side 'err' transactions", cnt_obid_err), UVM_NONE)+  `uvm_info(info_tag, $sformatf("received %0d D-side 'first err' transactions", cnt_obid_firsterr), UVM_NONE)+  `uvm_info(info_tag, $sformatf("observed %0d rvfi nmi handler entries", cnt_rvfi_nmihandl), UVM_NONE)+  `uvm_info(info_tag, $sformatf("received %0d I-side 'err' transactions", cnt_obii_err), UVM_NONE)+  `uvm_info(info_tag, $sformatf("retired %0d expectedly ifault instructions", cnt_rvfi_errmatch), UVM_NONE)+  `uvm_info(info_tag, $sformatf("observed %0d rvfi ifault handler entries", cnt_rvfi_ifaulthandl), UVM_NONE)++endfunction : check_phase+++function bit uvme_cv32e40x_buserr_sb_c::should_instr_err(uvma_rvfi_instr_seq_item_c#(ILEN,XLEN) rvfi_trn);++  uvma_obi_memory_addr_l_t  err_addrs[$];+  bit [31:0]                rvfi_addr = rvfi_trn.pc_rdata;++  // Extract all addrs from queue of I-side OBI "err" transactions+  foreach (obii_err_queue[i]) err_addrs[i] = obii_err_queue[i].address;

easier to read if using begin-end construct instead of one-liner loops (and often also less error prone)

silabs-robin

comment created time in 13 days

PullRequestReviewEvent

Pull request review commentopenhwgroup/core-v-verif

Create bus errors (obi/rvfi) scoreboard for 40x

+// Copyright 2021 OpenHW Group+// Copyright 2021 Silicon Labs, Inc.+//+// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");+// you may not use this file except in compliance with the License.+// You may obtain a copy of the License at+//+//     https://solderpad.org/licenses/+//+// Unless required by applicable law or agreed to in writing, software+// distributed under the License is distributed on an "AS IS" BASIS,+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+// See the License for the specific language governing permissions and+// limitations under the License.+//+// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0+++`ifndef __UVME_CV32E40X_BUSERR_SB_SV__+`define __UVME_CV32E40X_BUSERR_SB_SV__+++`uvm_analysis_imp_decl(_obid)  // D-side OBI+`uvm_analysis_imp_decl(_obii)  // I-side OBI+`uvm_analysis_imp_decl(_rvfi)+++// Class: uvme_cv32e40x_buserr_sb_c+// A scoreboard to check that OBI "err" bus faults arrive at the RVFI.+// For I-side "err"s, the main mode of checking is to store every err-flagged+//   OBI transaction in a queue, and then compare the PC addresses of RVFI+//   retires to see that they have the expected impact.+// For D-side "err"s, the main mode of checking is to watch for the first "err"+//   (in, potentially, a series of "err"s) and demand that no more than two+//   RVFI retires (non-debug/step) happen before we must enter the NMI handler.+// There are also a couple of other checks to see if all counts are as expected.+class uvme_cv32e40x_buserr_sb_c extends uvm_scoreboard;++  string info_tag = "BUSERRSB";++  uvm_analysis_imp_obid#(uvma_obi_memory_mon_trn_c, uvme_cv32e40x_buserr_sb_c)  obid;+  uvm_analysis_imp_obii#(uvma_obi_memory_mon_trn_c, uvme_cv32e40x_buserr_sb_c)  obii;+  uvm_analysis_imp_rvfi#(uvma_rvfi_instr_seq_item_c#(ILEN,XLEN), uvme_cv32e40x_buserr_sb_c)  rvfi;++  // OBI D-side variables:+  int cnt_obid_trn;      // Count of all obi d-side transactions+  int cnt_obid_err;      // Count of all d-side "err" transactions+  int cnt_obid_firsterr; // Count of all first d-side "err", in case of multiple "err" before handler "taken"+  // OBI I-side variables:+  int cnt_obii_trn;  // Count of all obi i-side transactions+  int cnt_obii_err;  // Count of all i-side "err" transactions+  // RVFI variables:+  int cnt_rvfi_trn;         // Count of all rvfi transactions+  int cnt_rvfi_nmihandl;    // Count of all nmi handler entries+  int cnt_rvfi_ifaulthandl; // Count of all instr bus fault handler entries+  int cnt_rvfi_errmatch;    // Count of all retires matched with expected I-side "err"+  // Expectations variables:+  bit                       pending_nmi;       // Whether nmi happened and handler is expected+  int                       late_retires;      // Number of non-debug/step/handler retires since "pending_nmi"+  uvma_obi_memory_mon_trn_c obii_err_queue[$]; // All I-side OBI trns last seen with "err"++  `uvm_component_utils(uvme_cv32e40x_buserr_sb_c)++  extern function              new(string name="uvme_cv32e40x_buserr_sb", uvm_component parent=null);+  extern virtual function void write_obid(uvma_obi_memory_mon_trn_c trn);+  extern virtual function void write_obii(uvma_obi_memory_mon_trn_c trn);+  extern virtual function void write_rvfi(uvma_rvfi_instr_seq_item_c#(ILEN,XLEN) trn);+  extern virtual function void build_phase(uvm_phase phase);+  extern virtual function void check_phase(uvm_phase phase);+  extern function bit          should_instr_err(uvma_rvfi_instr_seq_item_c#(ILEN,XLEN) rvfi_trn);+  extern function void         remove_from_err_queue(uvma_obi_memory_mon_trn_c  trn);+  extern function void         add_to_err_queue(uvma_obi_memory_mon_trn_c  trn);++endclass : uvme_cv32e40x_buserr_sb_c+++function uvme_cv32e40x_buserr_sb_c::new(string name="uvme_cv32e40x_buserr_sb", uvm_component parent=null);++  super.new(name, parent);++endfunction : new+++function void uvme_cv32e40x_buserr_sb_c::write_obid(uvma_obi_memory_mon_trn_c trn);++  cnt_obid_trn++;++  if (trn.err) begin+    cnt_obid_err++;++    if (!pending_nmi) begin+      cnt_obid_firsterr++;+      pending_nmi = 1;+    end+  end++endfunction : write_obid+++function void uvme_cv32e40x_buserr_sb_c::write_obii(uvma_obi_memory_mon_trn_c trn);++  cnt_obii_trn++;++  if (trn.err) begin+    cnt_obii_err++;+    add_to_err_queue(trn);+  end else begin+    // Acquit this address, as it was (re)fetched wo/ err+    remove_from_err_queue(trn);+  end++endfunction : write_obii+++function void uvme_cv32e40x_buserr_sb_c::write_rvfi(uvma_rvfi_instr_seq_item_c#(ILEN,XLEN) trn);++  bit [31:0] mcause = trn.csrs["mcause"].get_csr_retirement_data;+  bit [31:0] dcsr = trn.csrs["dcsr"].get_csr_retirement_data;+  bit step = dcsr[2];+  bit stepie = dcsr[11];++  cnt_rvfi_trn++;++  // Expected ifault retires+  if (should_instr_err(trn)) begin+    cnt_rvfi_errmatch++;++    assert (trn.trap)+      else `uvm_error(info_tag, $sformatf("retire at 0x%08x (expected 'err') lacks 'rvfi_trap'", trn.pc_rdata));+    assert (cnt_rvfi_errmatch - cnt_rvfi_ifaulthandl <= 1)+      else `uvm_error(info_tag, "too many err retires without ifault handling");+  end++  // D-side NMI handler+  if (trn.intr && mcause[31] && (mcause[30:0] inside {128, 129})) begin+    cnt_rvfi_nmihandl++;++    assert (pending_nmi)+      else `uvm_error(info_tag, "nmi handlered entered without sb having seen an 'err' on d-bus");+    pending_nmi = 0;++    assert (cnt_obid_firsterr == cnt_rvfi_nmihandl)+      else `uvm_error(info_tag, "expected D-bus 'err' count equal to handler entry count");+  end++  // I-side exception handler+  if (trn.intr && !mcause[31] && (mcause[31:0] == 48)) begin+    cnt_rvfi_ifaulthandl++;++    assert (cnt_rvfi_errmatch == cnt_rvfi_ifaulthandl)+      else `uvm_error(info_tag, "ifault handler entered without matching an ifault retirement");+  end++  // Retires after D-side "first err"+  if (pending_nmi && !trn.dbg_mode && !(step && !stepie)) begin+    late_retires++;+    assert (late_retires <= 2 + 1)  // "+1" is for the "rvfi_valid" that belongs to before the nmi+      else `uvm_error(info_tag, "more than 2 instructions retired before the nmi was taken");+  end+  if (!pending_nmi) begin+    late_retires = 0;+  end++endfunction : write_rvfi+++function void uvme_cv32e40x_buserr_sb_c::build_phase(uvm_phase phase);++  super.build_phase(phase);++  obid = new("obid", this);+  obii = new("obii", this);+  rvfi = new("rvfi", this);++endfunction : build_phase+++function void uvme_cv32e40x_buserr_sb_c::check_phase(uvm_phase phase);++  super.check_phase(phase);++  // Check OBI D-side+  assert (cnt_obid_trn > 0)+    else `uvm_warning(info_tag, "zero D-side OBI transactions received");+  assert (cnt_obid_trn >= cnt_obid_err)+    else `uvm_error(info_tag, "obid 'err' transactions counted wrong");+  assert (cnt_obid_trn != cnt_obid_err)+    else `uvm_warning(info_tag, "all the D-side OBI transactions were errs");

L186's >= overlaps L186's !=, is it necessary to both warn and err in case of >= ?

Same goes for the I-side further down.

silabs-robin

comment created time in 13 days

PullRequestReviewEvent
PullRequestReviewEvent

pull request commentgoogle/riscv-dv

Bitmanip v1.0.0 support

Note that I have split out the zb*-extensions from the b-extensions, as the notion of a common B extension is somewhat deprecated. I would suggest building any further sub-extensions to the B-extension as separate Zb*-extensions for ease of maintenance.

silabs-hfegran

comment created time in 16 days

issue commentgoogle/riscv-dv

support for bitmanip 1.0.0 in the near term

Hi, I have added support for the v.1.0.0 extensions with PR #832 Sub-extensions for v.0.9x have not been updated in this PR.

strichmo

comment created time in 16 days

PR opened google/riscv-dv

Bitmanip v1.0.0 support

This commits add support for the Zba, Zbb, Zbc and Zbs extensions.

`define BITMANIP_V1_0_0 in riscv_instr_pkg.sv enables these added features, and support for 0.92 has been retained, selectable by instead defining BITMANIP_V0_9_2

Similar to the previous b-extension, the zb*-extensions are enabled by setting the +enable_zb*_extension plusargs and adding the required isas (RV32ZB* / RV64ZB*) to the list of supported isa.

+1211 -2

0 comment

18 changed files

pr created time in 16 days

push eventsilabs-hfegran/riscv-dv

Henrik Fegran

commit sha e5da72ddd24040a808df21cce9c5229ff75b9408

Added v1.0.0 bitmanip support Signed-off-by: Henrik Fegran <Henrik.Fegran@silabs.com>

view details

push time in 16 days

push eventsilabs-hfegran/riscv-dv

Henrik Fegran

commit sha 4ab094ce18f3b5aa36c4d537716f6aac90031078

Added v1.0.0 bitmanip support Signed-off-by: Henrik Fegran <Henrik.Fegran@silabs.com>

view details

push time in 16 days

push eventsilabs-hfegran/riscv-dv

Henrik Fegran

commit sha 85555ac57db40176142ccb368d853c660140b50d

Fixes Signed-off-by: Henrik Fegran <Henrik.Fegran@silabs.com>

view details

Henrik Fegran

commit sha 850e112eda8af5e24daacf709eca217efa2252c7

Fixes Signed-off-by: Henrik Fegran <Henrik.Fegran@silabs.com>

view details

Henrik Fegran

commit sha c762e8bf699900e2723f19a1768972413e6f5749

Fixes Signed-off-by: Henrik Fegran <Henrik.Fegran@silabs.com>

view details

push time in 16 days

push eventsilabs-hfegran/riscv-dv

Henrik Fegran

commit sha 811581de5955c65df52149a82bc3e4fb0f201c7f

Bugfixes Signed-off-by: Henrik Fegran <Henrik.Fegran@silabs.com>

view details

push time in 16 days

create barnchsilabs-hfegran/riscv-dv

branch : dev_hf_bitmanipv1_0

created branch time in 16 days

create barnchsilabs-hfegran/core-v-verif

branch : dev_hf_scancg_en_floating

created branch time in 23 days

create barnchsilabs-hfegran/cv32e40x

branch : dev_hf_bugfix

created branch time in 23 days

PullRequestReviewEvent

Pull request review commentopenhwgroup/cv32e40x

Updated pma-related assertions

 module cv32e40x_mpu_sva import cv32e40x_pkg::*; import uvm_pkg::*;       else `uvm_error("mpu", "PMA number of regions is badly configured")    // Region matching-  a_pma_match_bounds :-    assert property (@(posedge clk) disable iff (!rst_n)-                     is_pma_matched |-> (is_lobound_ok && is_hibound_ok))-      else `uvm_error("mpu", "PMA region match doesn't fit bounds")-  a_pma_match_lowest :-    assert property (@(posedge clk) disable iff (!rst_n)-                     is_pma_matched |-> (pma_match_num == pma_lowest_match))-      else `uvm_error("mpu", "PMA region match wasn't lowest")-  a_pma_match_index :-    assert property (@(posedge clk) disable iff (!rst_n)-                     is_pma_matched |-> ((0 <= pma_match_num) && (pma_match_num <= 16)))-      else `uvm_error("mpu", "illegal cfg index")+  generate+    if (PMA_NUM_REGIONS) begin+      a_pma_match_bounds :+        assert property (@(posedge clk) disable iff (!rst_n)+                         is_pma_matched |-> (is_lobound_ok && is_hibound_ok))+          else `uvm_error("mpu", "PMA region match doesn't fit bounds")+      a_pma_match_lowest :+        assert property (@(posedge clk) disable iff (!rst_n)+                         is_pma_matched |-> (pma_match_num == pma_lowest_match))+          else `uvm_error("mpu", "PMA region match wasn't lowest")+      a_pma_match_index :+        assert property (@(posedge clk) disable iff (!rst_n)+                         is_pma_matched |-> ((0 <= pma_match_num) && (pma_match_num <= 16)))

Agreed, this should have been < 16

silabs-hfegran

comment created time in 24 days

Pull request review commentopenhwgroup/cv32e40x

Updated pma-related assertions

 always_ff @(posedge clk , negedge rst_ni)                      (data_req_o && !data_we_o |-> !data_memtype_o[0]))       else `uvm_error("core", "Load instruction classified as bufferable") -  // Check that atomic operations are always non-bufferable-  a_atomic_non_bufferable :-    assert property (@(posedge clk) disable iff (!rst_ni)-                     (data_req_o && |data_atop_o |-> !data_memtype_o[0]))-      else `uvm_error("core", "Atomic operation classified as bufferable")-    ++  generate+    if (!A_EXT) begin+      a_atomic_disabled_never_atop :+        assert property (@(posedge clk) disable iff (!rst_ni)+                         !data_atop_o)

Thanks, updated code accordingly

silabs-hfegran

comment created time in 24 days

PullRequestReviewEvent

push eventsilabs-hfegran/cv32e40x

Henrik Fegran

commit sha a052ebfa1dafd29cc49091b590600418396d5a4b

Implemented core and mpu assertion review feedback Signed-off-by: Henrik Fegran <Henrik.Fegran@silabs.com>

view details

push time in 24 days

Pull request review commentopenhwgroup/cv32e40x

Updated pma-related assertions

 always_ff @(posedge clk , negedge rst_ni)                      (data_req_o && !data_we_o |-> !data_memtype_o[0]))       else `uvm_error("core", "Load instruction classified as bufferable") -  // Check that atomic operations are always non-bufferable-  a_atomic_non_bufferable :-    assert property (@(posedge clk) disable iff (!rst_ni)-                     (data_req_o && |data_atop_o |-> !data_memtype_o[0]))-      else `uvm_error("core", "Atomic operation classified as bufferable")-    ++  generate+    if (!A_EXT) begin+      a_atomic_disabled_never_atop :+        assert property (@(posedge clk) disable iff (!rst_ni)+                         !data_atop_o)+          else `uvm_error("core", "Atomic operations should never occur without A-extension enabled")+    end+    else begin+      // Check that atomic operations are always non-bufferable+      a_atomic_non_bufferable :+        assert property (@(posedge clk) disable iff (!rst_ni)+                         (data_req_o && |data_atop_o |-> !data_memtype_o[0]))+          else `uvm_error("core", "Atomic operation classified as bufferable")

This is not a typo - it is in line with the other messages in this sva-file; i.e. not reporting what the assertion should do, but actually what (erroneously) happened.

silabs-hfegran

comment created time in a month

more