I am a student learning to create uvm frameworks and I have a problem when I create a RAL and add it to my existing UVM framework (which was working fine before). I have been double checking for three days but still have no clue and I hope someone can help me. My current dut is a cpu featch part
The main problem is that I feel that the RAL has been built, but whenever I try to use the read command, it reports an error
I googled it and it says it’s a signal connection error but I can’t really find it, hope you can help me
Maybe this is a really stupid question
** Fatal: (SIGSEGV) Bad handle or reference.
Time: 0 ns Iteration: 49 Process: /uvm_pkg::uvm_task_phase::execute/fork#137(#ublk#215181159#137)_7fefed9ae04 File: /software/mentor/questa10.7c/questasim/linux_x86_64/../verilog_src/uvm-1.1d/src/base/uvm_component.svh
Fatal error in Task stage1_tb_top_sv_unit/stage1_scoreboard::run at /home/SOCV-1/Desktop/stage1/uvm/stage1_scoreboard.sv line 51
HDL call sequence:
Stopped at /home/SOCV-1/Desktop/stage1/uvm/stage1_scoreboard.sv 51 Task stage1_tb_top_sv_unit/stage1_scoreboard::run
called from /software/mentor/questa10.7c/questasim/linux_x86_64/../verilog_src/uvm-1.1d/src/base/uvm_component.svh 2288 Task uvm_pkg/uvm_component::run_phase
called from /software/mentor/questa10.7c/questasim/linux_x86_64/../verilog_src/uvm-1.1d/src/base/uvm_common_phases.svh 245 Task uvm_pkg/uvm_run_phase::exec_task
called from /software/mentor/questa10.7c/questasim/linux_x86_64/../verilog_src/uvm-1.1d/src/base/uvm_task_phase.svh 150 Function uvm_pkg/uvm_task_phase::execute
here is code
`include "uvm_macros.svh"
import uvm_pkg::*;
`include "stage1_sequencer.sv"
class reg_iram extends uvm_mem;
uvm_reg_field reg_data;
`uvm_object_utils(reg_iram)
function new(input string name="reg_iram");
super.new(name, 48, 32);
endfunction
endclass
//----------------------------------------------------------------------
class reg_model extends uvm_reg_block;
reg_iram iram;
virtual function void build();
default_map = create_map("default_map", 0, 4, UVM_BIG_ENDIAN);
iram = reg_iram::type_id::create("iram", , get_full_name());
iram.configure(this, "");
//iram.build();
default_map.add_mem(iram, 'h0);
endfunction
`uvm_object_utils(reg_model)
function new(input string name="reg_model");
super.new(name, UVM_NO_COVERAGE);
endfunction
endclass
//---------------------------------------------------------------------
class my_adapter extends uvm_reg_adapter;
string tID = get_type_name();
`uvm_object_utils(my_adapter)
function new(string name="my_adapter");
super.new(name);
endfunction
function uvm_sequence_item reg2bus(const ref uvm_reg_bus_op rw);
stage1_transaction st1_tr;
st1_tr = new("st1_tr");
st1_tr.M_PCIN = rw.addr;
//st1_tr.bus_op = (rw.kind == UVM_READ) BUS_RD: BUS_WR;
//if(st1_tr.bus_op == BUS_WR)
st1_tr.IR_reg= rw.data;
//return bus_tr;
endfunction
function void bus2reg(uvm_sequence_item bus_item, ref uvm_reg_bus_op rw);
stage1_transaction st1_tr;
//if(!cast(st1_tr, bus_item)) begin
//`uvm_fatal(tID, "provided stage1_item is not of correct type, expecting stage1_trans action")
//return;
//end
//rw.kind = (st1_tr.bus_op == BUS_RD) UVM_READ : UVM_WRITE;
rw.addr = st1_tr.M_PCIN;
//rw.data = (st1_tr.bus_op == BUS_RD) st1_tr.rd_data : st1_tr.rw_data;
rw.status = UVM_IS_OK;
endfunction
endclass
Regarding these comments, I want to only read data from my dut, so I have commented out the parts I don’t want as I understand them, if I have any errors please let me know to help me improve
here is interface
//interface
interface stage1_if;
logic IF_CLK;
logic IF_RST;
logic IF_IR_LATCH_EN;
logic IF_NPC_LATCH_EN;
logic IF_MUXPC;
logic[31:0] IF_M_PCIN;
logic[31:0] IF_IR;
logic[31:0] IF_PC_COUNT;
logic[31:0] IF_ID_RA_VAL;
logic[31:0] IF_ID_RB_VAL;
logic[31:0] IF_IMM;
logic[4:0] IF_W_RE_NUM;
logic[4:0] IF_RA;
logic[4:0] IF_RB;
modport port(input IF_CLK, IF_RST, IF_IR_LATCH_EN, IF_NPC_LATCH_EN, IF_MUXPC, IF_M_PCIN, output IF_PC_COUNT, IF_IR, IF_ID_RA_VAL, IF_ID_RB_VAL, IF_IMM, IF_W_RE_NUM, IF_RA, IF_RB);
endinterface
here is sequence
`include "uvm_macros.svh"
import uvm_pkg::*;
class stage1_transaction extends uvm_sequence_item;
rand logic IR_LATCH_EN;
rand logic NPC_LATCH_EN;
rand logic muxpc;
rand logic[31:0] M_PCIN;
logic[31:0] IR;
logic[31:0] IR_reg;
logic[31:0] PC_count;
logic[31:0] id_ra_val;
logic[31:0] id_rb_val;
logic[31:0] id_imm;
logic[4:0] w_re_num;
logic[4:0] ra;
logic[4:0] rb;
function new(string name = "stage1_transaction");
super.new(name);
endfunction: new
`uvm_object_utils_begin(stage1_transaction)
`uvm_field_int(IR_LATCH_EN, UVM_ALL_ON)
`uvm_field_int(NPC_LATCH_EN, UVM_ALL_ON)
`uvm_field_int(muxpc, UVM_ALL_ON)
`uvm_field_int(M_PCIN, UVM_ALL_ON)
`uvm_field_int(IR, UVM_ALL_ON)
`uvm_field_int(IR_reg, UVM_ALL_ON)
`uvm_field_int(PC_count, UVM_ALL_ON)
`uvm_field_int(id_ra_val, UVM_ALL_ON)
`uvm_field_int(id_rb_val, UVM_ALL_ON)
`uvm_field_int(id_imm, UVM_ALL_ON)
`uvm_field_int(w_re_num, UVM_ALL_ON)
`uvm_field_int(ra, UVM_ALL_ON)
`uvm_field_int(rb, UVM_ALL_ON)
`uvm_object_utils_end
endclass: stage1_transaction
class stage1_sequence extends uvm_sequence#(stage1_transaction);
`uvm_object_utils(stage1_sequence)
function new(string name = "stage1_sequence");
super.new(name);
endfunction: new
task body();
stage1_transaction st1_tx;
forever begin
st1_tx = stage1_transaction::type_id::create("st1_tx");
start_item(st1_tx);
assert(st1_tx.randomize());
finish_item(st1_tx);
end
endtask: body
endclass // stage1_sequence
typedef uvm_sequencer#(stage1_transaction) stage1_sequencer;
here is driver
`include "reg_iram.sv"
`include "uvm_macros.svh"
import uvm_pkg::*;
class stage1_driver extends uvm_driver#(stage1_transaction);
`uvm_component_utils(stage1_driver)
virtual stage1_if vif;
event begin_record, end_record;
function new(string name = "stage1_driver",uvm_component parent);
super.new(name, parent);
endfunction: new
function void build_phase(uvm_phase phase);
super.build_phase(phase);
void'(uvm_resource_db#(virtual stage1_if)::read_by_name
(.scope("ifs"), .name("stage1_if"), .val(vif)));
endfunction: build_phase
task run_phase(uvm_phase phase);
super.run_phase(phase);
fork
reset_signals();
get_and_drive(phase);
record();
join
endtask: run_phase
virtual task reset_signals();
wait(vif.IF_RST == 1);
begin
vif.IF_IR_LATCH_EN <= 0;
vif.IF_NPC_LATCH_EN <= 0;
vif.IF_MUXPC <= 0;
vif.IF_M_PCIN <= 0;
@(posedge vif.IF_RST);
end
endtask // reset_signals
virtual task get_and_drive(uvm_phase phase);
wait(vif.IF_RST == 0);
@(negedge vif.IF_CLK);
forever begin
seq_item_port.get(req);
`uvm_info("process hints","driver begin record",UVM_NONE);
->begin_record;
driver_transfer(req);
end
endtask // get_and_drive
virtual task driver_transfer(stage1_transaction tr);
@(posedge vif.IF_CLK);
`uvm_info("process hints","begin driver transfer",UVM_NONE);
vif.IF_IR_LATCH_EN = tr.IR_LATCH_EN;
vif.IF_NPC_LATCH_EN = tr.NPC_LATCH_EN;
vif.IF_MUXPC = tr.muxpc;
vif.IF_M_PCIN = tr.M_PCIN;
@(posedge vif.IF_CLK);
`uvm_info("process hints","driver end record",UVM_NONE);
->end_record;
@(posedge vif.IF_CLK);
endtask // driver_transfer
virtual task record_tr();
forever begin
@(begin_record);
begin_tr(req, "stage1_driver");
@(end_record);
end_tr(req);
end
endtask // record_tr
endclass // stage1_driver
here is monitor
`include "uvm_macros.svh"
import uvm_pkg::*;
`include "stage1_driver.sv"
class stage1_monitor_before extends uvm_monitor;
`uvm_component_utils(stage1_monitor_before)
uvm_analysis_port#(stage1_transaction) item_collected_port_before;
virtual stage1_if vif;
stage1_transaction tr;
event begin_record, end_record;
function new(string name = "stage1_monitor_before", uvm_component parent);
super.new(name, parent);
endfunction // new
function void build_phase(uvm_phase phase);
super.build_phase(phase);
void'(uvm_resource_db#(virtual stage1_if)::read_by_name
(.scope("ifs"), .name("stage1_if"), .val(vif)));
item_collected_port_before = new(.name("item_collected_port_before"), .parent(this));
tr = stage1_transaction::type_id::create("tr", this);
endfunction // build_phase
task run_phase(uvm_phase phase);
super.run_phase(phase);
fork
collect_transaction(phase);
record_tr();
join
endtask // run_phase
virtual task collect_transaction(uvm_phase phase);
wait (vif.IF_RST == 1);
forever begin
#20ns
->begin_record;
@(posedge vif.IF_CLK);
tr.PC_count = vif.IF_PC_COUNT;
tr.id_ra_val = vif.IF_ID_RA_VAL;
tr.id_rb_val = vif.IF_ID_RB_VAL;
tr.id_imm = vif.IF_IMM;
tr.w_re_num = vif.IF_W_RE_NUM;
tr.ra = vif.IF_RA;
tr.rb = vif.IF_RB;
item_collected_port_before.write(tr);
->end_record;
end
endtask // collect_transaction
virtual task record_tr();
forever begin
@(begin_record);
begin_tr(tr, "stage1_monitor_before");
@(end_record);
end_tr(tr);
end
endtask // record_tr
endclass // p4adder_monitor_before
//------------------------------------------------------------
class stage1_monitor_after extends uvm_monitor;
`uvm_component_utils(stage1_monitor_after)
uvm_analysis_port#(stage1_transaction) item_collected_port_after;
//------------------------------------
uvm_analysis_port#(stage1_transaction) reg_port;
virtual stage1_if vif;
//---------------------------reg_model----------------
//reg_model p_rm;
//----------------------------------------------------
event begin_record, end_record;
stage1_transaction tr;
function new(string name = "stage1_monitor_before", uvm_component parent);
super.new(name, parent);
endfunction // new
function void build_phase(uvm_phase phase);
super.build_phase(phase);
void'(uvm_resource_db#(virtual stage1_if)::read_by_name
(.scope("ifs"), .name("stage1_if"), .val(vif)));
item_collected_port_after = new(.name("item_collected_port_after"), .parent(this));
//---------------------------------
reg_port = new(.name("reg_port"), .parent(this));
tr = stage1_transaction::type_id::create("tr", this);
endfunction // build_phase
task run_phase(uvm_phase phase);
super.run_phase(phase);
fork
collect_transaction(phase);
record_tr();
join
endtask // run_phase
virtual task collect_transaction(uvm_phase phase);
forever begin
->begin_record;
item_collected_port_after.write(tr);
->end_record;
end
endtask // collect_transaction
virtual task record_tr();
forever begin
@(begin_record);
begin_tr(tr, "stage1_monitor_after");
@end_record;
end_tr(tr);
end
endtask // record_tr
endclass // stage1_monitor_after
here is agent
`include "uvm_macros.svh"
import uvm_pkg::*;
`include "stage1_monitor.sv"
class stage1_agent extends uvm_agent;
`uvm_component_utils(stage1_agent)
uvm_analysis_port#(stage1_transaction) agent_collected_port_before;
uvm_analysis_port#(stage1_transaction) agent_collected_port_after;
//----------------------------------------------------------
uvm_analysis_port#(stage1_transaction) agent_reg_port;
stage1_sequencer sqr;
stage1_driver drv;
stage1_monitor_before mon_before;
stage1_monitor_after mon_after;
function new(string name = "stage1_agent", uvm_component parent);
super.new(name, parent);
endfunction // new
function void build_phase(uvm_phase phase);
super.build_phase(phase);
agent_collected_port_before = new(.name("agent_collected_port_before"), .parent(this));
agent_collected_port_after = new(.name("agent_collected_port_after"), .parent(this));
//---------------------------
agent_reg_port = new(.name("agent_reg_port"), .parent(this));
mon_before = stage1_monitor_before::type_id::create("mon_before", this);
sqr = stage1_sequencer::type_id::create("sqr", this);
drv = stage1_driver::type_id::create("drv", this);
mon_after = stage1_monitor_after::type_id::create("mon_after", this);
endfunction // build_phase
virtual function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
mon_before.item_collected_port_before.connect(agent_collected_port_before);
mon_after.item_collected_port_after.connect(agent_collected_port_after);
//--------------------------------------------------
mon_after.reg_port.connect(agent_reg_port);
drv.seq_item_port.connect(sqr.seq_item_export);
endfunction // connect_phase
endclass // p4adder_agent
here is scoreboard
`include "uvm_macros.svh"
import uvm_pkg::*;
`include "stage1_agent.sv"
class stage1_scoreboard extends uvm_scoreboard;
`uvm_component_utils(stage1_scoreboard)
uvm_analysis_export #(stage1_transaction) sb_export_before;
uvm_analysis_export #(stage1_transaction) sb_export_after;
uvm_tlm_analysis_fifo #(stage1_transaction) before_fifo;
uvm_tlm_analysis_fifo #(stage1_transaction) after_fifo;
stage1_transaction transaction_before;
stage1_transaction transaction_after;
//-------------------------
reg_model rm;
function new(string name = "stage1_scoreboard", uvm_component parent);
super.new(name, parent);
transaction_before = new("transaction_before");
transaction_after = new("transaction_after");
endfunction // new
function void build_phase(uvm_phase phase);
super.build_phase(phase);
sb_export_before = new("sb_export_before", this);
sb_export_after = new("sb_export_after", this);
before_fifo = new("before_fifo", this);
after_fifo = new("after_fifo", this);
endfunction // build_phase
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
sb_export_before.connect(before_fifo.analysis_export);
sb_export_after.connect(after_fifo.analysis_export);
endfunction // connect_phase
task run();
uvm_status_e status;
uvm_reg_data_t value[];
forever begin
rm.iram.burst_read(.status(status), .value(value), .offset(0));
before_fifo.get(transaction_before);
after_fifo.get(transaction_after);
compare();
end
endtask // run
virtual function void compare();
`uvm_info("HTNTS",{"START COMPARE"},UVM_NONE);
endfunction // compare
endclass // stage1_scoreboard
here is env
`include "uvm_macros.svh"
import uvm_pkg::*;
`include "stage1_scoreboard.sv"
class stage1_env extends uvm_env;
`uvm_component_utils(stage1_env)
stage1_agent st1_agent;
stage1_scoreboard st1_sb;
//----------------------------------------reg_model----------------------
reg_model rm;
my_adapter reg_sqr_adapter;
// my_adapter reg_mon_adapter;
// uvm_reg_predictor #(stage1_transaction) reg_predictor;
function new(string name = "pstage1_env", uvm_component parent);
super.new(name, parent);
endfunction // new
function void build_phase(uvm_phase phase);
super.build_phase(phase);
rm = reg_model::type_id::create(.name("rm"), .parent(this));
rm.configure(null, "");
rm.build();
rm.lock_model();
rm.reset();
reg_sqr_adapter = my_adapter::type_id::create("reg_sqr_adapter", this);
//reg_mon_adapter = my_adapter::type_id::create("reg_mon_adapter", this);
//reg_predictor = new("reg_predictor", this);
st1_agent = stage1_agent::type_id::create(.name("st1_agent"), .parent(this));
st1_sb = stage1_scoreboard::type_id::create(.name("st1_sb"), .parent(this));
endfunction // build_phase
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
st1_agent.agent_collected_port_before.connect(st1_sb.sb_export_before);
st1_agent.agent_collected_port_after.connect(st1_sb.sb_export_after);
rm.default_map.set_sequencer(st1_agent.sqr, reg_sqr_adapter);
rm.default_map.set_auto_predict(1);
//reg_predictor.map = rm.default_map;
//reg_predictor.adapter = reg_mon_adapter;
//st1_agent.agent_reg_port.connect(reg_predictor.bus_in);
endfunction // connect_phase
endclass // p4adder_env
here is test
`include "uvm_macros.svh"
import uvm_pkg::*;
`include "stage1_env.sv"
class stage1_test extends uvm_test;
`uvm_component_utils(stage1_test)
stage1_env st1_env;
function new(string name ="new", uvm_component parent);
super.new(name,parent);
endfunction // new
function void build_phase(uvm_phase phase);
super.build_phase(phase);
st1_env = stage1_env::type_id::create(.name("st1_env"), .parent(this));
endfunction // build_phase
task run_phase(uvm_phase phase);
stage1_sequence st1_seq;
phase.raise_objection(this);
st1_seq = stage1_sequence::type_id::create(.name("st1_seq"), .contxt(get_full_name()));
assert(st1_seq.randomize());
st1_seq.start(st1_env.st1_agent.sqr);
phase.drop_objection(this);
endtask // run_phase
endclass // stage1_test
here is top
`include "uvm_macros.svh"
`include "stage1_test.sv"
import uvm_pkg::*;
module stage1_tb_top;
//interface declaration
stage1_if vif();
//connect the interface to dut
stage1 dut(.CLK(vif.IF_CLK),
.RST(vif.IF_RST),
.IR_LATCH_EN(vif.IF_IR_LATCH_EN),
.NPC_LATCH_EN(vif.IF_NPC_LATCH_EN),
.muxpc(vif.IF_MUXPC),
.M_PCIN(vif.IF_M_PCIN),
.PC_count(vif.IF_PC_COUNT),
.IR(vif.IF_IR),
.id_ra_val(vif.IF_ID_RA_VAL),
.id_rb_val(vif.IF_ID_RB_VAL),
.id_imm(vif.IF_IMM),
.w_re_num(vif.IF_W_RE_NUM),
.ra(vif.IF_RA),
.rb(vif.IF_RB));
initial begin
//registers the interface in the configuration block
//so that other blocks can use it
uvm_resource_db#(virtual stage1_if)::set(.scope("ifs"), .name("stage1_if"), .val(vif));
//executes the test
run_test("stage1_test");
end
//variable initialization
initial begin
vif.IF_CLK = 1'b1;
vif.IF_RST = 1'b1;
#5 vif.IF_RST = ~vif.IF_RST;
end
//clock generation
always
#5 vif.IF_CLK = ~vif.IF_CLK;
endmodule