ASIC Verification: Time Consuming Methods

Thursday, March 6, 2008

Time Consuming Methods

In the previous sections, we discussed regular methods that execute in zero simulation time. Some methods executes over multiple cycles and are used to synchronize processes in an 'e' program with processes or events in DUT. These kind of methods are called Time Consuming Methods (TCM). In this section we are going to see how to describe TCM, how to call and start a TCM and the difference b/w wait and sync actions.

Definition of TCM

A TCM is a procedure contains actions that define its behavior over time. In TCM, simulation time elapses. Within a single program, multiple TCMs can execute either sequence or in parallel. Here is an example that illustrates the TCM definition.
====================================================================

<'
struct
trasmitter
{
event clk is rise ('~/top/clock') @sim;
event rx_evt;

// Define a TCM called transmit().
// It becomes a TCM, because of @clk sampling event

transmit() @clk is {
wait cycle;
// Wait for the next emission of clk event
emit receive_evt;
// Emit the receive_evt
out("Rx event is emitted");
};
// End of transmit() method
}; // End of struct
'>
====================================================================

Characteristics of TCMs

  • A TCM can read/write locally declared variables and fields within a struct, accept arguments and return a value.
  • The maximum number of parameters you can declare is 14.
Invoking TCMs

Before invoking TCMs, you should create an instance of the struct. TCM can be started or called.

  • From a regular method, you can call another RM and can start a TCM
  • From a TCM, you can call both methods but can start only a TCM
You can execute a TCM by calling it from another TCM. A called TCM begins execution when its sampling event is emitted. The calling TCM is blocked until the called TCM returns before continuing the execution. The following program shows how to call a TCM from another TCM
====================================================================
<'
struct method1
{
event nclk is fall ('~/top/clock') @sim; // Negative edge of clock
event reset_n is rise ('~/top/rstn')@sim; // Active low reset
event rst_deasserted; // Declare an event

// Define a TCM init_dut()
// @nclk is the default sampling event

init_dut () @nclk is

{
wait [4] reset_n; // Wait for 4 occurrences of reset_n
wait [2]; // Wait for 2 nclk cycles
out("DUT is coming out of reset");
};
// Define a TCM tcm1()
tcm1() @nclk is
{
wait [1];
init_dut();// Call a TCM init_dut()
emit rst_deasserted; // rst_deasserted is emitted at the end of init_dut()
}; // End of tcm1()
};// End of struct
'>
===================================================================

You can start a TCM from another TCM, but here a started TCM will not block the execution of starting TCM. You can very well replace the init_dut() in tcm1() of the above program with start init_dut(). But the event rst_deasserted is emitted immediately after starting init_dut().

A TCM can also be extended in the same way as a regular method by means of is also, is first and is only keywords.

Wait and Sync Actions

There are two actions that are used to synchronize temporal activities within e and b/w the DUT and 'e' simulator.

Wait Action

The wait action suspends the execution of the current TCM until a given temporal expression succeeds. A TCM can't continue during the same cycle in which it reaches a wait. Even if the temporal execution succeeds in the current simulator callback, the TCM won't proceed. The TCM has to wait at least until the next simulator callback. Therefore, the wait action always requires at least one cycle of TCM's sampling event before execution continues.

Sync Action

The sync action suspends the execution of the current TCM until a given temporal expression succeeds. With a sync action, execution can continue in the same simulator callback. The following example explains the difference b/w wait and sync actions.

Using Verilog Tasks

In TCMs, it is possible to call verilog tasks and functions directly from the 'e' code.
Example shows the use of a verilog task call from an 'e' code.

===================================================================
<'
struct task_from_e
{
address : int(bits:3);
data : list of byte;
};

unit memory
{
verilog task 'top.mem' ( addr : 3 : in, data : 8: out, status : 32 : out);
event rd_en;

// Define a TCM
get_mem(mw: task_from_e) @rd_en is
{
// Call the mem task defined in verilog 'top' module
'top.mem'(mw.address, data, error_staus);
}; // End of TCM
}; // End of struct
'>
===================================================================

Verilog Funtions

Example shows the usage of verilog function call from an 'e' code

===================================================================
<'
// Verilog function defined outside of unit
// 2 args. addr and data
// Return value is 32 bit

verilog function 'top.write_mem' (addr:32, data:64) : 32;

unit memory_drv
{
event enable is rise ('~/top/enable') @sim;
wr_mem() @enable is
{
var err_st : int;
err_st = 'top.wr_mem'(33, 45);
}; // End of wr_mem()
}; // End of struct
'>
===================================================================

No comments: