Here's a collapsed set of questions asked during the live web seminar along with Chris's answers. If you don't see your question here, or need further clarification, you can always ask on the Verification Academy Forums.
Can you please elaborate why transaction is not extended from uvm_transaction instead extended from uvm_sequence_item?
The uvm_transaction class was not designed to be part of group of transactions. The class uvm_sequence_item has additional properties that keep track of where this item is inside a sequence.
Why should I not randomize the output variables in the transaction class?
Filling in the transaction’s output variables with random values, like “99”, does not help verify the design. When the transaction object is created, randomize the variables that represent the design inputs. Then the object can be sent to testbench's predictor (part of the scoreboard or reference model) which calculate the output values. For example, if you are modeling an ALU, the inputs might be “ADD 2, 2”. The testbench predicts that the design’s output is “4”. Now you can compare this expected output to the actual design output.
When extending from a base uvm_sequence_item do you need to have all of your signals in the base class? Can you add additional signals in the extended class or will that cause issues with do_copy/do_compare?
Build your transaction classes in layers, and divide them up like the protocol layers. The base class might have just the basic signals. Extend the class for higher levels of protocol, adding signals as needed. Also extend these classes to add new functionality such as constraints, and other members.
What are the methods to copy if an object has object handles?
The copy() method performs a deep copy. Either you implement this with a do_copy() or the field macros. I did not show a deep do_copy() that worked with handles as there was not enough time.
When you compare two values in SystemVerilog, always use the case equality operator, ===, to correctly handle X and Z bits. This way you don't have to try to remember if the properties are 2-state or 4-state - let the compiler figure that out.
If bit type signal, why '==='?
Pick the most general compare operator, and use it for 2-state and 4-state types.
Has there been any improvement in the field macros? The comparison between using custom do_*methods vs the built-in field macros was done using ovm if I recall correctly.
Yes, original field macros, written for OVM, were much less efficient than hand written code. The UVM versions are much better. Only worry about efficiency if a code profile shows that these are causing problems.
Where do we use "record"?
With the record() method, you can save transactions for waveform display, or write to a file to log their values. The compare() and clone() methods are used far more often than record().
I've used sprint() inside a uvm_info macro to control the verbosity.
That follows my recommendation of using uvm_info for all messaging. You are right - sprint() and convert2string() are very similar here.
How do_copy will work for parametrized class?
The do_copy() method can use the parameters just like any other method in a parameterized class. This is true for parameterized values and parameterized types.
If we miss super.do.**, compilation/runtime error will be resulted or not
If you leave out a call to super.do*(), your code may not work correctly. It will compile and run without errors, but won't work correctly.
Any good reason to switch from VMM to UVM?
Availability of Verification IP is the top reason. Improving your resume is another. There are 10-100x more UVM users than VMM.
For do_copy , without $cast?
The methods do_copy() and do_compare are passed handles of type uvm_object. You can not access properties in your transaction with this base handle, and need to cast it to a handle of your transaction type. Just try it! Remember, a base handle can point to a derived object.
Why is mixing field macros and do methods not great?
If you mix the two styles for a single hierarchy of transaction classes, you may get unexpected effects. The most notable is that the two print styles don't blend together. Try it and see.
Can we get parent object handle name inside the uvm_sequence_item ? Like if we want to print the parent of the transaction for debug?
Yes, there is a get_parent_sequence() in the uvm_sequence_item class.
Isn't it nice to have logic [2:0] input_field instead of bit [2:0] input_field. This way, design can be excersized by giving "x" inputs too to check if "x" propogation happens inside design or not.
Yes, you could inject X values. However the simulator's X-Prop extensions might be a better approach.
Chris, you mentioned using rand bit for tx_item i/p properties. Any downsides of using "rand logic" instead?
In general, randomization only produces 2-state values, so why use a 4-state type? It won't hurt, but logic is the wrong type for the job. Additionally, it will run a tiny bit slower, and take a tiny bit more memory.
If you have a bus that has SOP, EOP, data, valid, etc... Would you create a transaction for each step? (SOP, data, data, ..., EOP)? Or one transaction that's a queue of data bytes, and have the driver auto add the SOP and EOP flags? What about CRCs (both valid and invalid)?
Take a step back and think about this from an OOP view. Does it make sense to have a transaction with just a single byte? Are there operations that you want to perform on the byte-level transactions, or are you more focused on the entire stream?
If my trans has over 100 variables, what is the best way to print ? for ex: If I want tabular print then uvm_printer can have it , right? what should be the proper approach?
What are you really trying to do? If you use the field macros, uvm_printer formats properties for printing. I always used the default formatting, but with fewer properties. When I use the do methods, I never use uvm_printer.
We're using field macros in our TB and want to improve performance, is it possible to (somehow) measure/stimate the performance gain if we move to do_* style?
Use the code profiler to find the actual bottlenecks in your simulation. It could be field macros, or the uvm_config_db, or maybe even the RTL.
How to randomize variables without using rand function?
I assume you mean class-based constrained randomization with the randomize() method. There are multiple way's to generate random values in SystemVerilog, why would you want to avoid the most powerful and widely supported approach?
Any example, where we need to write separate compare methods out of transaction class?
You seem to be asking if you ever need to write a compare method outside of a transaction class. In UVM, transactions are described with classes, so what would you be comparing? UVM components are never compared or copied.