Category Archives: Alerts and Logs

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

Using Logs

Logs provide a mechanism to conditionally print a formatted message. What makes them powerful is that they can be enabled or disabled from different places in the testbench. Log supports levels DEBUG, INFO, FINAL, and ALWAYS. The level ALWAYS enabled, all the others are disabled by default.

In common with alerts, logs support two modes: simple and hierarchy. In simple mode, there is a single set of global controls for enabling DEBUG, INFO, and FINAL. In hierarchy mode, there are separate controls for enabling DEBUG, INFO, and FINAL in each model and/or control point in the hierarchy.

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 Log Control

Simple mode is available by default. In simple mode, there is a single set of global controls for enabling DEBUG, INFO, and FINAL. The following provides a short example of setting log controls.

All designs that use log (or alert) need to reference the package AlertLogPkg.

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

In simple mode, levels can be enabled or disabled from anywhere in the testbench by calling SetLogEnable. The log ALWAYS is always enabled, all other logs are disabled by default.

SetLogEnable(DEBUG, TRUE) ;

The following log will print “A message” when DEBUG is enabled.

Log ("A message", DEBUG) ;

The format of a log message is as follows.

%% Log   DEBUG  A Message  at 15110 ns

Hierarchy Mode: Each model supports separate controls.

In hierarchy mode, there are separate controls for enabling DEBUG, INFO, and FINAL in each model and/or control point in the hierarchy.

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 log (or alert), a model must allocate an AlertLogID. Then when calling log (or alert), 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 creates an AlertLogID for the CpuModel.

constant CPU_ALERT_ID : AlertLogIDType := 
    --            Name (string value),         Parent AlertLogID
    GetAlertLogID(PathTail(CpuModel'PATH_NAME), ALERTLOG_ BASE_ID) ;

The AlertLogID is specified first in calls to Log and SetLogEnable.

SetLogEnable(CPU_ALERT_ID, DEBUG, TRUE) ; 
Log (CPU_ALERT_ID, "A message", DEBUG) ;

The format of a log message includes the AlertLogID as shown below.

%% Log   DEBUG  in CpuModel_1, A Message  at 15110 ns

Log enables can also be read from a file using the procedure ReadLogEnables.

ReadLogEnables("./Test1EnableDebug.txt") ;

The file read format is:

U_CpuModel DEBUG
U_UART_TX DEBUG INFO
U_UART_RX FINAL INFO DEBUG

Going Further

For a complete command reference guide, see AlertLogPkg_User_Guide.pdf

Announcing OSVVM™ 2015.03

OSVVM 2015.03 is a minor release that updates only AlertLogPkg. All other packages remain unchanged.

In AlertLogPkg, added AlertIfEqual, AlertIfNotEqual, and AlertIfDiff (file). Added ReadLogEnables to initialize LogEnables from a file. Added ReportNonZeroAlerts. Added PathTail to extract an instance name from MyEntity’PathName. Added ReportLogEnables and GetAlertLogName. See AlertLogPkg_User_Guide.pdf for details.

For hierarchy mode, AlertIfEqual, AlertIfNotEqual, and AlertIfDiff have the AlertLogID parameter first. Overloading was added for AlertIf and AlertIfNot to make these consistent. Now with multiple parameters, it is easier to remember that the AlertLogID parameter is first. The older AlertIf and AlertIfNot with the AlertLogID as the second parameter were kept for backward compatibility, but are considered bad practice to use in new code.

Added ParentID parameter to FindAlertLogID. This is necessary to correctly find an ID within an entity that is used more than once.

Bug fix: Updated GetAlertLogID to use the two parameter FindAlertLogID. Without this fix, Alerts with the same name incorrectly use the same AlertLogID.

Bug fix: Updated NewAlertLogRec (called by GetAlertLogID) so a new record gets Alert and Log enables based on its ParentID rather than the ALERTLOG_BASE_ID. Issue, if created an Comp1_AlertLogID, and disabled a level (such as WARNING), and then created a childID of Comp1_AlertLogID, WARNING would not be disabled in childID.

Bug fix: Updated ClearAlerts to correctly set stop counts (broke since it previously did not use named association). Without this fix, after calling ClearAlerts, a single FAILURE would not stop a simulation, however, a single WARNING would stop a simulation.

Since 2015.01 has known bugs, it has been deleted from the downloads page.