-
Notifications
You must be signed in to change notification settings - Fork 705
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a Frontend model to the CVA6 scoreboard
Signed-off-by: Alae-Eddine Ez-Zejjari <[email protected]>
- Loading branch information
1 parent
4619a67
commit c78d021
Showing
15 changed files
with
1,732 additions
and
1 deletion.
There are no files selected for viewing
1,150 changes: 1,150 additions & 0 deletions
1,150
verif/env/uvme/frontend/uvme_cva6_frontend_model.sv
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.