Wednesday, February 23, 2011

SV final vs initial

Final block Vs Initial block
The only statements allowed inside a final block are those permitted inside a function declaration. This guarantees that they execute within a single simulation cycle. Unlike an initial block, the final block does not execute as a separate process; instead, it executes in zero time, the same as a function call.

factory mechanism can be used for both components (structure) and objects (transaction/data)

yes, both object classes and component classes can be overridden hence
"ovm_object_utils" and "ovm_componenet_utils"

What is a factory?
ovm_factory - creates objects and components according to user-defined type and instance-based overrides.
ovm_factory is used to manufacture (create) OVM objects and components.  Only one instance of the factory is present in a given simulation (termed a singleton).  Object and component types are registered with the factory using lightweight proxies to the actual objects and components being created.  The ovm_object_registry #(T,Tname) and ovm_component_registry #(T,Tname) class are used to proxy ovm_objects and ovm_components.

Preregistration requirements:
When overriding by type, the original_type and override_type are handles to the types’ proxy objects.  Preregistration is not required.

When overriding by name, the original_type_name typically refers to a preregistered type in the factory.  It may, however, be any arbitrary string.  Future calls to any of the create_* methods with the same string and matching instance path will produce the type represented by override_type_name, which must be preregistered with the factory.

It is worth noting that environments that exclusively use the type-based factory methods (*_by_type) do not require type registration.  The factory’s type-based methods will register the types involved “on the fly,” when first used.  However, registering with the `ovm_*_utils macros enables name-based factory usage and implements some useful utility functions.

A full_inst_path of “*” is effectively a type override, as it will match all contexts.

Registering order does that matter?
Yes, it does.
When the factory processes instance overrides, the instance queue is processed in order of override registrations, and the first override match prevails.  Thus, more specific overrides should be registered first, followed by more general overrides.

How is searching for overrides done?
Override searches are recursively applied, with instance overrides taking precedence over type overrides.  If foo overrides bar, and xyz overrides foo, then a request for bar will produce xyz.  Recursive loops will result in an error, in which case the type returned will be that which formed the loop.  Using the previous example, if bar overrides xyz, then bar is returned after the error is issued.

what is ovm_object_wrapper?
Ah, the very important thing of factory concept. The ovm_object_wrapper provides an abstract interface for creating object and component proxies.  Instances of these lightweight proxies, representing every ovm_object-based and ovm_component-based object available in the test environment, are registered with the ovm_factory.  When the factory is called upon to create an object or component, it finds and delegates the request to the appropriate proxy.

what does the utility macro for objects/components registry do ?
The `ovm_*_utils macros for simple, non-parameterized classes will register the type with the factory and define the get_type, get_type_name, and create virtual methods inherited from ovm_object.  It will also define a static type_name variable in the class, which will allow you to determine the type without having to allocate an instance.

what about these (factory) utility macros for parameterized classes?
The `ovm_*_param_utils macros for parameterized classes differ from `ovm_*_utils classes in "The get_type_name method and static type_name variable are not defined.  You will need to implement these manually"
any name based methods/operations will not work.

http://ovmworld.org/docs_2.1.1/html/files/base/ovm_factory-svh.html

"events" in systemverilog

CH-17 Event Details
System verilog events are superior to verilog (named) events
@ and -> operators are backward compatible


sv events are two types: persistent and non-persistent (non-persistent events are same as verilog named events)
non-persistent events don't have a state, hence ascertaining them is not possible i.e the statement "if(posedge clock)" is illegal

sv events act as handles to synchronization queues and can be passed as arguments to tasks, dynamically allocated, reclaimed, assigned to one another
persistence of sv events last for the time step in which they are triggered.

A persistent event will unblock all processes that execute wait() either before or at the time same simulation time as the event is triggered
that is not the case with non-persistent events, wait or @ should be executed before the trigger happens ->
if wait (or @) is executed at the same time as the trigger, the process waiting may unblock or not depending on the execution order of these two processes (wait/@ and ->)
this is a race condition and will not happen with persistent events regardless of the order of execution
persistent events are declared as follows
event bit event_identifier; (note the differnce, bit is added)

wait construct is meaningful only when the event is persistent


does $wait_all() require all the events in the arguments be triggered in the same time stamp?
may be not...coz the spec says
any of the specified event may be triggered more than once...triggering an event more than once in a single time step might be possible but a rarity
so assuming the requirement is not in same time step...but get clarification

how good an idea is to use wait_order to check if events happen in order or not ...an assertion on sequence/order...???

if an event is assigned null, the event is ignored i.e processes waiting on that event does not block, they unblock

verilog/sv questions

what is the output of the following code

clock is a peridoic square wave (clock signal) with a period of 10

always @(negedge clock)
if( posedge clock )
#5 out = ~clock;




2.

fork

T1:

T2:

T3: begin

E2 = E1;

while(1) -> E2;

end

join


when will the processes and finally for-join finish and in which order

what happens if E2 = E1 is placed before fork-join

Friday, October 8, 2010

where are these methods defined in OVM?

In my OVM tests I see functions/tasks called without handle ..where are they defined

let us consider, for example, global_stop_request
this is defined in ovm_global.svh and is a global function/method.
it is a convenience function as it allows us to call ovm_top.stop_request() from anywhere.
 

enabling/disabling topology printing in OVM

ovm_root can print topology after elaboration phase.
ovm_root also has a variable to control this feature, enable_print_topology
when set ovm_root prints topology after elaboration phase, to disable printing set the variable to zero.


ovm_top.print_topology();
does the printing, an optional printer can be used as an argument to the print topology.