Previous Section Next Section

9.2 Data Checking

There are two aspects to checking in e, data checks and temporal checks. This section covers facilities for data checking.

9.2.1 Comparing Two Structs for Equality

Using the pack() and unpack() methods, structs can be converted to a list of bits or bytes and vice versa. Therefore, it is recommended that all verification be done in e code by means of abstract structs. The pack() method should be used to convert the structs to a list of bits at the time of driving. Similarly, the unpack() method should be used to convert the list of bits received from the DUT into an abstract struct. Finally, the abstract structs should be compared for equality instead of bits. Figure 9-3 shows the methodology for the comparison of these structs.[2] This methodology is also recommended for simplifying debugging of miscomparisons.

[2] The methodology for struct comparison is just one example. There are many other ways of comparing for equality. For example, in a CPU verification system, a reference model is used and the output of that model is compared with the DUT for equality. Although the methodology may change, usage of methods described in this section still applies.

Figure 9-3. Comparing Input and Output Structs

graphics/09fig03.gif

In e, two structs can be compared field by field to check for mismatches. As shown in Figure 9-3, this is very useful when the input struct and the output struct are compared. There are two routines that compare structs for field-by-field equality, deep_compare() and deep_com-pare_physical().

9.2.1.1 deep_compare_physical()

This routine recursively compares each physical field of a struct instance with the corresponding field of another struct instance. Virtual fields are ignored. If there are multiple levels of instantiation hierarchy, then deep_compare_physical() compares at these levels. The syntax for deep_compare_physical() is as follows:

deep_compare_physical(struct-inst1: exp, struct-inst2: exp, max-diffs: int): list of string;

Example 9-4 shows the usage of the deep_compare_physical() routine.

Example 9-4 deep_compare_physical() Routine
Example shows the usage of the deep_compare_physical() routine.
<'
struct packet { //Define a struct
    %header: header; //Physical field, header is a struct
    %data[10] :list of byte; //Physical field
    protocol: [ATM, ETH, IEEE]; //Virtual field
};

struct header {
    %code: uint; //Physical field
                 //deep_compare_physical() will go into
                 //header struct and do a comparison of code field
};

extend sys {
    pmi[2]: list of packet; //Generate two packet instances
    post_generate() is also {
        var diff: list of string;
        //Call to deep_compare_physical()
        diff = deep_compare_physical(pmi[0], pmi[1], 10);
                //Compare the physical fields of pmi[0] and pmi[1] for
               //equality. This is a recursive comparison. It will
             //compare fields, code and data. However, it
             //will ignore the protocol
             //field. Output is a list of string mismatches.
              //The number 10 is the max mismatches to be reported.
        if (diff.size() != 0) { //If there are mismatches
            out(diff); //print out the mismatches.
        }; //Otherwise, if there are no mismatches, a null
             //string will be printed, meaning the packets matched
           //successfully.
    };
};
'>
9.2.1.2 deep_compare()

The deep_compare() routine recursively compares both virtual and physical fields of a struct instance with the corresponding fields of another struct instance. If there are multiple levels of instantiation hierarchy, then deep_compare() compares at these levels. The syntax for deep_compare() is as follows:

deep_compare(struct-inst1: exp, struct-inst2: exp, max-diffs: int): list of string;

Example 9-5 adds to the code in Example 9-4 to show the usage of the deep_compare() routine.

Example 9-5 deep_compare() Routine
<'
extend sys {
post_generate() is also {
        var diff1: list of string;
        //Call to deep_compare()
        diff1 = deep_compare(pmi[0], pmi[1], 10);
              //Compare both physical and virtual fields of
              //pmi[0] and pmi[1] for
              //equality. This is a recursive comparison. It will
              //compare the fields, code, data and protocol.
              //Output is a list of string mismatches.
              //The number 10 is the max mismatches to be reported.
        if (diff1.size() != 0) { //If there are mismatches
            out(diff1); //print out the mismatches.
        }; //Otherwise, if there are no mismatches, a null
           //string will be printed, meaning the packets matched
           //successfully.
    };
};
'>

