mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-22 05:07:21 -04:00
Add different slave modes to mem_if
This commit is contained in:
parent
ba56248f18
commit
fc6f5356fb
11 changed files with 91 additions and 39 deletions
4
Makefile
4
Makefile
|
@ -8,7 +8,7 @@ library = work
|
|||
top_level = core_tb
|
||||
test_top_level = core_tb
|
||||
# test targets
|
||||
tests = alu scoreboard fifo mem_arbiter store_queue lsu
|
||||
tests = alu scoreboard fifo mem_arbiter store_queue lsu core
|
||||
# UVM agents
|
||||
agents = include/ariane_pkg.svh $(wildcard tb/agents/*/*.sv)
|
||||
# path to interfaces
|
||||
|
@ -68,7 +68,7 @@ $(tests):
|
|||
# Optimize top level
|
||||
vopt${questa_version} ${compile_flag} $@_tb -o $@_tb_optimized +acc -check_synthesis
|
||||
# vsim${questa_version} $@_tb_optimized
|
||||
# vsim${questa_version} +UVM_TESTNAME=$@_test -coverage -classdebug $@_tb_optimized
|
||||
# vsim${questa_version} -c +UVM_TESTNAME=$@_test -coverage -classdebug $@_tb_optimized
|
||||
vsim${questa_version} +UVM_TESTNAME=$@_test +uvm_set_action="*,_ALL_,UVM_ERROR,UVM_DISPLAY|UVM_STOP" -c -coverage -classdebug -do "coverage save -onexit $@.ucdb; run -a; quit -code [coverage attribute -name TESTSTATUS -concise]" $@_tb_optimized
|
||||
|
||||
build-moore:
|
||||
|
|
|
@ -14,8 +14,13 @@
|
|||
// University of Bologna.
|
||||
|
||||
package mem_if_agent_pkg;
|
||||
// configure the slave memory interface
|
||||
// 1. either as a slave with random grant response
|
||||
// 2. as a master interface making random data requests
|
||||
// 3. as a slave with no grant randomization
|
||||
// 4. replay data
|
||||
typedef enum {
|
||||
SLAVE, MASTER
|
||||
SLAVE, SLAVE_REPLAY, SLAVE_NO_RANDOM, MASTER
|
||||
} mem_if_config;
|
||||
// Mode of request either read or write
|
||||
typedef enum {
|
||||
|
|
|
@ -20,7 +20,8 @@ class mem_if_driver extends uvm_driver #(mem_if_seq_item);
|
|||
|
||||
// Virtual Interface
|
||||
virtual mem_if fu;
|
||||
|
||||
// create a 4 kB memory
|
||||
logic [7:0] rmem [4096];
|
||||
//---------------------
|
||||
// Data Members
|
||||
//---------------------
|
||||
|
@ -31,41 +32,47 @@ class mem_if_driver extends uvm_driver #(mem_if_seq_item);
|
|||
super.new(name, parent);
|
||||
endfunction
|
||||
|
||||
task read_mem(logic [64:0] address, string path);
|
||||
$readmemh(path, rmem, address);
|
||||
$display("Read instruction memory file @%0h from %s", address, path);
|
||||
endtask : read_mem
|
||||
|
||||
task run_phase(uvm_phase phase);
|
||||
mem_if_seq_item cmd;
|
||||
|
||||
// --------------
|
||||
// Slave Port
|
||||
// --------------
|
||||
// this driver is configured as a SLAVE
|
||||
if (m_cfg.mem_if_config == SLAVE) begin
|
||||
// we serve all requests from the memory file we store in our configuration object
|
||||
// --------------
|
||||
// Slave Port
|
||||
// --------------
|
||||
logic [7:0] imem [400];
|
||||
if (m_cfg.mem_if_config inside {SLAVE, SLAVE_REPLAY, SLAVE_NO_RANDOM}) begin
|
||||
|
||||
logic [63:0] address [$];
|
||||
logic [63:0] addr;
|
||||
logic slave_data_gnt;
|
||||
semaphore lock = new(1);
|
||||
slave_data_gnt = 1'b1;
|
||||
|
||||
// we serve all requests from the memory file we store in our configuration object
|
||||
// read memory file
|
||||
// TODO: get the filename and address from plusarg
|
||||
if (m_cfg.mem_if_config inside {SLAVE, SLAVE_NO_RANDOM}) begin
|
||||
read_mem(64'b0, "add_test.v");
|
||||
end
|
||||
|
||||
// grant process is combinatorial
|
||||
fork
|
||||
slave_gnt: begin
|
||||
fu.mck.data_gnt <= 1'b1;
|
||||
forever begin
|
||||
|
||||
// @(fu.mck);
|
||||
// wait until we got a valid request
|
||||
// randomize grant delay - the grant may come in the same clock cycle
|
||||
repeat ($urandom_range(0,3)) @(fu.mck);
|
||||
fu.mck.data_gnt <= 1'b1;
|
||||
repeat ($urandom_range(0,3)) @(fu.mck);
|
||||
fu.mck.data_gnt <= 1'b0;
|
||||
// now set the grant to one
|
||||
// if the request is still here go for it
|
||||
// end else begin
|
||||
// fu.mck.data_gnt <= 1'b0;
|
||||
// slave_data_gnt = 1'b0;
|
||||
// end
|
||||
// do we have another request?
|
||||
// we don't to give random grants
|
||||
// instead we always grant immediately
|
||||
if (m_cfg.mem_if_config != SLAVE_NO_RANDOM) begin
|
||||
forever begin
|
||||
// randomize grant delay - the grant may come in the same clock cycle
|
||||
repeat ($urandom_range(0,3)) @(fu.mck);
|
||||
fu.mck.data_gnt <= 1'b1;
|
||||
repeat ($urandom_range(0,3)) @(fu.mck);
|
||||
fu.mck.data_gnt <= 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
slave_serve: begin
|
||||
|
@ -84,10 +91,24 @@ class mem_if_driver extends uvm_driver #(mem_if_seq_item);
|
|||
// we an wait a couple of cycles here
|
||||
// but at least one
|
||||
lock.get(1);
|
||||
repeat ($urandom_range(1,3)) @(fu.mck);
|
||||
// we give the rvalid in the next cycle if didn't request randomization
|
||||
if (m_cfg.mem_if_config != SLAVE_NO_RANDOM)
|
||||
repeat ($urandom_range(1,3)) @(fu.mck);
|
||||
|
||||
fu.mck.data_rvalid <= 1'b1;
|
||||
addr = address.pop_front();
|
||||
fu.mck.data_rdata <= addr;
|
||||
// simply replay the address on the data port
|
||||
if (m_cfg.mem_if_config == SLAVE_REPLAY)
|
||||
fu.mck.data_rdata <= addr;
|
||||
else begin
|
||||
// read from memory
|
||||
fu.mck.data_rdata <= {
|
||||
rmem[$unsigned(addr + 3)],
|
||||
rmem[$unsigned(addr + 2)],
|
||||
rmem[$unsigned(addr + 1)],
|
||||
rmem[$unsigned(addr + 0)]
|
||||
};
|
||||
end
|
||||
lock.put(1);
|
||||
end else
|
||||
fu.mck.data_rvalid <= 1'b0;
|
||||
|
@ -102,11 +123,11 @@ class mem_if_driver extends uvm_driver #(mem_if_seq_item);
|
|||
join_none
|
||||
|
||||
// although no other option exist lets be specific about its purpose
|
||||
// this is a master interface
|
||||
// -> this is a master interface
|
||||
// --------------
|
||||
// Master Port
|
||||
// --------------
|
||||
end else if (m_cfg.mem_if_config == MASTER) begin
|
||||
// --------------
|
||||
// Master Port
|
||||
// --------------
|
||||
// request a read
|
||||
// initial statements, sane resets
|
||||
fu.sck.data_req <= 1'b0;
|
||||
|
|
|
@ -79,7 +79,7 @@ class mem_if_monitor extends uvm_component;
|
|||
cmd.be = be.pop_front();
|
||||
cmd.data = fu.pck.data_rdata;
|
||||
// was this from a master or slave agent monitor?
|
||||
cmd.isSlaveAnswer = (m_cfg.mem_if_config == SLAVE) ? 1'b1 : 1'b0;
|
||||
cmd.isSlaveAnswer = (m_cfg.mem_if_config inside {SLAVE, SLAVE_REPLAY, SLAVE_NO_RANDOM}) ? 1'b1 : 1'b0;
|
||||
// export the item via the analysis port
|
||||
$cast(cloned_item, cmd.clone());
|
||||
m_ap.write(cloned_item);
|
||||
|
|
|
@ -16,7 +16,7 @@ module core_tb;
|
|||
logic clk_i;
|
||||
logic rst_ni;
|
||||
|
||||
mem_if #(.DATA_WIDTH(32)) instr_if(clk_i);
|
||||
mem_if instr_if(clk_i);
|
||||
mem_if data_if(clk_i);
|
||||
debug_if debug_if();
|
||||
core_if core_if(clk_i);
|
||||
|
@ -35,10 +35,10 @@ module core_tb;
|
|||
|
||||
.instr_if_address_o ( instr_if.address ),
|
||||
.instr_if_data_req_o ( instr_if.data_req ),
|
||||
.instr_if_data_be_o ( instr_if.data_be ),
|
||||
.instr_if_data_be_o ( instr_if.data_be[3:0] ),
|
||||
.instr_if_data_gnt_i ( instr_if.data_gnt & instr_if.data_req ),
|
||||
.instr_if_data_rvalid_i ( instr_if.data_rvalid ),
|
||||
.instr_if_data_rdata_i ( instr_if.data_rdata ),
|
||||
.instr_if_data_rdata_i ( instr_if.data_rdata[31:0] ),
|
||||
|
||||
.data_if_address_o ( data_if.address ),
|
||||
.data_if_data_wdata_o ( data_if.data_wdata ),
|
||||
|
@ -81,6 +81,7 @@ module core_tb;
|
|||
program testbench (core_if core_if, mem_if instr_if);
|
||||
initial begin
|
||||
uvm_config_db #(virtual core_if)::set(null, "uvm_test_top", "core_if", core_if);
|
||||
uvm_config_db #(virtual mem_if )::set(null, "uvm_test_top", "instr_mem_if", instr_if);
|
||||
// print the topology
|
||||
uvm_top.enable_print_topology = 1;
|
||||
// Start UVM test
|
||||
|
|
11
tb/env/core/core_env.svh
vendored
11
tb/env/core/core_env.svh
vendored
|
@ -23,6 +23,8 @@ class core_env extends uvm_env;
|
|||
// Data Members
|
||||
//------------------------------------------
|
||||
core_if_agent m_core_if_agent;
|
||||
mem_if_agent m_mem_if_instr_agent;
|
||||
|
||||
core_if_sequencer m_core_if_sequencer;
|
||||
core_env_config m_cfg;
|
||||
//------------------------------------------
|
||||
|
@ -45,6 +47,15 @@ class core_env extends uvm_env;
|
|||
m_cfg.m_core_if_agent_config);
|
||||
m_core_if_agent = core_if_agent::type_id::create("m_core_if_agent", this);
|
||||
|
||||
uvm_config_db #(core_if_agent_config)::set(this, "m_core_if_agent*",
|
||||
"core_if_agent_config",
|
||||
m_cfg.m_core_if_agent_config);
|
||||
// get instruction memory interface
|
||||
m_mem_if_instr_agent = mem_if_agent::type_id::create("m_mem_if_instr_agent", this);
|
||||
uvm_config_db #(mem_if_agent_config)::set(this, "m_mem_if_instr_agent*",
|
||||
"mem_if_agent_config",
|
||||
m_cfg.m_instr_if_agent_config);
|
||||
|
||||
// Get sequencer
|
||||
m_core_if_sequencer = core_if_sequencer::type_id::create("m_core_if_sequencer", this);
|
||||
|
||||
|
|
2
tb/env/core/core_env_config.svh
vendored
2
tb/env/core/core_env_config.svh
vendored
|
@ -21,9 +21,11 @@ class core_env_config extends uvm_object;
|
|||
|
||||
// a functional unit master interface
|
||||
virtual core_if m_core_if;
|
||||
virtual mem_if m_instr_mem_if;
|
||||
|
||||
// an agent config
|
||||
|
||||
core_if_agent_config m_core_if_agent_config;
|
||||
mem_if_agent_config m_instr_if_agent_config;
|
||||
|
||||
endclass : core_env_config
|
||||
|
|
1
tb/env/core/core_env_pkg.sv
vendored
1
tb/env/core/core_env_pkg.sv
vendored
|
@ -19,6 +19,7 @@ package core_env_pkg;
|
|||
`include "uvm_macros.svh"
|
||||
// Testbench related imports
|
||||
import core_if_agent_pkg::*;
|
||||
import mem_if_agent_pkg::*;
|
||||
// Includes for the config for the environment
|
||||
`include "core_env_config.svh"
|
||||
// Includes the environment
|
||||
|
|
|
@ -18,8 +18,9 @@ package core_lib_pkg;
|
|||
// Standard UVM import & include:
|
||||
import uvm_pkg::*;
|
||||
`include "uvm_macros.svh"
|
||||
// Import the memory interface agent
|
||||
// Import the core and memory interface agent
|
||||
import core_if_agent_pkg::*;
|
||||
import mem_if_agent_pkg::*;
|
||||
// ------------------------------------------------
|
||||
// Environment which will be instantiated
|
||||
// ------------------------------------------------
|
||||
|
|
|
@ -38,7 +38,7 @@ class core_test_base extends uvm_test;
|
|||
// ---------------------
|
||||
// functional unit interface
|
||||
core_if_agent_config m_core_if_cfg;
|
||||
|
||||
mem_if_agent_config m_instr_mem_if_cfg;
|
||||
//------------------------------------------
|
||||
// Methods
|
||||
//------------------------------------------
|
||||
|
@ -57,12 +57,22 @@ class core_test_base extends uvm_test;
|
|||
// create agent core_if configuration
|
||||
m_core_if_cfg = core_if_agent_config::type_id::create("m_core_if_cfg");
|
||||
m_env_cfg.m_core_if_agent_config = m_core_if_cfg;
|
||||
|
||||
m_instr_mem_if_cfg = mem_if_agent_config::type_id::create("m_instr_mem_if_cfg");
|
||||
// configure the instruction interface as a slave device
|
||||
m_instr_mem_if_cfg.mem_if_config = SLAVE_NO_RANDOM;
|
||||
m_env_cfg.m_instr_if_agent_config = m_instr_mem_if_cfg;
|
||||
// get core_if virtual interfaces
|
||||
// get master interface DB
|
||||
if (!uvm_config_db #(virtual core_if)::get(this, "", "core_if", m_core_if_cfg.m_vif))
|
||||
`uvm_fatal("VIF CONFIG", "Cannot get() interface core_if from uvm_config_db. Have you set() it?")
|
||||
m_env_cfg.m_core_if = m_core_if_cfg.m_vif;
|
||||
|
||||
uvm_config_db #(int)::dump();
|
||||
|
||||
if (!uvm_config_db #(virtual mem_if)::get(this, "", "instr_mem_if", m_instr_mem_if_cfg.fu))
|
||||
`uvm_fatal("VIF CONFIG", "Cannot get() interface mem_if from uvm_config_db. Have you set() it?")
|
||||
m_env_cfg.m_instr_mem_if = m_instr_mem_if_cfg.fu;
|
||||
|
||||
// create environment
|
||||
uvm_config_db #(core_env_config)::set(this, "*", "core_env_config", m_env_cfg);
|
||||
|
|
|
@ -57,7 +57,7 @@ class mem_arbiter_test_base extends uvm_test;
|
|||
// create a slave configuration
|
||||
m_cfg_slave = mem_if_agent_config::type_id::create("m_cfg_slave");
|
||||
m_env_cfg.m_mem_if_slave_agent = m_cfg_slave;
|
||||
m_env_cfg.m_mem_if_slave_agent.mem_if_config = SLAVE;
|
||||
m_env_cfg.m_mem_if_slave_agent.mem_if_config = SLAVE_REPLAY;
|
||||
|
||||
// create agent memory master configuration
|
||||
m_cfg_masters[0] = mem_if_agent_config::type_id::create("m_cfg_master0");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue