UVM环境介绍
HEAD commitID: 1f968ef
// Copyright 2020 OpenHW Group
// Copyright 2020 Datum Technology Corporation
// Copyright 2020 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.
`ifndef __UVMA_INTERRUPT_IF_SV__
`define __UVMA_INTERRUPT_IF_SV__
/**
* Encapsulates all signals and clocking of Interrupt interface. Used by
* monitor and driver.
*/
interface uvma_interrupt_if
(
);
// ---------------------------------------------------------------------------
// Interface wires
// ---------------------------------------------------------------------------
wire clk;
wire reset_n;
wire [31:0] irq;
wire irq_ack;
wire [4:0] irq_id;
// Used to time true interrupt entry with tracer instruction retirement
wire deferint;
wire ovp_cpu_state_stepi;
// -------------------------------------------------------------------
// Testbench control
// ---------------------------------------------------------------------------
// -------------------------------------------------------------------
bit is_active; // Set to active drive the interrupt lines
bit [31:0] irq_drv; // TB interrupt driver
// -------------------------------------------------------------------
// Begin module code
// -------------------------------------------------------------------
// Mux in driver to irq lines
assign irq = is_active ? irq_drv : 1'b0;
initial begin
is_active = 1'b0;
irq_drv = '0;
end
/**
* Used by target DUT.
*/
clocking dut_cb @(posedge clk or reset_n);
endclocking : dut_cb
/**
* Used by uvma_interrupt_drv_c.
*/
clocking drv_cb @(posedge clk or reset_n);
input #1step irq_ack,
irq_id;
output irq_drv;
endclocking : drv_cb
/**
* Used by uvma_interrupt_mon_c.
*/
clocking mon_cb @(posedge clk or reset_n);
input #1step irq_ack,
irq_id,
irq_drv;
endclocking : mon_cb
modport dut_mp (clocking dut_cb);
modport active_mp (clocking drv_cb);
modport passive_mp(clocking mon_cb);
endinterface : uvma_interrupt_if
`endif // __UVMA_INTERRUPT_IF_SV__
该文件是中断验证环境的接口定义文件,主要功能包括:
wire clk;
wire reset_n;
wire [31:0] irq;
wire irq_ack;
wire [4:0] irq_id;
clk
:时钟信号reset_n
:复位信号(低有效)irq
:32位中断请求信号irq_ack
:中断响应信号irq_id
:中断ID标识bit is_active;
bit [31:0] irq_drv;
is_active
:控制是否主动驱动中断irq_drv
:测试平台驱动值clocking dut_cb @(posedge clk or reset_n);
endclocking
clocking drv_cb @(posedge clk or reset_n);
input #1step irq_ack, irq_id;
output irq_drv;
endclocking
assign irq = is_active ? irq_drv : 1'b0;
initial begin
is_active = 1'b0;
irq_drv = '0;
end
该接口文件具有以下特点:
作为验证环境的基础组件,它为中断验证提供了可靠的接口定义,确保验证组件能够正确访问DUT信号。
// Copyright 2020 OpenHW Group
// Copyright 2020 Datum Technology Corporation
// Copyright 2020 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.
`ifndef __UVMA_INTERRUPT_MON_TRN_LOGGER_SV__
`define __UVMA_INTERRUPT_MON_TRN_LOGGER_SV__
/**
* Component writing Interrupt monitor transactions interrupt data to disk as plain text.
*/
class uvma_interrupt_mon_trn_logger_c extends uvml_logs_mon_trn_logger_c#(
.T_TRN (uvma_interrupt_mon_trn_c),
.T_CFG (uvma_interrupt_cfg_c ),
.T_CNTXT(uvma_interrupt_cntxt_c )
);
`uvm_component_utils(uvma_interrupt_mon_trn_logger_c)
/**
* Default constructor.
*/
function new(string name="uvma_interrupt_mon_trn_logger", uvm_component parent=null);
super.new(name, parent);
endfunction : new
/**
* Writes contents of t to disk
*/
virtual function void write(uvma_interrupt_mon_trn_c t);
// TODO Implement uvma_interrupt_mon_trn_logger_c::write()
// Ex: fwrite($sformatf(" %t | %08h | %02b | %04d | %02h |", $realtime(), t.a, t.b, t.c, t.d));
endfunction : write
/**
* Writes log header to disk
*/
virtual function void print_header();
// TODO Implement uvma_interrupt_mon_trn_logger_c::print_header()
// Ex: fwrite("----------------------------------------------");
// fwrite(" TIME | FIELD A | FIELD B | FIELD C | FIELD D ");
// fwrite("----------------------------------------------");
endfunction : print_header
endclass : uvma_interrupt_mon_trn_logger_c
/**
* Component writing INTERRUPT monitor transactions interrupt data to disk as JavaScript Object Notation (JSON).
*/
class uvma_interrupt_mon_trn_logger_json_c extends uvma_interrupt_mon_trn_logger_c;
`uvm_component_utils(uvma_interrupt_mon_trn_logger_json_c)
/**
* Set file extension to '.json'.
*/
function new(string name="uvma_interrupt_mon_trn_logger_json", uvm_component parent=null);
super.new(name, parent);
fextension = "json";
endfunction : new
/**
* Writes contents of t to disk.
*/
virtual function void write(uvma_interrupt_mon_trn_c t);
// TODO Implement uvma_interrupt_mon_trn_logger_json_c::write()
// Ex: fwrite({"{",
// $sformatf("\"time\":\"%0t\",", $realtime()),
// $sformatf("\"a\":%h," , t.a ),
// $sformatf("\"b\":%b," , t.b ),
// $sformatf("\"c\":%d," , t.c ),
// $sformatf("\"d\":%h," , t.c ),
// "},"});
endfunction : write
/**
* Empty function.
*/
virtual function void print_header();
// Do nothing: JSON files do not use headers.
endfunction : print_header
endclass : uvma_interrupt_mon_trn_logger_json_c
`endif // __UVMA_INTERRUPT_MON_TRN_LOGGER_SV__
该文件是中断验证环境的监控事务日志记录器实现,主要功能包括:
class uvma_interrupt_mon_trn_logger_c extends uvml_logs_mon_trn_logger_c#(
.T_TRN(uvma_interrupt_mon_trn_c),
.T_CFG(uvma_interrupt_cfg_c),
.T_CNTXT(uvma_interrupt_cntxt_c)
);
class uvma_interrupt_mon_trn_logger_json_c extends uvma_interrupt_mon_trn_logger_c;
function new(string name="uvma_interrupt_mon_trn_logger_json", uvm_component parent=null);
fextension = "json";
endfunction
endclass
function new(string name="uvma_interrupt_mon_trn_logger", uvm_component parent=null);
super.new(name, parent);
endfunction
virtual function void write(uvma_interrupt_mon_trn_c t);
// TODO Implement write logic
// Ex: fwrite($sformatf(" %t | %08h |", $realtime(), t.a));
endfunction
virtual function void print_header();
// TODO Implement header
// Ex: fwrite("---------------------");
endfunction
该日志记录器组件具有以下特点:
作为验证环境的辅助组件,它为中断监控事务提供了可靠的记录能力,便于后续分析和调试。
// Copyright 2020 OpenHW Group
// Copyright 2020 Datum Technology Corporation
// Copyright 2020 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.
`ifndef __UVMA_INTERRUPT_MON_TRN_SV__
`define __UVMA_INTERRUPT_MON_TRN_SV__
/**
* Object rebuilt from the Interrupt monitor Analog of uvma_interrupt_seq_item_c.
*/
class uvma_interrupt_mon_trn_c extends uvml_trn_mon_trn_c;
uvma_interrupt_mon_action_enum action;
int unsigned id;
`uvm_object_utils_begin(uvma_interrupt_mon_trn_c)
`uvm_field_enum(uvma_interrupt_mon_action_enum, action, UVM_DEFAULT)
`uvm_field_int(id, UVM_DEFAULT)
`uvm_object_utils_end
/**
* Default constructor.
*/
extern function new(string name="uvma_interrupt_mon_trn");
endclass : uvma_interrupt_mon_trn_c
`pragma protect begin
function uvma_interrupt_mon_trn_c::new(string name="uvma_interrupt_mon_trn");
super.new(name);
endfunction : new
`pragma protect end
`endif // __UVMA_INTERRUPT_MON_TRN_SV__
该文件是中断验证环境的监控事务类实现,主要功能包括:
class uvma_interrupt_mon_trn_c extends uvml_trn_mon_trn_c;
`uvm_object_utils_begin(uvma_interrupt_mon_trn_c)
`uvm_field_enum(uvma_interrupt_mon_action_enum, action, UVM_DEFAULT)
`uvm_field_int(id, UVM_DEFAULT)
`uvm_object_utils_end
uvma_interrupt_mon_action_enum action;
int unsigned id;
function uvma_interrupt_mon_trn_c::new(string name="uvma_interrupt_mon_trn");
super.new(name);
endfunction
该监控事务类具有以下特点:
作为验证环境的基础数据结构,它为中断监控提供了可靠的数据表示能力,确保监控数据能够正确传递和处理。
//
// Copyright 2020 OpenHW Group
// Copyright 2020 Datum Technology Corporation
// Copyright 2020 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.
//
`ifndef __UVMA_INTERRUPT_MON_SV__
`define __UVMA_INTERRUPT_MON_SV__
/**
* Component sampling transactions from a Clock & Reset virtual interface
* (uvma_interrupt_if).
*/
class uvma_interrupt_mon_c extends uvm_monitor;
// Objects
uvma_interrupt_cfg_c cfg;
uvma_interrupt_cntxt_c cntxt;
// TLM
// This analysis port will fire when the irq_ack_o is seen (core acknowledges the interrupt)
uvm_analysis_port#(uvma_interrupt_mon_trn_c) ap;
// This analysis port will fire when the first instruction in the ISR is retired (i.e. the MTVEC location)
uvm_analysis_port#(uvma_interrupt_mon_trn_c) ap_iss;
`uvm_component_utils_begin(uvma_interrupt_mon_c)
`uvm_field_object(cfg , UVM_DEFAULT)
`uvm_field_object(cntxt, UVM_DEFAULT)
`uvm_component_utils_end
/**
* Default constructor.
*/
extern function new(string name="uvma_interrupt_mon", uvm_component parent=null);
/**
* 1. Ensures cfg & cntxt handles are not null.
* 2. Builds ap.
*/
extern virtual function void build_phase(uvm_phase phase);
/**
* Oversees monitoring via monitor_clk() and monitor_reset() tasks in parallel
* forks.
*/
extern virtual task run_phase(uvm_phase phase);
/**
* Publish a monitor transactin when interrupt is taken.
*/
extern virtual task monitor_irq();
/**
* Publish a monitor transaction when interrupt is taken (delayed until the first instruction of the ISR is retired)
*/
extern virtual task monitor_irq_iss();
endclass : uvma_interrupt_mon_c
function uvma_interrupt_mon_c::new(string name="uvma_interrupt_mon", uvm_component parent=null);
super.new(name, parent);
endfunction : new
function void uvma_interrupt_mon_c::build_phase(uvm_phase phase);
super.build_phase(phase);
void'(uvm_config_db#(uvma_interrupt_cfg_c)::get(this, "", "cfg", cfg));
if (cfg == null) begin
`uvm_fatal("CFG", "Configuration handle is null")
end
void'(uvm_config_db#(uvma_interrupt_cntxt_c)::get(this, "", "cntxt", cntxt));
if (cntxt == null) begin
`uvm_fatal("CNTXT", "Context handle is null")
end
ap = new("ap", this);
ap_iss = new("ap_iss", this);
endfunction : build_phase
task uvma_interrupt_mon_c::run_phase(uvm_phase phase);
super.run_phase(phase);
if (cfg.enabled) begin
while (1) begin
wait (cntxt.vif.reset_n === 1'b0);
wait (cntxt.vif.reset_n === 1'b1);
fork begin
// To maintain random thread stability launch iss thread always, but it will exit immediately if no iss configured
fork
monitor_irq();
monitor_irq_iss();
join_none
wait (cntxt.vif.reset_n === 1'b0);
disable fork;
end
join
end
end
endtask : run_phase
task uvma_interrupt_mon_c::monitor_irq();
while(1) begin
@(cntxt.vif.mon_cb);
if (cntxt.vif.mon_cb.irq_ack) begin
uvma_interrupt_mon_trn_c mon_trn = uvma_interrupt_mon_trn_c::type_id::create("mon_irq_trn");
mon_trn.action = UVMA_INTERRUPT_MON_ACTION_IRQ;
mon_trn.id = cntxt.vif.mon_cb.irq_id;
ap.write(mon_trn);
end
end
endtask : monitor_irq
task uvma_interrupt_mon_c::monitor_irq_iss();
if ($test$plusargs("USE_ISS")) begin
while(1) begin
@(cntxt.vif.mon_cb);
if (cntxt.vif.mon_cb.irq_ack) begin
uvma_interrupt_mon_trn_c mon_trn = uvma_interrupt_mon_trn_c::type_id::create("mon_irq_trn");
mon_trn.action = UVMA_INTERRUPT_MON_ACTION_IRQ;
mon_trn.id = cntxt.vif.mon_cb.irq_id;
// Wait for the ISS to enter
wait (cntxt.vif.deferint == 1'b0);
wait (cntxt.vif.ovp_cpu_state_stepi == 1'b1);
ap_iss.write(mon_trn);
end
end
end
endtask : monitor_irq_iss
`endif // __UVMA_INTERRUPT_MON_SV__
该文件是中断验证环境的监控器实现,主要功能包括:
class uvma_interrupt_mon_c extends uvm_monitor;
uvm_analysis_port#(uvma_interrupt_mon_trn_c) ap;
uvm_analysis_port#(uvma_interrupt_mon_trn_c) ap_iss;
ap
:用于中断响应监控ap_iss
:用于ISS集成监控uvma_interrupt_cfg_c cfg;
uvma_interrupt_cntxt_c cntxt;
task run_phase(uvm_phase phase);
while (1) begin
wait (cntxt.vif.reset_n === 1'b0);
wait (cntxt.vif.reset_n === 1'b1);
fork
monitor_irq();
monitor_irq_iss();
join_none
end
endtask
task monitor_irq();
if (cntxt.vif.mon_cb.irq_ack) begin
uvma_interrupt_mon_trn_c mon_trn = uvma_interrupt_mon_trn_c::type_id::create("mon_irq_trn");
mon_trn.action = UVMA_INTERRUPT_MON_ACTION_IRQ;
mon_trn.id = cntxt.vif.mon_cb.irq_id;
ap.write(mon_trn);
end
endtask
该监控器组件具有以下特点:
作为验证环境的关键组件,它为中断接口提供了全面的监控能力,确保验证过程能够正确捕获DUT行为。
//
// Copyright 2020 OpenHW Group
// Copyright 2020 Datum Technology Corporation
// Copyright 2020 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.
//
`ifndef __UVMA_INTERRUPT_SQR_SV__
`define __UVMA_INTERRUPT_SQR_SV__
/**
* Component running Clock & Reset sequences extending uvma_interrupt_seq_base_c.
* Provides sequence items for uvma_interrupt_drv_c.
*/
class uvma_interrupt_sqr_c extends uvm_sequencer#(
.REQ(uvma_interrupt_seq_item_c),
.RSP(uvma_interrupt_seq_item_c)
);
// Objects
uvma_interrupt_cfg_c cfg;
uvma_interrupt_cntxt_c cntxt;
`uvm_component_utils_begin(uvma_interrupt_sqr_c)
`uvm_field_object(cfg , UVM_DEFAULT)
`uvm_field_object(cntxt, UVM_DEFAULT)
`uvm_component_utils_end
/**
* Default constructor.
*/
extern function new(string name="uvma_interrupt_sqr", uvm_component parent=null);
/**
* Ensures cfg & cntxt handles are not null
*/
extern virtual function void build_phase(uvm_phase phase);
endclass : uvma_interrupt_sqr_c
function uvma_interrupt_sqr_c::new(string name="uvma_interrupt_sqr", uvm_component parent=null);
super.new(name, parent);
endfunction : new
function void uvma_interrupt_sqr_c::build_phase(uvm_phase phase);
super.build_phase(phase);
void'(uvm_config_db#(uvma_interrupt_cfg_c)::get(this, "", "cfg", cfg));
if (cfg == null) begin
`uvm_fatal("CFG", "Configuration handle is null")
end
void'(uvm_config_db#(uvma_interrupt_cntxt_c)::get(this, "", "cntxt", cntxt));
if (cntxt == null) begin
`uvm_fatal("CNTXT", "Context handle is null")
end
endfunction : build_phase
`endif // __UVMA_INTERRUPT_SQR_SV__
该文件是中断验证环境的序列器实现,主要功能包括:
class uvma_interrupt_sqr_c extends uvm_sequencer#(
.REQ(uvma_interrupt_seq_item_c),
.RSP(uvma_interrupt_seq_item_c)
);
uvma_interrupt_cfg_c cfg;
uvma_interrupt_cntxt_c cntxt;
function void build_phase(uvm_phase phase);
void'(uvm_config_db#(uvma_interrupt_cfg_c)::get(this, "", "cfg", cfg));
if (cfg == null) begin
`uvm_fatal("CFG", "Configuration handle is null")
end
endfunction
该序列器组件具有以下特点:
作为验证环境的关键组件,它为中断序列执行提供了可靠的基础设施,确保验证激励能够正确生成和传递。
// 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
covergroup cg_executed_type(
string name,
instr_name_t instr_name
) with function sample (
uvma_isacov_instr_c instr
);
option.per_instance = 1;
option.name = name;
cp_executed: coverpoint instr.name {
bins EXECUTED = {
[0:$]};
}
endgroup : cg_executed_type
// There isn't a defined instruction type/format (yet in Zbb)
// The 2-source register format is mapped to R=type (from I spec)
// The 1-source register format is encompassed here
covergroup cg_zb_rstype(
string name,
bit reg_crosses_enabled,
bit reg_hazards_enabled,
bit rs_is_signed,
bit rd_is_signed
) with function sample (
uvma_isacov_instr_c instr
);
option.per_instance = 1;
option.name = name;
cp_rs: coverpoint instr.rs1;
cp_rd: coverpoint instr.rd;
cp_rd_rs_hazard: coverpoint instr.rd {
ignore_bins IGN_RS_HAZARD_OFF = {
[0:$]} with (!reg_hazards_enabled);
bins RD[] = {
[0:31]} iff (instr.rd == instr.rs1);
}
cross_rd_rs: cross cp_rd, cp_rs {
ignore_bins IGN_OFF = cross_rd_rs with (!reg_crosses_enabled);
}
cp_rs_value: coverpoint instr.rs1_value_type {
ignore_bins POS_OFF = {
POSITIVE} with (!rs_is_signed);
ignore_bins NEG_OFF = {
NEGATIVE} with (!rs_is_signed);
ignore_bins NON_ZERO_OFF = {
NON_ZERO} with (rs_is_signed);
}
cp_rd_value: coverpoint instr.rd_value_type {
ignore_bins POS_OFF = {
POSITIVE} with (!rd_is_signed);
ignore_bins NEG_OFF = {
NEGATIVE} with (!rd_is_signed);
ignore_bins NON_ZERO_OFF = {
NON_ZERO} with (rd_is_signed);
}
`ISACOV_CP_BITWISE(cp_rs_toggle, instr.rs1_value, 1)
`ISACOV_CP_BITWISE(cp_rd_toggle, instr.rd_value, 1)
endgroup : cg_zb_rstype
covergroup cg_zb_itype_shift (
string name,
bit reg_crosses_enabled,
bit reg_hazards_enabled,
bit rs_is_signed,
bit rd_is_signed
) with function sample (
uvma_isacov_instr_c instr
);
option.per_instance = 1;
option.name = name;
cp_rs: coverpoint instr.rs1;
cp_rd: coverpoint instr.rd;
cp_rd_rs_hazard: coverpoint instr.rd {
ignore_bins IGN_RS1_HAZARD_OFF = {
[0:$]} with (!reg_hazards_enabled);
bins RD[] = {
[0:31]} iff (instr.rd == instr.rs1);
}
cross_rd_rs: cross cp_rd, cp_rs {
ignore_bins IGN_OFF = cross_rd_rs with (!reg_crosses_enabled);
}
cp_rs_value: coverpoint instr.rs1_value_type {
ignore_bins POS_OFF = {
POSITIVE} with (!rs_is_signed);
ignore_bins NEG_OFF = {
NEGATIVE} with (!rs_is_signed);
ignore_bins NON_ZERO_OFF = {
NON_ZERO} with (rs_is_signed);
}
cp_shamt: coverpoint instr.immi[4:0] {
bins SHAMT[] = {
[0:31]};
}
cp_rd_value: coverpoint instr.rd_value_type {
ignore_bins POS_OFF = {
POSITIVE} with (!rd_is_signed);
ignore_bins NEG_OFF = {
NEGATIVE} with (!rd_is_signed);
ignore_bins NON_ZERO_OFF = {
NON_ZERO} with (rd_is_signed);
}
`ISACOV_CP_BITWISE(cp_rs_toggle, instr.rs1_value, 1)
`ISACOV_CP_BITWISE(cp_rd_toggle, instr.rd_value, 1)
endgroup : cg_zb_itype_shift
covergroup cg_zb_rstype_ext(
string name,
bit reg_crosses_enabled,
bit reg_hazards_enabled,
bit rs1_is_signed,
bit rs2_is_signed,
bit rd_is_signed
) with function sample (
uvma_isacov_instr_c instr
);
option.per_instance = 1;
option.name = name;
cp_rs1: coverpoint instr.rs1;
cp_rs2: coverpoint instr.rs2;
cp_rd: coverpoint instr.rd;
cp_rd_rs1_hazard: coverpoint instr.rd {
ignore_bins IGN_RS1_HAZARD_OFF = {
[0:$]} with (!reg_hazards_enabled);
bins RD[] = {
[0:31]} iff (instr.rd == instr.rs1);
}
cp_rd_rs2_hazard: coverpoint instr.rd {
ignore_bins IGN_RS1_HAZARD_OFF = {
[0:$]} with (!reg_hazards_enabled);
bins RD[] = {
[0:31]} iff (instr.rd == instr.rs2);
}
cross_rd_rs1_rs2: cross cp_rd, cp_rs1, cp_rs2 {
ignore_bins IGN_OFF = cross_rd_rs1_rs2 with (!reg_crosses_enabled);
}
cp_rs1_value: coverpoint instr.rs1_value_type {
ignore_bins POS_OFF = {
POSITIVE} with (!rs1_is_signed);
ignore_bins NEG_OFF = {
NEGATIVE} with (!rs1_is_signed);
ignore_bins NON_ZERO_OFF = {
NON_ZERO} with (rs1_is_signed);
}
cp_index: coverpoint instr.rs2[4:0] {
bins INDEX[] = {
[0:31]};
}
cp_rd_value: coverpoint instr.rd_value {
bins ZERO = {
0};
bins ONE = {
1};
}
`ISACOV_CP_BITWISE(cp_rs1_toggle, instr.rs1_value, 1)
`ISACOV_CP_BITWISE(cp_rs2_toggle, instr.rs2_value, 1)
endgroup : cg_zb_rstype_ext
covergroup cg_zb_itype_ext(
string name,
bit reg_crosses_enabled,
bit reg_hazards_enabled,
bit rs_is_signed,
bit rd_is_signed
) with function sample (
uvma_isacov_instr_c instr
);
option.per_instance = 1;
option.name = name;
cp_rs: coverpoint instr.rs1;
cp_rd: coverpoint instr.rd;
cp_rd_rs_hazard: coverpoint instr.rd {
ignore_bins IGN_RS1_HAZARD_OFF = {
[0:$]} with (!reg_hazards_enabled);
bins RD[] = {
[0:31]} iff (instr.rd == instr.rs1);
}
cross_rd_rs: cross cp_rd, cp_rs {
ignore_bins IGN_OFF = cross_rd_rs with (!reg_crosses_enabled);
}
cp_rs_value: coverpoint instr.rs1_value_type {
ignore_bins POS_OFF = {
POSITIVE} with (!rs_is_signed);
ignore_bins NEG_OFF = {
NEGATIVE} with (!rs_is_signed);
ignore_bins NON_ZERO_OFF = {
NON_ZERO} with (rs_is_signed);
}
cp_shift: coverpoint instr.immi[4:0] {
bins SHIFT[] = {
[0:31]};
}
cp_rd_value: coverpoint instr.rd_value {
bins ZERO = {
0};
bins ONE = {
1};
}
`ISACOV_CP_BITWISE(cp_rs_toggle, instr.rs1_value, 1)
endgroup : cg_zb_itype_ext
covergroup cg_rtype(
string name,
bit reg_crosses_enabled,
bit reg_hazards_enabled,
bit rs1_is_signed,
bit rs2_is_signed,
bit rd_is_signed
) with function sample (
uvma_isacov_instr_c instr
);
option.per_instance = 1;
option.name = name;
cp_rs1: coverpoint instr.rs1;
cp_rs2: coverpoint instr.rs2;
cp_rd: coverpoint instr.rd;
cp_rd_rs1_hazard: coverpoint instr.rd {
ignore_bins IGN_RS1_HAZARD_OFF = {
[0:$]} with (!reg_hazards_enabled);
bins RD[] = {
[0:31]} iff (instr.rd == instr.rs1);
}
cp_rd_rs2_hazard: coverpoint instr.rd {
ignore_bins IGN_RS2_HAZARD_OFF = {
[0:$]} with (!reg_hazards_enabled);
bins RD[] = {
[0:31]} iff (instr.rd == instr.rs2);
}
cross_rd_rs1_rs2: cross cp_rd, cp_rs1, cp_rs2 {
ignore_bins IGN_OFF = cross_rd_rs1_rs2 with (!reg_crosses_enabled);
}
cp_rs1_value: coverpoint instr.rs1_value_type {
ignore_bins POS_OFF = {
POSITIVE} with (!rs1_is_signed);
ignore_bins NEG_OFF = {
NEGATIVE} with (!rs1_is_signed);
ignore_bins NON_ZERO_OFF = {
NON_ZERO} with (rs1_is_signed);
}
cp_rs2_value: coverpoint instr.rs2_value_type {
ignore_bins POS_OFF = {
POSITIVE} with (!rs2_is_signed);
ignore_bins NEG_OFF = {
NEGATIVE} with (!rs2_is_signed);
ignore_bins NON_ZERO_OFF = {
NON_ZERO} with (rs2_is_signed);
}
cross_rs1_rs2_value: cross cp_rs1_value, cp_rs2_value;
cp_rd_value: coverpoint instr.rd_value_type {
ignore_bins POS_OFF = {
POSITIVE} with (!rd_is_signed);
ignore_bins NEG_OFF = {
NEGATIVE} with (!rd_is_signed);
ignore_bins NON_ZERO_OFF = {
NON_ZERO} with (rd_is_signed);
}
`ISACOV_CP_BITWISE(cp_rs1_toggle, instr.rs1_value, 1)
`ISACOV_CP_BITWISE(cp_rs2_toggle, instr.rs2_value, 1)
`ISACOV_CP_BITWISE(cp_rd_toggle, instr.rd_value, 1)
endgroup : cg_rtype
covergroup cg_rtype_lr_w(
string name,
bit reg_hazards_enabled,
bit rs1_is_signed,
bit rd_is_signed,
bit unaligned_access_amo_supported
) with function sample (
uvma_isacov_instr_c instr
);
option.per_instance = 1;
option.name = name;
cp_rs1: coverpoint instr.rs1;
cp_rd: coverpoint instr.rd;
cp_rd_rs1_hazard: coverpoint instr.rd {
ignore_bins IGN_RS1_HAZARD_OFF = {
[0:$]} with (!reg_hazards_enabled);
bins RD[] = {
[0:31]} iff (instr.rd == instr.rs1);
}
cp_rs1_value: coverpoint instr.rs1_value_type {
ignore_bins POS_OFF = {
POSITIVE} with (!rs1_is_signed);
ignore_bins NEG_OFF = {
NEGATIVE} with (!rs1_is_signed);
ignore_bins NON_ZERO_OFF = {
NON_ZERO} with (rs1_is_signed);
}
cp_rd_value: coverpoint instr.rd_value_type {
ignore_bins POS_OFF = {
POSITIVE} with (!rd_is_signed);
ignore_bins NEG_OFF = {
NEGATIVE} with (!rd_is_signed);
ignore_bins NON_ZERO_OFF = {
NON_ZERO} with (rd_is_signed);
}
cp_align_word: coverpoint (instr.rvfi.mem_addr[1:0]) {
ignore_bins IGN_OFF = {
[0:$]} with (!unaligned_access_amo_supported);
bins ALIGNED = {
0};
bins UNALIGNED[] = {
[1:3]};
}
`ISACOV_CP_BITWISE(cp_rs1_toggle, instr.rs1_value, 1)
`ISACOV_CP_BITWISE(cp_rd_toggle, instr.rd_value, 1)
endgroup : cg_rtype_lr_w
covergroup cg_rtype_sc_w (
string name,
bit reg_crosses_enabled,
bit reg_hazards_enabled,
bit rs1_is_signed,
bit rs2_is_signed,
bit unaligned_access_amo_supported
) with function sample (
uvma_isacov_instr_c instr
);
option.per_instance = 1;
option.name = name;
cp_rs1: coverpoint instr.rs1;
cp_rs2: coverpoint instr.rs2;
cp_rd: coverpoint instr.rd;
cp_rd_rs1_hazard: coverpoint instr.rd {
ignore_bins IGN_RS1_HAZARD_OFF = {
[0:$]} with (!reg_hazards_enabled);
bins RD[] = {
[0:31]} iff (instr.rd == instr.rs1);
}
cp_rd_rs2_hazard: coverpoint instr.rd {
ignore_bins IGN_RS2_HAZARD_OFF = {
[0:$]} with (!reg_hazards_enabled);
bins RD[] = {
[0:31]} iff (instr.rd == instr.rs2);
}
cross_rd_rs1_rs2: cross cp_rd, cp_rs1, cp_rs2 {
ignore_bins IGN_OFF = cross_rd_rs1_rs2 with (!reg_crosses_enabled);
}
cp_rs1_value: coverpoint instr.rs1_value_type {
ignore_bins POS_OFF = {
POSITIVE} with (!rs1_is_signed);
ignore_bins NEG_OFF = {
NEGATIVE} with (!rs1_is_signed);
ignore_bins NON_ZERO_OFF = {
NON_ZERO} with (rs1_is_signed);
}
cp_rs2_value: coverpoint instr.rs2_value_type {
ignore_bins POS_OFF = {
POSITIVE} with (!rs2_is_signed);
ignore_bins NEG_OFF = {
NEGATIVE} with (!rs2_is_signed);
ignore_bins NON_ZERO_OFF = {
NON_ZERO} with (rs2_is_signed);
}
cross_rs1_rs2_value: cross cp_rs1_value, cp_rs2_value;
cp_align_word: coverpoint (instr.rvfi.mem_addr[1:0]) {
ignore_bins IGN_OFF = {
[0:$]} with (!unaligned_access_amo_supported);
bins ALIGNED = {
0};
bins UNALIGNED[] = {
[1:3]};
}
`ISACOV_CP_BITWISE(cp_rs1_toggle, instr.rs1_value, 1)
`ISACOV_CP_BITWISE(cp_rs2_toggle, instr.rs2_value, 1)
`ISACOV_CP_BITWISE_0_0(cp_rd_toggle, instr.rd_value, 1)
// Note: "More specific failure codes might be defined in future versions or extensions to the ISA."
endgroup : cg_rtype_sc_w
covergroup cg_rtype_amo (
string name,
bit reg_crosses_enabled,
bit reg_hazards_enabled,
bit rs1_is_signed,
bit rd_is_signed,
bit unaligned_access_amo_supported
) with function sample (
uvma_isacov_instr_c instr
);
option.per_instance = 1;
option.name = name;
cp_rs1: coverpoint instr.rs1;
cp_rs2: coverpoint instr.rs2;
cp_rd: coverpoint instr.rd;
cp_rd_rs1_hazard: coverpoint instr.rd {
ignore_bins IGN_RS1_HAZARD_OFF = {
[0:$]} with (!reg_hazards_enabled);
bins RD[] = {
[0:31]} iff (instr.rd == instr.rs1);
}
cp_rd_rs2_hazard: coverpoint instr.rd {
ignore_bins IGN_RS2_HAZARD_OFF = {
[0:$]} with (!reg_hazards_enabled);
bins RD[] = {
[0:31]} iff (instr.rd == instr.rs2);
}
cross_rd_rs1_rs2: cross cp_rd, cp_rs1, cp_rs2 {
ignore_bins IGN_OFF = cross_rd_rs1_rs2 with (!reg_crosses_enabled);
}
cp_rs1_value: coverpoint instr.rs1_value_type {
ignore_bins POS_OFF = {
POSITIVE} with (!rs1_is_signed);
ignore_bins NEG_OFF = {
NEGATIVE} with (!rs1_is_signed);
ignore_bins NON_ZERO_OFF = {
NON_ZERO} with (rs1_is_signed);
}
cp_align_word: coverpoint (instr.rvfi.mem_addr[1:0]) {
ignore_bins IGN_OFF = {
[0:$]} with (!unaligned_access_amo_supported);
bins ALIGNED = {
0};
bins UNALIGNED[] = {
[1:3]};
}
`ISACOV_CP_BITWISE(cp_rs1_toggle, instr.rs1_value, 1)
`ISACOV_CP_BITWISE(cp_rs2_toggle, instr.rs2_value, 1)
`ISACOV_CP_BITWISE(cp_rd_toggle, instr.rd_value, 1)
endgroup : cg_rtype_amo
covergroup cg_rtype_slt(
string name,
bit reg_crosses_enabled,
bit reg_hazards_enabled,
bit rs1_is_signed,
bit rs2_is_signed,
bit rd_is_signed
) with function sample (
uvma_isacov_instr_c instr
);
option.per_instance = 1;
option.name = name;
cp_rs1: coverpoint instr.rs1;
cp_rs2: coverpoint instr.rs2;
cp_rd: coverpoint instr.rd;
cp_rd_rs1_hazard: coverpoint instr.rd {
ignore_bins IGN_RS1_HAZARD_OFF = {
[0:$]} with (!reg_hazards_enabled);
bins RD[] = {
[0:31]} iff (instr.rd == instr.rs1);
}
cp_rd_rs2_hazard: coverpoint instr.rd {
ignore_bins IGN_RS2_HAZARD_OFF = {
[0:$]} with (!reg_hazards_enabled);
bins RD[] = {
[0:31]} iff (instr.rd == instr.rs2);
}
cross_rd_rs1_rs2: cross cp_rd, cp_rs1, cp_rs2 {
ignore_bins IGN_OFF = cross_rd_rs1_rs2 with (!reg_crosses_enabled);
}
cp_rs1_value: coverpoint instr.rs1_value_type {
ignore_bins POS_OFF = {
POSITIVE} with (!rs1_is_signed);
ignore_bins NEG_OFF = {
NEGATIVE} with (!rs1_is_signed);
ignore_bins NON_ZERO_OFF = {
NON_ZERO} with (rs1_is_signed);
}
cp_rs2_value: coverpoint instr.rs2_value_type {
ignore_bins POS_OFF = {
POSITIVE} with (!rs2_is_signed);
ignore_bins NEG_OFF = {
NEGATIVE} with (!rs2_is_signed);
ignore_bins NON_ZERO_OFF = {
NON_ZERO} with (rs2_is_signed);
}
cross_rs1_rs2_value: cross cp_rs1_value, cp_rs2_value;
cp_rd_value: coverpoint instr.rd_value {
bins SLT[] = {
[0:1]};
}
`ISACOV_CP_BITWISE(cp_rs1_toggle<