Using Alerts

Like VHDL assert, calling an alert signals errors during run time with a message, such as the following:

%% Alert ERROR   CpuModel:  No nRdy during CPU Read at 20160 ns

What differentiates alert from assert is that when the test is done, a report of the alerts that were accumulated during a test can be printed. If the test passed, a message of the following format can be printed:

%% DONE  PASSED  t1_basic  at 120180 ns

Alerts support two modes: simple and hierarchy. In simple mode, there is single global alert counter that accumulates the number of FAILURE, ERROR, and WARNING level alerts for the entire testbench. With simple mode, if a test fails, a message of the following format can be printed:

%% DONE  FAILED  t1_basic  Total Error(s) = 2  Failures: 0  Errors: 1  Warnings: 1  at 0 ns

In hierarchy mode, there is a hierarchy of alert counters. Each model and/or source of alerts has its own set of alert counters. Counts from lower levels propagate up to the top level counter. The goal of hierarchy mode is to be able to produce a summary of alerts for each model and/or source of alerts, such as the following. It is hierarchy mode that differentiates AlertLogPkg from other alert reporting packages.

%% DONE  FAILED  Testbench  Total Error(s) = 21  Failures: 1  Errors: 20  Warnings: 0  at 10117000 ns
%%    Default            Failures: 0  Errors: 4  Warnings: 0
%%    OSVVM              Failures: 0  Errors: 0  Warnings: 0
%%    U_CpuModel         Failures: 0  Errors: 4  Warnings: 0
%%      Data Error       Failures: 0  Errors: 2  Warnings: 0
%%      Protocol Error   Failures: 1  Errors: 2  Warnings: 0
%%    U_UART_TX          Failures: 0  Errors: 6  Warnings: 0
%%    U_UART_RX          Failures: 0  Errors: 6  Warnings: 0

All of the alert information is stored in a data structure internal to the AlertLogPkg. In addition to counting alerts, this allows us to disable or enable alerts, and to stop when a specified number of alerts of a given level have occurred.

All printing done by AlertLogPkg uses the OSVVM TranscriptPkg. Hence, if TranscriptFile is open, printing is directed to the file, otherwise, printing is directed to std.textio.OUTPUT.

Simple Mode:  Global Alert Counter

By default, there is a single global alert counter. All designs that use alert (or log) need to reference the package AlertLogPkg.

library osvvm ; 
    use osvvm.AlertLogPkg.all ; 
entity tb is

An alert is signaled by calling one of the Alert procedures: Alert, AlertIf, AlertIfNot, AlertIfEqual, AlertIfNotEqual, or AlertIfDiff (for files). Alerts can have a level of FAILURE, ERROR, or WARNING.

--                    message,         level
When others =>  Alert("Illegal State", FAILURE) ; 
. . . 
read(Buf, A, ReadValid) ;
--            condition, message,            level
AlertIfNot( ReadValid, "Read of A failed", FAILURE) ;
. . . 
--              value1,     value2,       message,             level 
AlertIfNotEqual(ActualData, ExpectedData, "Data Actual /= Expected", ERROR) ;

The output for an alert is as follows. Alert adds the time at which the error occurred.

%% Alert ERROR   Read of A failed  at 20160 ns

When a test completes, use ReportAlerts to provide a summary of errors.

ReportAlerts( Name => t1_basic) ;

When a test passes, the following message is generated:

%% DONE  PASSED  t1_basic  at 120180 ns

When a test fails, the following message is generated (on a single line):

%% DONE  FAILED  t1_basic  Total Error(s) = 2  Failures: 0  Errors: 1  Warnings: 1  at 120180  ns

Similar to assert, by default, when an alert FAILURE is signaled, a test failed message (see ReportAlerts) is produced and the simulation is stopped. Alerts generalize this capability with a stop count. A stop count allows a test to stop after a specified number of alerts have been seen. The default for FAILURE is 0 and the default for ERROR and WARNING is integer’right. The following call to SetAlertStopCount, causes a simulation to stop after 20 ERROR level alerts are received.

