Verification and Fault Localization in VHDL

1 downloads 0 Views 81KB Size Report
identified through verification, the location of the error in the source code is of interest ... process of finding, locating, and fixing a bug. Fixing the problem requires.
Verification and Fault Localization in VHDL Programs Roderick Bloem and Franz Wotawa Graz University of Technology Institute for Software Technology 8010 Graz, Inffeldgasse 16b/2, Austria {bloem, wotawa}@ist.tugraz.at

Introduction During the last decades, hardware-design languages like Verilog and VHDL have become very common for designing digital circuits. These languages allow designers to specify and test the behavior of circuits before they are produced. This helps to avoid incorrect designs and saves money, providing that the designs are rigorously tested. If faulty behavior is identified through verification, the location of the error in the source code is of interest. Finding this root cause of the misbehavior is not always as easy as expected. The source code is usually huge. Furthermore, it is often written by one team of hardware designers and tested by another team. Because hardware designs are becoming ever more complex, verification is becoming a bottleneck in the design flow. Hence, verification and fault localization are both important issues for hardware designers and their companies. Both are imperative for ensuring quality of the hardware designs, reducing time to market, and avoiding costly re-designs. As a consequence, they reduce the overall design costs. In this paper we give an overview of how modern verification techniques and diagnosis techniques can be combined to detect and locate faults in programs that are written in VHDL. In the first part of the paper we shall show how faults can be detected. We use a temporal logic to specify the expected behavior. Based on the specification we will see how formal methods, in particular model checking, can be used to detect the fault. In case an error is detected, a counter example is returned by the model checker. In the second part of the paper we discuss how this counter example and model-based diagnosis can be used to locate the fault in the source code. By locating we mean finding the causes of the misbehavior. In particular we are interested in the root cause, i.e., a statement in the program that when changed will correct the problem. Both parts of the paper require the use of logic and artificial intelligence methods. Transition Diagram

model-checking

compile

Properties

VHDL Program Counter-Example (Expected Values)

Logical Representation compile

(Model) -AB(C)

out(C)=’0’

out(C)=’1’ model-based diagnosis

correspond

Diagnoses (Possible Bug Locations)

AB(C)

Figure 1. The basic principle of detecting and locating a fault

Fault detection and correction are both parts of the debugging process. Thus, debugging can be seen as the process of finding, locating, and fixing a bug. Fixing the problem requires changing the program which is

usually a very difficult task. In theory the number of possible corrections is infinite. However, usually only a few possibilities are practicable, and these are very difficult to find. Fault correction is not addressed in this paper. Instead we introduce the basic ideas of combining model-checking techniques and model-based diagnosis to detect and locate faults in VHDL programs. Figure 1 shows this idea. Starting from a VHDL program that is automatically compiled to a transition diagram and a logical representation we apply modelchecking to prove the given properties. If the properties are correct, everything is fine and we do not need to fix a bug. If the properties are violated, however, there is a bug in the VHDL program which can be located by the model-based diagnosis engine. This engine takes the model and the counter examples and computes possible fault locations that are entailed by the given information.

Fault detection Symbolic model checking [2] automatically verifies whether a design satisfies a given specification. The more traditional method of testing requires a test bench, that is, predefined sequences of inputs and the associated intended outputs. Instead, specifications are stated formally as assertions on the system. Adherence of the design to the specifications is checked for all possible input combinations, ensuring full coverage of the design. If a program is not correct with respect to its specification, a counter example is provided. Model checking is particularly useful for bug that are difficult to find because they occur in unusual situations that may be neglected when test benches are constructed. In practice, the given specifications are in usually partial, i.e., only important properties are specified. We demonstrate the use of symbolic model checking on the VHDL program COUNTER(BEHAV) shown in Figure 2, which specifies the behavior of a digital 2 bit counter. The counter decrements its value if E1 is set to 1 and E2 is set to 0; if both inputs are set to 0 the counter is incremented. If E1 = 0 and E2 = 1 the counter is reset to 0, and finally, if both inputs are 1 the counter is set to the value 3. The output of the counter is coded with a 1-from-4 encoder, so that, e.g., the value 0 is represented by A1A2A3A4 = 1000.

---------------------------------------------- 2 Bit Counter with 1 from 4 coded output --- Behavior (CLK^ = CLK raises from 0 to 1): --- E1=0, E2=0 | Increment CLK^ -- E1=1, E2=0 | Decrement CLK^ -- E1=0, E2=1 | 0 CLK^ (RESET) -- E1=1, E2=1 | 3 CLK^ ---------------------------------------------entity COUNTER is port( E1,E2,CLK: in BIT; A1,A2,A3,A4: out BIT); end COUNTER; architecture BEHAV of COUNTER is signal D1,D2,Q1,Q2,NQ1,NQ2: BIT := '0'; begin -- Input combinatorial block comb_in: process (Q1,Q2,E1,E2) variable I1,I2: BIT; begin I1 := not((Q1 and Q2) or (not(Q1) and not(Q2))); I2 := (I1 and E1) or (not(I1) and not(E1)); D1