9.2.2 Check that Action

The check that action performs a data comparison and, depending on the results, prints a message. The keyword that is optional. The check that action is functionally equivalent to the if-then-else construct but is recommended for checks because it provides better clarity in documenting checking code. The syntax for the check that construct is as follows:

check [that] bool-exp [else dut_error(message: exp, ...)];

Example 9-6 shows the usage of the check that action.

Example 9-6 Check that Action
Example shows the usage of the check that action.
This is primarily used for data checking.
<'
extend sys {
check_hard_error() is {
    check that 'top.hard_error' == 1 else //boolean check
        dut_error("Error-5 -- Hard error not asserted");
};

//If the above boolean check does not match, an error message
// as shown below is displayed.
//*** Dut error at time 0
// Checked at line 4 in check2.e
// In sys-@0.check_hard_error():
//
// Error-5 -- Hard error not asserted
//
//Will stop execution immediately (check effect is ERROR)
//
// *** Error: A Dut error has occurred

//If the else dut_error() clause is omitted, a default
//message is displayed
'>

9.2.3 dut_error() Method

This method is used to specify a DUT error message string. This action is usually associated with an if action, a check that action, or an expect struct member. If the boolean expression in the associated action or struct member evaluates to TRUE, then the error message string is displayed. The syntax for the dut_error() method is as follows:

dut_error(message: exp, ...);

Example 9-7 shows the usage of the dut_error() method.

Example 9-7 dut_error() Method
Example shows the usage of the dut_error() method.
<'
extend sys {
    m() is {
        if 'data_out' != 'data_in' then
          {dut_error("DATA MISMATCH: Expected ", 'data_in')};
    };
};

//If there is a mismatch, the following message
//will be printed on the screen
//*** Dut error at time 0
// Checked at line 4 in /tests/check6.e
// In sys-@0.m():
//
//DATA MISMATCH: Expected 1
//
//Will stop execution immediately (check effect is ERROR)
//
// *** Error: A Dut error has occurred
//
'>

9.2.4 Check Failure Effects

Often, you may want your error/debug messages to behave differently in module testing, system testing and regression. e allows you to change the behavior of error/debug messages without touching the original e code. This can be done either from an extension of the existing e code or from Specman Elite. Check failure effects can be set by use of the set_check() routine from e code or the set check command from the Specman Elite prompt. The syntax for the set_check() routine is as follows:

set_check(static-match: string, check-effect: keyword);

Table 9-3 describes the components of a set_check() routine.

Table 9-3. Components of set_check() Routine

static-match

A regular expression enclosed in double quotes. Only checks whose message string matches this regular expression are modified. Use … to match white space or non-white space characters.

check-effect is one of the following:

ERROR

Specman Elite issues an error message, increases num_of_dut_errors, breaks the run immediately and returns to the simulator prompt.

ERROR_BREAK_RUN

Specman Elite issues an error message, increases num_of_dut_errors, breaks the run at the next cycle boundary and updates the simulation GUI with the latest values.

ERROR_AUTOMATIC

Specman Elite issues an error message, increases num_of_dut_errors, breaks the run at the next cycle boundary, and performs the end of test checking and finalization of test data that is normally performed when stop_run() is called.

ERROR_CONTINUE

Specman Elite issues an error message, increases num_of_dut_errors, and continues execution.

WARNING

Specman Elite issues a warning, increases num_of_dut_warnings and continues execution.

IGNORE

Specman Elite issues no messages, does not increase num_of_-dut_errors or num_of_dut_warnings, and continues execution.

Example 9-8 shows the usage of the set_check() routine.

Example 9-8 Usage of set_check() Routine
Example shows how to extend the setup() method
of sys to set up check effects. If the e code
shown below is loaded, all dut_error() messages
in that simulation will be shown as WARNING.
<'
extend sys {
    setup() is also {
        set_check("...", WARNING);
    };
};
'>
//The check effect can also be set from the
//the Specman Elite prompt.
//Specman> set check "..." WARNING
Previous Section Next Section