SetAlertStopCount(ERROR, 20) ;

Alerts can be enabled by a general enable, SetGlobalAlertEnable (disables all alert handling) or an enable for each alert level, SetAlertEnable. The following call to SetAlertEnable disables WARNING level alerts.

SetGlobalAlertEnable(TRUE) ; -- Default
SetAlertEnable(WARNING, FALSE) ;

Hierarchy of Alerts

In hierarchy mode, each model and/or source of alerts has its own set of alert counters. Counts from lower levels propagate up to the top level counter. The reason to use hierarchy mode is to get a summary of errors for each model and/or source of alerts in the testbench:

%% DONE  FAILED  Testbench  Total Error(s) = 21  Failures: 1  Errors: 20  Warnings: 0  at 10117000 ns
%%    Default            Failures: 0  Errors: 4  Warnings: 0
%%    OSVVM              Failures: 0  Errors: 0  Warnings: 0
%%    U_CpuModel         Failures: 0  Errors: 4  Warnings: 0
%%      Data Error       Failures: 0  Errors: 2  Warnings: 0
%%      Protocol Error   Failures: 1  Errors: 2  Warnings: 0
%%    U_UART_TX          Failures: 0  Errors: 6  Warnings: 0
%%    U_UART_RX          Failures: 0  Errors: 6  Warnings: 0

To implement hierarchy mode, AlertLogPkg has a data structure inside of a shared variable. Each level in a hierarchy is referenced with an AlertLogID (of AlertLogIDType). To use alert (or log), a model must allocate an AlertLogID. Then when calling alert (or log), it specifies the AlertLogID as the first parameter in the call.

A new AlertLogID is created by calling the function GetAlertLogID. GetAlertLogID has two parameters: Name and ParentID (of AlertLogIDType). Name is a string value that will be printed as the hierarchy name.

The following example creates three AlertLogIDs: one for the CpuModel (CPU_ALERT_ID), as well as two separate alert counters for counting Data Errors (DATA_ALERT_ID) and Protocol Errors (PROTOCOL_ALERT_ID).  CpuModel uses ALERTLOG_BASE_ID (the default if not specified) as the ParentID. DATA_ALERT_ID and PROTOCOL_ALERT_ID use CPU_ALERT_ID as the ParentID.

constant CPU_ALERT_ID : AlertLogIDType := 
    --            Name (string value),         Parent AlertLogID
    GetAlertLogID(PathTail(CpuModel'PATH_NAME), ALERTLOG_ BASE_ID) ;
constant DATA_ALERT_ID : AlertLogIDType := 
    GetAlertLogID("Data Error", CPU_ALERT_ID) ;
constant PROTOCOL_ALERT_ID : AlertLogIDType := 
    GetAlertLogID("PROTOCOL Error", CPU_ALERT_ID) ;

The AlertLogID is specified first in calls to Alert, SetAlertEnable, and SetAlertStopCount.

--             AlertLogID,    Level,    Enable
SetAlertEnable(CPU_ALERT_ID,  WARNING,  FALSE) ; 
--                AlertLogID,   Level,   Count
SetAlertStopCount(CPU_ALERT_ID, ERROR,      20) ;
Alert(CPU_ALERT_ID, "CPU Error", ERROR) ;
AlertIf(PROTOCOL_ALERT_ID, inRdy /= '0', "during CPU Read operation", FAILURE);
AlertIfNotEqual(DATA_ALERT_ID, ReadData, ExpectedData, "Actual /= Expected Data");

The format of an alert message includes the AlertLogID as shown below.

%% Alert FAILURE in CPU_1, Expect data XA5A5 at 2100 ns

Going Further

For a complete command reference guide, see AlertLogPkg_User_Guide.pdf