mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-23 13:27:10 -04:00
Add a monitor to the icache <-> mem interface in UVM testbench
This is enough to report transactions up to the scoreboard. At the moment, there's nothing listening, but you can see them going through with make run VERBOSITY=h and then looking at the dumps in run.log.
This commit is contained in:
parent
d7c90e519e
commit
9af4b3973c
5 changed files with 86 additions and 7 deletions
|
@ -11,7 +11,7 @@ class ibex_icache_scoreboard
|
|||
|
||||
// TLM agent fifos
|
||||
uvm_tlm_analysis_fifo #(ibex_icache_core_bus_item) core_fifo;
|
||||
uvm_tlm_analysis_fifo #(ibex_icache_mem_resp_item) mem_fifo;
|
||||
uvm_tlm_analysis_fifo #(ibex_icache_mem_bus_item) mem_fifo;
|
||||
|
||||
`uvm_component_new
|
||||
|
||||
|
@ -42,10 +42,10 @@ class ibex_icache_scoreboard
|
|||
endtask
|
||||
|
||||
virtual task process_mem_fifo();
|
||||
ibex_icache_mem_resp_item item;
|
||||
ibex_icache_mem_bus_item item;
|
||||
forever begin
|
||||
mem_fifo.get(item);
|
||||
`uvm_info(`gfn, $sformatf("received ibex_mem_intf_seq item:\n%0s", item.sprint()), UVM_HIGH)
|
||||
`uvm_info(`gfn, $sformatf("received mem transaction:\n%0s", item.sprint()), UVM_HIGH)
|
||||
end
|
||||
endtask
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ filesets:
|
|||
- ibex_icache_mem_agent_pkg.sv
|
||||
- ibex_icache_mem_req_item.sv: {is_include_file: true}
|
||||
- ibex_icache_mem_resp_item.sv: {is_include_file: true}
|
||||
- ibex_icache_mem_bus_item.sv: {is_include_file: true}
|
||||
- ibex_icache_mem_agent_cfg.sv: {is_include_file: true}
|
||||
- ibex_icache_mem_agent_cov.sv: {is_include_file: true}
|
||||
- ibex_icache_mem_driver.sv: {is_include_file: true}
|
||||
|
|
|
@ -17,6 +17,7 @@ package ibex_icache_mem_agent_pkg;
|
|||
// package sources
|
||||
`include "ibex_icache_mem_req_item.sv"
|
||||
`include "ibex_icache_mem_resp_item.sv"
|
||||
`include "ibex_icache_mem_bus_item.sv"
|
||||
`include "ibex_icache_mem_model.sv"
|
||||
`include "ibex_icache_mem_agent_cfg.sv"
|
||||
`include "ibex_icache_mem_agent_cov.sv"
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// A transaction item that represents something happening on the memory bus. A 'request' is
|
||||
// initiated by the cache and comes with an address. A 'response' comes from the memory system
|
||||
// (including possibly the PMP checker). It comes with data and error flags.
|
||||
|
||||
class ibex_icache_mem_bus_item extends uvm_sequence_item;
|
||||
|
||||
// Is this a request or a response?
|
||||
logic is_response;
|
||||
|
||||
// Request address (only valid for request transactions)
|
||||
logic [31:0] address;
|
||||
|
||||
// Response data and error flags (only valid for response transactions)
|
||||
logic [31:0] rdata;
|
||||
logic err;
|
||||
logic pmp_err;
|
||||
|
||||
`uvm_object_utils_begin(ibex_icache_mem_bus_item)
|
||||
`uvm_field_int(is_response, UVM_DEFAULT)
|
||||
`uvm_field_int(address, UVM_DEFAULT | UVM_HEX)
|
||||
`uvm_field_int(rdata, UVM_DEFAULT | UVM_HEX)
|
||||
`uvm_field_int(err, UVM_DEFAULT)
|
||||
`uvm_field_int(pmp_err, UVM_DEFAULT)
|
||||
`uvm_object_utils_end
|
||||
|
||||
`uvm_object_new
|
||||
|
||||
endclass
|
|
@ -3,7 +3,7 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
class ibex_icache_mem_monitor
|
||||
extends dv_base_monitor #(.ITEM_T (ibex_icache_mem_resp_item),
|
||||
extends dv_base_monitor #(.ITEM_T (ibex_icache_mem_bus_item),
|
||||
.CFG_T (ibex_icache_mem_agent_cfg),
|
||||
.COV_T (ibex_icache_mem_agent_cov));
|
||||
|
||||
|
@ -13,7 +13,7 @@ class ibex_icache_mem_monitor
|
|||
// the base class provides the following handles for use:
|
||||
// ibex_icache_mem_agent_cfg: cfg
|
||||
// ibex_icache_mem_agent_cov: cov
|
||||
// uvm_analysis_port #(ibex_icache_resp_item): analysis_port
|
||||
// uvm_analysis_port #(ibex_icache_mem_bus_item): analysis_port
|
||||
|
||||
// Incoming requests. This gets hooked up to the sequencer to service requests
|
||||
uvm_analysis_port #(ibex_icache_mem_req_item) request_port;
|
||||
|
@ -32,6 +32,7 @@ class ibex_icache_mem_monitor
|
|||
fork
|
||||
collect_requests();
|
||||
collect_grants();
|
||||
collect_responses();
|
||||
join
|
||||
endtask
|
||||
|
||||
|
@ -69,6 +70,40 @@ class ibex_icache_mem_monitor
|
|||
end
|
||||
endtask
|
||||
|
||||
task automatic collect_responses();
|
||||
ibex_icache_mem_bus_item bus_trans;
|
||||
|
||||
forever begin
|
||||
// A response is signalled by either rvalid or pmp_err being true. Both are possible on the
|
||||
// same cycle, corresponding to two different requests.
|
||||
//
|
||||
// Note that we're sampling on posedge clk. A PMP error that is signalled combinatorially as a
|
||||
// response to a request will be spotted on the following clock cycle (the same time as the
|
||||
// cache sees it).
|
||||
if (cfg.vif.monitor_cb.pmp_err) begin
|
||||
bus_trans = ibex_icache_mem_bus_item::type_id::create("bus_trans");
|
||||
bus_trans.is_response = 1'b1;
|
||||
bus_trans.address = '0;
|
||||
bus_trans.rdata = '0;
|
||||
bus_trans.err = 0;
|
||||
bus_trans.pmp_err = 1'b1;
|
||||
analysis_port.write(bus_trans);
|
||||
end
|
||||
|
||||
if (cfg.vif.monitor_cb.rvalid) begin
|
||||
bus_trans = ibex_icache_mem_bus_item::type_id::create("bus_trans");
|
||||
bus_trans.is_response = 1'b1;
|
||||
bus_trans.address = '0;
|
||||
bus_trans.rdata = cfg.vif.monitor_cb.rdata;
|
||||
bus_trans.err = cfg.vif.monitor_cb.err;
|
||||
bus_trans.pmp_err = 0;
|
||||
analysis_port.write(bus_trans);
|
||||
end
|
||||
|
||||
@(cfg.vif.monitor_cb);
|
||||
end
|
||||
endtask
|
||||
|
||||
// This is called immediately when an address is requested and is used to drive the PMP response
|
||||
function automatic void new_request(logic [31:0] addr);
|
||||
ibex_icache_mem_req_item item = new("item");
|
||||
|
@ -81,12 +116,22 @@ class ibex_icache_mem_monitor
|
|||
|
||||
// This is called on a clock edge when an request is granted
|
||||
function automatic void new_grant(logic [31:0] addr);
|
||||
ibex_icache_mem_req_item item = new("item");
|
||||
ibex_icache_mem_req_item item;
|
||||
ibex_icache_mem_bus_item bus_trans;
|
||||
|
||||
item = ibex_icache_mem_req_item::type_id::create("item");
|
||||
item.is_grant = 1'b1;
|
||||
item.address = addr;
|
||||
item.address = addr;
|
||||
`DV_CHECK_RANDOMIZE_FATAL(item)
|
||||
request_port.write(item);
|
||||
|
||||
bus_trans = ibex_icache_mem_bus_item::type_id::create("bus_trans");
|
||||
bus_trans.is_response = 1'b0;
|
||||
bus_trans.address = addr;
|
||||
bus_trans.rdata = '0;
|
||||
bus_trans.err = 0;
|
||||
bus_trans.pmp_err = 0;
|
||||
analysis_port.write(bus_trans);
|
||||
endfunction
|
||||
|
||||
endclass
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue