Skip to content

Commit

Permalink
Add a Frontend model to the CVA6 scoreboard
Browse files Browse the repository at this point in the history
Signed-off-by: Alae-Eddine Ez-Zejjari <[email protected]>
  • Loading branch information
AEzzejjari committed Nov 15, 2024
1 parent 4619a67 commit c78d021
Show file tree
Hide file tree
Showing 15 changed files with 1,732 additions and 1 deletion.
1,150 changes: 1,150 additions & 0 deletions verif/env/uvme/frontend/uvme_cva6_frontend_model.sv

Large diffs are not rendered by default.

204 changes: 204 additions & 0 deletions verif/env/uvme/frontend/uvme_cva6_frontend_mon.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
// Copyright 2024 Thales DIS SAS
//
// 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
//
// Original Author: Alae Eddine EZ ZEJJARI ([email protected]) – sub-contractor MU-Electronics for Thales group


`ifndef __UVME_CVA6_FRONTEND_MON_SV__
`define __UVME_CVA6_FRONTEND_MON_SV__


// Frontend transaction
class uvme_cva6_frontend_transaction_c extends uvm_sequence_item;

logic flush;
logic flush_bp;

uvme_frontend_icache_req_t icache_req;
uvme_frontend_icache_rsp_t icache_rsp;

uvme_frontend_bp_resolve_t resolve_branch;

logic fetch_valid[RTLCVA6Cfg.NrIssuePorts];
logic fetch_ready[RTLCVA6Cfg.NrIssuePorts];
uvme_frontend_fetched_data_t fetch_instr[RTLCVA6Cfg.NrIssuePorts];

logic boot_valid;

logic eret;
logic[RTLCVA6Cfg.VLEN-1:0] epc;

logic ex_valid;
logic halt;
logic[RTLCVA6Cfg.VLEN-1:0] trap_vector_base;

logic set_pc_commit;
logic[RTLCVA6Cfg.VLEN-1:0] pc_commit;

logic set_debug_pc;

`uvm_object_utils_begin(uvme_cva6_frontend_transaction_c)
`uvm_field_int ( flush , UVM_DEFAULT | UVM_BIN)
`uvm_field_int ( flush_bp , UVM_DEFAULT | UVM_BIN)
`uvm_object_utils_end

/**
* Default constructor.
*/
function new(string name="uvme_cva6_frontend_transaction");
super.new(name);
endfunction

endclass : uvme_cva6_frontend_transaction_c


// Frontend Monitor
// Instantiate a virtual interface of the frontend
// Capture all the necessary signals in a frontend transaction and send them through an analysis port.
class uvme_cva6_frontend_mon_c extends uvm_monitor;

`uvm_component_utils(uvme_cva6_frontend_mon_c)

// Objects
uvme_cva6_cfg_c cfg;

// Analysis Ports
uvm_analysis_port #(uvme_cva6_frontend_transaction_c) frontend_packets_collected;

// Handle to agent switch interface
virtual uvmt_frontend_intf frontend_vif;

event reset_asserted ;
event reset_deasserted ;

/**
* Constructor
*/
function new(string name="uvme_cva6_frontend_mon", uvm_component parent=null);
super.new(name, parent);
endfunction

/**
* Build Phase
*/
function void build_phase(uvm_phase phase);

super.build_phase(phase);

// Instantiation of the uvm_analysis_port
frontend_packets_collected = new("frontend_packets_collected" , this) ;

if (!uvm_config_db#(virtual uvmt_frontend_intf)::get(this, "", "cva6_frontend_bus", frontend_vif)) begin
`uvm_fatal("VIF", $sformatf("Could not find vif handle of type %s in uvm_config_db", $typename(frontend_vif)))
end
else begin
`uvm_info("VIF", $sformatf("Found vif handle of type %s in uvm_config_db", $typename(frontend_vif)), UVM_DEBUG)
end

void'(uvm_config_db#(uvme_cva6_cfg_c)::get(this, "", "cfg", cfg));
if (!cfg)
`uvm_fatal("CFG", "Configuration handle is null")

