I found this post really helpful and easy to understand, I have a question regarding to this lets say your register has 64 different fields and if you want to define access policy for the entire register (i.e secure only write access) you’ll need 64 uvm_reg_field_cb::add(field_n, custom_cbs); which to me seems to a lot code to be written, do you think/know if there is a different way to setup custom register access policies(for the entire register at once).
Since ‘predict()’ isn’t virtual and there aren’t any ‘pre/post’ predict hooks defined in ‘uvm_reg_field’, our options are limited.
One solution would be to override ‘do_predict()’, which is virtual and gets called by ‘predict()’. Since it’s not mentioned in the standard, I wouldn’t recommend doing this.
The only viable option is to use callbacks. Adding the callback on 64 fields doesn’t mean we need 64 calls to ‘add(…)’, since we can loop over all fields of a reg:
Thank you very much for your reply Tudor, indeed I works, Sorry to hijack with questions your blog, I have another question that has been causing me a lot of trouble to implement my register model, most of the examples over the web (if not all) describe how to create custom accesses based on fields using post predict which is pasive and gets triggered no matter who triggered the write/read operation (if explicit prediction it is used) this is fine but what about predicting the write value based on physical bus signals send from (APB PPROT for example or AXI PROT) this signals can alter the predicted write value of the register based on its value. I have come across to the usage of the extension field memeber of the uvm_reg_item in the reg2bus function of adapter class to provide any additional information for write/read to the actual VIP/sequencer that is going to execute the bus transaction, but only afects how the transaction is send to the bus
I couldn’t find any mechanism (callback, method) to predict accurately the model based on signals such as those, even extending the predictor doesnt helped me out since all information about the bus operation is (except for data and addr) is discarded by the predictor when calling adapter.bus2reg(tr,rw)
Sorry if I was no able to elaborate my question/comment properly
If you just need to ignore writes/reads when a protection level doesn’t match, then you can create your own predictor class and override its ‘write(…)’ function:
class my_protected_predictor extends uvm_reg_predictor #(apb_item);
apb_prot_t allowed_prot;
virtual function void write(apb_item tr);
if (apb_item.prot >= allowed_prot)
write(tr);
endfunction
endclass
This is usually the case. Moreover, wrong protection should also issue a bus error and the predictor shouldn’t get triggered in that case. Ideally this would have been done through a ‘UVM_NOT_OK’ response in the converted ‘reg_bus_op’, but I think there’s a bug in the UVM code so you need a custom predictor for that too:
class my_protected_predictor extends uvm_reg_predictor #(apb_item);
apb_prot_t allowed_prot;
virtual function void write(apb_item tr);
if (apb_item.resp == OKAY)
write(tr);
endfunction
endclass
If depending on the value of the protection signal you can get different read/write values, then it’s more complicated. You need to capture the current transaction in some callback somewhere and assign it from the ‘write(…)’ function of the predictor:
class some_callback extends uvm_reg_cbs;
apb_item trans;
// do stuff in ‘post_predict(…)’ based on trans
endclass
class my_protected_predictor extends uvm_reg_predictor #(apb_item);
some_callback cb;
The same instance of the CB you need to pass to the registers as well. This way you know what protection you had. It’s also guaranteed that the transaction is updated before ‘predict(…)’ gets called.
P.S. No problem with asking questions, that’s what the blog is for.
The last one isn’t the cleanest approach, but I don’t really see any other possibility, because the code for ‘uvm_reg_predictor’ isn’t modular at all (the ‘write(…)’ function has 100 lines, for example).
I have slightly different question.
In my environment mixed languages, SV-UVM is for passive and specman for drive part.
I want to use UVM RAL only for passive mode only , is this possible?
Can we have uvm_reg_adapter,uvm_reg_predictor and call back’s way of predicting in this environment for passive mode only? I saw that with out sequencer specified for address map , uvm ral throws error from uvm_reg_map class’s set_sequencer() method definition.
I never tried this, but this should be theoretically possible. At the end of the day, it’s not much different from a situation where you’re doing virtual reuse. Whether there’s some “bug” in the UVM source code that prevents this, I can’t say (e.g. some calls to sequencer stuff, even when working in passive operation).
Hello Timi, I’m facing a special design W1P register, which returns the value to 0 after 1 clock when wrote 1.
your solution of creating a new uvm_reg_field is the most fit, however post_predict function doesn’t allow handling time. So if the only option is to use post_write task ?