You can have a reg_model handle in any object including uvm_compnents. A typical example for this approach is a scoreboard which compares values depending on a register content. In this scenario you do not need to perform a backdoor por frontdoor access. Simply perform a get on the register to get the actual content of that register.
I am also facing the same issue when using the ral model for read the register in my uvm_monitor am getting an error:
Error-[IOUCM] Illegal use of class method
/$PROJ_DIR/hxtop_interrupt_monitor.sv
Though as of nowam using ral model in my TB and all the registers sequences are working fine.
Can you please suggest me wat go wrong here?
In reply to yuvraj khare:
Could you please show some more code from your monitor?
And I’d like to ask you what are you doing with the read register value in the monitor?
Basically it is Interrupt monitor, so am reading the status of interrupt (if interrupt is mask) i.e. using RAL model
if(top_cfg.interrupt_mask != 32’h0) begin
while(interrupt_status == 0) begin
regmodel.reg_bank.REG_ISR.read(status,interrupt_status);
end
Getting an error where am using the reg model.
Please let me know!
function void Interrupt_monitor::build_phase (uvm_phase phase);
super.build_phase(phase);
if(!uvm_config_db#(virtual prot_if)::get(this,“”,“prot_vif”,prot_vif)) uvm_fatal(get_type_name(), $sformatf("Unable to get prot_vif from cfg database")) if (!uvm_config_db #(ral_sys_model)::get(null,get_full_name(),"regmodel",regmodel)) uvm_fatal(get_type_name(), “Unable to get the regmodel from cfg database”))
endfunction : build_phase
task Interrupt_monitor::run_phase (uvm_phase phase);
super.run_phase(phase);
forever begin
fork
begin
interrupt_service();
end
join
end
endtask :run_phase
task Interrupt_monitor::interrupt_service();
fork
begin
sys_interrupt();
end
begin
count = count+1;
end
join_any
endtask :interrupt_service
task Interrupt_monitor::sys_interrupt();
fork
begin //{
if(top_cfg.interrupt_mask != 32’h0) begin
while(interrupt_status == 0) begin
regmodel.reg_bank.REG_ISR.read(status,interrupt_status);
end
if(interrupt_status | hxtop_cfg.intr_enable == hxtop_cfg.intr_enable) uvm_info(get_type_name(), $psprintf("Interrupt status is set for correct interrupt "), UVM_NONE) else uvm_info(get_type_name(), $psprintf("Interrupt status is not for correct interrupt "), UVM_NONE)
end
end //}
begin //{
if(interrupt_mask == 32’h0) begin //{
case(top_cfg.intr_enable)
32’h0000_0000: begin
wait(prot_vif.interrupt != 0);
end
32’h0000_0040: begin
wait(prot_vif.interrupt[4] != 0);
end
endcase
join_any
endtask : sys_interrupt
In reply to yuvraj khare:
i guess you might not be actually getting the error at ral model but somewhere else. Is there any typo while declaring interrupt method. It should be sys_interrupt(). Also, there is no declaration of interrupt_status.
class Interrupt_monitor extends uvm_monitor;
`uvm_component_utils(Interrupt_monitor)
bit [31:0] interrupt_mask;
ral_sys_model regmodel;
virtual prot_if prot_vif;
extern function new(string name, uvm_component parent);
extern function void build_phase (uvm_phase phase);
extern task run_phase (uvm_phase phase);
extern task interrupt_service ();
extern task interrupt (); // It should be sys_interrupt
endclass : Interrupt_monitor
function void Interrupt_monitor::build_phase (uvm_phase phase);
super.build_phase(phase);
if(!uvm_config_db#(virtual prot_if)::get(this,"","prot_vif",prot_vif))
`uvm_fatal(get_type_name(), $sformatf("Unable to get prot_vif from cfg database"))
if (!uvm_config_db #(ral_sys_model)::get(null,get_full_name(),"regmodel",regmodel))
`uvm_fatal(get_type_name(), "Unable to get the regmodel from cfg database"))
endfunction : build_phase
task Interrupt_monitor::run_phase (uvm_phase phase);
super.run_phase(phase);
forever begin
fork
begin
interrupt_service();
end
join
end
endtask :run_phase
task Interrupt_monitor::interrupt_service();
fork
begin
sys_interrupt();
end
begin
count = count+1;
end
join_any
endtask :interrupt_service
task Interrupt_monitor::sys_interrupt();
fork
begin //{
if(top_cfg.interrupt_mask != 32'h0) begin
while(interrupt_status == 0) begin
regmodel.reg_bank.REG_ISR.read(status,interrupt_status);
end
if(interrupt_status | hxtop_cfg.intr_enable == hxtop_cfg.intr_enable)
` uvm_info(get_type_name(), $psprintf("Interrupt status is set for correct interrupt "), UVM_NONE)
else
`uvm_info(get_type_name(), $psprintf("Interrupt status is not for correct interrupt "), UVM_NONE)
end
end //}
begin //{
if(interrupt_mask == 32'h0) begin //{
case(top_cfg.intr_enable)
32'h0000_0000: begin
wait(prot_vif.interrupt != 0);
end
32'h0000_0040: begin
wait(prot_vif.interrupt[4] != 0);
end
endcase
join_any
endtask : sys_interrupt
That is the reason we ask to show the full code here so that we can help you out. In the example you have shown there is no way i can know what is there inside your reg_model class and lot of other things missing. How would you expect someone to help and figure out your error unless you show full scenario or codes.
A monitor is assigned to be a passive component. You are violating this rule by using a read to the RAL. In the testbench you need only a get. The get takes the register value from the mirror in the testbench. The read is doing a read through the bus interface and a get.
I’m wondering why you are observing your interrupt in the monitor. Finally you have to start in case of an interrupt an interrupt sequence. This happens in the sequencer. How do you send the interrupt information to the sequence/sequencer? There is no standard interface. You have to implment this on your own.
Why do you not use the existing interface betwenn the driver and the sequencer?
How to implement is you can see in a code example of the Verification Academy. Code Example Downloads | Verification Academy, interrupts - simple.