After upgrading to IEEE 1800-2017, I encountered another issue with individual access. The issue persists on 2020.3.1, which is included into XCELIUM 25.03.
I found some bug reports that seemed close to my issue, but they were marked “obsolete”.
So, I’m defining some register with multiple fields.
class signals_reg extends uvm_reg;
`uvm_object_utils(signals_reg)
function new (string name = "signals_reg");
super.new(name, 64, UVM_NO_COVERAGE);
endfunction : new
rand uvm_reg_field field0, field1;
virtual function void build();
field1 = uvm_reg_field::type_id::create("field1");
field0 = uvm_reg_field::type_id::create("field0");
// access has_reset
// lsb_pos | reset|indv_acc
// size | |volatile| |rand |
// | | | | | | | |
field1.configure(this,32, 32, "RW", 1, 0, 1, 1, 1);
field0.configure(this,32, 0, "RW", 1, 0, 1, 1, 1);
endfunction: build
endclass
Then I added it to the reg block (and then connect it in some way). There’s a reg adapter that supports byte enable (no warnings about it).
Regmap is set to n_butes=1 for the example.
reg_map = create_map(
.name ( "reg_map" ),
.base_addr ( 0 ),
.n_bytes ( 4 ),
.endian ( UVM_LITTLE_ENDIAN ),
.byte_addressing ( 1 )
);
signals = signals_reg::type_id::create("signals");
signals.configure(this);
signals.build();
reg_map.add_reg(signals, 4*15, "RW");
In the test, I’m trying to read the fields separately.
uvm_status_e st;
uvm_reg_data_t dt;
REGS.axi_signals.field0.read(st, dt);
REGS.axi_signals.field1.read(st, dt);
Each field gets one read operation, which is totally expected. But the addresses are somehow broken.
UVM_INFO <...>/UVM/CDNS-IEEE-31/sv/src/reg/uvm_reg_map.svh(2206) @ 43 ns: reporter [UVM/REG/ADDR] Reading 'h0 at 'h3c via map "reg_block.reg_map"...
...
UVM_INFO <...>/UVM/CDNS-IEEE-31/sv/src/reg/uvm_reg_map.svh(2206) @ 105 ns: reporter [UVM/REG/ADDR] Reading 'h0 at 'h3d via map "reg_block.reg_map"...
Some more facts:
- On UVM 1.2 the addresses were calculated correctly. But another issue appears here - the first field in the register somehow tries to read/write an extra byte with every access.
- Disabling individual access fixes everything - whole register reads correctly, with two operations (on 32-bit bus). Addresses 0x3C and 0x40, as expected.
- get_lsb_pos() from field1 returns 32, and printing it shows
signals[63:32], so it’s identified correctly. - Changing n_bytes in uvm_reg_map somehow affects the calculations. Changing it to
2splits reads into (0x3c, 0x3e and 0x3e, 0x40). And setting it to1makes the addresses work correctly, as if the field offset is divided by it somewhere. - Disabling byte addressing didn’t change anything.
- No warnings are displayed about indv access.
Did I configure something wrong? Or is it a known bug? Is there any workaround for this issue, with or without modifying the original files?