endfunction : build_phase

/**
* Pre reset phase
*/
virtual task pre_reset_phase(uvm_phase phase);
-> reset_asserted;
endtask : pre_reset_phase

/**
* Reset phase
*/
virtual task reset_phase(uvm_phase phase);
super.reset_phase(phase);
endtask : reset_phase

/**
* Post reset phase
*/
virtual task post_reset_phase(uvm_phase phase);
-> reset_deasserted;
endtask : post_reset_phase

/**
* Run Phase
*/
task run_phase(uvm_phase phase);
forever begin
@(reset_deasserted);
fork
receive_frontend_transaction_task(phase);
join_none
@(reset_asserted);
disable fork;
end
endtask : run_phase

/**
* Task receive frontend request and response
*/
task receive_frontend_transaction_task(uvm_phase phase);
uvme_cva6_frontend_transaction_c frontend_transaction;
int predict;
int boot_valid = 1;

forever begin
@(posedge frontend_vif.clk);
frontend_transaction = new();
frontend_transaction.flush = frontend_vif.flush_i;
frontend_transaction.flush_bp = frontend_vif.flush_bp_i;
frontend_transaction.icache_rsp.req = frontend_vif.icache_dreq_o.req;
frontend_transaction.icache_rsp.kill_s1 = frontend_vif.icache_dreq_o.kill_s1;
frontend_transaction.icache_rsp.kill_s2 = frontend_vif.icache_dreq_o.kill_s2;
frontend_transaction.icache_rsp.vaddr = frontend_vif.icache_dreq_o.vaddr;
frontend_transaction.icache_req.ready = frontend_vif.icache_dreq_i.ready;
frontend_transaction.icache_req.valid = frontend_vif.icache_dreq_i.valid;
frontend_transaction.icache_req.data = frontend_vif.icache_dreq_i.data;
frontend_transaction.icache_req.vaddr = frontend_vif.icache_dreq_i.vaddr;
frontend_transaction.resolve_branch = frontend_vif.resolved_branch_i;
for(int i = 0; i < RTLCVA6Cfg.NrIssuePorts; i++) begin
frontend_transaction.fetch_valid[i] = frontend_vif.fetch_entry_valid_o[i];
frontend_transaction.fetch_ready[i] = frontend_vif.fetch_entry_ready_i[i];
frontend_transaction.fetch_instr[i].address = frontend_vif.fetch_entry_o[i].address;
frontend_transaction.fetch_instr[i].instruction = frontend_vif.fetch_entry_o[i].instruction;
predict = frontend_vif.fetch_entry_o[i].branch_predict.cf;
frontend_transaction.fetch_instr[i].predict = predict;
frontend_transaction.fetch_instr[i].predicted_address = frontend_vif.fetch_entry_o[i].branch_predict.predict_address;
end
frontend_transaction.eret = frontend_vif.eret_i;
frontend_transaction.epc = frontend_vif.epc_i;
frontend_transaction.ex_valid = frontend_vif.ex_valid_i;
frontend_transaction.halt = frontend_vif.halt_i;
frontend_transaction.trap_vector_base = frontend_vif.trap_vector_base_i;
frontend_transaction.set_pc_commit = frontend_vif.set_pc_commit_i;
frontend_transaction.pc_commit = frontend_vif.pc_commit_i;
frontend_transaction.set_debug_pc = frontend_vif.set_debug_pc_i;
if(boot_valid == 1) begin
frontend_transaction.boot_valid = 1;
end else begin
frontend_transaction.boot_valid = 0;
end
boot_valid = 0;

frontend_packets_collected.write(frontend_transaction);
end // forever
endtask : receive_frontend_transaction_task
endclass : uvme_cva6_frontend_mon_c


