In reply to msuthar:
Let’s look at the API involved. First, the write task in uvm_reg.
task uvm_reg::write(output uvm_status_e status,
input uvm_reg_data_t value,
input uvm_path_e path = UVM_DEFAULT_PATH,
input uvm_reg_map map = null,
input uvm_sequence_base parent = null,
input int prior = -1,
input uvm_object extension = null,
input string fname = "",
input int lineno = 0);
Usually you’ll find authors are lazy and only provide the minimum parameters required. In other words, status and value. You’ll supply path if you want to change it to a backdoor transaction, or you’ll supply map if you want to pick between one of multiple maps ( and by extension sequencers ).
What happens if you go with the default parameters? Then the default map ( the first map registered ) will be selected and used.
The parent parameter is interesting, as it suggests you can pass context to the register model. In theory, this context could be used to determine which sequencer your sequence is running on and by extension which map to use. So let’s dig deeper to see what happens.
uvm_reg::write calls uvm_reg::do_write. Unless you supplied a map when you called ::write(), as we enter this task, rw.map and rw.local_map are null.
task uvm_reg::do_write (uvm_reg_item rw);
uvm_reg_cb_iter cbs = new(this);
uvm_reg_map_info map_info;
uvm_reg_data_t value;
m_fname = rw.fname;
m_lineno = rw.lineno;
if (!Xcheck_accessX(rw,map_info,"write()"))
return;
And unless you specified to use a backdoor the Xcheck_accessX() method does the following.
if (rw.path != UVM_BACKDOOR) begin
rw.local_map = get_local_map(rw.map,caller);
And if rw.map is null here, rw.local_map is set to the the default map. This brings us back to ::do_write() to execute your transaction.
// EXECUTE WRITE...
case (rw.path)
// ...VIA USER BACKDOOR
UVM_BACKDOOR: begin
//...
end
UVM_FRONTDOOR: begin
uvm_reg_map system_map = rw.local_map.get_root_map();
m_is_busy = 1;
// ...VIA USER FRONTDOOR
if (map_info.frontdoor != null) begin
//...
end
// ...VIA BUILT-IN FRONTDOOR
else begin : built_in_frontdoor
rw.local_map.do_write(rw);
end
Despite the fact that if parent != null, this information is available, nowhere in this call stack, is the sequencer your sequence is running on consulted. Your register transaction is executed using either the map you supplied or the default map. So if you don’t supply one, you’ll use the default.
So, in your case I’m assuming you are not supplying the map parameter to ::write(). Or if you are, you are supplying the same map regardless of which sequencer you’re running on.
If you supply the parent parameter to uvm_reg::write(), or use the uvm_req_sequence::write_reg() helper task which does that for you, there is sufficient context information for UVM to figure all this out for you. But it doesn’t. :(