Spec Tutor
Spec Tutor
Specman Elite TM
Tutorial
(c) 1999 by Verisity. All rights reserved.
Revision 1.1
Trademarks
Verisity is a registered trademark of Verisity. The Verisity logo, Specman, Specview,
Specman Elite, Verification Advisor, Pure IP, and Invisible Specman are trademarks of
Verisity. All other trademarks are the exclusive property of their respective owners.
Confidentiality Notice
No part of this information product may be reproduced, transmitted, or translated in any
form or by any means, electronic, mechanical, manual, optical, or otherwise without prior
written permission from Verisity.
Information in this product is subject to change without notice and does not represent a
commitment on the part of Verisity. The information contained herein is the proprietary
and confidential information of Verisity or its licensors, and is supplied subject to, and may
be used only by Verisity’s customers in accordance with, a written agreement between
Verisity and its customers. Except as may be explicitly set forth in such agreement,
Verisity does not make, and expressly disclaims, any representations or warranties as to the
completeness, accuracy, or usefulness of the information contained in this document.
Verisity does not warrant that use of such information will not infringe any third party
rights, nor does Verisity assume any liability for damages or costs of any kind that may
result from use of such information.
1 Introduction
Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-1
Tutorial Goals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-3
Setting up the Tutorial Environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-4
Document Conventions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-4
8 Analyzing Coverage
Goals for this Chapter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-1
What You Will Learn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-1
Running Tests with Coverage Groups Defined . . . . . . . . . . . . . . . . . . . . . . . . . . 8-2
Viewing State Machine Coverage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-4
Viewing Instruction Stream Coverage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-8
Viewing Corner Case Coverage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-10
• Data and temporal checking — you can quickly create self-checking modules that
ensure data correctness and temporal conformance. For data checking you can use a
reference model or a rule-based approach.
• Functional coverage analysis — because you can measure the progress of your
verification effort against a functional test plan, you avoid creating redundant tests that
waste simulation cycles.
Figure 1-1 on page 1-2 shows the main component technologies of the Specman Elite
system and its interface with an HDL simulator.
HDL simulator
Tutorial Goals
The goal of this tutorial is to give you first-hand experience in how the Specman Elite
system effectively addresses functional verification challenges.
As you work through the tutorial, you follow the process described in Figure 1-2 on
page 1-3. The tutorial uses the Specman Elite system to create a verification environment
for a simple CPU design.
Generate constraint-
driven tests
Create corner-case
tests
Appendix A, “Setting up the Tutorial Environment” describes how to perform these steps.
Note Keep in mind that even if Specman Elite software is currently installed in
your environment, you still have to download and install the tutorial files.
Document Conventions
The tutorial uses the document conventions described in Table 1-1 on page 1-4.
courier bold Text that you need to type exactly as it appears to complete a procedure or
modify a file.
bold In text, bold indicates Specman Elite keywords. For example, in the phrase
“the verilog trace statement,” verilog and trace are keywords.
% In examples that show commands being entered, the % symbol indicates the
UNIX prompt.
• Design specifications
• Interface specifications
• Functional test plan
• Overall verification environment
For more detailed information on the CPU instructions, the CPU interface, and the CPU’s
internal registers, see Appendix B, “Design Specifications for the CPU”.
CPU
clock ALU
r1
r2 pc
r3 pcs
The state machine diagram for the CPU is shown in Figure 2-2 on page 2-2. The second
fetch cycle is only for immediate instructions.
Start
Fetch2
Execute
There is a 1-bit signal associated with each state, exec, fetch2, fetch1, start. If no reset
occurs, the fetch1 signal must be asserted exactly one cycle after entering the execute state.
• Register instructions — the second operand is another one of the four internal
registers.
byte 1
bit 7 6 5 4 3 2 1 0
• Immediate instructions — the second operand is an 8-bit value. When the opcode is
of type JMP, JMPC, or CALL, this operand must be a 4-bit memory location.
byte 1 2
bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
Test 1
Test Objective
Create a simple go-no-go test to confirm that the verification environment is working
properly.
Test Strategy
• Generate five instructions.
• Use either the ADD or ADDI opcode.
• Set op1 to REG0.
• Set op2 either to REG1 for a register instruction or to value 0x5 for an immediate
instruction.
Test 2
Test Objective
Create multiple random tests to gain high percentage coverage on commonly executed
instructions.
Test Strategy
• Use constraints to drive random testing towards the more common arithmetic and logic
operations rather than the control flow operations.
• Create 15 sets of tests
Test 3
Test Objective
Generate a corner case test scenario that exercises JMPC opcode when carry bit is asserted.
Note that it is difficult to efficiently cover this scenario by purely random or purely directed
tests.
Test Strategy
• Generate many arithmetic opcodes to increase the chances of carry bit assertion.
• Monitor the DUT and use on-the-fly generation to generate many JMPC opcodes when
the carry signal is high.
• Constrain the Specman Elite test generator to create valid CPU instructions
• Compare the program counter in the CPU to those in a reference model
• Define temporal rules to check the DUT behavior
• Define coverage points for state machine transitions and instructions
Constraints
Reference Model
Test Generator
struct cpu {
ins: list of instructions;
simulate(cpu:cpu_state) is {
case opcode { Temporal
[ADD, SUB,…]: Rules
{cpu.jump(cpu.pc +
1);};
.......
Instructions Checker
Design Under Test
Pass
CPU
Fail
Coverage
Because the focus of this tutorial is the Specman Elite system, we do not include an HDL
simulator. Rather than instantiating an HDL DUT, we model the DUT in e and simulate it
in Specman Elite. The process you use to drive and sample the DUT in e is exactly the
same as a DUT in HDL.
Now you are ready to create the first piece of the verification environment, the CPU
instruction stream.
As you work through this chapter, you gain experience with one of the Specman Elite
system’s enabling features — easy specification capture. With just a few constructs from
the e language you can define legal CPU instructions exactly as they are described in the
interface specifications.
This chapter introduces the e constructs shown in Table 3-1 on page 3-2.
extend Adds the data structure for the CPU instructions to the Specman Elite system
of data structures.
list of Creates an array or list without having to keep track of pointers or allocate
memory.
For a complete description of the legal CPU instructions, refer to Appendix B, “Design
Specifications for the CPU”.
Procedure
Follow this procedure to capture the design specifications in e:
The first part of the file has a summary of the design specifications for the CPU
instructions.
Register Instruction:
bit | 7 6 5 4 | 3 2 | 1 0 |
| opcode | op1 | op2 |
(reg)
Immediate Instruction:
byte | 1 | 2 |
bit | 7 6 5 4 | 3 2 | 1 0 | 7 6 5 4 3 2 1 0 |
| opcode | op1 | don’t | op2 |
| care |
4. Find the portion of the file that starts with the <' e code delineator and review the
constructs:
<'
defines the legal type cpu_opcode: [ // Opcodes
opcodes as an ADD, ADDI, SUB, SUBI,
enumerated type AND, ANDI, XOR, XORI,
JMP, JMPC, CALL, RET,
NOP
] (bits: 4);
};
when complete,
this construct extend sys {
adds the CPU // creates a stream of instructions
instruction set to
the Specman Elite };
system '>
5. Define two fields in the instr structure, one to hold the opcode and one to hold the first
operand.
Use the enumerated types, cpu_opcode and reg, to define the types of these fields. To
indicate that Specman Elite must drive the values generated for these fields into the
DUT, place a % character in front of the field name. You will see how this % character
facilitates packing automation in Chapter 5, “Driving and Sampling the DUT”. The
structure definition should now look like this:
struct instr {
add these two %opcode :cpu_opcode;
lines into the file %op1 :reg;
The second operand is either a 2-bit register or an 8-bit memory location, depending
on the kind of instruction, so you need to define a single field (kind) that specifies the
two kinds of instructions. Because the generated values for kind are not driven into the
design, do not put a % in front of the field name.
struct instr {
%opcode :cpu_opcode;
add this line to %op1 :reg;
define the field kind :[imm, reg];
‘kind’ and define
an enumerated // defines 2nd op of reg instruction
type at the .
same time .
.
};
7. Define the conditions under which the second operand is a register and those under
which it is a byte of data.
struct instr {
%opcode :cpu_opcode;
%op1 :reg;
kind :[imm, reg];
8. Constrain the opcodes for immediate instructions and register instructions to the
proper values.
Whenever the opcode is one of the register opcodes, then the kind field must be reg.
Whenever the opcode is one of the immediate opcodes, then the kind field must be
imm. You can use the keep construct with the implication operator => to easily create
these complex constraints.
struct instr {
.
.
.
// defines legal opcodes for reg instr
keep opcode in [ADD, SUB, AND, XOR, RET, NOP]
=> kind == reg;
};
9. Constrain the second operand to a valid memory location (less than 16) when the
instruction is immediate.
You can use the when construct together with keep and => to create this constraint.
struct instr {
.
.
.
// ensures 4-bit addressing scheme
when imm instr {
keep opcode in [JMP, JMPC, CALL] => op2 < 16;
};
};
1. Find the lines of code that extend the Specman Elite system:
extend sys {
// creates a stream of instructions
};
When defining a field that is an array or a list, you must precede the field type with the
keyword list of.
extend sys {
// creates a stream of instructions
!instrs: list of instr;
};
The exclamation point preceding the field name instrs tells Specman Elite to create an
empty data structure to hold the instructions. Then, each test tells Specman Elite when
to generate values for the list, either before simulation (pre-run generation) or during
simulation (on-the-fly generation). In this tutorial you use both types of generation.
Now you have created the core definition of the CPU instructions. You are ready to
extend this definition to create the first test.
As you work through this chapter to create the first test, you gain experience with the
following enabling features of the Specman Elite system:
• Constraint solver — the core technology that intelligently resolves all specification
constraints and test constraints and then generates the desired test.
This chapter shows new uses of the e constructs introduced in Chapter 3, “Creating the
CPU Instruction Structure”. It also introduces the Specman Elite commands shown in
Table 4-1 on page 4-2.
keep Limits the possible values of the instruction fields and the number of
instructions generated for this test.
Objects->Modules Lists the e modules you have loaded into Specman Elite.
The steps required to generate the first test for the CPU model are:
Test Objectives
The objective is to confirm that the verification environment is working properly.
Test Specifications
To meet the test objectives, the test should
Procedure
Follow this procedure to capture the test constraints in e:
<'
import CPU_top;
extend instr {
// test constraints
};
extend sys {
// generate 5 instructions
};
.
.
.
4. Add lines below the comments to constrain the opcode, operands, and number of
instructions:
<'
extend instr {
//test constraints
constrains the keep opcode in [ADD, ADDI];
opcode and keep op1 == REG0;
operands when reg instr { keep op2 == REG1; };
when imm instr { keep op2 == 0x5; };
};
extend sys {
constrains the //generate 5 instructions
number of keep instrs.size() == 5;
instructions };
• CPU_tst1.e — imports (includes) CPU_top.e and contains the test constraints for the
first test.
The working directory should now contain four files, CPU_instr.e, CPU_misc.e,
CPU_top.e, and CPU_tst1.e
3. From the working directory, type in the following command at the UNIX prompt to
invoke Specman Elite’s graphical user interface, Specview™:
% specview &
✓ If the Main Specman window does not appear, make sure that you have defined the
Specman Elite environment variables correctly. You can source the
<install_dir>/<release_number>/env.csh file to set these variables.
5. When the Select a File window appears, double-click on the CPU_tst1.e file name in
the list of files.
load /tutorial/CPU_tst1.e…
Load complete
✓ If the CPU_tst1.e file name does not appear in the dialog box, you probably did not
invoke Specview from the working directory. Use the list of directories in the dialog
box to navigate to the working directory and select the correct file.
✓ If the CPU_tst1.e file does not load completely because of a syntax error, use the
UNIX diff utility to compare your version of CPU_tst1.e to tutorial/gold/CPU_tst1.e.
Fix the error and click the Reload button. Alternatively, you can click on the blue
hypertext link in the Main Specman window, and the error location will be displayed
in the Debugger window.
6. To see a list of loaded modules, select Objects->Modules or click the Modules button.
CPU_instr
CPU_misc
CPU_top
CPU_tst1
1. In the Main Specman window, select Test->Test or click the Test button.
The print sys.instrs window appears, showing the generated list of five instructions.
✓ If the results you see are significantly different from the results shown here, use the
UNIX diff utility to compare your version of the e files to the files in tutorial/gold/.
2. Review the list to confirm that the instructions follow both the general constraints for
CPU instructions and the constraints for this particular test.
Based on the definition, specification constraints, and test constraints that you have
provided, the Specman Elite generator quickly generated the desired instruction stream.
Now you are ready to drive this instruction stream into the DUT and run simulation.
In a typical verification environment, where the DUT is modeled in an HDL, you need to
link the Specman Elite system with an HDL simulator before running simulation. In order
to streamline this tutorial, however, we have modeled the DUT in e.
As you work through this chapter, you gain experience with these features of the Specman
Elite verification system:
• DUT signal access — you can easily access signals and variables in the DUT, either
for driving and sampling test data or for synchronizing TCMs.
• Simulator interface automation — you can drive and sample a DUT without having
to write PLI (Verilog simulators) or FLI/CLI (VHDL simulators) code. The Specman
Elite system automatically creates the necessary PLI/FLI calls for you.
• Time consuming methods (TCMs) — you can write procedures in e that are
synchronized to other TCMs or to an HDL clock. You can use these procedures to drive
and sample test data.
This chapter introduces the e constructs shown in Table 5-1 on page 5-2.
event Creates a temporal object, in this case a clock, that is used to synchronize
the TCMs.
method () is… Creates a procedure (method) that is a member of a struct and manipulates
the fields of that struct. Methods can execute in a single point of time, or
they can be time consuming methods (TCMs).
pack () Converts data from higher level e structs and fields into the bit or byte
representation expected by the DUT.
These are the steps for driving and sampling the DUT:
Drive instructions protocol has one TCM for pre-run generation, where the complete list
of instructions is generated and then simulation starts. There is another TCM for on-the-fly
generation, where signals in the DUT are sampled before the instruction is generated. The
test in this chapter uses the simple methodology of pre-run generation, while subsequent
tests in this tutorial use the significantly more powerful on-the-fly generation.
All the TCMs required to drive the CPU are described briefly in Table 5-2 on page 5-3. A
complete description of one of the TCMs follows the table. You can also view the
CPU_drive.e file in the tutorial/src directory, if you would like to see the complete
description of the other TCMs in e.
Name Function
drive_cpu() Calls reset_cpu () and then, depending on whether the list of CPU
instructions is empty or not, calls gen_and_drive_instrs () or
drive_pregen_instrs ().
reset_cpu() Drives the rst signal in the DUT to low for one cycle, to high for five
cycles, and then to low.
Figure 5-1 on page 5-4 shows the e code for the drive_one_instr () TCM. The CPU
architecture requires that the tests drive and sample the DUT on the falling edge of the
clock, so all TCMs are synchronized to cpuclk which is defined as follows:
extend sys {
event cpuclk is (fall('top.clk')@tick_end);
};
emit instr.start_drv_DUT;
The assignment statements in Figure 5-1 on page 5-4 show how to drive and sample
signals in an HDL model. Each pair of single quotation marks identifies an object as an
HDL signal.
The start_drv_DUT event emitted by drive_one_instr is not used by any of the TCMs that
drive the CPU. You will use it in a later chapter to trigger functional coverage analysis.
The last line shown in Figure 5-1 on page 5-4 executes the reference model and is
commented out at the moment. You will use it in a later chapter to trigger data checking.
The pack() function is a Specman Elite built-in function that facilitates the conversion
from higher level data structure to the bit stream required by the DUT. The % character
you used in Chapter 3, “Creating the CPU Instruction Structure”, denotes the fields that
should be driven into the DUT. The pack() function intelligently and automatically
performs the conversion, as shown in Figure 5-2 on page 5-5.
opcode == ADD 0 0 0 0
op1 == REG0 0 0
op2 == REG1 0 1
The instruction packed into a bit stream, using the packing.high ordering
0 0 0 0 0 0 0 1
list of bit [7] list of bit [0]
The difference is that this time you are including the DUT (contained in CPU_dut.e) and
TCMs that drive it (contained in CPU_drive.e).
Procedure
1. Copy the tutorial/src/CPU_drive.e to the working directory.
5. Remove the comment characters in front of the import line so the lines look like this:
you need to check whether the working directory contains the following files:
CPU_instr.e CPU_drive.e
CPU_misc.e CPU_top.e
CPU_dut.e CPU_tst1.e
Add the missing file and then click the Reload button.
8. Click the Modules button to confirm that six modules are loaded:
CPU_instr CPU_drive
CPU_misc CPU_top
CPU_dut CPU_tst1
✓ If some of the modules are missing, first check whether you are loading the
CPU_top.e file that you just modified. The modified CPU_top.e file must be in the
working directory.
Once the modified CPU_top.e file is in the working directory, click the Restore button.
This action should remove all the currently loaded modules from the session. Then
click the Load button and select CPU_tst1.e in the Select A File dialog box.
You should see the following messages (or something similar) in the Main Specman
window.
Doing setup…
Generating the test using seed 0x1…
Starting the test…
Running the test…
DUT executing instr 0 : ADD REG0x0, REG0x1
DUT executing instr 1 : ADDI REG0x0, @0x05
DUT executing instr 2 : ADD REG0x0, REG0x1
DUT executing instr 3 : ADD REG0x0, REG0x1
DUT executing instr 4 : ADDI REG0x0, @0x05
Last specman tick - stop_run() was called
Normal stop - stop_run() is completed
Checking the test…
Checking is complete - 0 DUT errors, 0 DUT warnings.
Wrote 1 cover_struct to CPU_tst1_1.ecov
You can see from the output that five instructions were executed and no errors were found.
It looks like the verification environment is working properly, so you are ready to generate
a large number of tests.
As you work through this chapter, you gain experience with two of the Specman Elite
verification system’s enabling features:
• Constraint-driven random test generation — this feature lets you focus random test
generation on the areas of the design that need to be exercised the most.
• Random seed generation — by changing the seed used for random generation, you
can quickly cause the Specman Elite system to generate a whole new set of tests.
This chapter introduces the e constructs and Specview commands shown in Table 6-1 on
page 6-2.
select Used with keep soft to control the distribution of the generated values.
Specview Commands
Config->Generation Used to create a user-defined seed for random test generation.
File->Save Saves the current test environment, including the random seed, to a .esv
file. You can load this file with the File->Restore command.
Procedure
Follow this procedure to see how to create weighted constraints in e:
3. Find the portion of the file that looks like this and review the keep soft constraint:
<'
puts equal weight extend instr {
on arithmetic and keep soft opcode == select {
logical operations 30 : [ADD, ADDI, SUB, SUBI];
and less weight 30 : [AND, ANDI, XOR, XORI];
10 : [JMP, JMPC, CALL, RET, NOP];
on control flow };
operations };
'>
Procedure
This procedure shows how to create a random seed:
1. Click on the Restore button in the Main Specman window to remove all the e modules
from the current session.
3. Click on the Modules button and confirm that the following modules are loaded:
CPU_instr CPU_drive
CPU_misc CPU_top
CPU_dut CPU_tst2
5. In the Seed field of the Specman Elite Configuration Options window, enter your lucky
number.
You should see an equal distribution of arithmetic and logic operations and fewer
control flow operations.
Procedure
This procedure generates tests using a Specman Elite-generated seed:
You should see an equal distribution of arithmetic and logic operations and fewer
control flow operations. The results should be different from the previous run.
4. Optionally you could repeat steps 1-3 several times to confirm that you see different
results each time.
✓ If you see similar results in subsequent runs, it is likely that you forgot to reload the
design before running the test. If you do not reload the design, the test is run with the
current seed.
You can see that using different random seeds lets you easily generate many tests. Quickly
analyzing the results of all these tests would be difficult without Specman Elite’s coverage
analysis technology. The next two chapters show how to use coverage analysis to
accurately measure the progress of your verification effort.
As you work through this chapter, you gain experience with another one of the Specman
Elite verification system’s enabling features — the Functional Coverage Analyzer. The
Specman Elite coverage analysis feature lets you define exactly what functionality of the
device you want to monitor and report. With coverage analysis, you can see whether
generated tests meet the goals set in the functional test plan and whether these tests
continue to be sufficient as the design develops, the design specifications change, and bug
fixes are implemented.
This chapter introduces the e constructs shown in Table 7-1 on page 7-2.
transition Identifies an object whose current and previous values are to be collected
when the sampling point occurs.
Procedure
Follow this procedure to define coverage points for the FSM:
3. Find the portion of the file that looks like the excerpt below and review the event
declaration that defines the sampling point for the FSM:
extend cpu_env {
4. Add the cover group and cover items for state machine coverage.
The cover group name (cpu_fsm) must be the same as the event name defined in step 3
above. The item statement declares the name of the coverage item (fsm), its data type
(FSM_type), and the object in the DUT to be sampled. The transition statement says
that the current and previous values of fsm must be collected. In summary this means
that whenever the sys.cpuclk signal changes, Specman Elite collects the current and
previous values of top.cpu.curr_FSM.
extend cpu_env {
event cpu_fsm is @sys.cpuclk;
• opcode
• op1
This coverage group uses as a sampling point an event declared and triggered in the
CPU_drive.e file
drive_one_instr(instr: instr) @sys.cpuclk is {
.
.
.
emit instr.start_drv_DUT;
.
.
.
Thus data collection for the instruction stream occurs each time an instruction is driven
into the DUT.
Procedure
Follow this procedure to extend the instr struct to define these coverage points:
1. Find the portion of the CPU_cover.e file that looks like the excerpt below and review
the cover group declaration.
extend instr {
};
extend instr {
cover start_drv_DUT is {
item opcode;
item op1;
};
};
extend instr {
cover start_drv_DUT is {
item opcode;
item op1;
item carry: bit = 'top.carry';
};
};
Cross coverage lets you define the intersections of two or more coverage items,
generating a more informative report.
extend instr {
cover start_drv_DUT is {
item opcode;
item op1;
item carry: bit = sys.cpu_dut.carry;
cross opcode, carry;
};
};
Now that you’ve defined the coverage groups, you are ready to simulate and view the
coverage reports.
As you work through this chapter, you gain experience with these Specman Elite features:
• Cross Coverage — lets you view the intersections of two or more cover items.
• Apropos — helps you find the information you need in the Specman Elite Online
Documentation.
This chapter introduces the Specview commands shown in Table 8-1 on page 8-2.
Specview Commands
Tools -> Coverage Displays coverage reports and creates cross-coverage reports.
Help Invokes the Specman Elite Online Documentation browser.
The steps required to analyze test coverage for the CPU design are:
Procedure
1. Open the working directory’s copy of the CPU_top.e file in an editor.
// Add Coverage:
//import CPU_cover;
3. Remove the comment characters in front of the import line so the lines look like this:
// Add Coverage:
import CPU_cover;
6. Click the Modules button to confirm that seven modules are loaded:
CPU_instr
CPU_misc
CPU_dut
CPU_drive
CPU_cover
CPU_top
CPU_tst2
You should see something similar to the following messages in the Main Specman
window. The last line indicates that the coverage data was written to an .ecov file.
test
Doing setup…
Generating the test using seed 0x1
Starting the test…
Running the test…
DUT executing instr 0 : RET REG0x3, REG0x0
DUT executing instr 1 : JMPC REG0x3, @0x02
DUT executing instr 2 : ADD REG0x3, REG0x2
DUT executing instr 3 : AND REG0x3, REG0x1
DUT executing instr 4 : JMPC REG0x3, @0x09
.
.
.
Last specman tick - stop_run() was called
Normal stop - stop_run() is completed
Checking the test…
Checking is complete - 0 DUT errors, 0 DUT warnings.
Wrote 1 cover_struct to CPU_tst2_1.ecov
If you are using a different seed or a version of the Specman Elite verification system other
than 3.2, you may see different results in your coverage reports.
Procedure
1. Click the Cover button in the Main Specman window.
3. In the Items field, select fsm and click the Display Item button.
The state machine register report appears in the Coverage Analysis window. From the
report it is easy to see that, for example, the fetch1 state was entered 88 times in the
227 times sampled.
4. In the Items field, select transition_fsm and click the Display Item button.
As you scroll down the display, perhaps the first thing you notice about the state
machine transition report is that there are a number of transitions that never occurred.
This is because these transitions are illegal.
5. To see how to define transitions as illegal so that they do not appear in the coverage
report, click the Help button in the Main Specman window.
6. Enter the words transition cover item syntax in the Search field and press Return.
The transition construct is a cover item, so this search will find the description of the
correct syntax for this construct.
7. When the list of files that describe cover item options appears, select the first item in
the list, eref: transition cover item syntax.
The tag eref indicates that this document is part of the e Language Reference Manual.
8. When the transition construct description appears, scroll down the page to the illegal
cover item option description.
9. Continue scrolling down to the Examples section, and you will find an example
showing the use of the illegal option:
cover state_change is {
item st;
transition st using illegal =
not ((prev_st == START and st == FETCH1)
or (prev_st == FETCH1 and st == FETCH2)
or (prev_st == FETCH1 and st == EXEC)
or (prev_st == FETCH2 and st == EXEC)
or (prev_st == EXEC and st == START));
};
If you like, you can follow this example to enhance the transition statement in
CPU_cover.e to ignore the illegal transitions.
Procedure
1. Copy tutorial/src/regression_3.2.ecov file to the working directory.
3. Click the Read… button in the Show Coverage dialog box and select the
regression_3.2.ecov file.
5. In the Items field, select opcode and click the Display Item button.
The opcode coverage report appears in the Coverage Analysis window. These results
show that the current set of tests fulfill the requirement in the functional test plan to
focus on arithmetic and logic operations rather than control flow operations.
6. In the Items field, select op1 and click the Display Item button.
The op1 coverage report appears in the Coverage Analysis window. All possible op1
values appear to be well covered.
7. In the Items field, select opcode and click the Add button under Cross Items.
8. In the Items field, select op1 and click the Add button under Cross Items.
9. Click the Display Cross button to display the intersection of opcode and op1.
This coverage report shows whether the tests have covered every possible combination
of opcode and register.
Procedure
1. Click the Cover button in the Main Specman window.
3. In the Items field, select cross__opcode__carry and click the Display Item button.
The cross coverage report for opcode and carry appears in the Coverage Analysis
window.
You can see that the JMPC code was issued 39 times, and that carry was low each time.
The ability to cross test input with the DUT’s internal state yields valuable
information — the tests created so far do not truly test the JMPC opcode. You could raise
the weight on JMPC and hope to achieve the goal. However, many simulation cycles
would be wasted to cover this corner case. The Specman Elite system lets you attack this
type of corner case scenario much more efficiently. In the next chapter you learn how to do
this.
This chapter introduces the e constructs shown in Table 9-1 on page 9-1.
Procedure
1. Copy the tutorial/src/CPU_tst3.e file to the working directory.
3. Find the portion of the file that contains the keep soft constraint:
extend instr {
keep soft opcode == select {
// high weights on arithmetic
};
};
4. Put a high weight on arithmetic operations and low weights on the others.
extend instr {
keep soft opcode == select {
// high weights on arithmetic
keeps high weight 40 : [ADD, ADDI, SUB, SUBI];
on arithmetic 20 : [AND, ANDI, XOR, XORI];
operations 10 : [JMP, CALL, RET, NOP];
This methodology enables you to reach the corner case from multiple paths, in other
words, from different opcodes issued prior to the JMPC opcode. This test shows how the
DUT behaves under various sequences of opcodes.
Procedure
1. Find the portion of the CPU_tst3.e file that looks like this:
extend instr {
keep soft opcode == select {
// high weights on arithmetic
40 : [ADD, ADDI, SUB, SUBI];
20 : [AND, ANDI, XOR, XORI];
10 : [JMP, CALL, RET, NOP];
2. On a separate line within the select block, enter a weight for the JMPC opcode,
together with the name of the carry signal.
extend instr {
keep soft opcode == select {
// high weights on arithmetic
40 : [ADD, ADDI, SUB, SUBI];
20 : [AND, ANDI, XOR, XORI];
10 : [JMP, CALL, RET, NOP];
You are now ready to run this test to create the corner case test scenario. Before running
this test, you want to address another important part of functional verification:
self-checking module creation. In the next chapter, you learn easy self-checking module
creation, another powerful feature provided by the Specman Elite system.
As you work through this chapter, you gain experience with two of the Specman Elite
verification system’s enabling features:
• Specman Elite temporal constructs — these powerful constructs let you easily
capture the DUT interface specifications, verify the protocols of the interfaces, and
efficiently debug them. The temporal constructs minimize the size of complex
self-checking modules and significantly reduce the time it takes to implement
self-checking.
This chapter introduces the e constructs shown in Table 10-1 on page 10-2.
check Checks that a Boolean expression is true and if not, reports an error.
Procedure
Follow this procedure to create the check:
event fetch1_assert is
(change('top.fetch1')and
true('top.fetch1' == 1)) @sys.cpuclk;
defines rise of
fetch1 //Interface Spec: After entering instruction
//execution state, fetch1 signal must be
//asserted in the following cycle.
4. Define a temporal check for the enter_exec_st event by creating an expect statement.
event fetch1_assert is
(change('top.fetch1')and
true('top.fetch1' == 1)) @sys.cpuclk;
Reference models are not required for data checking; you can use a rule-based
methodology instead. However, reference models are part of a typical strategy for
verifying CPU designs. The Specman Elite system supports reference models written in
Verilog, VHDL, C, or, as in this tutorial, e. All you need to do is create checks that
compare the program counter in the DUT to their counterparts in the reference model.
Procedure
This procedure has two parts:
Notice that there is an event, exec_done, and associated method, on_exec_done. The
Specman Elite system automatically creates an associated method for every event you
define. The method is empty until you extend it. The method executes every time the
event occurs.
// Data Checker
event definition event exec_done is (fall('top.exec') and
true('top.rst' == 0))@sys.cpuclk;
method on_exec_done() is {
// Compare PC - program counter
associated with };
event .
.
.
2. Add a check for the program counter by creating a check statement and removing the
comment characters in front of dut_error.
// Data Checker
event exec_done is (fall('top.exec') and
issues an error if true('top.rst' == 0))@sys.cpuclk;
there is a
mismatch in the on_exec_done() is {
program counters // Compare PC - program counter
of the DUT and check that sys.cpu_dut.pc ==
sys.cpu_refmodel.pc else
the reference
dut_error("DATA MISMATCH(pc)");
model };
2. At the top of the file find the line that imports the CPU reference model.
<'
imports the import CPU_refmodel;
reference model
extend sys {
event cpuclk is
(fall('top.clk')@tick_end);
cpu_env : cpu_env;
cpu_dut : cpu_dut;
// cpu_refmodel : cpu_refmodel;
};
'>
4. Find the line that extends the Specman Elite system by creating an instance of the CPU
reference model.
<'
import CPU_refmodel;
extend sys {
event cpuclk is
(fall('top.clk')@tick_end);
cpu_env : cpu_env;
creates an cpu_dut : cpu_dut;
instance of the cpu_refmodel : cpu_refmodel;
reference model };
'>
6. Find the line in the reset_cpu TCM that resets the reference model.
reset_cpu() @sys.cpuclk is {
'top.rst' = 0;
wait [1] * cycle;
'top.rst' = 1;
wait [5] * cycle;
sys.cpu_refmodel.reset();
resets the
'top.rst' = 0;
reference model };
8. Find the line that executes the reference model when the DUT is in the execute state.
The difference is that this time you are including the reference model and checks.
Procedure
1. Open the working directory’s copy of the CPU_top.e file in an editor.
// Add Checking:
//import CPU_checker;
3. Remove the comment characters in front of the import line so the lines look like this:
// Add Checking:
import CPU_checker;
7. Click the Restore button to remove any loaded modules from the current session.
Remember that this is the test that you wrote in Chapter 9, “Writing a Corner Case
Test”.
It looks like we hit a bug here. Specman Elite is reporting a protocol violation.
test
Doing setup ...
Generating the test using seed 0x7...
Starting the test ...
Running the test ...
DUT executing instr 0 : SUB REG0x0, REG0x2
DUT executing instr 1 : NOP REG0x2, REG0x3
DUT executing instr 2 : ADDI REG0x1, @0x9e
DUT executing instr 3 : SUBI REG0x1, @0x65
DUT executing instr 4 : SUB REG0x1, REG0x0
DUT executing instr 5 : ADD REG0x0, REG0x2
DUT executing instr 6 : SUB REG0x0, REG0x1
DUT executing instr 7 : SUBI REG0x3, @0xca
PROTOCOL ERROR
10. Click on the error hyperlink to view the line in the source that generated this message.
This message comes from the checker module that you just created.
In the next chapter, you learn how to identify the conditions under which this bug occurs
and how to bypass the bug until it can be fixed.
• The Specman Elite debugger — Powerful debugging features with visibility into the
HDL design.
• The Specman Elite bypass feature — You can temporarily prevent the Specman Elite
system from generating test data that reveals a bug in the design. This feature lets you
continue testing while the bug is being fixed.
This chapter introduces the Specview commands shown in Table 11-1 on page 11-2.
Specview Commands
Debug -> Thread Opens the Thread Browser, which displays all the TCMs
(threads) that are currently active.
Debug -> Show Thread Source… Opens the Debugger window, which displays the source
for the current thread with the current line highlighted.
Debugger: Run -> Step Advances simulation to the next line of e code.
2. Setting breakpoints.
4. Bypassing bugs.
Procedure
1. In the Main Specman window, select Debug->Threads.
The Thread Browser indicates the status of each TCM that is currently active in
Specman Elite:
• Clock generation
• Drive and Sample CPU
• DUT
To debug the error, look first at the TCM that drives the DUT.
2. On the line for [email protected]_cpu, select Src to bring up the corresponding source
file for this thread.
The Debugger window appears, showing CPU_drive.e. The highlighted line shows
that the drive_one_instr TCM is waiting for the top.exec signal to rise.
For
step 3
For
step 5
3. To find out the current instruction type, highlight the phrase instr.kind, located 9 lines
above the highlighted wait statement.
6. Optionally you could find out the value of any HDL signals. For example, to display
the value of top.data, highlight the phrase ‘top.data’ and click the print button.
Setting Breakpoints
You have determined that the bug appears on an immediate instruction when the opcode is
JMPC. It may be possible to narrow down even further the conditions under which the bug
occurs. You can set a breakpoint on the statement that drives the immediate instruction
data into the DUT to see what the operands of the instruction are.
Procedure
1. Highlight any portion of the line:
'top.data' = pack(packing.high, instr.imm'op2);
This line should now be underlined to indicate a breakpoint has been set.
3. To activate the breakpoint just before the error occurs (at system time 525), in the
Debugger window, select Breakpoint -> Show Breakpoints.
Edit
Box
for
step 4
4. In the edit box at the top of the window, modify the current breakpoint as follows:
break on line 53 @CPU_drive if (sys.time > 475)
Procedure
1. To run the simulation in debug mode, click the Reload button in the Main Specman
window.
4. In the Debugger window, select Run -> Step Anywhere to advance to the next source
line in any subsequent thread.
5. Repeat the Run -> Step Anywhere until the current thread is Thread #3 in the
CPU_DUT.e file, as indicated in the title bar at the top of the window.
6. In the Debugger window, continue to click the Step button to step through the
simulation.
After about 22 steps, you will hit the PROTOCOL error. The PROTOCOL error is
displayed in the Main Specman window and the Step button is greyed out.
For the purpose of simplifying this tutorial, we planted an obvious bug in the DUT.
Whenever a JMPC instruction jumps to a location greater than 10, execution requires
two extra cycles to complete.
Specman Elite’s extensibility feature, however, lets you temporarily prevent Specman Elite
from generating the conditions that cause the bug to be revealed.
This particular bug seems to surface when the JMPC operation is performed using a
memory location greater than 10. In order to continue testing other scenarios, you simply
extend the test constraints to prevent Specman Elite from generating this combination.
Procedure
Here is the procedure for bypassing the JMPC bug.
<'
extend instr {
};
'>
4. In the Main Specman window, select Debug->Delete All Breakpoints to exit debug
mode.
Tutorial Summary
Congratulations! You have successfully completed the major steps required to verify a
design with the Specman Elite verification system. Here’s a review of what you have
accomplished in this tutorial:
• You captured the interface specifications for the CPU instructions in e and created the
instruction stream.
• You used specification constraints to ensure that only legal instructions were generated.
You used test constraints to create a simple go-no-go test.
• You created a Specman Elite TCM (time consuming method) to define the driver
protocol and then drove the generated CPU instruction stream into the DUT. The results
confirmed that you had generated the first test and driven it correctly into the design.
• Using Specman Elite’s unique Functional Coverage Analyzer, you accurately measured
the effectiveness of the coverage of the regression tests. You identified a corner case
“hole” by viewing the graphical coverage reports.
• To address the corner case scenario, you used Specman Elite’s powerful on-the-fly
generation capability to generate a test based on the internal state of the design during
simulation. Compared to the traditional deterministic test approach, this approach tests
the corner case much more effectively from multiple paths.
• Then you used the unique temporal constructs provided by Specman Elite to create a
self-checking monitor that verifies protocol conformance.
• When the self-checking monitor revealed a bug, the GUI debugger provided extensive
features to debug the design efficiently.
Note that you have created this verification environment, including self-checking modules
and functional coverage analysis, in a short period of time. Once the environment is
established, creating a large number of effective tests is merely one click away! The
ultimate result of using Specman Elite is a drastic reduction in verification time and
resources.
1. Change directory to the directory where you want to store the downloaded files.
where <OS> is one of the platforms that Specman Elite supports, either solaris or hpux.
1. Log in to the machine where you want to install the Specman Elite software.
% rlogin solaris/hpux-machine
3. When the Specman Elite Install Script Menu appears, select option 1, “Complete
installation”.
After you have installed the machine-independent files (including the online docs) and
the machine-dependent files, the script will ask you to select a license installation step.
4. Choose option 1, “Install license server” from the “License handling” menu.
The script creates a new license file based on the license file you obtained via e-mail,
activates the license server, updates the SPECMAN_LICENSE_FILE environment
variable, and optionally creates the “rc.specman” file.
5. Exit the installation script after the license handling procedure is completed.
6. Source the Specman Elite environment file (env.csh or env.sh), for example:
% source <install_dir>/<release_number>/env.csh
7. Make sure the Specman Elite object in your PATH is the one you have just installed.
% which specman
<install_dir>/<OS>/specman
%
✓ If you have difficulty starting Specview or obtaining a license, call Verisity customer
support at (650) 934-6890.
1. Change directory to the directory where you want to install the tutorial files.
% cd <tutor_dir>
%
gold:
CPU_bypass.e CPU_instr.e CPU_tst2.e
CPU_checker.e CPU_misc.e CPU_tst3.e
CPU_cover.e CPU_refmodel.e regression_3.2.ecov
CPU_drive.e CPU_top.e
CPU_dut.e CPU_tst1.e
src:
CPU_bypass.e CPU_instr.e CPU_tst2.e
CPU_checker.e CPU_misc.e CPU_tst3.e
CPU_cover.e CPU_refmodel.e regression_3.2.ecov
CPU_drive.e CPU_top.e
CPU_dut.e CPU_tst1.e
%
You can see that there are two sets of files. As you work through this tutorial, you will
be modifying the files in the src directory. If you have trouble making the modifications
correctly, you can view or use the files in the gold directory. The files in the gold
directory are complete and correct.
Now that the files are installed, you are ready to proceed with the design verification task
flow shown in Figure 1-2 on page 1-3. To start the first step in that flow, turn to Chapter 2,
“Understanding the Environment”. In this chapter, you review the design specifications
and functional test plan for the CPU design and define the overall verification environment.
• CPU instructions
• CPU interface
• CPU register list
CPU Instructions
The instructions are from three main categories:
• Register instructions — the second operand is another one of the four internal registers
• Immediate instructions — the second operand is an 8-bit value contained in the next
instruction. When the opcode is of type JMP, JMPC, or CALL, this operand must be a
4-bit memory location.
byte 1
bit 7 6 5 4 3 2 1 0
byte 1 2
bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
Table B-1 on page B-2 shows a summary description of the CPU instructions.
CPU Interface
The CPU has three inputs and no outputs, as shown in Table B-2 on page B-3.
When the CPU is reset by the rst, rst must return to its inactive value no sooner than
min_reset_duration and no later than max_reset_duration.
register 0 8 bits r0
register 1 8 bits r1
register 2 8 bits r2
register 3 8 bits r3