`endif // __UVME_CVA6_FRONTEND_MON_SV__
170 changes: 170 additions & 0 deletions verif/env/uvme/frontend/uvme_cva6_frontend_sb.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
// Copyright 2024 Thales DIS SAS
//
// 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
//
// Original Author: Alae Eddine EZ ZEJJARI ([email protected]) – sub-contractor MU-Electronics for Thales group


`ifndef __UVME_CVA6_FRONTEND_SB_SV__
`define __UVME_CVA6_FRONTEND_SB_SV__


// Frontend Scoreboard
// The scoreboard contains a frontend model and monitor of the Frontend interface
// The scoreboard captures the decoded committed instructions using an analysis port and counts all instruction types.
// It also captures transactions monitored through an analysis port and counts all types of instructions sent to the decode stage, requests sent to the cache, and cache responses.
class uvme_cva6_frontend_sb_c extends uvm_scoreboard;

// Objects
uvme_cva6_cfg_c cfg;

uvm_tlm_analysis_fifo#(uvma_isacov_mon_trn_c) isa_trn_fifo;
uvm_tlm_analysis_fifo#(uvme_cva6_frontend_transaction_c) frontend_trn_fifo;
uvma_isacov_mon_trn_c#(ILEN,XLEN) isa_instr;
uvme_cva6_frontend_transaction_c frontend_instr;

uvme_cva6_frontend_model_c frontend_model;
uvme_cva6_frontend_mon_c frontend_mon;

int fetched_inst_count;
int req_cache_inst_count;
int cached_inst_count;
int axi_inst_count;
int mispredict_count;
int branch_inst_count;
int branch_mispredict_count;
int ret_inst_count;
int ret_mispredict_count;
int jump_inst_count;
int jump_mispredict_count;
int isa_inst_count;

`uvm_component_utils_begin(uvme_cva6_frontend_sb_c)
`uvm_component_utils_end

/**
* Default constructor.
*/
function new(string name="uvme_cva6_frontend_sb_c", uvm_component parent=null);
super.new(name, parent);
endfunction

/**
* Create and configures sub-scoreboards via:
*/
virtual function void build_phase(uvm_phase phase);

void'(uvm_config_db#(uvme_cva6_cfg_c)::get(this, "", "cfg", cfg));
if (!cfg)
`uvm_fatal("CFG", "Configuration handle is null")

isa_trn_fifo = new("isa_trn_fifo", this);
frontend_trn_fifo = new("frontend_trn_fifo", this);

this.frontend_mon = uvme_cva6_frontend_mon_c::type_id::create("frontend_mon", this);
if(cfg.enable_frontend_model) begin
this.frontend_model = uvme_cva6_frontend_model_c::type_id::create("frontend_model", this);
end

endfunction

/**
* Connect the analysis port
*/
function void connect_phase(uvm_phase phase);

super.connect_phase(phase);

