joniale Posted June 30, 2017 Report Share Posted June 30, 2017 Hi , To whom may correspond I think there is some kind of error in the UVM 1.1d register model. I have been experimenting with the UVM register model and i have seen the following code in uvm_reg_map.svh task uvm_reg_map::do_bus_write (uvm_reg_item rw, uvm_sequencer_base sequencer, uvm_reg_adapter adapter); uvm_reg_addr_t addrs[$]; uvm_reg_map system_map = get_root_map(); int unsigned bus_width = get_n_bytes(); uvm_reg_byte_en_t byte_en = -1; uvm_reg_map_info map_info; int n_bits; int lsb; int skip; int unsigned curr_byte; int n_access_extra, n_access; int n_bits_init; Xget_bus_infoX(rw, map_info, n_bits_init, lsb, skip); addrs=map_info.addr; // if a memory, adjust addresses based on offset if (rw.element_kind == UVM_MEM) foreach (addrs[i]) addrs[i] = addrs[i] + map_info.mem_range.stride * rw.offset; foreach (rw.value[val_idx]) begin: foreach_value uvm_reg_data_t value = rw.value[val_idx]; /* calculate byte_enables */ if (rw.element_kind == UVM_FIELD) begin int temp_be; int idx; n_access_extra = lsb%(bus_width*8); n_access = n_access_extra + n_bits_init; temp_be = n_access_extra; value = value << n_access_extra; while(temp_be >= 8) begin byte_en[idx++] = 0; temp_be -= 8; end temp_be += n_bits_init; while(temp_be > 0) begin byte_en[idx++] = 1; temp_be -= 8; end byte_en &= (1<<idx)-1; for (int i=0; i<skip; i++) void'(addrs.pop_front()); while (addrs.size() > (n_bits_init/(bus_width*8) + 1)) void'(addrs.pop_back()); end curr_byte=0; n_bits= n_bits_init; The code continues but the interesting part is already there. Lets assume we have a register with 4 bytes and 1byte per address granularity (byte_addressing). Now, we do a FIELD access of 8bits length (the first byte of a register). The field is configured "individual_accessible, so UVM should only access that FIELD. The reg2bus should generate that byte request to be written. In other words, the vector "addrs" should have only one byte address. Going to the code, i see that initially the addrs has the 4 address ( the whole register) and when it comes to the "if (rw.element_kind == UVM_FIELD) begin" and it will pop_back()/remove all the exceeding bytes that doesn't need to complete "n_bits_init" of the field access. The problem is here: UVM has //while (addrs.size() > (n_bits_init/(bus_width*8) + 1)) and i think it should be while (addrs.size() > ((n_bits_init-1)/(bus_width*8) + 1)) //ejonalv possible error in UVM? check That is because in case we want to write 8 bits, it will calculate 8/8+1=2 address in the UVM version, but in fact it should require only 1 address. This is of course applicable for the READ variation. Did i misunderstand something? It is very hard to go through the register model without proper documentation in the code. I am looking forward your answer Best Regards Jonathan Quote Link to comment Share on other sites More sharing options...
uwes Posted July 3, 2017 Report Share Posted July 3, 2017 i think this is yet another issue in the register model related to https://accellera.mantishub.io/view.php?id=5446 Quote Link to comment Share on other sites More sharing options...
joniale Posted May 9, 2018 Author Report Share Posted May 9, 2018 Hi again, I want to report another minor issue. the issue is applicable in case you want a layering sequence for registers in AXI. I mean what is described here: https://www.mentor.com/products/fv/resources/overview/a-new-class-of-registers-2e32ca83-d5ee-4e34-8880-c006be7e537f As you can see a layering sequence allows you to create randomized register accesses that are not possible with the adapter and the default uvm_reg_map. This is needed to test that registers are written/read correctly with different AXI accessed than the fix accesses done by the uvm library. In that case you have to disable your adapter (being null) to avoid the bus_write and bus_read functions as described in the paper of the link. Unfortunately, the function "is_indv_accessible" needs an "adapter". That means you cannot access is_individual_accessible field flag of your register model, in case you are using the sequence layering methodology. To workaround this problem and be able to use UVM_FIELD kind accesses, we can redirect all uvm_reg_field write/read fuctions with a custom uvm_reg_field read/write functions(this can be done with settypeoverride by type all uvm_reg_field classes). In those new custom_reg_field functions you can, 1. redirect the field call to a register type call with the same inputs and second use the extension to pass in the redirected REGISTER write/read the uvm_reg_item corresponding to the original FIELD access. Afterwards, you can check in the sequence layer if the UVM_REG register request item has an extension containing a FIELD!=null. If that is the case, it means the register access is not a register access but in fact a redirected FIELD access. That field access can be processed in your layering sequence, that creates the stimuli needed for that field. //////// However, the correct way would be that uvm retrieves the "supports_byte_enable" information not from the adapter but from uvm_reg_map. In other words, i think that the configuration flags "supports_byte_enable" and "provides_responses" should be declared inside the uvm_reg_map and not inside the adapter. Besides, there should be set and get functions for those signals so that these can be set from the environment or from the adapter itself. I hope i have explained the issue. Best regards, Jonathan Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.