Last Updated on April 11, 2014
The register abstraction layer (RAL) of UVM provides several methods to access registers. This post will explain how the register-access methods work. In Register Abstraction, we introduced the overview of RAL and explained how to define registers. In this post, we will cover how to access the registers.
Properties of uvm_reg_field
Before diving into the register-access methods, let’s look at how a register value is stored. As seen in Register Abstraction, uvm_reg_field
is the lowest register-abstraction layer which represents the bits of a register. The uvm_reg_field
uses several properties to store a variety of register-field values:
m_reset["HARD"]
stores a hard reset value. Note that them_reset
is an associative array with a kind of reset as the key.m_mirrored
stores the value of what we think in our design under test (DUT).m_desired
stores the value of what we want to set to the DUT.value
stores the value to be sampled in a functional coverage, or the value to be constrained when the field is randomized.
Note that among these properties, only the value
property is public. The other properties are local, thus we cannot access them directly from the out side of the class. We will show you how to access these local properties using register-access methods later.
configure()
The first thing we do after creating a uvm_reg_field
is configuring it. In Register Abstraction, we configured the flavor
field as follows. Note that in Register Abstraction, we defined the flavor
field as "WO"
(write-only), but we defined it as "RW"
(read/write) here to make the field more generic.
1 2 3 4 5 6 7 8 9 10 | flavor = uvm_reg_field::type_id::create( "flavor" ); flavor.configure( .parent ( this ), .size ( 3 ), .lsb_pos ( 0 ), .access ( "RW" ), .volatile ( 0 ), .reset ( 0 ), .has_reset ( 1 ), .is_rand ( 1 ), .individually_accessible( 0 ) ); |
If the has_reset
argument is 1
, the value of reset
argument is taken as the "HARD"
reset value. If the has_reset
value is 0
, the value of reset
is ignored. The value of reset
should match the reset state of the DUT. If you want to modify the reset value after the configuration, you can use set_reset()
method.
flavor.set_reset( .value( 0 ), .kind( "HARD" ) ); // kind == "HARD" by default |
reset()
The reset()
method resets the properties of a register field, if the m_reset[kind]
exists. The default kind
is "HARD"
. If the m_reset[kind]
does not exist, the reset()
method does nothing. Note that the reset()
method does not reset a register in the DUT. It only resets the properties of a register-field object.
flavor.reset( .kind( "HARD" ) ); // kind == "HARD" by default |
set()
The set()
method sets the desired value of a register field. The set()
method does not set the value to a register in the DUT. It only sets the value to the m_desired
and the value
properties of a register-field object. To actually set the value to the register in the DUT, use write()
or update()
method. These methods will be explained later.
flavor.set( .value( 1 ) ); |
get()
The get()
method gets the desired value of a register field. The get()
method does not get the value from a register in the DUT. It only gets the value of the m_desired
property. To actually get the value from the DUT, use read()
or mirror()
methods. These methods will be explained later. Similarly to the get()
method, there are two more getters to access the local properties. The get_reset()
retrieves the value of the m_reset[kind]
property, while the get_mirrored_value()
method retrieves the value of the m_mirrored
property.
uvm_reg_data_t desired_value = flavor.get(); uvm_reg_data_t reset_value = flavor.get_reset( .kind( "HARD" ) ); // kind == "HARD" by default uvm_reg_data_t mirrored_value = flavor.get_mirrored_value(); |
randomize()
The randomize()
method is a SystemVerilog method. It randomizes the value
property of a register-field object. After the randomization, the post_randomize()
method copies the value of the value
property to the m_desired
property. Note that the pre_randomize()
method copies the value of the m_desired
to the value
property if the rand_mode
of the value
property is OFF
.
assert( flavor.randomize() ); |
write()
The write()
method actually writes a value to the DUT.
uvm_status_e status; flavor.write( .status( status ), .value( 1 ) ); |
The write()
method involves multiple steps.
- A
uvm_reg_item
object corresponding to the write operation is created. - The
uvm_reg_adapter
converts the write operation to a corresponding bus transaction. - The
uvm_driver
executes the bus transaction to the DUT. - The
uvm_monitor
captures the bus transaction. - The
uvm_reg_predictor
asks theuvm_reg_adapter
to convert the bus transaction to a corresponding register operation. - The register operation is converted to a
uvm_reg_item
. - The
uvm_reg_item
is used to update thevalue
,m_mirrored
, andm_desired
properties.
Note that if the individually_accessible
argument was 0
when the register field was configured, the entire register containing the field is written, because the field is not individually accessible. In this case, the m_mirrored
values are used as the write values for the other fields.
read()
The read() method actually reads a register value from the DUT.
uvm_status_e status; uvm_reg_data_t value; flavor.read( .status( status ), .value( value ) ); |
Similarly to the write()
method, the read()
method involves multiple steps.
- A
uvm_reg_item
object corresponding to the read operation is created. - The
uvm_reg_adapter
converts the read operation to a corresponding bus transaction. - The
uvm_driver
executes the bus transaction to the DUT. - The
uvm_reg_apapter
converts the bus transaction with read data to a register operation. - The
read()
method returns the read value to the caller. - In the mean time, the
uvm_monitor
captures the bus transaction. - The
uvm_reg_predictor
asks theuvm_reg_adapter
to convert the bus transaction to a corresponding register operation. - The register operation is converted to a
uvm_reg_item
. - The
uvm_reg_item
is used to update thevalue
,m_mirrored
, andm_desired
properties.
Note that if the individually_accessible
argument was 0
when the register field was configured, the entire register containing the field is read. In this case, the m_mirrored
values are updated for the other fields as well.
update()
The update()
method actually writes a register value to the DUT. The update()
method belongs to the uvm_reg
class. The uvm_reg_field
class does not have the update()
method.
uvm_status_e status; jb_recipe_reg.update( .status( status ) ); |
The differences between the write()
method and the update()
method are:
- The
write()
method takes a value as its argument, while theupdate()
method uses the value of them_desired
property as the value to write. - The
update()
method writes the value only if them_mirrored
and them_desired
are not equal.
The update()
method internally calls the write( .value( m_desired ) )
. Because of this, the value of the m_mirrored
will be updated as well, after the update.
mirror()
The mirror()
method actually reads a register from the DUT.
uvm_status_e status; flavor.mirror( .status( status ), .check( UVM_CHECK ) ); |
The differences between the read()
method and the mirror()
method are:
- The
read()
method returns the register value to the caller, while themirror()
method does not return the register value. Themirror()
method only updates the value of them_mirrored
property. - The
mirror()
method compares the read value against them_desired
if the value of thecheck
argument isUVM_CHECK
.Note that the UVM Class Library document states that it compares the read value against the mirrored value, but if you look at the line 2,944 ofuvm_reg.svh
of uvm-1.1c code base, it actually compares against the desired value, not against the mirrored value.
April 11, 2014: uvm-1.1d code base has corrected this issue. The
mirror()
compares the read value against the mirrored value now. Please see the line 2,951 ofuvm_reg.svh
if you are curious about this fix.)Another caveat about the check is that if you set the
volatile
argument to be1
when you configured the register field, the register field won’t be checked even though you set thecheck
argument to beUVM_CHECK
. This is because we cannot predict the value of the register field deterministically as it might have been changed (volatile) in the DUT.
The mirror()
method internally calls do_read()
method. This is the same method the read()
method internally calls. Because of this, the mirror()
method will update the value
and the m_desired
properties, in addition to the m_mirrored
property.
predict()
The predict()
method updates the mirrored value.
flavor.predict( .value( 1 ) ); |
The predict()
method also updates the value
and the m_desired
properties.
Summary
The table below summarizes how each method updates the properties of the register-field object.
Method | m_reset |
value |
m_desired |
m_mirrored |
DUT |
---|---|---|---|---|---|
configure |
set the value of val |
||||
set_reset(val) |
set the value of val |
||||
reset() |
copy the value of m_reset |
copy the value of m_reset |
copy the value of m_reset |
||
set(val) |
set the value of val |
set the value of val |
|||
get_reset() |
return the value of m_reset |
||||
get() |
return the value of m_desired |
||||
get_mirrored_value() |
return the value of m_mirrored |
||||
randomize() |
randomize | copy the value of value |
|||
write(.value(val)) |
set the value of val |
set the value of val |
set the value of val |
write the value of val |
|
read(.value(val)) |
set the read value | set the read value | set the read value | read the register | |
update() |
set the value of m_desired |
set the value of m_desired |
set the value of m_desired |
write the value of m_desired |
|
mirror() |
set the read value | set the read value | set the read value | read the register | |
predict |
set the value of val |
set the value of val |
set the value of val |
Hi Shimizu,
Great work. When are you expecting to post information about back-door access? There are many confusions and also most of the times the backdoor methods aren’t working properly.
Thanks,
Arun
I finally posted Register Access through the Back Door.
Hey nice work,
It helps me a lot…
Keep it up
Thamks,
Kiran
Nice work Keisuke!
Very informative tutorial and graphics.
Anupam
Hi,
A very good article and visuals are very helpful.
Thank you very much for putting this up.
Neha
Hi Neha,
I am glad to hear the article was useful.
Keisuke Shimizu, thanks for the information. This helped me alot.
–muqseed.
Wonderful representation of all the access methods.
Hi, great pos and great blog. Do you know if there can be any race conditions between the predictor updating a register value and another thread trying to get the mirrored value in the same tick ? I wonder if there is some intelligence in the register model to order same tick set/get calls. Cheers
Good question. If you explicitly call the
predict(value)
to update them_mirrored
value while the same register field is being accessed by the front-door (either read or write), the front-door access “wins”. But as far as I see the source code of theuvm_reg_field
, them_mirrored
is not thread-safe between set (do_predict
) and get (get_mirrored_value
).Thanks for your reply. In my case I have indeed a predictor component that captures system transactions and performs register predict(value) considering these transactions, hence any subsequent reads to these registers should match the read data against the mirrored value. Extra I have some callbacks registered on the registers which trigger uvm_events taken from the uvm_event_pool. Because these events are triggered in post_predict I think it’s probably safe to sync on them on checking components.
Interesting. Thank you for sharing your methodology.
Hi have a small doubt in case of Mirror .
As you mentioned It compare with desired value. But in my case I am doing like this.
1.First doing write on reg which is changing both m_desired and m_mirrored to say ‘h55
2.Doing predict which changes both values to new values say ‘h66
2.Now doing set which is changing m_desired to new value say ‘h77
3.Doing mirror with check
It showing following uvm_error
UVM_ERROR /tools/cadence/INCISIV131/tools/uvm/uvm_lib/uvm_sv/sv/reg/uvm_reg.svh(2892) @ 885000000: reporter [RegModel] Register “reg_block_h.CH0SBREG7_h” value read from DUT (0x0000000000000055) does not match mirrored value (0x0000000000000066)
UVM_INFO /tools/cadence/INCISIV131/tools/uvm/uvm_lib/uvm_sv/sv/reg/uvm_reg.svh(2911) @ 885000000: reporter [RegModel] Field ch0_dev_head (reg_block_h.CH0SBREG7_h[7:0]) mismatch read=8’h55 mirrored=8’h66
which proves that it compares with m_mirrored value not m_desired
any comment ??
Thank you for your experiment. I checked the uvm-1.1d code base and confirmed that the bug in uvm-1.1c has fixed. I updated my article accordingly. Thanks!
Hi,
great article.
I have a question about mirror value updating. if I rely on reg_block ‘update’ method to do register write, it will look at m_desired and m_mirror.
my question is : do we need to use a predictor to update that mirror data?
if using analysis port bus_in in predictor, ‘write’ imp in predictor will call adapter.bus2reg and corresponding reg predictor method to update mirror, but I also see uvm_reg_map will call adapter bus2reg in its ‘do_bus_write’ function, which is called when a reg do write.
if I don’t put that predictor in my env, is mirror value updated well? any impact to collect RAL coverage?
if predictor is not necessary, what’s its usage?
Thanks.Pan
searching something from website, seems if DUT is only modified through RAL reg access method, predictor is not necessary in env, if DUT is updated by other sources (not from RAL), env has to need a predictor to sync RAL register value with DUT to keep everything up to date.
is my understanding correct?
Yes, that is correct.
Very useful and elaborated
I am glad to hear that it was useful. Thanks.
Hi,
I have some doubt regarding ral??
I want to know the perfect usage of set_sequencer??why it is used??
I want to know whether the read() method clears the regsiter or not??
I want to know the example of mirror where to use in ral?
uvm_reg_adapter
converts the register request into a bus-specificuvm_sequence_item
. Then, auvm_sequencer
executes theuvm_sequence_item
. Theset_sequencer
function of theuvm_reg_map
class sets this adapter and sequencer to a register map.read
method does not clear the register in the DUT. It updates them_mirrored
,value
andm_desired
properties of RAL with the read value.mirror
method to read all of the registers in a register block (theread
method cannot do this). Themirror
method gives you an option to compare the read value against the current mirrored value, too.Thanks Sir,
understand nicely
I want to ask some more doubts..
a) use of volatile and its need..when to make that bit one?
b) not able to read the burst of data using burst_read()…i seen some other guys are also facing the same issue.
Thanks,
sagar
a) The
volatile
bit should be set if the DUT may update the value of the register field. A status register is an example. If the value of the register is not predictable, set thevolatile
bit.b) I need more information in order to answer your question.
Hi Great Article.
I am curious about to know how the update happen from the DUT register to the Register model’s Register, if the volatile bit made High during configuration.
The mirrored value of the register model is updated when there is a read or write activity. This is regardless of the volatile bit value. Setting the volatile bit means that the value of the register is not predictable because the DUT may change the value. If the volatile bit is set, the register read value won’t be compared against the mirrored value because the mirrored value may hold a stale value.
Hello sir,
one more question!!
I have one more doubt!!
I dont understand the use of these two arguments in every method like write,read,mirror,etc
what is the use of following two arguments??
some examples?
input int prior = -1
input uvm_object extension = null,
Thanks,
sagar
1. The
prior
is to specify the priority of the register transaction when it is executed on a sequencer. If not specified (-1), default priority (100) is used. Higher numbers indicate higher priority. You might want to set higher priority when you access an interrupt status register, for example.2. The
extension
is to pass extra information that can be used when you convert a register transaction into a bus transaction. For example, if you want to use a specific thread ID of the target bus, you can pass the thread ID information as theextension
.Thank you sir for your nice answers.!!
I would like to ask one more question regarding ral!
In explicit prediction my register model is not getting updated..after i set set_auto_predict(0).
so my question is do i need to write separate code for explicit prediction.or it should work automatically?
You need to have a predictor. Please see the Environment section of this article.
Hi
I m trying a UVM backdoor write from a sequence.
The steps which i follow are :
1. In the build phase of the reg file where the register classes are built, i add
reg_name.add_hdl_path_slice( inst1.inst2.inst3.reg_name_sig,0,32); where reg_name is the instance of the register of interest and reg_name_sig is the output of the instance inst3 in the design.
2. In the build phase of the reg model where the reg file is built ( rf is the register file instance) i add
add_hdl(uvm_env_top.tbench_top.DUT, RTL); where uvm_env_top is a module in which the testbench top module is instantiated. The DUT is the instance of the RTL in testbenchtop module
3. In the register sequence, i call the following API
rm.rf.reg_name.write(status, data, UVM_BACKDOOR); where rm is the register model instance
4. In the log file, I observe the statement :
Wrote register via DPI backdoor: rm.reg_name = 0x01
But I do not observe the same in the waveform.
The signal DUT.inst1.inst2.inst3.reg_name_sig is still 0 and the write doesnt take effect
Can anyone please give me inputs on whether the method i followed for backdoor write is correct. If not, what is to be done?
How about changing the
reg_name_sig
(output port?) to the actualreg
representing thereg_name
inreg_name.add_hdl_path_slice( inst1.inst2.inst3.reg_name_sig, 0, 32 )
?I added a new article about back-door register access. It might help.
Hii,
your tutorial was supereb.
all my theoratical doughts related to ral is now solved.
Thank you… 🙂
But, I’m facing problem when I’m trying to use explicit predictor.
my register model is not updating.
in environment I have return this code.
///////////////////////// connect_phase
cfg.wdogcfg_rb.wdog_map.set_sequencer(m_top.seqrh,reg2wrtr);
wrtr2reg_predictor.map=cfg.wdogcfg_rb.wdog_map;
wrtr2reg_predictor.adapter=reg2wrtr;
cfg.wdogcfg_rb.wdog_map.set_auto_predict(0);
m_top.mmon.monitor_port.connect(wrtr2reg_predictor.bus_in); ///it creates any problem?
///////////////////////
in your example you have taken one analysis port in agent and then you made connection between predictor and( agent,monitor) In my code I have connected predictor directly to monitor.
is there anything extra code we need to write in other component or object class.??
Thank you
Your
connect_phase
looks fine. Check thebus2reg
function of thereg2wrtr
adapter.Thanx for the rply.
actuly in monitor I was storing data as xtn.pwdata and xtn.prdata. while in adapter I writtern rw.data=xtn.data thats why its not updating the regmodel.so now monitor also storing data as xtn.data and its working correctly. thanks for the support 🙂
Hello !!
I tried declaring some of the reserved registers with access type “NOACCESS” but it throws the below error.
UVM_ERROR /packages/uvm/uvm-1.2/src/reg/uvm_reg_field.svh(832) @ 0: reporter [RegModel] Access policy ‘NOACCESS’ for field ‘blue_reg_model.BLACK.CTRL.RES18’ is not defined. Setting to RW.
What access type can we define for reserved registers ?? [Note: Nothing should happen if those registers are accessed]
Appreciate Your Help!
Desperado !!
"NOACCESS"
policy is not predefined in theuvm_reg_field
class unlike other access policies. Try callingvoid'(uvm_reg_field::define_access("NOACCESS"));
before you callconfigure
, or simply use"RO"
as the access policy.Hello Keisuke !! Appreicate your suggestion !! I did define my user defined access type with a callback and implemented the same and it goes fine. It would be great if you can shed some light on the other questions as well !! Thanks !
Register Size/Definition Changes based on Mode Register Selection !! Suggestion for a better UVM Register Model ?
Hello !!
a. Have a scenario where my DUT works in two different modes. Say mode X and mode Y. And this selection is made using the mode register.
b. And based on the mode selection [either X or Y], the definition of other register changes.
For Example:
In Mode X, Register A size is 32-Bits.
Whereas in Mode Y, Register A size is 16-Bits.
In Mode X, definition of Register B is CTRL register of 32-bits in size.
Whereas in Mode Y, definition of Register B is DEBUG register of 32-bits in size with different field elements.
c. Keeping the above scenario, which would be a better way to define the UVM Register Model ? Is it better to have two separate register model one for Mode X and other for Mode Y ? Or to maintain only one register mode and internally change the register/field configurations based on the mode selection ?
Which would be a better approach and better for control-ability. Share in you inputs/suggestions !!
Regards,
Desperado !!
I would create two registers and two reg maps. For example, in the
build
method of the reg block class, I would do:If the auto-predict mode is not used, you will need to switch the reg map of the predictor depending on the mode, too.
Register Adapter With Strobe Based Register Access ?
a. I have a scenario where in the Block “x” registers are configured through APB bus !
b. But the tricky part is that the APB bus is strobe based access !!!
c. If I do a register write, then the adapter basically have to convert the register based TX to the Bus based TX. But here the proper register offset address and the strobe value needs to be set instead of default register address !
Had anyone came across such situation i.e. block register access using APB with Strobe based access ? If so share in your thought process !!
Appreciate Your Help !!
I don’t quite understand your question, but isn’t it enough to set the
PADDR
andPSTRB
of the APB in thereg2bus
function of the reg adapter, based on the value ofaddr
andbyte_en
of theuvm_reg_bus_op
structure?Hii,
Mirror method will gives error whenever there is a missmatch of data.
is it possible to print some other msg also with the uvm_error when data missmatch.??
If you just want to print a message every time a specific register is read, you could use the
post_read
callback of theuvm_reg
class. The following example shows how to print the register information every time thejelly_bean_taste_reg
is read.If you want to print a message only if a read data is mismatched, you could override the
do_check
function as follows. This function is not documented, so use it at your own risk 😉Hi,
Thank you very much for the solution its working correctly.
Thanks for the such a nice support.
Hi,
One more question Sir,
how to use “set_report_severity_id_file” I tried many things but either its give error or it will not do anything,
so can you tell me with small example.
Thank you
Khushmit
Sorry for the very slow response. I wrote a new article about this. Did you call
set_report_severity_action
to addUVM_LOG
action?Hi,
Could you please explain the difference between reg2bus and bus2reg function?
Thanks,
Neelima
The
reg2bus
is called when you read/write the registers. The function converts the register operation into a bus transaction. For example, if you use AHB, the function returns an AHB transaction corresponding to the register access. On the other hand, thebus2reg
converts in opposite direction. This function is called when you have a register read/write on the bus. For example, a register predictor calls this function to convert an AHB transaction into a register operation. Please see Register Adapter section of Register Abstraction for an example.Thank you for the response. I would appreciate if you inputs on how to write adapter code when address and data channels are independent., for example for AXI. Do we have to manage this in the driver or is there any other way to do this? though writes are working i have problem with reads
Sorry for the slow response. The driver should take care of the read data. You need to return the read data either by storing the data to the read request itself, or by returning it as a separate response. In the latter case, set
provides_responses
bit in the adapter. If this bit is set, the reg map uses the response object when it calls thebus2reg
function. Otherwise, the request object is used. The adapter functions (reg2bus
andbus2reg
) should simply convert theuvm_reg_bus_op
to/from the corresponding bus transaction. Let me know if you need further clarification.Thank you for the great tutorial. Do you have any examples using provides_responses? I am not able to get responses to come back from the driver. Where do you set the response object or request object? I am expecting a completion as a response from a read from my DUT. Thank you.
I wrote a new article about this. Let me know if you have further questions.
Hello Keisuke,
I am trying to write a MSB of a register with bit_size 32(data[]: 0x80000000) and I am getting the following warning:
UVM_WARNING /uvm_reg_field.svh(1481) @ : reporter [RegModel] uvm_reg_field::write(): Value greater than field
Can you please explain me why I am getting this warning
It seems you are writing 32-bit value to a 1-bit field. Try
your_reg.your_reg_field.write( status, 1'b1 )
or
your_reg.write( status, 32'h80000000 )
Hello Keisuke, Thanks for your reply. I am getting the following warning when I try to set a value in a register field
UVM_WARNING (UVM/FLD/SET/BSY) Setting the value of field “xxx” while containing register “yyy” is being accessed may result in loss of desired field value. A race condition between threads concurrently accessing the register model is the likely cause of the problem.
Can you please explain me why I am getting this warning!! Your assistance is kindly appreciated 🙂
This is most likely you called the
set()
function while you were in the middle of reading/writing the same register via the front-door.Hello Keisuke,
First of all thank you for this tutorial,
as I’m a beginner in the world of UVM,I want to know the difference between : sequencer , sequences and adapter.
Thanks.
Mourad.
Roughly speaking, you define the series of transactions (stimuli) in a sequence. Sequencer arbitrates the sequences and send the series of transactions to a driver. Adapter converts one kind of transaction into another. In the RAL context, it converts generic register transactions from/to specific bus transactions (like AHB).
Hello Keisuke,
Excellent post . Can you please throw some light on predict method ?
What if I set auto_predict for certain register model ?
If you set the auto-predict mode, the register model will automatically update its mirror when you read/write the register using the RAL. However, it won’t capture the read/write not initiated by the RAL. Please see this for more information.
Hello Keisuke,
Thanks for Very detailed explanation on RAL. It was very helpful…
Shimizu-san,
Thank you very much for all you have done for the UVM community. I have a short question on the read() diagram you have above. I noticed that in step 4), the register adapter generates a bus2reg transaction (without waiting for the step 6 and 7) to come back. Can you explain why that is done? I am having problem when the read() transaction is meant to be an invalid transaction and I am blocking the result from step 6 and 7 (through the blocking of the uvm_monitor) but unable to block the feedback from step 4 as it seems “automatic”. Thank you.
Regards,
Bennett
Does your driver return a separate response for the read data? If so, make sure you set the
provides_responses
bit in your reg adapter. Otherwise, the reg map callsbus2reg()
as soon as the driver has finished a request.Hi Keisuke,
Thanks for this great post.
I’m trying to model DFT registers at Register Abstract Level.
I ran into a problem is that DFT registers are usually larger than 64 bits width. When I implement bus2reg() function, I don’t know how to pass the extra data back to the register read operation, since uvm_reg_bus_op.data defaults to 64bits.
Could you give me some suggestions?
Thanks in advance!
Best Regards,
Rui
If you define
UVM_REG_DATA_WIDTH
, you can use more than 64-bits.In case you want to redefine the UVM_REG_DATA_WIDTH then would you have to recompile the whole UVM library? Is not there any other way? Why this hard limitation?
Yes, you need to recompile the library because the
UVM_REG_DATA_WIDTH
defines the bit width of the packed array,uvm_reg_data_t
. I think the reason behind this is to optimize the memory footprint of the register models.Hi Keisuke,
Thanks a lot for the detailed explanation here. I have a question. From a single read() I want rw.addr to be written on the bus and then data to be read. I got the information that I can do this using custom frontdoor and set_frontdoor. But I am not getting how exactly I am supposed to change rw.kind=UVM_READ to UVM_WRITE first and then again to UVM_READ? will I be able to get 2 different bus items from a single reg item? Can you please help?
I assume you need two separate bus transactions for a read. For example, you write an address to the address register, then read back data from the data register.
Unfortunately, the
reg2bus()
function cannot return two bus transactions or auvm_sequence
. My solution would be building layered sequencers and monitors. In the diagram, thereg2bus()
function returns a read transaction object. Then the Transaction Sequencer converts the read transaction into two bus transactions, one for address write and the other for data read.On the predictor side, the Bus Monitor captures these two bus transactions. Then the Transaction Monitor converts back them into a read transaction, which goes to the Register Predictor. Hope this helps.
Hi Keisuke,
It seems that uvm_reg::write task updates value in regmodel even in explicit prediction mode.
I have used set_auto_predict(0), so I expected that register.write will only launch bus transaction, but it also directly/immediately updated regmodel value(mirror register). Same code was working well with UVM-1.0 while in UVM-1.1 this issues appears.
This is because in uvm_reg::write (UVM-1.1), there is unconditional call of set function which was not there in UVM-1.0
Yes, as you pointed out, the
value
is firstly updated by thewrite
, then updated again whendo_predict
is called by thewrite
itself (auto predict) or by theuvm_reg_predictor
(manual predict).Hi.. Very helpful explanations related to RAL. I have situation in which I need to compare the present and previous value of the register.From the above post I understand tat all the values- m_mirrored,m_desired and value gets updated when read is done on the register. I want the previous value of the register stored somewhere…How can I do tat ?
Thanks in advance
The easiest way would be using the
mirror
task.The
mirror
task compares the read-back value against the last mirrored value ifcheck
isUVM_CHECK
. The task issues an error message if the values do not match. You can disable the check field-by-field by callingyour_reg_field.set_compare( UVM_NO_CHECK )
before calling themirror
.If the previous register values need to be stored somewhere for more complex comparison, then I would create a subscriber that keeps track of the register values.
Hi Keisuke,
I have some question about RAL, would you please answer those:
1. I understand that value of m_mirrored always equal value of register in DUT, is that right ?
2. As you said “The update() method writes the value only if the m_mirrored and the m_desired are not equal.” Would you please so example to make m_mirrored and the m_desired are not equal.
Thank.
Tuyend
m_mirrored
value is updated only when the register is read or written. If the DUT modifies the value of register internally (like a counter), the mirrored value becomes outdated.set( 1 )
, them_mirrored
andm_desired
become unequal.Hi Keisuke,
I have two maps in my ral mode one is ahb and spi. when I was using spi map as default map mirror operation is working(its doing score board properly) after that I added the ahb map and removed spi s default map and created two maps(spi , ahb).
Now mirror is not working. can you pls advice what code I should add for mirror to work.
What is uvm_status in reg for me its failing uvm_status has x althoug the reg value is zero.
Thanks,
Sampath
Do you specify which register map to use when you call
mirror
likemirror( status, .map( ahb_map ) )
?Hi Shimzu San ,
Hajimi masthe . I tried doing update method using following method
spi_reg.set(8’h80)
spi_reg.update(status)
spi_reg.get() –> This will yild as ‘h80
spi_reg.get_mirrored_value -> 8’h0
I dont understand y update is not writing with m_desired value
Assuming you used the front-door access, did you see a correct bus transaction when you called the
update
? If yes, check thebus2reg
function of your reg adapter.Great work Keisuke! Now i know better how the rgm access work 🙂
Hi Keisuke,
How to write only specific register field instead of entire register?
To write a register field individually,
If both of them are true, then set
supports_byte_enable
property of theuvm_reg_adapter
, andindividually_accessible
argument of theconfigure
function of theuvm_reg_field
.Hi Keisuke, you tutorial is very much useful. Thanks a lot to you and all the friends for their doubts and your responses.
its gives a log of insight theoretically as well as at the application/usage
Thanks for your comment. I’m glad it’s useful.
Hi Keisuke,
1. Can we set same adapter for two different regmaps?
like this
regmap1.set_sequencer(sequencer1,adapter);
regmap2.set_sequencer(sequencer2,adapter)
2. can two regmaps share a single sequencer?
regmap1.set_sequencer(sequence1,adapter1);
regmap2.set_sequencer(sequencer1,adapter2);
I think you can do both.
Hi Keisuke,
In below code I am using first predict to write value 3 into m_desired and m_mirrored of ral model as per theory there should not be any effect in dut but when I am trying to read dut using read_reg it is giving me m_desired value and m_mirrored value equal to 3 where I am expecting if predict is not writing dut reg then after read my mirrored value should be equal 2.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
I tried your code and I’ve got mirror_value=2 at the end. I am not sure why you got 3, though.
Hi Keisuke,
There is available an example for reading the default values of the DUT registers (without any previous write operation)?
Thank you.
If you do
your_reg.read( status, value )
, it will actually read the register from the DUT. If you just wanted to know the reset value of the model, you can doyour_reg.get_reset()
. This function DOES NOT read the value from the DUT. It just returns the reset value of the model.Thank you for the great post.
I have a question about m_mirrored value. I understand that m_mirrored can get updated through ral functions like write/read/update/mirror/peek/poke, etc since it uvm_monitor captures bus transactions and eventually update it.
Does this apply to non-ral register access too ? Namely if I issue register access not through ral functions, is the bus transaction still going to be captured and finally gets updated to the m_mirrored ?
As long as the monitor is attached to the bus and the monitor is connected to the predictor, the
m_mirrored
should be updated regardless of you access the register through RAL or not.