Hi,
I am not a very expert UVM user and I am running some trials with the register model.
In my testbench I have the following loop just to print the content of the register model:
my_regmodel.get_blocks(blks, UVM_HIER);
foreach (blks[b]) begin
$display("Block: %s (%s)", blks[b].get_name(), blks[b].get_full_name());
blks[b].get_registers(regs, UVM_HIER);
foreach (regs[r]) begin
$display("%s (%s) @0x%8h", regs[r].get_name(), regs[r].get_full_name(), regs[r].get_address());
regs[r].get_fields(fields);
foreach (fields[f]) begin
$display(" %s (%s): LSB=%0d, size=%0d, access=%s, reset_value=0x%0h, current_value=0x%0h",
fields[f].get_name(), fields[f].get_full_name(),
fields[f].get_lsb_pos(), fields[f].get_n_bits(), fields[f].get_access(),
fields[f].get_reset(), fields[f].get()
);
end
while (fields.size() > 0) void'(fields.pop_front()); // Empty the queue
end
while (regs.size() > 0) void'(regs.pop_front()); // Empty the queue
end
while (blks.size() > 0) void'(blks.pop_front()); // Empty the queue
This loop executed before any physical register access is performed.
I have the following question:
- why for all the registers the value I’m getting (get()) is different from the reset value and always 0? (of course there are a lot of registers with reset value different from 0).
Am I missing any operation to “synchronize” the model with the actual state of the circuit?
Thanks a lot in advance for any help.
Best regards,
Stefano
In reply to stefanotraferro:
Hi Stefano,
in which phase are you exercising your register model?
In reply to chr_sue:
Hi,
thanks for replying. This piece of code is in the body of my test sequence and it is executed after calling
super.body()
My test sequence is a derived class from a class which is, in turn, derived from uvm_reg_sequence:
- - my_parent_seq
[list]
- my_seq
[/list]
The code of my_parent_seq is simply:
class my_parent_seq extends uvm_reg_sequence;
`uvm_object_utils(my_parent_seq)
my_reg_model regmodel;
// Sequencer
my_uvc_sequencer p_sequencer;
function new(string name = "");
super.new(name);
set_automatic_phase_objection(1);
endfunction: new
virtual task body();
assert($cast(p_sequencer, m_sequencer));
assert($cast(regmodel, p_sequencer.cfg.regmodel));
endtask: body
endclass: my_parent_seq
What I’ve noticed is that the values returned by get() are updated to the actual value only after a physical read, which is not would I would expect.
Here’s a practical example:
- I have a register with default (reset) value 0x03fc;
- the two LSBs are associated to a field;
- I change the value of that field to 3:
temp_reg = my_regmodel.reg_blk.get_reg_by_name("my_region.my_reg");
temp_field = temp_reg.get_field_by_name("my_field"); temp_field.set( 3 );
temp_reg.update(status); assert(status == UVM_IS_OK);
At this point, I am expecting the generated transaction to write 0x03ff to the register, instead it writes 0x0003.
The only way to get 0x03ff is to read the register first.
Another note: the UVM test reg_all passes I guess just for the reason that the first set of accesses is a read of the complete register map to perform the reset value sub-test.
Is all of this expected?
Am I really supposed to physically read the complete register map to have a consistent model?
Thanks in advance for any help.
In reply to stefanotraferro:
After constructing a sequence with sequence items are data fields are initialized to its inital values. If you want to see the reste values you have to execute a reset sequence first. The UVM library provides you such a sequence (uvm_reg_hw_reset_seq).
In reply to chr_sue:
Thanks for your reply.
So, since uvm_reg_hw_reset_seq performs physical register accesses, the initialization of the model is done through actual register access as I was guessing, isn’t it?
Am I missing something?
In reply to stefanotraferro:
No it is not the initializaion it is setting the reg values to its reset value and it goes through accessing the registers physically.
In reply to chr_sue:
Thanks for the reply.
I guess I’ve found the solution: the .reset() method must be invoked to synchronize the mirrored values with the reset values:
my_regmodel.reset()
This method is called by the sequences available in the UVM library, but must be explicitly called in case of a custom sequence.