//Establishing connections between monitor ports and scoreboard
frontend_mon.frontend_packets_collected.connect(this.frontend_trn_fifo.analysis_export);
if( cfg.enable_frontend_model) begin
//Establishing connections between monitor ports and model if the model is enabled
this.frontend_mon.frontend_packets_collected.connect(frontend_model.mon2mod_export);
`uvm_info(get_type_name(), $sformatf("FRENTEND MODEL IS ACTIVE"), UVM_LOW)
end

endfunction

/**
* Frontend-scoreboard run phase.
*/
task run_phase(uvm_phase phase);
super.run_phase(phase);
fork
begin
// Count the instruction coming from the isacove
forever begin
isa_trn_fifo.get(isa_instr);
isa_inst_count++;
if(isa_instr.instr.group == BRANCH_GROUP)
branch_inst_count++;
else if(isa_instr.instr.group == RET_GROUP)
ret_inst_count++;
else if(isa_instr.instr.group == JUMP_GROUP)
jump_inst_count++;
end
end
begin
// Count the instruction coming from the Frontend
forever begin
frontend_trn_fifo.get(frontend_instr);
scoreboarding_frontend();
end
end
join_any
endtask


function void scoreboarding_frontend();

if(frontend_instr.icache_req.valid) cached_inst_count++;

if(frontend_instr.icache_rsp.req && frontend_instr.icache_req.ready) req_cache_inst_count++;

for(int i = 0; i < RTLCVA6Cfg.NrIssuePorts; i++) begin
if(frontend_instr.fetch_valid[i] && frontend_instr.fetch_ready[i]) fetched_inst_count++;
end

if(frontend_instr.resolve_branch.is_mispredict) mispredict_count++;

if(frontend_instr.resolve_branch.is_mispredict && frontend_instr.resolve_branch.cf_type == 1) branch_mispredict_count++;

if(frontend_instr.resolve_branch.is_mispredict && frontend_instr.resolve_branch.cf_type == 4) ret_mispredict_count++;

if(frontend_instr.resolve_branch.is_mispredict && (frontend_instr.resolve_branch.cf_type == 2 || frontend_instr.resolve_branch.cf_type == 3)) jump_mispredict_count++;

endfunction : scoreboarding_frontend

/**
* Disply the final results of the scoreboarding
*/
function void check_phase(uvm_phase phase);

super.check_phase(phase);
`uvm_info("Frontend scorboard checks", $sformatf("number of fetch requested by the frotend req_cache_inst_count = %d", req_cache_inst_count), UVM_NONE)
`uvm_info("Frontend scorboard checks", $sformatf("number of fetch sent by the cache cached_inst_count = %d", cached_inst_count), UVM_NONE)
`uvm_info("Frontend scorboard checks", $sformatf("number of instruction sent to decode fetched_inst_count = %d", fetched_inst_count), UVM_NONE)
`uvm_info("Frontend scorboard checks", $sformatf("number of instruction seen in the isa isa_inst_count = %d", isa_inst_count), UVM_NONE)
`uvm_info("Frontend scorboard checks", $sformatf("number of mispredict seen in the execut stage mispredict_count = %d", mispredict_count), UVM_NONE)
`uvm_info("Frontend scorboard checks", $sformatf("number of branch instruction seen in the isa branch_inst_count = %d", branch_inst_count), UVM_NONE)
`uvm_info("Frontend scorboard checks", $sformatf("number of branch mispredict seen in the execute stage branch_commit_count = %d", branch_mispredict_count), UVM_NONE)
`uvm_info("Frontend scorboard checks", $sformatf("number of ret instruction seen in the isa ret_inst_count = %d", ret_inst_count), UVM_NONE)
`uvm_info("Frontend scorboard checks", $sformatf("number of ret mispredict seen in the execute stage ret_commit_count = %d", ret_mispredict_count), UVM_NONE)
`uvm_info("Frontend scorboard checks", $sformatf("number of ret instruction seen in the isa jump_inst_count = %d", jump_inst_count), UVM_NONE)
`uvm_info("Frontend scorboard checks", $sformatf("number of jump mispredict seen in the execute stage jump_mispredict_count = %d", jump_mispredict_count), UVM_NONE)
endfunction

endclass : uvme_cva6_frontend_sb_c
`endif // __UVME_CVA6_FRONTEND_SB_SV__
3 changes: 3 additions & 0 deletions verif/env/uvme/uvme_cva6_cfg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ class uvme_cva6_cfg_c extends uvma_core_cntrl_cfg_c;
// Software interrupt supported
rand bit sw_int_supported;

rand bit enable_frontend_model;

`uvm_object_utils_begin(uvme_cva6_cfg_c)
`uvm_field_int ( enabled , UVM_DEFAULT )
`uvm_field_enum(uvm_active_passive_enum, is_active , UVM_DEFAULT )
Expand Down Expand Up @@ -103,6 +105,7 @@ class uvme_cva6_cfg_c extends uvma_core_cntrl_cfg_c;
soft trn_log_enabled == 1;
soft force_disable_csr_checks == 0;
soft sys_clk_period == uvme_cva6_sys_default_clk_period; // see uvme_cva6_constants.sv
soft enable_frontend_model == 1; // see uvme_cva6_constants.sv
}

constraint cva6_riscv_cons {
Expand Down
Loading

0 comments on commit c78d021

Please sign in to comment.