mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-23 21:39:13 -04:00
[ibex/dv] Add clocking blocks to Ibex interfaces
This PR adds clocking blocks to all major Ibex interfaces and updates all corresponding interface accesses to use these clocking blocks. A few notes: - `ibex_mem_intf` has two driver clocking blocks, one for host side and one for device side. This is because our Ibex testbench currently provides both host and device agents for both I/D interfaces (of course we only use the reactive device agents in the main testbench). - `csr_if` and `dut_if` only have one clocking block each, as all signals in each will only be either sampled or driven, never both. - Some utility tasks have been added to some interfaces to wait for a specified number of clock cycles.
This commit is contained in:
parent
96cf24a41a
commit
1f26d93267
13 changed files with 241 additions and 137 deletions
|
@ -2,10 +2,13 @@
|
|||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
interface ibex_mem_intf#(parameter int ADDR_WIDTH = 32,
|
||||
parameter int DATA_WIDTH = 32);
|
||||
interface ibex_mem_intf#(
|
||||
parameter int ADDR_WIDTH = 32,
|
||||
parameter int DATA_WIDTH = 32
|
||||
) (
|
||||
input clk
|
||||
);
|
||||
|
||||
logic clock;
|
||||
logic reset;
|
||||
logic request;
|
||||
logic grant;
|
||||
|
@ -17,4 +20,51 @@ interface ibex_mem_intf#(parameter int ADDR_WIDTH = 32,
|
|||
logic [DATA_WIDTH-1:0] rdata;
|
||||
logic error;
|
||||
|
||||
clocking host_driver_cb @(posedge clk);
|
||||
input reset;
|
||||
output request;
|
||||
input grant;
|
||||
output addr;
|
||||
output we;
|
||||
output be;
|
||||
input rvalid;
|
||||
output wdata;
|
||||
input rdata;
|
||||
input error;
|
||||
endclocking
|
||||
|
||||
clocking device_driver_cb @(posedge clk);
|
||||
input reset;
|
||||
input request;
|
||||
output grant;
|
||||
input addr;
|
||||
input we;
|
||||
input be;
|
||||
output rvalid;
|
||||
input wdata;
|
||||
output rdata;
|
||||
output error;
|
||||
endclocking
|
||||
|
||||
clocking monitor_cb @(posedge clk);
|
||||
input reset;
|
||||
input request;
|
||||
input grant;
|
||||
input addr;
|
||||
input we;
|
||||
input be;
|
||||
input rvalid;
|
||||
input wdata;
|
||||
input rdata;
|
||||
input error;
|
||||
endclocking
|
||||
|
||||
task automatic wait_clks(input int num);
|
||||
repeat (num) @(posedge clk);
|
||||
endtask
|
||||
|
||||
task automatic wait_neg_clks(input int num);
|
||||
repeat (num) @(negedge clk);
|
||||
endtask
|
||||
|
||||
endinterface : ibex_mem_intf
|
||||
|
|
|
@ -31,11 +31,11 @@ class ibex_mem_intf_master_driver extends uvm_driver #(ibex_mem_intf_seq_item);
|
|||
endtask : run_phase
|
||||
|
||||
virtual protected task get_and_drive();
|
||||
@(negedge vif.reset);
|
||||
@(negedge vif.host_driver_cb.reset);
|
||||
forever begin
|
||||
@(posedge vif.clock);
|
||||
vif.wait_clks(1);
|
||||
seq_item_port.get_next_item(req);
|
||||
repeat(req.req_delay) @(posedge vif.clock);
|
||||
vif.wait_clks(req.req_delay);
|
||||
$cast(rsp, req.clone());
|
||||
rsp.set_id_info(req);
|
||||
drive_transfer(rsp);
|
||||
|
@ -45,31 +45,31 @@ class ibex_mem_intf_master_driver extends uvm_driver #(ibex_mem_intf_seq_item);
|
|||
|
||||
virtual protected task reset_signals();
|
||||
forever begin
|
||||
@(posedge vif.reset);
|
||||
vif.request <= 'h0;
|
||||
vif.addr <= 'hz;
|
||||
vif.wdata <= 'hz;
|
||||
vif.be <= 'bz;
|
||||
vif.we <= 'bz;
|
||||
@(posedge vif.host_driver_cb.reset);
|
||||
vif.host_driver_cb.request <= 'h0;
|
||||
vif.host_driver_cb.addr <= 'hz;
|
||||
vif.host_driver_cb.wdata <= 'hz;
|
||||
vif.host_driver_cb.be <= 'bz;
|
||||
vif.host_driver_cb.we <= 'bz;
|
||||
end
|
||||
endtask : reset_signals
|
||||
|
||||
virtual protected task drive_transfer (ibex_mem_intf_seq_item trans);
|
||||
if (trans.req_delay > 0) begin
|
||||
repeat(trans.req_delay) @(posedge vif.clock);
|
||||
vif.wait_clks(trans.req_delay);
|
||||
end
|
||||
vif.request <= 1'b1;
|
||||
vif.addr <= trans.addr;
|
||||
vif.be <= trans.be;
|
||||
vif.we <= trans.read_write;
|
||||
vif.wdata <= trans.data;
|
||||
wait(vif.grant === 1'b1);
|
||||
@(posedge vif.clock);
|
||||
vif.request <= 'h0;
|
||||
vif.addr <= 'hz;
|
||||
vif.wdata <= 'hz;
|
||||
vif.be <= 'bz;
|
||||
vif.we <= 'bz;
|
||||
vif.host_driver_cb.request <= 1'b1;
|
||||
vif.host_driver_cb.addr <= trans.addr;
|
||||
vif.host_driver_cb.be <= trans.be;
|
||||
vif.host_driver_cb.we <= trans.read_write;
|
||||
vif.host_driver_cb.wdata <= trans.data;
|
||||
wait (vif.host_driver_cb.grant === 1'b1);
|
||||
vif.wait_clks(1);
|
||||
vif.host_driver_cb.request <= 'h0;
|
||||
vif.host_driver_cb.addr <= 'hz;
|
||||
vif.host_driver_cb.wdata <= 'hz;
|
||||
vif.host_driver_cb.be <= 'bz;
|
||||
vif.host_driver_cb.we <= 'bz;
|
||||
rdata_queue.put(trans);
|
||||
endtask : drive_transfer
|
||||
|
||||
|
@ -77,10 +77,10 @@ class ibex_mem_intf_master_driver extends uvm_driver #(ibex_mem_intf_seq_item);
|
|||
ibex_mem_intf_seq_item tr;
|
||||
forever begin
|
||||
rdata_queue.get(tr);
|
||||
@(posedge vif.clock);
|
||||
while(vif.rvalid !== 1'b1) @(posedge vif.clock);
|
||||
vif.wait_clks(1);
|
||||
while(vif.rvalid !== 1'b1) vif.wait_clks(1);
|
||||
if(tr.read_write == READ)
|
||||
tr.data = vif.rdata;
|
||||
tr.data = vif.host_driver_cb.rdata;
|
||||
seq_item_port.put_response(tr);
|
||||
end
|
||||
endtask : collect_response
|
||||
|
|
|
@ -28,12 +28,12 @@ class ibex_mem_intf_monitor extends uvm_monitor;
|
|||
endfunction: build_phase
|
||||
|
||||
virtual task run_phase(uvm_phase phase);
|
||||
wait(vif.reset === 1'b0);
|
||||
wait (vif.monitor_cb.reset === 1'b0);
|
||||
forever begin
|
||||
fork : check_mem_intf
|
||||
collect_address_phase();
|
||||
collect_data_phase();
|
||||
wait(vif.reset === 1'b1);
|
||||
wait (vif.monitor_cb.reset === 1'b1);
|
||||
join_any
|
||||
// Will only reach this point when mid-test reset is asserted
|
||||
disable check_mem_intf;
|
||||
|
@ -45,21 +45,21 @@ class ibex_mem_intf_monitor extends uvm_monitor;
|
|||
ibex_mem_intf_seq_item mailbox_result;
|
||||
// Clear the mailbox of any content
|
||||
while (collect_data_queue.try_get(mailbox_result));
|
||||
wait(vif.reset === 1'b0);
|
||||
wait (vif.monitor_cb.reset === 1'b0);
|
||||
endtask
|
||||
|
||||
virtual protected task collect_address_phase();
|
||||
ibex_mem_intf_seq_item trans_collected;
|
||||
forever begin
|
||||
trans_collected = ibex_mem_intf_seq_item::type_id::create("trans_collected");
|
||||
while(!(vif.request && vif.grant)) @(posedge vif.clock);
|
||||
trans_collected.addr = vif.addr;
|
||||
trans_collected.be = vif.be;
|
||||
while(!(vif.monitor_cb.request && vif.monitor_cb.grant)) vif.wait_clks(1);
|
||||
trans_collected.addr = vif.monitor_cb.addr;
|
||||
trans_collected.be = vif.monitor_cb.be;
|
||||
`uvm_info(get_full_name(), $sformatf("Detect request with address: %0x",
|
||||
trans_collected.addr), UVM_HIGH)
|
||||
if(vif.we) begin
|
||||
if(vif.monitor_cb.we) begin
|
||||
trans_collected.read_write = WRITE;
|
||||
trans_collected.data = vif.wdata;
|
||||
trans_collected.data = vif.monitor_cb.wdata;
|
||||
end else begin
|
||||
trans_collected.read_write = READ;
|
||||
end
|
||||
|
@ -69,7 +69,7 @@ class ibex_mem_intf_monitor extends uvm_monitor;
|
|||
item_collected_port.write(trans_collected);
|
||||
else
|
||||
collect_data_queue.put(trans_collected);
|
||||
@(posedge vif.clock);
|
||||
vif.wait_clks(1);
|
||||
end
|
||||
endtask : collect_address_phase
|
||||
|
||||
|
@ -78,9 +78,9 @@ class ibex_mem_intf_monitor extends uvm_monitor;
|
|||
forever begin
|
||||
collect_data_queue.get(trans_collected);
|
||||
do
|
||||
@(posedge vif.clock);
|
||||
while(vif.rvalid === 0);
|
||||
trans_collected.data = vif.rdata;
|
||||
vif.wait_clks(1);
|
||||
while(vif.monitor_cb.rvalid === 0);
|
||||
trans_collected.data = vif.monitor_cb.rdata;
|
||||
item_collected_port.write(trans_collected);
|
||||
end
|
||||
endtask : collect_data_phase
|
||||
|
|
|
@ -27,12 +27,12 @@ class ibex_mem_intf_slave_driver extends uvm_driver #(ibex_mem_intf_seq_item);
|
|||
|
||||
virtual task run_phase(uvm_phase phase);
|
||||
reset_signals();
|
||||
wait(vif.reset === 1'b0);
|
||||
wait (vif.device_driver_cb.reset === 1'b0);
|
||||
forever begin
|
||||
fork : drive_stimulus
|
||||
send_grant();
|
||||
get_and_drive();
|
||||
wait(vif.reset === 1'b1);
|
||||
wait (vif.device_driver_cb.reset === 1'b1);
|
||||
join_any
|
||||
// Will only be reached after mid-test reset
|
||||
disable drive_stimulus;
|
||||
|
@ -52,26 +52,26 @@ class ibex_mem_intf_slave_driver extends uvm_driver #(ibex_mem_intf_seq_item);
|
|||
end
|
||||
end while (req != null);
|
||||
reset_signals();
|
||||
wait(vif.reset === 1'b0);
|
||||
wait (vif.device_driver_cb.reset === 1'b0);
|
||||
endtask
|
||||
|
||||
virtual protected task reset_signals();
|
||||
vif.rvalid <= 1'b0;
|
||||
vif.grant <= 1'b0;
|
||||
vif.rdata <= 'b0;
|
||||
vif.error <= 1'b0;
|
||||
vif.device_driver_cb.rvalid <= 1'b0;
|
||||
vif.device_driver_cb.grant <= 1'b0;
|
||||
vif.device_driver_cb.rdata <= 'b0;
|
||||
vif.device_driver_cb.error <= 1'b0;
|
||||
endtask : reset_signals
|
||||
|
||||
virtual protected task get_and_drive();
|
||||
wait(vif.reset === 1'b0);
|
||||
wait (vif.device_driver_cb.reset === 1'b0);
|
||||
fork
|
||||
begin
|
||||
forever begin
|
||||
ibex_mem_intf_seq_item req, req_c;
|
||||
@(posedge vif.clock);
|
||||
vif.wait_clks(1);
|
||||
seq_item_port.get_next_item(req);
|
||||
$cast(req_c, req.clone());
|
||||
if(~vif.reset) begin
|
||||
if(~vif.device_driver_cb.reset) begin
|
||||
rdata_queue.put(req_c);
|
||||
end
|
||||
seq_item_port.item_done();
|
||||
|
@ -86,8 +86,8 @@ class ibex_mem_intf_slave_driver extends uvm_driver #(ibex_mem_intf_seq_item);
|
|||
virtual protected task send_grant();
|
||||
int gnt_delay;
|
||||
forever begin
|
||||
while(vif.request !== 1'b1) begin
|
||||
@(negedge vif.clock);
|
||||
while(vif.device_driver_cb.request !== 1'b1) begin
|
||||
vif.wait_neg_clks(1);
|
||||
end
|
||||
if (!std::randomize(gnt_delay) with {
|
||||
gnt_delay dist {
|
||||
|
@ -98,11 +98,11 @@ class ibex_mem_intf_slave_driver extends uvm_driver #(ibex_mem_intf_seq_item);
|
|||
}) begin
|
||||
`uvm_fatal(`gfn, $sformatf("Cannot randomize grant"))
|
||||
end
|
||||
repeat(gnt_delay) @(negedge vif.clock);
|
||||
if(~vif.reset) begin
|
||||
vif.grant = 1'b1;
|
||||
@(negedge vif.clock);
|
||||
vif.grant = 1'b0;
|
||||
vif.wait_neg_clks(gnt_delay);
|
||||
if(~vif.device_driver_cb.reset) begin
|
||||
vif.device_driver_cb.grant <= 1'b1;
|
||||
vif.wait_neg_clks(1);
|
||||
vif.device_driver_cb.grant <= 1'b0;
|
||||
end
|
||||
end
|
||||
endtask : send_grant
|
||||
|
@ -110,17 +110,17 @@ class ibex_mem_intf_slave_driver extends uvm_driver #(ibex_mem_intf_seq_item);
|
|||
virtual protected task send_read_data();
|
||||
ibex_mem_intf_seq_item tr;
|
||||
forever begin
|
||||
@(posedge vif.clock);
|
||||
vif.rvalid <= 1'b0;
|
||||
vif.rdata <= 'x;
|
||||
vif.error <= 1'b0;
|
||||
vif.wait_clks(1);
|
||||
vif.device_driver_cb.rvalid <= 1'b0;
|
||||
vif.device_driver_cb.rdata <= 'x;
|
||||
vif.device_driver_cb.error <= 1'b0;
|
||||
rdata_queue.get(tr);
|
||||
if(vif.reset) continue;
|
||||
repeat(tr.rvalid_delay) @(posedge vif.clock);
|
||||
if(~vif.reset) begin
|
||||
vif.rvalid <= 1'b1;
|
||||
vif.error <= tr.error;
|
||||
vif.rdata <= tr.data;
|
||||
if(vif.device_driver_cb.reset) continue;
|
||||
vif.wait_clks(tr.rvalid_delay);
|
||||
if(~vif.device_driver_cb.reset) begin
|
||||
vif.device_driver_cb.rvalid <= 1'b1;
|
||||
vif.device_driver_cb.error <= tr.error;
|
||||
vif.device_driver_cb.rdata <= tr.data;
|
||||
end
|
||||
end
|
||||
endtask : send_read_data
|
||||
|
|
|
@ -2,12 +2,34 @@
|
|||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
interface irq_if;
|
||||
logic clock;
|
||||
interface irq_if(input clk);
|
||||
logic reset;
|
||||
logic irq_software;
|
||||
logic irq_timer;
|
||||
logic irq_external;
|
||||
logic [14:0] irq_fast;
|
||||
logic irq_nm; // non-maskeable interrupt
|
||||
|
||||
clocking driver_cb @(posedge clk);
|
||||
input reset;
|
||||
output irq_software;
|
||||
output irq_timer;
|
||||
output irq_external;
|
||||
output irq_fast;
|
||||
output irq_nm;
|
||||
endclocking
|
||||
|
||||
clocking monitor_cb @(posedge clk);
|
||||
input reset;
|
||||
input irq_software;
|
||||
input irq_timer;
|
||||
input irq_external;
|
||||
input irq_fast;
|
||||
input irq_nm;
|
||||
endclocking
|
||||
|
||||
task automatic wait_clks(input int num);
|
||||
repeat (num) @(posedge clk);
|
||||
endtask
|
||||
|
||||
endinterface
|
||||
|
|
|
@ -22,7 +22,7 @@ class irq_master_driver extends uvm_driver #(irq_seq_item);
|
|||
forever begin
|
||||
fork : drive_irq
|
||||
get_and_drive();
|
||||
wait(vif.reset === 1'b1);
|
||||
wait (vif.driver_cb.reset === 1'b1);
|
||||
join_any
|
||||
// Will only reach here on mid-test reset
|
||||
disable drive_irq;
|
||||
|
@ -43,7 +43,7 @@ class irq_master_driver extends uvm_driver #(irq_seq_item);
|
|||
endtask
|
||||
|
||||
virtual protected task get_and_drive();
|
||||
wait(vif.reset === 1'b0);
|
||||
wait (vif.driver_cb.reset === 1'b0);
|
||||
forever begin
|
||||
seq_item_port.try_next_item(req);
|
||||
if (req != null) begin
|
||||
|
@ -52,30 +52,30 @@ class irq_master_driver extends uvm_driver #(irq_seq_item);
|
|||
drive_seq_item(rsp);
|
||||
seq_item_port.item_done(rsp);
|
||||
end else begin
|
||||
@(posedge vif.clock);
|
||||
vif.wait_clks(1);
|
||||
end
|
||||
end
|
||||
endtask : get_and_drive
|
||||
|
||||
virtual protected task reset_signals();
|
||||
@(negedge vif.reset);
|
||||
@(negedge vif.driver_cb.reset);
|
||||
drive_reset_value();
|
||||
endtask : reset_signals
|
||||
|
||||
virtual protected task drive_seq_item (irq_seq_item trans);
|
||||
vif.irq_software <= trans.irq_software;
|
||||
vif.irq_timer <= trans.irq_timer;
|
||||
vif.irq_external <= trans.irq_external;
|
||||
vif.irq_fast <= trans.irq_fast;
|
||||
vif.irq_nm <= trans.irq_nm;
|
||||
vif.driver_cb.irq_software <= trans.irq_software;
|
||||
vif.driver_cb.irq_timer <= trans.irq_timer;
|
||||
vif.driver_cb.irq_external <= trans.irq_external;
|
||||
vif.driver_cb.irq_fast <= trans.irq_fast;
|
||||
vif.driver_cb.irq_nm <= trans.irq_nm;
|
||||
endtask : drive_seq_item
|
||||
|
||||
task drive_reset_value();
|
||||
vif.irq_software <= '0;
|
||||
vif.irq_timer <= '0;
|
||||
vif.irq_external <= '0;
|
||||
vif.irq_fast <= '0;
|
||||
vif.irq_nm <= '0;
|
||||
vif.driver_cb.irq_software <= '0;
|
||||
vif.driver_cb.irq_timer <= '0;
|
||||
vif.driver_cb.irq_external <= '0;
|
||||
vif.driver_cb.irq_fast <= '0;
|
||||
vif.driver_cb.irq_nm <= '0;
|
||||
endtask : drive_reset_value
|
||||
|
||||
endclass : irq_master_driver
|
||||
|
|
|
@ -23,10 +23,10 @@ class irq_monitor extends uvm_monitor;
|
|||
|
||||
virtual task run_phase(uvm_phase phase);
|
||||
forever begin
|
||||
wait(vif.reset === 1'b0);
|
||||
wait (vif.monitor_cb.reset === 1'b0);
|
||||
fork : monitor_irq
|
||||
collect_irq();
|
||||
wait(vif.reset === 1'b1);
|
||||
wait (vif.monitor_cb.reset === 1'b1);
|
||||
join_any
|
||||
// Will only reach here on mid-test reset
|
||||
disable monitor_irq;
|
||||
|
@ -46,19 +46,26 @@ class irq_monitor extends uvm_monitor;
|
|||
bit[DATA_WIDTH-1:0] stored_irq_val = '0;
|
||||
bit[DATA_WIDTH-1:0] current_irq = '0;
|
||||
forever begin
|
||||
current_irq = {vif.irq_nm, vif.irq_fast, 4'b0, vif.irq_external, 3'b0,
|
||||
vif.irq_timer, 3'b0, vif.irq_software, 3'b0};
|
||||
current_irq = {vif.monitor_cb.irq_nm,
|
||||
vif.monitor_cb.irq_fast,
|
||||
4'b0,
|
||||
vif.monitor_cb.irq_external,
|
||||
3'b0,
|
||||
vif.monitor_cb.irq_timer,
|
||||
3'b0,
|
||||
vif.monitor_cb.irq_software,
|
||||
3'b0};
|
||||
if (current_irq !== stored_irq_val) begin
|
||||
stored_irq_val = current_irq;
|
||||
irq = irq_seq_item::type_id::create("irq");
|
||||
irq.irq_software = vif.irq_software;
|
||||
irq.irq_timer = vif.irq_timer;
|
||||
irq.irq_external = vif.irq_external;
|
||||
irq.irq_fast = vif.irq_fast;
|
||||
irq.irq_nm = vif.irq_nm;
|
||||
irq.irq_software = vif.monitor_cb.irq_software;
|
||||
irq.irq_timer = vif.monitor_cb.irq_timer;
|
||||
irq.irq_external = vif.monitor_cb.irq_external;
|
||||
irq.irq_fast = vif.monitor_cb.irq_fast;
|
||||
irq.irq_nm = vif.monitor_cb.irq_nm;
|
||||
irq_port.write(irq);
|
||||
end
|
||||
@(posedge vif.clock);
|
||||
vif.wait_clks(1);
|
||||
end
|
||||
endtask : collect_irq
|
||||
|
||||
|
|
9
dv/uvm/core_ibex/env/core_ibex_csr_if.sv
vendored
9
dv/uvm/core_ibex/env/core_ibex_csr_if.sv
vendored
|
@ -9,4 +9,13 @@ interface core_ibex_csr_if(input logic clk);
|
|||
logic [31:0] csr_wdata;
|
||||
logic [31:0] csr_rdata;
|
||||
ibex_pkg::csr_op_e csr_op;
|
||||
|
||||
clocking csr_cb @(posedge clk);
|
||||
input csr_access;
|
||||
input csr_addr;
|
||||
input csr_wdata;
|
||||
input csr_rdata;
|
||||
input csr_op;
|
||||
endclocking
|
||||
|
||||
endinterface
|
||||
|
|
14
dv/uvm/core_ibex/env/core_ibex_dut_probe_if.sv
vendored
14
dv/uvm/core_ibex/env/core_ibex_dut_probe_if.sv
vendored
|
@ -16,6 +16,20 @@ interface core_ibex_dut_probe_if(input logic clk);
|
|||
logic debug_req;
|
||||
ibex_pkg::priv_lvl_e priv_mode;
|
||||
|
||||
clocking dut_cb @(posedge clk);
|
||||
output fetch_enable;
|
||||
output debug_req;
|
||||
input reset;
|
||||
input illegal_instr;
|
||||
input ecall;
|
||||
input wfi;
|
||||
input ebreak;
|
||||
input dret;
|
||||
input mret;
|
||||
input core_sleep;
|
||||
input priv_mode;
|
||||
endclocking
|
||||
|
||||
initial begin
|
||||
debug_req = 1'b0;
|
||||
end
|
||||
|
|
|
@ -12,9 +12,9 @@ module core_ibex_tb_top;
|
|||
logic fetch_enable;
|
||||
|
||||
clk_if ibex_clk_if(.clk(clk), .rst_n(rst_n));
|
||||
irq_if irq_vif();
|
||||
ibex_mem_intf data_mem_vif();
|
||||
ibex_mem_intf instr_mem_vif();
|
||||
irq_if irq_vif(.clk(clk));
|
||||
ibex_mem_intf data_mem_vif(.clk(clk));
|
||||
ibex_mem_intf instr_mem_vif(.clk(clk));
|
||||
|
||||
|
||||
// DUT probe interface
|
||||
|
@ -89,10 +89,8 @@ module core_ibex_tb_top;
|
|||
);
|
||||
|
||||
// Data load/store vif connection
|
||||
assign data_mem_vif.clock = clk;
|
||||
assign data_mem_vif.reset = ~rst_n;
|
||||
// Instruction fetch vif connnection
|
||||
assign instr_mem_vif.clock = clk;
|
||||
assign instr_mem_vif.reset = ~rst_n;
|
||||
assign instr_mem_vif.we = 0;
|
||||
assign instr_mem_vif.be = 0;
|
||||
|
@ -118,7 +116,6 @@ module core_ibex_tb_top;
|
|||
assign rvfi_if.mem_rdata = dut.rvfi_mem_rdata;
|
||||
assign rvfi_if.mem_wdata = dut.rvfi_mem_wdata;
|
||||
// Irq interface connections
|
||||
assign irq_vif.clock = clk;
|
||||
assign irq_vif.reset = ~rst_n;
|
||||
// Dut_if interface connections
|
||||
assign dut_if.ecall = dut.u_ibex_core.id_stage_i.controller_i.ecall_insn;
|
||||
|
|
|
@ -68,10 +68,10 @@ class core_ibex_base_test extends uvm_test;
|
|||
enable_irq_seq = cfg.enable_irq_single_seq || cfg.enable_irq_multiple_seq;
|
||||
phase.raise_objection(this);
|
||||
run = phase;
|
||||
dut_vif.fetch_enable = 1'b0;
|
||||
dut_vif.dut_cb.fetch_enable <= 1'b0;
|
||||
clk_vif.wait_clks(100);
|
||||
load_binary_to_mem();
|
||||
dut_vif.fetch_enable = 1'b1;
|
||||
dut_vif.dut_cb.fetch_enable <= 1'b1;
|
||||
send_stimulus();
|
||||
wait_for_test_done();
|
||||
phase.drop_objection(this);
|
||||
|
@ -116,11 +116,11 @@ class core_ibex_base_test extends uvm_test;
|
|||
virtual task wait_for_test_done();
|
||||
fork
|
||||
begin
|
||||
wait (dut_vif.ecall === 1'b1);
|
||||
wait (dut_vif.dut_cb.ecall === 1'b1);
|
||||
vseq.stop();
|
||||
`uvm_info(`gfn, "ECALL instruction is detected, test done", UVM_LOW)
|
||||
// De-assert fetch enable to finish the test
|
||||
dut_vif.fetch_enable = 1'b0;
|
||||
dut_vif.dut_cb.fetch_enable <= 1'b0;
|
||||
fork
|
||||
check_perf_stats();
|
||||
// Wait some time for the remaining instruction to finish
|
||||
|
|
|
@ -131,15 +131,15 @@ class debug_seq extends core_base_seq#(irq_seq_item);
|
|||
if (!uvm_config_db#(virtual core_ibex_dut_probe_if)::get(null, "", "dut_if", dut_vif)) begin
|
||||
`uvm_fatal(get_full_name(), "Cannot get dut_if")
|
||||
end
|
||||
dut_vif.debug_req <= 1'b0;
|
||||
dut_vif.dut_cb.debug_req <= 1'b0;
|
||||
super.body();
|
||||
endtask
|
||||
|
||||
virtual task send_req();
|
||||
`uvm_info(get_full_name(), "Sending debug request", UVM_HIGH)
|
||||
dut_vif.debug_req <= 1'b1;
|
||||
dut_vif.dut_cb.debug_req <= 1'b1;
|
||||
clk_vif.wait_clks(50);
|
||||
dut_vif.debug_req <= 1'b0;
|
||||
dut_vif.dut_cb.debug_req <= 1'b0;
|
||||
endtask
|
||||
|
||||
endclass
|
||||
|
|
|
@ -47,7 +47,7 @@ class core_ibex_reset_test extends core_ibex_base_test;
|
|||
clk_vif.wait_clks($urandom_range(0, 50000));
|
||||
fork
|
||||
begin
|
||||
dut_vif.fetch_enable = 1'b0;
|
||||
dut_vif.dut_cb.fetch_enable <= 1'b0;
|
||||
clk_vif.reset();
|
||||
end
|
||||
begin
|
||||
|
@ -61,7 +61,7 @@ class core_ibex_reset_test extends core_ibex_base_test;
|
|||
end
|
||||
join
|
||||
// Assert fetch_enable to have the core start executing from boot address
|
||||
dut_vif.fetch_enable = 1'b1;
|
||||
dut_vif.dut_cb.fetch_enable <= 1'b1;
|
||||
end
|
||||
endtask
|
||||
|
||||
|
@ -223,7 +223,7 @@ class core_ibex_debug_intr_basic_test extends core_ibex_base_test;
|
|||
end
|
||||
check_next_core_status(HANDLING_IRQ, "Core did not jump to vectored interrupt handler", 750);
|
||||
check_priv_mode(PRIV_LVL_M);
|
||||
operating_mode = dut_vif.priv_mode;
|
||||
operating_mode = dut_vif.dut_cb.priv_mode;
|
||||
// check mstatus
|
||||
wait_for_csr_write(CSR_MSTATUS, 500);
|
||||
mstatus = signature_data;
|
||||
|
@ -329,16 +329,16 @@ class core_ibex_debug_intr_basic_test extends core_ibex_base_test;
|
|||
begin
|
||||
case (ret)
|
||||
"dret": begin
|
||||
wait (dut_vif.dret === 1'b1);
|
||||
wait (dut_vif.dut_cb.dret === 1'b1);
|
||||
end
|
||||
"mret": begin
|
||||
wait (dut_vif.mret === 1'b1);
|
||||
wait (dut_vif.dut_cb.mret === 1'b1);
|
||||
end
|
||||
default: begin
|
||||
`uvm_fatal(`gfn, $sformatf("Invalid xRET instruction %0s", ret))
|
||||
end
|
||||
endcase
|
||||
wait (dut_vif.priv_mode === select_mode());
|
||||
wait (dut_vif.dut_cb.priv_mode === select_mode());
|
||||
end
|
||||
begin : ret_timeout
|
||||
clk_vif.wait_clks(timeout);
|
||||
|
@ -352,7 +352,7 @@ class core_ibex_debug_intr_basic_test extends core_ibex_base_test;
|
|||
endtask
|
||||
|
||||
virtual function void check_priv_mode(priv_lvl_e mode);
|
||||
`DV_CHECK_EQ_FATAL(dut_vif.priv_mode, mode,
|
||||
`DV_CHECK_EQ_FATAL(dut_vif.dut_cb.priv_mode, mode,
|
||||
"Incorrect privilege mode")
|
||||
endfunction
|
||||
|
||||
|
@ -397,7 +397,7 @@ class core_ibex_directed_test extends core_ibex_debug_intr_basic_test;
|
|||
check_stimulus();
|
||||
end : stimulus
|
||||
begin
|
||||
wait(dut_vif.ecall === 1'b1);
|
||||
wait (dut_vif.dut_cb.ecall === 1'b1);
|
||||
disable stimulus;
|
||||
if (run.get_objection_count(this) > 1) begin
|
||||
run.drop_objection(this);
|
||||
|
@ -475,8 +475,8 @@ class core_ibex_irq_wfi_test extends core_ibex_directed_test;
|
|||
|
||||
virtual task check_stimulus();
|
||||
forever begin
|
||||
wait (dut_vif.wfi === 1'b1);
|
||||
wait(dut_vif.core_sleep === 1'b1);
|
||||
wait (dut_vif.dut_cb.wfi === 1'b1);
|
||||
wait (dut_vif.dut_cb.core_sleep === 1'b1);
|
||||
send_irq_stimulus();
|
||||
end
|
||||
endtask
|
||||
|
@ -492,13 +492,15 @@ class core_ibex_irq_csr_test extends core_ibex_directed_test;
|
|||
virtual task check_stimulus();
|
||||
vseq.irq_raise_single_seq_h.max_delay = 0;
|
||||
// wait for a write to mstatus - should be in init code
|
||||
wait(csr_vif.csr_access === 1'b1 && csr_vif.csr_addr === CSR_MSTATUS &&
|
||||
csr_vif.csr_op != CSR_OP_READ);
|
||||
wait (csr_vif.csr_cb.csr_access === 1'b1 &&
|
||||
csr_vif.csr_cb.csr_addr === CSR_MSTATUS &&
|
||||
csr_vif.csr_cb.csr_op != CSR_OP_READ);
|
||||
// send interrupt immediately after detection
|
||||
send_irq_stimulus();
|
||||
// wait for a write to mie - should be in init code
|
||||
wait(csr_vif.csr_access === 1'b1 && csr_vif.csr_addr === CSR_MIE &&
|
||||
csr_vif.csr_op != CSR_OP_READ);
|
||||
wait (csr_vif.csr_cb.csr_access === 1'b1 &&
|
||||
csr_vif.csr_cb.csr_addr === CSR_MIE &&
|
||||
csr_vif.csr_cb.csr_op != CSR_OP_READ);
|
||||
// send interrupt immediately after detection
|
||||
send_irq_stimulus();
|
||||
endtask
|
||||
|
@ -562,7 +564,7 @@ class core_ibex_debug_in_irq_test extends core_ibex_directed_test;
|
|||
send_debug_stimulus(operating_mode, "Core did not enter debug mode from interrupt handler");
|
||||
end
|
||||
begin
|
||||
wait(dut_vif.dret == 1'b1);
|
||||
wait (dut_vif.dut_cb.dret == 1'b1);
|
||||
send_irq_stimulus_end();
|
||||
end
|
||||
join
|
||||
|
@ -591,8 +593,9 @@ class core_ibex_nested_irq_test extends core_ibex_directed_test;
|
|||
// Send nested interrupt after the checks of the first interrupt have finished
|
||||
in_nested_trap = 1'b1;
|
||||
// wait until we are setting mstatus.mie to 1'b1 to send the next set of interrupts
|
||||
wait(csr_vif.csr_access === 1'b1 && csr_vif.csr_addr === CSR_MSTATUS &&
|
||||
csr_vif.csr_op != CSR_OP_READ);
|
||||
wait (csr_vif.csr_cb.csr_access === 1'b1 &&
|
||||
csr_vif.csr_cb.csr_addr === CSR_MSTATUS &&
|
||||
csr_vif.csr_cb.csr_op != CSR_OP_READ);
|
||||
send_irq_stimulus(1'b0);
|
||||
vseq.irq_raise_seq_h.max_delay = initial_irq_delay;
|
||||
in_nested_trap = 1'b0;
|
||||
|
@ -611,8 +614,8 @@ class core_ibex_debug_wfi_test extends core_ibex_directed_test;
|
|||
|
||||
virtual task check_stimulus();
|
||||
forever begin
|
||||
wait (dut_vif.wfi === 1'b1);
|
||||
wait (dut_vif.core_sleep === 1'b1);
|
||||
wait (dut_vif.dut_cb.wfi === 1'b1);
|
||||
wait (dut_vif.dut_cb.core_sleep === 1'b1);
|
||||
clk_vif.wait_clks($urandom_range(100));
|
||||
send_debug_stimulus(init_operating_mode, "Core did not jump into debug mode from WFI state");
|
||||
end
|
||||
|
@ -629,12 +632,14 @@ class core_ibex_debug_csr_test extends core_ibex_directed_test;
|
|||
virtual task check_stimulus();
|
||||
vseq.debug_seq_single_h.max_delay = 0;
|
||||
// wait for a dummy write to mstatus in init code
|
||||
wait(csr_vif.csr_access === 1'b1 && csr_vif.csr_addr === CSR_MSTATUS &&
|
||||
csr_vif.csr_op != CSR_OP_READ);
|
||||
wait (csr_vif.csr_cb.csr_access === 1'b1 &&
|
||||
csr_vif.csr_cb.csr_addr === CSR_MSTATUS &&
|
||||
csr_vif.csr_cb.csr_op != CSR_OP_READ);
|
||||
send_debug_stimulus(init_operating_mode, "Core did not trap to debug mode upon debug stimulus");
|
||||
// wait for a dummy write to mie in the init code
|
||||
wait(csr_vif.csr_access === 1'b1 && csr_vif.csr_addr === CSR_MIE &&
|
||||
csr_vif.csr_op != CSR_OP_READ);
|
||||
wait (csr_vif.csr_cb.csr_access === 1'b1 &&
|
||||
csr_vif.csr_cb.csr_addr === CSR_MIE &&
|
||||
csr_vif.csr_cb.csr_op != CSR_OP_READ);
|
||||
send_debug_stimulus(init_operating_mode, "Core did not trap to debug mode upon debug stimulus");
|
||||
endtask
|
||||
|
||||
|
@ -648,7 +653,7 @@ class core_ibex_dret_test extends core_ibex_directed_test;
|
|||
|
||||
virtual task check_stimulus();
|
||||
forever begin
|
||||
wait (dut_vif.dret === 1'b1);
|
||||
wait (dut_vif.dut_cb.dret === 1'b1);
|
||||
check_illegal_insn("Core did not treat dret like illegal instruction");
|
||||
end
|
||||
endtask
|
||||
|
@ -678,7 +683,7 @@ class core_ibex_debug_ebreak_test extends core_ibex_directed_test;
|
|||
// capture the first write of dpc
|
||||
wait_for_csr_write(CSR_DPC, 500);
|
||||
dpc = signature_data;
|
||||
wait (dut_vif.ebreak === 1'b1);
|
||||
wait (dut_vif.dut_cb.ebreak === 1'b1);
|
||||
// compare the second writes of dcsr and dpc against the captured values
|
||||
wait_for_csr_write(CSR_DCSR, 1000);
|
||||
`DV_CHECK_EQ_FATAL(dcsr, signature_data,
|
||||
|
@ -713,7 +718,7 @@ class core_ibex_debug_ebreakmu_test extends core_ibex_directed_test;
|
|||
check_dcsr_cause(DBG_CAUSE_HALTREQ);
|
||||
wait_ret("dret", 5000);
|
||||
forever begin
|
||||
wait (dut_vif.ebreak === 1'b1);
|
||||
wait (dut_vif.dut_cb.ebreak === 1'b1);
|
||||
check_next_core_status(IN_DEBUG_MODE,
|
||||
"Core did not enter debug mode after execution of ebreak", 2000);
|
||||
check_priv_mode(PRIV_LVL_M);
|
||||
|
@ -840,7 +845,7 @@ class core_ibex_mem_error_test extends core_ibex_directed_test;
|
|||
exc_type = EXC_CAUSE_STORE_ACCESS_FAULT;
|
||||
end
|
||||
check_mcause(1'b0, exc_type);
|
||||
wait (dut_vif.mret === 1'b1);
|
||||
wait (dut_vif.dut_cb.mret === 1'b1);
|
||||
`uvm_info(`gfn, "exiting mem fault checker", UVM_LOW)
|
||||
endtask
|
||||
|
||||
|
@ -876,7 +881,7 @@ class core_ibex_mem_error_test extends core_ibex_directed_test;
|
|||
"Core did not register correct memory fault type", 500);
|
||||
exc_type = EXC_CAUSE_INSTR_ACCESS_FAULT;
|
||||
check_mcause(1'b0, exc_type);
|
||||
wait (dut_vif.mret === 1'b1);
|
||||
wait (dut_vif.dut_cb.mret === 1'b1);
|
||||
`uvm_info(`gfn, "exiting mem fault checker", UVM_LOW)
|
||||
endtask
|
||||
|
||||
|
@ -891,7 +896,7 @@ class core_ibex_umode_tw_test extends core_ibex_directed_test;
|
|||
virtual task check_stimulus();
|
||||
bit [ibex_mem_intf_agent_pkg::DATA_WIDTH-1:0] mcause;
|
||||
forever begin
|
||||
wait (dut_vif.wfi === 1'b1);
|
||||
wait (dut_vif.dut_cb.wfi === 1'b1);
|
||||
check_illegal_insn("Core did not treat U-mode WFI as illegal");
|
||||
end
|
||||
endtask
|
||||
|
@ -907,9 +912,9 @@ class core_ibex_invalid_csr_test extends core_ibex_directed_test;
|
|||
virtual task check_stimulus();
|
||||
forever begin
|
||||
// Wait for a CSR access
|
||||
wait (csr_vif.csr_access == 1'b1);
|
||||
wait (csr_vif.csr_cb.csr_access == 1'b1);
|
||||
check_illegal_insn($sformatf("Core did not treat access to CSR 0x%0x from %0s as illegal",
|
||||
csr_vif.csr_addr, init_operating_mode));
|
||||
csr_vif.csr_cb.csr_addr, init_operating_mode));
|
||||
end
|
||||
endtask
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue