Figure 4.10: General Body Code The HW-HUME boxes that use fair matching will have a different main body than the boxes using unfair matching. However, the translation of each match is similar. Section B.6.3 describes the creation of the main body of a process.
Fair Matching Fair matching is denoted by Fair . In HW-HUME fair matching is specified by the fair keyword. In PROMELA the fair matching is achieved with an if clause. Each match is an option in the if clause, specified with a double colon ‘::’ prefix. The first statement in a match is called the guard condition. If it succeeds the rest of the statement in that option is executed. The guard condition in the PROMELA for HW-HUME implementation is to check if the receive operation succeeds on the input channels. The guard conditions do not have to be mutually exclusive. If several of the options succeed, one of them is randomly selected, giving the if clause a non-deterministic and fair nature.
Figure 4.11: Fair Matching
In PROMELA the process will be blocked if none of the guard conditions succeed when the input is matched. In HW-HUME the only thing that happens is that no output is generated and the next box starts executing. To translate this behaviour into the PROMELA model, an else statement is appended after the last match. The code that follows will execute if all other guard conditions fail. In the else option the process control is redirected to the ‘finish’ label using the goto statement. The ‘finish’ label is placed right after the point the if clause ends. This approach is illustrated with two matches in figure 4.11. Unfair Matching Unfair matching is denoted by
Unfair
and is more cumbersome to translate than fair matching.
Unfair matching is identified by the match keyword in the box body, and is performed in a top to bottom order, giving it a deterministic nature. This cannot be represented directly in PROMELA hence it must be manually implemented. The solution is to use a set of if-else statements, as figure 4.12 shows.
Figure 4.12: Unfair Matching
The first match has a different semantics since it does not start with an else statement. The fact that an if statement has to be ended with a fi statement complicates the translation further. The reason for this is that for each match, the code for all the following matches must be translated before the match can be ended with the fi statement. The figure shows this with the first if statement being ended with the fi statement, after all the code for the second match. As for Fair , the last if statement is ended with an else statement that redirects process control to the ‘finish’ label using the goto statement. This will happen if none of the options match the input.
4.6.4 Matches The translation of one match is denoted by Match . Match uses matches and Exp to translate the expression that generates output.
Patt
for translating pattern
The ‘show’ box in figure 4.7 uses unfair matching. However, in this special case it does not really matter since the box only contains one match. In the PROMELA representation a pattern is matched by checking the input channels. The inputs are then received and omitted from the input channels, followed by sending the outputs to the output channels. The ‘show’ box contains two input variables and one output variable. Therefore in the PROMELA process prelude, two input channels ‘in1’ and ‘in2’ and one output channel ‘out1’ were created. These channels are used.
Figure 4.13: Creating Channels for Matching
The output of the box is a tuple. This is not reflected in the match obtained from the body element, as figure 4.7 shows. This complicates the translation, since the box prelude must be used during the translation of each match, as the prelude keeps track of the type of the variable, i.e. whether or not the type is a tuple. If it is a tuple, all the values are sent over the same channel. If it is not a tuple they are sent on different channels. Figure 4.13 shows the prelude for the ‘show’ box and illustrates how this is created in PROMELA. The translation of the values is ignored in the figure. In the match in figure 4.13, the channels are first checked to test if the operation succeeds. The testing is achieved by enclosing the right hand side of the receive operator ‘?’ in brackets ‘[ ]’. This test is the guard condition. An arrow ‘→’ separates it from the rest of the body. If the guard condition succeeds the values are read and omitted from the channel, and the output is sent to the output channel. The channel references are created based on the variables in the box prelude. The input channels only hold base values, which makes the translation operation straightforward. The tuple in the output is more cumbersome to translate. Figure 4.14 illustrates the translation of it.
Figure 4.14: Creating Values in Matches
In the PROMELA code on the right hand side of the thick dashed line, each element in the expression is separated by a comma. During the translation the output element in the box prelude is traversed. For each variable in the output element, the corresponding element in the match is obtained, and translated using Values . If the element is a tuple, as the case in figure 4.14, each element in the tuple is translated separately. Each of the element is then appended to the right hand side of the send operator ‘!’ of the output channel, separated by a comma. The variables ‘s’ and ‘c’ use the same name in PROMELA as in HW-HUME. The newline escape sequence character however, is translated into the numeric value ‘-1’, as defined in Values . Figure 4.15 shows the ‘show’ process. It is the PROMELA representation of the ‘show’ box listed in figure 4.7.
1 2 3 4 5 6 7 8 9 10 11 12 13
p r o c t y p e show1 ( chan i n 1 , i n 2 , o u t 1 , control ) { bit s ; bit c ; start : c o n t r o l ?BEGIN ; if : : ( i n 1 ? [ s ] && i n 2 ? [ c ] ) − > i n 1 ? s ; i n 2 ? c ; o u t 1 ! s , c , − 1 ; : : e l s e goto f i n i s h fi ; finish : c o n t r o l !END; goto s t a r t ; }
Figure 4.15: The ‘show1’ Process
4.7 The Control Process The creation of the control process is denoted by Control . The control process is used to coerce the execution model in HW-HUME into the PROMELA model. Each run in a process will then execute in a sequential order, starting with the process that was first declared. The stream processes also follow this execution model. Since a HW-HUME box was used as an example when illustrating the creation of a channel, the ‘output’ stream is used in figure 4.16.
As shown in the figure the name of the process followed by ‘ control’ identifies the channel. For processes generated from HW-HUME boxes, the box name is also used. Names ensures that the name is valid PROMELA.
Figure 4.16: Creating the Control Process
First a ‘BEGIN’ message is sent to the channel, and then the control process is blocked until an ‘END’ message is returned. It is blocked because the channel is synchronous. Since the other processes must receive a ‘BEGIN’ message before they can execute, the process that last received a ‘BEGIN’ message is the only runnable process. The control process for the half adder example is shown in figure 4.17.
1 2 3 4 5 6 7 8 9 10
Control
is defined in section B.7.
a c t i v e proctype C o n t r o l ( ) { do : : g e n c o n t r o l ! BEGIN ; g e n c o n t r o l ?END; f a n o u t c o n t r o l ! BEGIN ; f a n o u t c o n t r o l ?END; x o r c o n t r o l ! BEGIN ; x o r c o n t r o l ?END; a n d c o n t r o l ! BEGIN ; a n d c o n t r o l ?END; s h o w 1 c o n t r o l ! BEGIN ; s h o w 1 c o n t r o l ?END; o u t p u t c o n t r o l ! BEGIN ; o u t p u t c o n t r o l ?END; od ; }
Figure 4.17: The Control Process
4.8 Stream Processes HW-HUME supports both input streams and output streams. In both cases the stream declaration, the wire declaration that wires the stream to a box, and the box declaration that uses the stream, are required to create the PROMELA process. declarations.
Stream
Stream is used to obtain the elements required from these
is also used when generating the channels for interprocess communication
for input streams. This is defined in section B.8.
4.8.1 Input Streams The half adder model does not include any input stream. To explain input streams a few modification have been applied to the model in figure 2.5. An input stream has been introduced and the input for the ‘gen’ box is obtained from that stream. The source of the stream is the standard input.
The output that ‘gen’ wires to itself in figure 2.5 has also been removed. Figure 4.18 illustrates the modification applied to the model in figure 2.5. These declarations are found using Stream .
Stream also extracts the elements required from each of the declarations. 1 2 3 4 5 6 7 8 9 10 11 12
box gen in ( t : : i n t 6 4 ) out ( x , y : : B i t ) match 0 −> (0,0) | 1 −> (0,1) | 2 −> (1,0) | 3 −> (1,1) ; stream i n p u t from ” s t d i n ” ; w i r e gen ( i n p u t ) ( f a n o u t . x , f a n o u t . y ) ;
Figure 4.18: The Modified ‘gen’ Box A PROMELA model has to be run in a closed environment to be verified with SPIN. As a consequence the model cannot accept any input from the environment (users or files). An input stream in HW-HUME streams values from the environment, and thus it cannot be allowed in PROMELA . In the PROMELA representation this is solved by creating a process that simulates the input from the users. Since only integer values are allowed in PROMELA for HW-HUME, the simulator simply uses variables that are incremented by one each run, and sent to the output stream. The PROMELA “input stream process” uses the same name as the input stream in HW-HUME. The created process does not have any parameters, and is declared to be active to initially instantiate a process. Inside the process the output channel where the stream is sending the values, is obtained. The name of the channel is the name of the input stream, followed by ‘ out’. The variable ‘out’ is set to refer to the channel, as shown in figure 4.19.
Figure 4.19: Creating the Reference to the Stream for the Input Stream Process
In each run, the input stream sends the current values of the declared variables to the output channel, and increments the variables by one. There will always be one or more variables. To create the variables, the input variable in in the HW-HUME box that the stream is wired to is used. This is shown in figure 4.20. As the figure illustrates, each variable is given the name ‘var’, followed by an unique number indicating its position in the input variable of the HW-HUME box that it was translated from. In this example it is only a base type, but if it was a tuple several variables would have been created.
Types
Figure 4.20: Creating the Reference to the Input Stream Variables
is used to obtain the correct PROMELA type. The last part of the process is the main body. It follows the same execution model as the other processes, i.e. it must receive a ‘BEGIN’ message before each run, and send an ‘END’ message at the end of each run. This has already been shown for the processes generated from boxes (figure 4.10). In the main body the process first checks if the channel can be sent to. It can only be sent to if the channel is empty. This is achieved with the predefined ‘empty()’ function. If it succeeds the variables are sent to the output stream, and incremented by one. Figure 4.21 illustrates how this code is generated.
Figure 4.21: Creating the Input Stream Body
As the figure illustrates, the expression type of the variable in the box that uses the stream is used to refer to the variable. This because the variable might be a tuple. For each element in the expression type, ‘var’ followed by a number indicating the position (in the tuple) is appended to the right hand side of the send operator ‘!’. Each element is separated by a comma. The variables are also incremented by one after the send statement has succeeded. Figure 4.22 contains the generated PROMELA code that simulates the user input in the updated half adder example listed in figure 4.18. The translation of input streams is denoted by InStream and defined in section B.8.1.
4.8.2 Output Streams The half adder includes an output stream. It is named ‘output’ and prints the values to standard output. The stream is used by wiring the output from the ‘show’ box to the stream. The stream declaration, together with the wire and box declaration for ‘show’, are required to translate the stream. The elements are shown in figure 4.23. Since an output stream cannot manipulate a model, it is allowed during verification in SPIN. However, PROMELA only supports streams to standard output. Consequently all output streams will
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
a c t i v e proctype i n p u t ( ) { chan o u t = i n p u t o u t ; i n t var1 = 0 ; start : i n p u t c o n t r o l ?BEGIN ; if : : ( empty ( o u t ) ) − > o u t ! v a r 1 ; v a r 1 ++; : : e l s e goto f i n i s h fi ; finish : i n p u t c o n t r o l !END; goto s t a r t ; }
Figure 4.22: The Input Stream Process
1 2 3 4 5 6 7 8 9
box show in ( s , c : : Bit ) o u t ( s c : : ( B i t , B i t , char ) ) match ( s , c ) −> ( s , c ,’\ n ’); stream o u t p u t t o ” s t d o u t ” ; w i r e show ( x o r . z , and . z ) ( o u t p u t ) ;
Figure 4.23: The Output Stream Declarations be sent to standard output, regardless of the destination in the HW-HUME model. To verify the model in SPIN, the destination of a stream is not important, only the existence of the stream. This implies that nothing important will be abstracted away in this modification. As for input streams, an output stream is translated into a PROMELA process. This translation is denoted by OutStream . To obtain all the required elements it uses Stream . An output stream process is very similar to an input stream process. It only has some minor modifications. As with the input stream, the process uses the same name as the HW-HUME stream, ensured to be valid PROMELA by using Names . It does not have any parameters. It uses the active keyword as a prefix to initially instantiate a process. The channel from which the stream receives the messages must be obtained. This is achieved by using the variable that is wired to the stream. This is illustrated in figure 4.24. As the figure shows, the channel is called ‘in’ and
Names
is used to ensure that the name is
a valid PROMELA name. The process receives values from the channel and assigns them to a set of variables. These variables must be declared. This is achieved in the same way as the input stream process. The only difference is that the variables are not initialised. This is illustrated in figure 4.25. The figure shows the translation of a tuple. For each element in the tuple a variable is created
Figure 4.24: Creating the Reference to the Output Stream Channel
Figure 4.25: Creating the Output Stream Variables
with the name ‘var’, followed by an integer indicating the position in the tuple.
Types
is used to
obtain the correct PROMELA type. Also note that the type ‘Bit’ is of type ‘word 1’. In the main body of the process it is first checked if it is possible to read from the input channel, achieved by enclosing the right hand side of the receive operator ‘?’ in brackets ‘[ ]’. If this succeeds the content of the message is assigned to the declared variables and printed to standard output using the predefined ‘printf()’ function. This is illustrated in figure 4.26.
Figure 4.26: Creating the Main Body of the Output Stream Process
Each PROMELA variable created from the tuple in the figure is separated by a comma when it is read from the channel. This is the case both in the guard condition where the channel is just checked, and when the channel is actually read from. In the ‘printf()’ function, ‘%d’ must be used in the string to reference a variable, which is in the variable list following the string. This means that for each variable ‘%d’ must be added to the string, and a reference to the variable must be added to the parameter list following the string. Figure 4.27 lists the the source code of the PROMELA process
created from the HW-HUME ‘output’ stream declaration.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
OutStream is defined in section B.8.2.
a c t i v e proctype o u t p u t ( ) { chan i n = s h o w 1 s c ; b i t var1 ; b i t var2 ; short var3 ; start : o u t p u t c o n t r o l ?BEGIN ; if : : ( in ?[ var1 , var2 , var3 ] ) − > in ? var1 , var2 , var3 ; p r i n t f (”%d %d %d \ n ” , v a r 1 , v a r 2 , v a r 3 ) : : e l s e goto f i n i s h fi ; o u t p u t c o n t r o l !END; goto s t a r t ; }
Figure 4.27: The Output Stream Process
4.9 The Init Process The creation of the init process is denoted by Init and is divided into two distinct parts. The first part is concerned with initialising the channels, denoted by ChanInit . It is applied when an initial
value is specified with the initially keyword in a HW-HUME wire declaration. In the half adder, only the input channel of the ‘gen’ box has an initial value. Figure 4.28 illustrates the initialisation of that channel.
Figure 4.28: Creating the Channel Initialisation
Note that
Names
is applied to the names, and
Values
to the value to ensure that the created
code is valid PROMELA. If Names had not been used on the t’ variable, SPIN would have produced a syntax error, since quotation marks are not allowed. The second part of the init process is the instantiation of the processes. This is denoted by
ProcInst . When instantiating a process the corresponding channels must be obtained, and sent as actual parameters. Since the channels were created based on the output variables in the box prelude, the output channels can be created based on the same elements. To obtain the input channels, the
corresponding wire declaration is used. The name of the control channel is simply the box/wire name followed by ‘ control’. Figure 4.29 instantiates the ‘gen’ process.
Figure 4.29: Creating the Instantiation of Processes As shown in the figure, Names must be applied to all the names. The process name is created based on the name of the wire. This is also used as a prefix to all the variables when creating the output channels. This cannot be applied when obtaining the input channels. This is because the input can descend from other processes, even though in this example the input descends from itself. Figure 4.30 contains the init process. The creation of the init process is denoted in section B.9. 1 2 3 4 5 6 7 8 9 10 11
init { gen tq !0; run gen ( g e n t q , g e n t q , g e n x , g e n y , g e n c o n t r o l ) ; run f a n o u t ( g e n x , g e n y , f a n o u t x 1 , f a n o u t y 1 , fanout x2 , fanout y2 , fanout control ) ; run x o r ( f a n o u t x 1 , f a n o u t y 1 , x o r z , x o r c o n t r o l ) ; run and ( f a n o u t x 2 , f a n o u t y 2 , a n d z , a n d c o n t r o l ) ; run show1 ( x o r z , a n d z , s h o w 1 s c , s h o w 1 c o n t r o l ) ; }
Figure 4.30: The Init Process
4.10 Using the Translation Rules In this section a simple ‘not’ gate is translated by applying the translation rules defined in appendix B. The syntax for translation is described in the introduction. The rule number used is enclosed in parentheses on the right side of the rule. Figure 4.31 lists the source code of the HW-HUME ‘not’ box declaration that is translated. The creation of a PROMELA process from a box is divided into three distinct steps. First the prelude is created. If there are any variables, they are then declared. At the end the main body is created. The two last steps are inside the body of the process, which are enclosed by brackets ‘{}’.
Proc ~ hboxdecli 7→ Prelude ~ hboxdecli { Vars ~ hboxdecli Body ~ hboxdecli }
(35)
box n o t in ( a : : i n t 1 ) out ( a ’ : : i n t 1 ) fair 0 −> 1| 1 −> 0;
Figure 4.31: The Hume Code of the ‘NOT’ gate
4.10.1 Process Prelude The creation of the PROMELA process prelude is divided into two parts, the creation of the process name, and the creation of the parameter list.
Prelude ~ hboxdecli 7→ Prelude ~ name hboxdecli Prelude ~ param hboxdecli
(36)
Name Definition The name definition starts with the proctype keyword which identifies that a process is being declared.
Names is used on the box name to ensure that the translated name is valid PROMELA.
Prelude ~ name box hboxidi hpreludei hbodyi 7→ proctype Names ~ Names ~ not 7→ not
hboxidi
(37) (19,20)
Defining Parameters The parameters for the PROMELA process are created using the prelude of the box.
Prelude ~ param box hboxidi hpreludei hbodyi 7→ Prelude ~ hpreludei
(38)
To create the input channels, the input elements are used, and to create the output channels the output elements are used. In this case there is only one of each, in addition to the control channel. The control channel uses the name ‘control’.
Prelude ~
in ( a :: int 1 ) out ( a’ :: int 1) 7→ ( chan Prelude ~ in a :: int 1 , Prelude ~ out a’ :: int 1 , control )
(39)
Each input channel is given the name ‘in’ followed by a number indicating the position in the list. The HW-HUME box only has one input element, which is given the name ‘in1’ in the PROMELA representation.
Prelude ~ in a :: int 1 7→ Prelude ~ in a Prelude ~ in a 7→ in1
(41) (42)
The input channels are created in a similar manner. There is only one output channel, which is named ‘out1’.
Prelude ~ out a’ :: int 1 7→ Prelude ~ out a’ Prelude ~ out a’ 7→ out1
(44) (45)
Summary The creation of the process prelude is summarised in the following rule. Note that this is not a defined rule in the appendix. It is only used to summarise the first part of the process creation.
Prelude ~ hboxdecli 7→ proctype not (chan in1, out1, control) 4.10.2 Variable Declarations To create a variable the expression types of the input elements, together with the box matches, are required. In the ‘not’ gate there is only one input element, which is extracted.
Vars ~ box hboxidi hpreludei hbodyi 7→ Vars ~ hpreludei hbodyi Vars ~ in ( a :: int 1 ) out ( a’ :: int 1 ) fair hboxmatchesi 7→ Vars ~ a :: int 1 hboxmatchesi Vars ~ a :: int 1 hboxmatchesi 7→ Vars ~ int 1 hboxmatchesi
(46) (47) (49)
During the creation of variable declarations, the pattern in each match must be scrutinised for variables. The ‘not’ gate contains two matches which are separated recursively and examined independently. For each match, the pattern, which is on the right hand side of the arrow ‘→’ is extracted. If the pattern type is a variable, the variable must be declared. For both matches, this is not the case hence no variables are declared.
Vars ~ int 1 0 → 1|1 → 0 7→ Vars ~ int 1 0 → 1 Vars ~ int 1 1 → 0 Vars ~ int 10 → 1 7→ Vars ~ int 1 0 Vars ~ int 11 → 0 7→ Vars ~ int 1 1
(50) (51) (51)
Summary As for the process prelude, the variable declaration has been summarised in a rule. Since the body of the box did not contain any variable, no variable declarations are performed. This is indicated with an epsilon ‘ε’.
Vars ~ hboxdecli 7→ ε 4.10.3 Process Body There are two semantically different bodies that can be created, depending on whether fair or unfair matching is applied. Regardless of the matching form, the synchronisation with the control process is identical.
Body ~ box hboxidi hpreludei hbodyi 7→ start: control?BEGIN; Body ~ hpreludei hbodyi finish: control!END;
goto start;
(55)
The ‘not’ gate uses fair matching, where each match is an option in an if clause. The if clause is created, together with the else option handling the case where the input does not match any of the options.
Body ~ hpreludei fair hboxmatchesi 7→ Fair ~ hpreludei fair hboxmatchesi Fair ~ hpreludei fair hboxmatchesi
(56)
7→ if
Fair ~ hpreludei hboxmatchesi :: else goto finish fi;
(58)
The two matches are separated recursively, and examined independently.
Fair ~ hpreludei 0 → 1|1 → 0 7→ Fair ~ hpreludei 0 → 1 Fair ~ hpreludei 1 → 0
(59)
Each match is an option in the if clause, identified by using two colons ‘::’ as a prefix. The match is separated with the guard condition on the left hand side of the arrow ‘→’, which checks the channels, and the right hand side of the arrow, which receives and omits the input from the input channel and sends the output to the output channels. The guard condition is enclosed by parentheses.
Fair ~ hpreludei 0 → 1 7→ :: Match ~ hpreludei 0 → 1 Match ~ in(a::int 1) out(a’::int 1) 0 → 1 7→ ( Patt ~ a::int 1 0 ) → Exp ~ a::int 1 0 Exp ~ a’::int 1 1
(60) (64)
The right hand side of the receive operator ‘?’ in the guard condition is enclosed by brackets ‘[ ]’. In this example there is only one input channel, holding one base value.
Patt ~ a::int 1 0 7→ in1?[ Patt ~ int 1 0 ] Patt ~ int 1 0 7→ Values ~ 0 Values ~ 0 7→ 0
(68) (70) (11)
The operation that receives the values is almost identical to the guard condition with the difference being that the brackets are removed.
Exp ~ a::int 1 0 7→ in1? Patt ~ int 1 0 ; Patt ~ int 1 0 7→ Values ~ 0 Values ~ 0 7→ 0
(74) (70) (11)
The code that produces the output is generated in similar way as the “input code”. The name of the only output channel in the process is ‘out1’, and the send operator ‘!’ is used instead of the receive operator.
Exp ~ a’::int 1 1 7→ out1! Exp ~ int 1 1 ; Exp ~ int 1 1 7→ Values ~ 1 Values ~ 1 7→ 1
(78) (80) (11)
The generation of the second match is identical to the generation of the first match. The guard condition on the right hand side of the arrow is enclosed by parentheses.
Fair ~ hpreludei 0 → 1 7→ :: Match ~ hpreludei 1 → 0 Match ~ in(a::int 1) out(a’::int 1) 1 → 0 7→ ( Patt ~ a::int 1 1 ) → Exp ~ a::int 1 1 Exp ~ a’::int 1 0
(60) (64)
The guard condition is first created, by enclosing the right hand side of the receive operator ‘?’ in brackets.
Patt ~ a::int 1 1 7→ in1?[ Patt ~ int 1 1 ] Patt ~ int 1 1 7→ Values ~ 1 Values ~ 1 7→ 1
(78) (80) (11)
The code that receives the value from the input channel is then created.
Exp ~ a::int 1 1 7→ in1? Patt ~ int 1 1 ; Patt ~ int 1 1 7→ Values ~ 1 Values ~ 1 7→ 1
(74) (70) (11)
At the end the code that sends the output to the output channel is created.
Exp ~ a’::int 1 0 7→ out1! Exp ~ int 1 0 ; Exp ~ int 1 0 7→ Values ~ 0 Values ~ 0 7→ 0
(78) (80) (11)
Summary The “summary rule” illustrates that the creation of a the process body is the most demanding part of the translation of a HW-HUME box into PROMELA. Compared to the other parts the number of code lines created is far greater. The amount of rules used to create the code is also superior compared to the other two parts.
Body ~
hboxdecli 7→ start: control?BEGIN; if :: ( in1?[0] ) → in1?0; out1!1; :: ( in1?[1] ) → in1?1; out1!0; :: else goto finish fi; finish: control!END; goto start;
4.10.4 The Promela Process Figure 4.32 summarises the translation of the HW-HUME ‘not’ gate by listing the created PROMELA representation. An important detail is the amount of PROMELA code required to represent the simple HW-HUME example. This is discussed in chapter 6.
p r o c t y p e n o t ( chan i n 1 , o u t 1 , control ) { start : c o n t r o l ?BEGIN ; if : : ( in1 ? [ 0 ] ) − > in1 ? 0 ; out1 ! 1 ; : : ( in1 ? [ 1 ] ) − > in1 ? 1 ; out1 ! 0 ; : : e l s e goto f i n i s h fi ; finish : c o n t r o l !END; goto s t a r t ; }
Figure 4.32: The Promela Representation of the ‘NOT’ Gate
Chapter 5
The Hw-Hume to Promela Translator 5.1 Introduction This chapter describes the ‘hwhpromela’ program. The program is used to model check HW-HUME models. This is achieved by first translating the HW-HUME source code into PROMELA. The user can then decide whether or not to use SPIN to verify or simulate the model. The program implements the semantic rules introduced in chapter 4. Since this is the main objective of the program, and the translation rules are already thoroughly described, the documentation is relative superficial. Appendix C contains the user guide for the program.
5.2 Requirements Due to the task, size and nature of the program the functional and non-functional requirements have not been separated. The program has the following requirements to the system: - The program has only been tested on a JAVAVirtual Machine (JVM) running on a LINUX system, and therefore there are no guarantees that it will work on other platforms. - The program uses the HUME parser (hparse), written in HASKELL , when parsing the HW-HUME code. The parser must be available for the program to work correctly. - SPIN is used to validate and simulate the generated model, and must be available. Also note that the different versions of SPIN vary. The program has only been tested with SPIN version 4.1.3 from 24 April 2004. The main task of the program is to automate the rules from chapter 4, and make the source code as close to the rules as possible. The rules are defined in appendix B. The program has the following functional and non-functional requirements: - The interface of the program should be a simple command based interface if possible. - By specifying a HW-HUME filename, the program should use the file as input, and generate a corresponding PROMELA model, which is written to a different file with a different file extension. 45
- The user should be able to simulate or verify the generated model, and should be able to run a guided simulation if a verification fails. - The program should output the translation time after a translation is performed. If a model is verified the verification and total runtime should be returned as well.
Figure 5.1: Use Case Diagram of Translator
Figure 5.1 shows the different options of the program, by using an UML use-case diagram 1 : Generate PROMELA code is the main task of the translator. The translator accepts as input a HWHUME file, and translates it into a PROMELA file. The ‘.hume’ file extension is replaced by a ‘.pml’ extension. If the file extension on the HW-HUME file is not ‘.hume’, ‘.pml’ is simply appended to end of the HW-HUME filename in the PROMELA file. The translation time is returned to the user when the translation finishes. Random simulation of the SPIN model is concerned with running SPIN in a random simulation mode after the HW-HUME model is translated. During random simulation the next statement in a randomly selected process is always chosen for execution. Verify the SPIN model is the option that verifies the model after the HW-HUME is translated. The result of the verification is returned back to the user, together with the translation time, verification time and the total time used. Guided simulation of SPIN model can only be performed if a verification from an earlier run failed.
5.3 Design Figure 5.2 illustrates the different states of the program using an UML activity diagram. As the diagram shows, the activities of the program depend on the input arguments from the user. The arguments are represented in the figure with the variable ‘args’. If ‘-g’ is used as an argument, the ‘hwhpromela’ will start SPIN and run the guided simulation without any translation. If not, the specified HW-HUME program is first translated. The HUME parser is used during this activity. After the HW-HUME program has been translated, the PROMELA representation of it is created. If no 1
For a good introduction on UML please see [12]
arguments are specified, the program terminates after this step. If ‘-v’ is specified, the generated PROMELA program is verified using SPIN. SPIN will only search for deadlocks. If ‘-r’ is specified, the generated PROMELA program is run using random simulation.
Figure 5.2: Activity Diagram of Translator
Figure 5.3 illustrates the stages of the translation from HW-HUME into PROMELA. The process is divided into four distinct parts. First the lexical and syntax analysis is performed. It accepts a HWHUME program as input, and parses it first using the HUME parser. This is covered in section 5.3.1. The result of the lexical and syntax analysis is used to create the abstract syntax tree, covered in section 5.3.2. The abstract syntax tree is then used to generate the PROMELA code, which is explained in section 5.3.3. JAVA2 has been used to implement the translator.
Figure 5.3: The Translator
5.3.1 Lexical/Syntax Analysis For the syntax and semantics analysis, JAVA Compiler Compiler( JAVACC )[21] has been used. JAVACC is a JAVA version of the Lex and Yacc[31] tools. 2
An introduction on using Java to write compilers is given in [2]
JAVACC is the most popular parser generator for use in JAVA applications. The parser generator is a tool that reads a grammar specification and converts it into a JAVA program that can recognise matches to the grammar [21]. The lexical and syntax analysis had already been done by Chunxu Liu. This version has been used in the translator.
5.3.2 Abstract Syntax Tree The JAVACC utility includes a mechanism to create an abstract syntax tree (AST). It is a preprocessor for JAVACC that is run before the JAVACC parser. The utility is called JJTREE . The output of JJTREE is used as input to the JAVACC utility. It inserts parse tree building actions in the JAVACC source (The grammar file). The grammar file is then used as input in JAVACC [22]. Figure 5.4 illustrates a part of the abstract syntax tree when parsing the half adder example from figure 2.5. The figure illustrates the iteration to the name of the ‘gen’ box. The root node of the tree is ‘Decls’. It contains a set of ‘Decl’ nodes, which in this case hold a ‘BoxDecl’, that declares the ‘gen’ box. The ‘BoxId’ node holds the name of the box, which is ‘gen’. The AST follows the structure defined in HUME. Appendix A contains the abstract syntax for HW-HUME, which holds a subset of the AST in full HUME.
Figure 5.4: Part of Abstract Syntax Tree
5.3.3 Code Generation In the code generation step the PROMELA code is generated, and written to a file. It implements the translation rules defined in appendix B. One JAVA method is created, where possible, for each rule defined in the appendix. In the methods the HW-HUME elements are obtained by traversing the AST, illustrated in figure 5.4. This is then translated into PROMELA. The class diagram in figure 5.5 shows how the ‘hwhpromela’ class uses the AST like a “black box”. All methods are implemented in the ‘hwhpromela’ class.
Figure 5.5: Class Diagram
Chapter 6
Evaluation 6.1 Introduction This chapter presents an evaluation of the translation and the verification results. The evaluation is conducted based on experiments with a set of HW-HUME examples. They are translation and verified using the ‘hwhpromela’ program. The evaluations scrutinises the time used for the translation and verification, the amount of work required by the verifier, and the difference in code size between the HW-HUME and PROMELA model. The first sections introduces the examples, and the last section contains the actual analysis. Appendix F contains the HW-HUME source code for the examples used. The generated PROMELA code is listed in appendix G, and appendix H includes the outputs from the verifications. The generated PROMELA source code for examples 1, 3 and 4 are listed in appendix G. Due to the size of the PROMELA code, the source code for the rest of the examples have not been included. Note that the line numbers in the figures in this chapter containing verification outputs are not part of the outputs, if not specified.
6.2 Example 1: A Half Adder The first HW-HUME model that is verified is the half adder used as an example in the previous chapters. The full HW-HUME source code is listed in figure 2.5 on page 12. The PROMELA source code of the translation is listed in section G.1. Figure 6.1 displays the output when running the program in a random simulation mode, by using the ‘-r’ argument in ‘hwhpromela’. As in figure 2.6 on page 14 that runs the HW-HUME version of the program, the output displays the first two runs. Lines 3 to 6 shows the first run and lines 7 to 10 the second. The output is almost the same as the output of the first and second runs in HW-HUME, shown in figure 2.6. The only difference is that each line ends with ‘-1’. This is simply the PROMELA translation of the newline escape sequence. Figure 6.2 contains parts of the output when validating the half adder using ‘hwhpromela’. The complete output is listed in section H.1. Line 1 indicates that a full state space search is explored. In line 2 the minus sign ‘-’ indicates that no never claim or LTL formula has been used 1 . Line 4 indicates that a check for acceptance or 1
LTL formulae are translated into never claims in the LTL parser.
49
1 2 3 4 5 6
$ j a v a hwhpromela − r h a l f . hume h a l f . pml g e n e r a t e d 0 0 −1 1 0 −1 1 0 −1 0 1 −1
7 8 9 10 11
0 1 1 0 .
0 0 0 1 .
−1 −1 −1 −1 .
Figure 6.1: Running the Half Adder 1 2 3 4 5 6 7 8 9 10 11
Full s t a t e s p a c e search for : never claim assertion violations acceptance cycles i n v a l i d end s t a t e s
− ( none s p e c i f i e d ) + − ( not s e l e c te d ) +
S t a t e −vector 1 5 6 byte , depth reached 2 7 5 , e r r o r s : 0 217 s t a t e s , stored 1 s t a t e s , matched 2 1 8 t r a n s i t i o n s ( = s t o r e d +m a t c h e d ) 0 atomic s t e p
Figure 6.2: Output when Verifying Half Adder non-progress cycles was not conducted. The plus sign ‘+’ on lines 3 and 5 indicate that a search for assertion violation and invalid end states (deadlocks) has been conducted [18]. Line 7 specifies that the complete description of a global system state requires 156 bytes, and the longest depth-first search path uses 275 transitions from the root. No errors were found, hence the verification succeeded. Line 8 declares that 217 unique global system states were stored in the state space, and line 9 declares that in one case the search returned to a previously visited state. Line 10 declares that a total of 218 transitions were explored in the search. This number indicates the amount of work performed in the verification. None of the transitions were in an atomic sequence [18]. After the verification is completed ‘hwhpromela’ displays the time elapsed to translate and verify the HW-HUME model. This part of the output is shown in figure 6.3. −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− T r a n s l a t i o n S u c c e s s f u l : V e r i f i c a t i o n Completed −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− Fi le Generated : h a l f . pml T r a n s l a t i o n Time : 4 0 9 ms V e r i f i c a t i o n Time : 3 3 1 0 ms T o t a l Running Time : 3 7 1 9 ms −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
Figure 6.3: Time Elapsed when Verifying Half Adder
6.3 Example 2: An XOR and an AND Gate Forming a Deadlock Example 1 illustrated a working model without any errors. However, the reason to translate the HW-HUME model into PROMELA, is to be able to use SPIN to verify if the model includes any errors. As an example with an error, the half adder example has been modified. One of the outputs in the ‘xor’ gate has been used as input to the ‘and’ gate and the other way around. This is illustrated in figure 6.4.
Figure 6.4: An ‘AND’ and an ‘XOR’ Gate Creating a Deadlock
The HW-HUME source code for this example is listed in section F.2. When verifying the model using ‘hwhpromela’, the verification fails. The part of the output showing this is listed in figure 6.5. The full verification output is listed in section H.2. Note that only one error is found. The objective of the verifier is to prove that a model contains errors. As soon as one error is found, the verifier normally stops executing. It has then succeeded in its task, and there is no need to continue. S t a t e −vector 1 3 2 byte , depth reached 4 6 , e r r o r s : 1 36 s t a t e s , stored 0 s t a t e s , matched 3 6 t r a n s i t i o n s ( = s t o r e d +m a t c h e d ) 0 atomic s t e p s
Figure 6.5: Output when Verifying Deadlock Example Figure 6.6 shows the part of the output where the deadlock occurs. In the output the number on the left hand side reflects the step number of an operation. As shown in the output, the model is deadlock when ‘gen’ tries to send a value to the first output channel. The previous value has not been removed from the channel, and ‘gen’ cannot send the new value to the output channel. 45: 46: 47:
proc 3 ( gen ) proc 3 ( gen ) proc 0 ( Control ) transition failed s p i n : t r a i l ends a f t e r 4 7
. . . . . . . . .
[ in1 ?1] [ out1 ! 2 ] [ g e n c o n t r o l ?END]
steps
Figure 6.6: Output when Running Guided Simulation on Deadlock Example
6.4 Example 3: Full Adder from Truth Table The problem with half adder is that it does not accept any carry input. A full adder is an extension of the half adder that accepts a carry input. A set of full adders can then be connected, by connecting the output carry of one adder to the input of another. Figure 6.7 illustrates a full adder as a “black box”.
Figure 6.7: A Full Adder
There are several ways to represent a full adder in HW-HUME. In this example it is represented from a truth table. Figure 6.8 shows the HW-HUME model of the full adder. The full adder is represented as a box called ‘adder’, that holds the truth table, and uses it to generate the ‘sum’ and ‘carry’ bits. The ‘gen’ box generates the different inputs, and ‘show’ redirects the result to standard output. The full HW-HUME source code is listed in section F.3, the generated PROMELA code is listed in section G.2, and the verification output in section H.3. The verification succeeded without errors.
Figure 6.8: Full Adder from a Truth Table
6.5 Example 4: Full Adder as Half Adders and OR gate A full adder can also be represented by using two half adders and an ‘or’ gate. The HW-HUME model in 6.9 shows such a system. The ‘gen’ box generates the two binary numbers which are added, together with a carry bit. The first half adder receives the two binary numbers as input and wires the sum to the input of the second half adder. The other input for the second adder is the carrier from the ‘gen’ box. The sum of the second adder is then the sum of the complete adder. The carry from both half adders are wired to an ‘or’ box. If one of them is ‘1’ the carry from the full adder is ‘1’. The HW-HUME source code is listed in section F.4, and the translated PROMELA version of it in section G.3. The output from the verification is shown in section H.4. The verification succeeded without any errors.
Figure 6.9: Full Adder as Half Adders and OR gate
6.6 Example 5: Full Adder as XOR, AND and OR gates In example 4 the half adders were implemented using a truth table. However, each half adder can be decomposed into ‘xor’ and ‘and’ gates, the same way example 1 represented the half adder. Figure 6.10 displays the HW-HUME model of the adder created this way.
Figure 6.10: Full Adder as XOR, AND and OR gates
The full HW-HUME source code is listed in section F.5, and the output of the verification is listed in section H.5. The verification succeeded.
6.7 Example 6-9: Connecting Adders In the examples in this section several adders are connected to increase the size of the programs. The results are then analysed in section 6.9. Four different adders have been created. They can add two, three, four and five bits respectively. The HW-HUME source code is found in section F.6 and the verification results in section H.6. Example 6 connects two adders by connecting the output carrier from the first adder to the input carrier of the second adder. This will form a two bit adder. The adder is illustrated in figure 6.11. Note that this is a simplification of the HW-HUME model. Each adder is based on example 5, which
Figure 6.11: Example 6: A Two Bit Adder
creates the adder by using ‘and’, ‘xor’ and ‘or’ gates. In addition each adder has an associated ‘gen’ box. In total, the PROMELA model generated from the HW-HUME model includes 21 processes and 52 channels. The verification of the two bit adder succeeded. Example 7 appends another adder to example 6, and by doing so, creates a three bit adder. The translated PROMELA model of the adder uses 29 processes and 76 channels. This verification also succeeded without any errors. Example 8 creates a four bit adder by connecting another adder to example 7. The PROMELA translated from the HW-HUME model of the adder consists of in total 37 processes and 100 channels. The verification of this model succeeded. Example 9 is created by appending another adder to example 8. This will create a five bit adder. The PROMELA model translated from the HW-HUME model uses a total of 45 processes and 124 channels. In this example the state vector in the verification was too small, and the verification consequently failed.
6.8 Example 10: Debugging with Spin Example 10 creates a 3 bit counter. Since it uses 3 bits, it counts from 0 to 7. Each bit is represented by a ‘digit’ box. Figure 6.12 shows such a ‘digit’.
Figure 6.12: The Digit
The box has two inputs, ‘clk’ and ‘a’, and two outputs, ‘ clk‘ ’ and ‘q’. The ‘a’ input is the current state of the ‘digit’. The output ‘q’ is also the state of ‘digit’, and is wired to the ‘fanout’ box. This box simply wires the one input to two identical outputs. This must be performed since all
wires in HW-HUME have a 1:1 relationship, and the output needs to be wired to two different boxes. One of the outputs of ‘fanout’ is wired back to ‘digit’, since it needs to remember its state. The other input ‘clk’ is used to change the state of the ‘digit’. If the value is ‘1’ the state will change. The other output is ‘clk‘’, and holds the carrier. Figure 6.13 contains the truth table for the ‘digit’. The box is implemented as a truth table.
clk 0 1 0 1
a 0 0 1 1
q 0 1 1 0
clk’ 0 0 0 1
Figure 6.13: Truth Table for a Digit
To create a 3 bit counter, three ‘digits’ are wired together. Figure 6.14 displays the HW-HUME model of the counter. The source of the ‘clk’ input in the first ‘digit’ is a box ‘clock’. This box receives the input from the last ‘digit’ box. When it receives the input, it signifies that one run has completed, and all ‘digits’ are updated. Each time ‘clock’ receives inputs, it sends ‘1’ to the first ‘digit’, forcing it to change state - hence the counter is either incremented by 1 or reset back to ‘0’. The carrier output ‘clk‘’ from the first ‘digit’ is wired to the next ‘digit’. The ‘clk‘ ’ output of this ‘digit’ is then wired to the ‘clk’ input of the last box, which wires its ‘clk‘’ output back to ‘clock’. The ‘q’ output of each ‘digit’, which holds the current state, is wired to a ‘fanout’ box, which wires one of the outputs to ‘show’. The ‘show’ box converts the binary number, created from the three ‘digits’, into a decimal format, and wires it to the standard output.
Figure 6.14: The Counter
The HW-HUME source code of the counter is listed in section F.7.1. When the counter reaches ‘4’, it for some reason hangs and stops counting. SPIN is applied to the model to find the error. The HWHUME model is verified by using the ‘-v’ argument when the model is run through ‘hwhpromela’. Figure 6.15 contains parts of the output when running the verifier. The full output can be obtained from section H.7.1. As line 1 in the figure shows, the model contains a deadlock (error). When a verification fails
1 2 3 4
S t a t e −vector 2 0 8 byte , depth reached 5 2 8 , e r r o r s : 1 412 s t a t e s , stored 0 s t a t e s , matched 4 1 2 t r a n s i t i o n s ( = s t o r e d +m a t c h e d )
Figure 6.15: Output when Verifying the Counter in SPIN, an error trail specifying the path of the error is generated. By running a guided simulation, this trail is followed to track down the error. In ‘hwhpromela’ the guided simulation is run on the HW-HUME model by using the ‘-g’ argument. In figure 6.16 the interesting parts of the output from the guided simulation have been extracted.
468: 469: . . . 476: 477: . . . 524: 525: . . . 528: 529:
proc proc
4 ( show1 ) 4 ( show1 )
. . . . . .
[ c o n t r o l ?BEGIN ] [ else ]
proc proc
4 ( show1 ) 4 ( show1 )
. . . . . .
[ else ] [ c o n t r o l !END]
proc proc
0 ( Control ) . . . 8 ( f1 ) . . .
[ f 1 c o n t r o l ! BEGIN ] [ c o n t r o l ?BEGIN ]
proc 8 ( f1 ) . . . [ out1 ! a ] proc 0 ( Control ) . . . [ f 1 c o n t r o l ?END] transition failed s p i n : t r a i l ends a f t e r 5 2 9 s t e p s
Figure 6.16: Running the Counter in Guided Simulation
The numbers on the left hand side reflects the step number of the different operations, and are part of the generated output. The verification fails after step 529. The error is that the ‘Control’ box does not receive the ‘END’ message back from the ‘f1’ process. Step 528 sends a value to the first output channel. As figure 6.14 shows, the ‘f1’ process has two output channels. This indicates that the problem is that ‘f1’ cannot send to the second output channel. This will happen if the last value sent was not removed from the channel. The box that receives this output is the ‘show’ box. Since it is not permitted to ignore inputs in HW-HUME, the only reason for this error, is that the input in the previous run did not match any of the patterns. This is confirmed by scrutinising the error trail in steps 468 to 477. It shows that only the else clauses were used, and hence no input matched, and the value remained in the channel. The error was that the binary representation of ‘3’(‘011’) was used to represent ‘5’(‘101’) in the pattern. Consequently none of the patterns matched ‘5’. The updated source code with the fixed error is listed in section F.7.2. Figure 6.17 illustrates part of the output when verifying the updated counter. The full output is listed in section H.7.2. As line 1 in the figure illustrates, the model did not contain any errors.
S t a t e −vector 2 0 8 byte , depth reached 7 4 5 , e r r o r s : 0 583 s t a t e s , stored 1 s t a t e s , matched 5 8 4 t r a n s i t i o n s ( = s t o r e d +m a t c h e d )
Figure 6.17: Output when Verifying the Updated Counter
6.8.1 Specifying Behaviour Until now SPIN has only been used to find deadlocks in a model. SPIN is much more powerful than just that. One feature, explained in chapter 3, is the linear temporal logic (LTL) where the order of events can be specified. To specify this, the PROMELA source code must edited. In addition the LTL properties must be defined. To illustrate the possibilities of SPIN, the following property is verified: “Each time the value of the counter is seven it will eventually be set to zero” To be able to express this in the PROMELA model, a global variable holding the current value of the counter must be created. Each time the value is read by the ‘output’ process that prints the value to the standard output, the global variable must be updated. 1 2 3 4
# define p ( value == 7) # define q ( value == 0) byte value = 0 ;
Figure 6.18: Declaring the Properties Figure 6.18 contains the declarations that have to be made in the PROMELA code. The variable ‘value’, declared on line 4, must be updated each time the counter is updated. ‘p’ is the event that the counter is ‘7’, and ‘q’ is the event that the counter is ‘0’. These events can also be specified in the LTL-editor in XSPIN. Desired Behaviour The behaviour defined is the desired behaviour. The following linear temporal logic formula expresses this behaviour:
(p →
q)
SPIN will then transform this formula into a never claim. The claim is shown in figure 6.19. As described in chapter 3, never claims specify behaviour that should never occur. As a consequence the never claim describes what should not happen, which is the negation of the specified behaviour. This is achieved by using the not operator ‘!’ in front of the claim, as line 1 shows. Figure 6.20 contains parts of the output from the verification. The plus sign ‘+’ at the end of line 2, indicates that the never claims are included in the verification. Line 7 specifies that the model contains no errors. The complete output is listed in section H.7.3.
1 2 3 4 5 6 7 8 9 10 11
never { T0 init :
/∗ !([]
( p −>
<>
q)) ∗/
if : : ( ! ( ( q ) ) & & ( p ) ) − > goto a c c e p t S 4 : : ( 1 ) − > goto T 0 i n i t fi ; accept S4 : if : : ( ! ( ( q ) ) ) − > goto a c c e p t S 4 fi ; }
Figure 6.19: Never Claim for Desired Behavoiur 1 2 3 4 5 6 7 8 9 10
Full s t a t e s p a c e search for : never claim assertion violations acceptance cycles i n v a l i d end s t a t e s
+ + ( i f within scope of claim ) + ( fairness disabled ) − ( d i s a b l e d by n e v e r c l a i m )
S t a t e −vector 2 1 2 byte , depth reached 1 3 4 6 , e r r o r s : 0 658 s t a t e s , stored ( 7 2 4 v i s i t e d ) 130 s t a t e s , matched 8 5 4 t r a n s i t i o n s ( = v i s i t e d +m a t c h e d )
Figure 6.20: Output when Verifying Desired Behaviour Error Behaviour Error behaviour, i.e. behaviour that should never happen, can also be specified. In this case the error behaviour can be defined as follows: “Eventually it should not happen that when the value of the counter is seven it will eventually be set to zero” When using the same definition of ‘p’ and ‘q’ as earlier, the following linear temporal logic formula expresses the error behaviour:
!(p →
q)
Parts of the output from the verification are listed in figure 6.21. The full output from XSPIN, together with the generated never claim, are listed in section H.7.3. Note that the never claim (see line 2 in figure 6.20) is also enabled in this example. S t a t e −vector 2 1 2 byte , depth reached 1 3 4 6 , e r r o r s : 0 658 s t a t e s , stored ( 7 2 4 v i s i t e d ) 130 s t a t e s , matched 8 5 4 t r a n s i t i o n s ( = v i s i t e d +m a t c h e d )
Figure 6.21: Output when Verifying Error Behaviour
6.9 Analysis of the Verification Result
1: Half Adder 2: Deadlock 3: Adder 1 4: Adder 2 5: Adder 3 6: Two Bit 7: Three Bit 8: Four Bit 9: Five Bit 10: Counter Average
Verification Vector Work 156 218 132 36 120 302 156 414 256 694 456 1273 652 1852 848 2431 1028 208 584
Time Consumption (ms) Translate Verify Sum 468 3411 3879 254 3153 3407 319 3371 3690 369 4054 4423 414 5735 6149 394 8297 8691 414 11458 11872 597 15942 16539 770 380 4723 5103
Lines Of Code
HW-HUME
PROMELA
50 41 41 50 73 94 112 130 148 51
183 159 153 202 312 549 786 1023 1260 312
Factor 3.66 3.88 3.73 4.04 4.27 5.84 7.02 7.87 8.51 6.12 5.49
Table 6.1: Translation and Verification Data
Table 6.1 contains data collected from the translation and verification processes. The first column refers to the examples in the previous sections. The analysis has been divided into three distinct parts, which are the verification, the time consumption and the code size. The table follows this structure. The second column holds the size of the state vector in the verification. This size is in bytes. The third column, named work, is the number of transitions explored in the search. This number illustrates the amount of work performed in the verification. The next three columns contain the time consumptions. In all cases the time is shown in milliseconds. The time is divided into translation time, verification time and total runtime. The last three columns look at the size of the source code in HW-HUME and PROMELA. The last column, factor, illustrates the relationship between them (PROMELA /HW-HUME). HW-HUME 5: 6: 7: 8: 9:
Adder Two Bit Adder Three Bit Adder Four Bit Adder Five Bit Adder
Box 3 3 4 5 6
Temp.Inst. 6 14 21 28 35
PROMELA Total 9 17 25 33 41
Process 13 21 29 37 45
Chan 28 52 76 100 124
Total 41 73 105 137 169
Time 6149 8691 11872 16539
Factor 4.27 5.84 7.02 7.87 8.51
Table 6.2: Data Objects
Table 6.2 only looks at example 5 to 9, which respectively are 1,2,3,4 and 5 bit adders. It examines the data object representations in HW-HUME and PROMELA. In HW-HUME it looks at the number of boxes, how many instances of templates, and the sum of these two values. In PROMELA the number of processes and channels are defined. The time is the total running time and factor has the same meaning as in table 6.1.
6.9.1 Verification There tends to be a relationship between the amount of work (number of transitions) and the size of the state vector. However, this is quite natural, since the more transitions the more space is required to represent them.
Figure 6.22: Relationship between State Vector and Box Instances
Of particular interests in this special case, is the relationship between the number of box instances in HW-HUME and the number of transitions and the size of the state vector. The number of templates is of little interests, since it is only when a template is instantiated that it is actually translated into PROMELA. Figure 6.22 graphically illustrates the relationship between the state vector and number of box instances, and figure 6.23 illustrates the relationship the number of transition and the number of box instances. An interesting result is that both for the space vector and for the number of transitions, the relationship seems to be linear. This leads to the size of the state vector and the number of transitions increasing linearly with the number of box instances. Most boxes are relatively small and simple, and behaves similarly. This is probably the reason for the linearity. Each time a new box is introduced, the amount of work (number of transitions) increases with the same factor.
Figure 6.23: Relationship between Number of Transitions and Box Instances
6.9.2 Time Consumption As table 6.1 shows, the translation time is relatively stable, using around 0.5 seconds, regardless of the code size of the HW-HUME or PROMELA model. The implies that the translation process do not require a lot of work, and most of the work is reading the source file (HW-HUME), and writing to the destination file (PROMELA).
Figure 6.24: Relationship between Verification Time and Hw-Hume Box Instances
The verification time increases when the total instances of HW-HUME boxes increases. Figure 6.24 illustrates the relationship between the running time (in seconds) and the total number of box instances. The figure shows that the running time increases exponentially rather than in a linear fashion
Figure 6.25: Relationship between Time, Processes and Channels
Figure 6.25 illustrates the relationship that the verification time has with the two global objects in PROMELA, which are channels and processes. From figure 6.25 you could assume that the number of communication links (channels) have a greater impact on the verification than the processes. It looks like introducing a greater amount of communication between process, will have a greater impact on the verification time, compared to introducing a greater amount of boxes.
6.9.3 Number of Code Lines When examining table 6.1 a big difference between the number of source code lines in HW-HUME and PROMELA can be seen. On average, for each code line of HW-HUME, PROMELA needs 5.49 lines to specify the same. From the same figure you can see that this factor tends to increase when the size of the example increases. Figure 6.26 graphically displays the relationship between the number of boxes and template instances and the factor indicating the relationship between the size of the HWHUME and PROMELA code. The function tends to increase monotonically toward a constant value, when the number of box instances increases. Why this happens is difficult to say. It is important to realise that the size of the examples used in the analysis were relatively small, and the results from larger scale programs might differ. There are many reasons for the code size of PROMELA begin on average 5.49 times greater than
Figure 6.26: Relationship between Code Lines Factor and Number of Box Instances
the HW-HUME code. As figure 6.26 illustrates, the factor increases with the number of box instances in HW-HUME. Table 6.2 shows that the number of boxes are stable, while the number of template instances increases in the examples. From one template, all instantiations are created on the same line, and one extra line is required for wiring each instance. The PROMELA representation of a template instance is a process. This process, and the corresponding channels, must be declared. This is probably the main reason, since a process declaration requires a significant amount of space. Another reason is that the execution model in HW-HUME must be coerced into the PROMELA version. To achieve this, a separate control process must be created, and each process must be synchronised with it. The channels that are used for this synchronisation must also be created. This code is not found in HW-HUME. Inside the boxes variables must also be specifically declared. In HW-HUME this is achieved directly in the pattern matches. For the interprocess communication one channel has to be created for each variable. In HWHUME it is sufficient with a wire declaration per box. Each stream in HW-HUME is created by a one line declaration. In PROMELA an entire process must be created, which also must be synchronised with the other processes. For input streams a channel must be created in addition. As a general conclusion the PROMELA code translated is “PROMELA for HW-HUME” and not PROMELA. If the same program were directly implemented in PROMELA, and not a translation from HW-HUME, the number of code lines would decrease dramatically. However, this would not reflect the HW-HUME program. To reflect it all the features mentioned are required.
Chapter 7
Conclusion 7.1 Introduction This chapter discusses various aspects of the project and looks at which would be feasible for future research. The discussion has been divided into the translation and verification, and the actual program developed.
7.2 The Analysis The verification results in the validation chapter provide empirical evidence as to the correctness of the translation. For all features in HW-HUME, a corresponding feature was found in PROMELA. The results from the verifications were as expected. In both cases where a deadlock was injected, SPIN was able to detect it. The generated PROMELA program had in all cases the same behaviour when simulated, as the HW-HUME program from which it was generated when executed. In the working HUME examples, no deadlock where found by the verifier, and the temporal properties was proven where defined.
7.2.1 Verification Result To break down SPIN with the default size of the state vector, a total of 45 processes and 124 channels were required. The biggest verified model used a total of 37 boxes and 100 channels. An interesting result from the verification was that the relationship between the amount of instantiated boxes in HW-HUME (processes in PROMELA) and the amount of work performed by the verifier was linear. The reason is most likely that all the boxes were of similar size in the examples used. However, since HW-HUME is targeted at modelling hardware systems, this is what you would expect in most of the cases. The story for full HUME is different, and this might give a different relationship.
7.2.2 Time Consumption The translation time was in all cases relative stable, using around 0.5 seconds, regardless of the size of the HW-HUME model. This denotes that the amount of work required to translate is relatively low, and most of the work is to read and write to a the source and destination files. An interesting result
63
from the verification was that it seemed that the amount of interprocess communication affected the verification time more than the number of boxes. This is interesting since in distributed systems the amount of message passing between processes is in most cases the bottle neck. The system with the lowest amount of messages passed is normally the most efficient one.
7.2.3 Number of Code Lines As expected, the number of code lines required to represent HW-HUME models in PROMELA was larger than the number of code lines in HW-HUME. But that the difference between them was as big as a factor of 5.59 was much more than assumed. The main reason for the big difference is the use of templates. The examples have relied heavily on the use of templates. This would be the case when modelling hardware systems, which would make HUME very good for that task. However, in full HUME you would expect this factor to be lower.
7.3 Translation Rules The notation used to express the translation rules were adequate in most cases. Though in some cases it did not have the expressive power required, and it had to be used to express something that it was not meant for. One such example is rule 42, on page 84. In that example the rule had to be used to express the position of a variable in a list, which it isn’t meant for. Another example is rule 54, where a condition is applied to the rule. Another expression form could probably have been used to formalise the rules further in those cases.
7.4 The Translator The translator behaves exactly the way it is supposed to do according to the design documentation and requirements. It has a simple user interface, and implement all the translation rules specified, which was the main objective. It also includes the required functions to simulate and verify the programs without the user having to use SPIN. As a consequence, the user needs no understanding and knowledge of SPIN or PROMELA. What the translator does not do is to let the user specify any properties that needs to be validated. If the user wishes to do so, the HW-HUME source must first be translated into PROMELA using the translator. Then the translated PROMELA code must be ran directly in SPIN or XSPIN, where the user can specify the error or desired behaviour. As a consequence the user must be familiar with SPIN and/or XSPIN. As the translator behaves at present, it only explores a small portion of the possibilities with the SPIN model checker. The programming language used to implement the translator was not necessarily the right one to use for such a problem. By using JAVA the defined rules could not be implemented directly. Where possible it has been attempted to implement a method resembling a rule, but in some cases this was impossible. One method could in some case implement several rules, and in some cases several methods were used to implement one rule. However, semantically the program does the same as the rules specified. This behaviour was calculated at the start of the implementation of the translator. Even if JAVA is a strictly object oriented
language the implementation was not carried out in an object oriented manner, since the implementation had to be as close to the rules as possible. Hence, JAVA was not used in the way in which it was intended to be. The reason for choosing JAVA was that the lexical and syntax analysis had already been done. However, by using languages like HASKELL [6] or PROLOG[10] a more direct implementation of the rules could have been obtained.
7.5 Future Work The future work has been divided up into what could be achieved in a short time, and what requires longer to complete. It addresses both the theoretical part, and the implementation of tools using the theory.
7.5.1 Short Term Continued translation of full HUME in the same way HW-HUME has been translated. The work has been started, but the translation rules for the aspects of HUME not covered by HW-HUME must be created. Full HUME includes features that are not found in model checking input languages like PROMELA. However, the notation of PROMELA resembles a programming language more than a modelling language [35]. Nevertheless, PROMELA has for instance no representation of floating point numbers that is found in HUME. Not being able for find a resembling representation of such aspects was the reason for the JAVA PATHFINDER [35] in version 2 which used a specialised model checker compared to the first version, which was a direct JAVA to PROMELA translation. By changing the implementation language to HASKELL or PROLOG in the translator a more direct implementation of the rules can be obtained. This implementation will most likely be more dynamic and easier to change. This should be applied if full HUME is translated into PROMELA. A comparison of the generated PROMELA code with the code created from a HUME → JAVA → PROMELA using the HUME to JAVA translator and JAVA PATHFINDER , could be carried out. This can help and support both the HUME to JAVA and the HUME to PROMELA projects. Implementing a graphical user interface (GUI) including a method to specify desired or error behaviour using linear temporal logic, would mean that user never had to see SPIN or PROMELA.
7.5.2 Long Term Other ways of verifying HUME should be considered. This could be alone or may be integrated to the SPIN approach. For instance, SPIN can be used to verify the box communication (expression layer) in HUME while a theorem prover can be used to verify the functionality of boxes. There is a current trend to such integration. E.g. the Stanford Temporal Prover (STeP)[34, 29] combines model checking with deductive methods when verifying systems. Another approach could be to customise SPIN for HUME, in the same way as the JAVA PATHFINDER version 2.
Upgrading HUME to specify error or desired behaviour would be an alternative to create a tool that specifies these properties, as described in the short term part. HUME can be extended so these properties can be programmed directly in the HUME source file, and then translated into the PROMELA counterpart. These properties can then be verified using SPIN. A PROMELA to HUME translator is an interesting idea. A system model can be created and verified using PROMELA. It can then be translated into HUME for implementation. The problem is that much of HUME’s expressive power will then be lost, since many of the aspects of HUME cannot be expressed in PROMELA, PROMELA only being a modelling language. One idea might be to only generate HUME skeletons for the boxes and communication links, and then implement the bodies of the boxes. Abstraction must be considered. The state explosion problem will eventually appear when the HUME programs increases in size. Finding a correct representation for all features of HUME in PROMELA might turn out to be too cumbersome or even insoluble. Both the ESTELLE to PROMELA [1] and the LOTOS to PROMELA [27] have this problem as well as the JAVA PATHFINDER. A solution might be to abstract at the features that cannot be represented, and use SPIN on the rest.
7.6 Conclusion The development of high integrity software systems calls for a wide range of tools and techniques, in particular, programming languages like HUME, that enable the use of a statically analysis techniques. However, HUME lacks the support of verification. In this project an investigation of the use of the SPIN verification system with HUME is conducted. It is resolved by translating a subset of HUME, known as HW-HUME, into the notation accepted by SPIN. The result of the translation is then verified. An empirical analysis performed on the translation and verification result led to a promising result for this combination. The analysis also provided some interesting relationships between HUME and the verification time and workload.
Bibliography [1] A. G. Kaloxylos. An Estelle to Promela Compiler. Master’s thesis, Heriot-Watt University, 1994. [2] Andrew W. Appel. Modern Compiler Implementation in Java: Basic Techniques. Cambridge University Press, 1997. [3] Bandera Project Homepage. http://bandera.projects.cis.ksu.edu/. August 2004. [4] Bell-Labs News:
Gerard Holzmann Wins Prestigious ACM Software System Award.
http://www.bell-labs.com/news/2002/march/holzmann.html. August 2004. [5] B. Berard, M. Bidoit, A.Finkel, F. Laroussinie, A. Petit, L. Petrucci, Ph. Schnoebelen, and P. McKenzie. Systems and Software Verification: Model-Checking Techniques and Tools. Springer, 2001. [6] Richard J. Bird. Introduction to Functional Programming using Haskell. Prentice-Hall Series in Computer Science. Prentice-Hall Europe, London, UK, second edition, 1998. [7] BLAST Project Homepage. http://www-cad.eecs.berkeley.edu/ tah/blast/. August 2004. [8] Edmund M. Clarke, Orna Grumberg, and Doron A. Peled. Model Checking. The MIT Press, Cambridge, Massachusetts, 1999. [9] Edmund M. Clarke and Jeannette M. Wing. Formal Methods: State of the Art and Future Directions. ACM Computing Surveys, 28(4):626–643, 1996. [10] William F. Clocksin and Christopher S. Mellish. Programming in PROLOG: Using the ISO Standard. Springer-Verlag Berlin, fifth edition, 2003. [11] James C. Corbett, Matthew B. Dwyer, John Hatcliff, Shawn Laubach, Corina S. P˘as˘areanu, Robby, and Hongjun Zheng. Bandera: Extracting Finite-State Models from Java Source Code. In International Conference on Software Engineering, pages 439–448, 2000. [12] Martin Fowler and Kendall Scott. UML Distilled: Applying the Standard Object Modeling Language. The Addison-Wesley Object Technology Series. Addison Wesley Longman, Inc., 1997. [13] Functional Programming at the University of St Andrews. http://www-fp.dcs.st-and.ac.uk/. August 2004. 67
[14] Rob Gerth. Concise Promela Reference. http://spinroot.com/spin/Man/Quick.html, 1997. [15] James Gleich. A Bug and a Crash: Sometimes a Bug Is More Than a Nuisance. New York Times, December 1996. [16] Greg Michaelson and Kevin Hammond and Jocelyn Serot. The Finite State-Ness of FSMHume. In Draft paper submitted to TFP 2003; Symposium on Trends in Functional Programming, Edinburgh, Scotland, September 2003, 2004. [17] Klaus Havelund and Thomas Pressburger.
Model Checking Java Programs Using Java
PathFinder. International Journal on Software Tools for Technology Transfer, 2(4), April 2000., 1998. [18] G. J. Holzmann. The Spin Model Checker, Primer and Reference Manual. Addison-Wesley, Reading, Massachusetts, 2003. [19] Gerard J. Holzmann. Basic Spin Manual. http://spinroot.com/spin/Man/Manual.html, October 1995. [20] Gerard J. Holzmann. The Model Checker SPIN. Software Engineering, 23(5):279–295, 1997. [21] JavaCC Home Page. https://javacc.dev.java.net/. August 2004. [22] JavaCC: JJTree Reference. https://javacc.dev.java.net/doc/jtree.html. August 2004. [23] jSpin - A Java GUI for Spin. http://stwww.weizmann.ac.il/g-cs/benari/jspin/index.htm. August 2004. [24] Greg Michaelson and Kevin Hammond. The Hume Manual, Version 0.1. http://www-fp.dcs.stand.ac.uk/hume/downloads/index.html, 2004. [25] Greg Michaelson and Kevin Hammond. The Hume Report Version 0.2. http://www-fp.dcs.stand.ac.uk/hume/downloads/index.html, 2004. [26] Greg Michaelson and Kevin Hammond. The Hume Report Version 0.3. http://www-fp.dcs.stand.ac.uk/hume/downloads/index.html, 2004. [27] N. Petalidis. Translating Lotos Specifications Into Promela. Master’s thesis, Heriot-Watt University, 1994. [28] Hanne Riis Nielson and Flemming Nielson. Semantics with Applications: A Formal Introduction. Wiley Series in Data Communications and Networking for Computer Progammers. wiley, chichester, 1992. [29] Nikolaj Bjorner and Anca Browne and Michael Colon and Bernd Finkbeiner and Zohar Manna and Henny Sipma and Tomas Uribe. Verifying Temporal Properties of Reactive Systems: A STeP Tutorial. Kluwer Academic Publishers, 2000. [30] Patrick Regan and Scott Hamilton. NASA’s Mission Reliable. Innovative Technology for Computer Professionals: Computer, January 2004.
[31] Robin Hunter. The Essence of Compilers. Prentice-Hall, 1999. [32] Spin Home Page. http://spinroot.com/spin/. August 2004. [33] The Hume Language: Home Page. http://www-fp.dcs.st-and.ac.uk/hume/. August 2004. [34] The Stanford Temporal Prover (STeP). http://www-step.stanford.edu/. August 2004. [35] Willem Visser, Klaus Havelund, Guillaume Brat, and SeungJoon Park. Model Checking Programs. In IEEE International Conference on Automated Software Engineering (ASE) , September 2000.
Appendix A
Abstract Syntax for Hw-Hume Backus Naur Form, or just BNF notation, is used to describe the abstract syntax of HW-HUME. The syntax is based on the syntax for full HUME [25]. The same names have been used to describe the nonterminals as in [25]. Bold text is used when representing terminals, and vertical bars ’|’ indicate alternatives. Optimal constructs are enclosed in brackets ’[ ]’ and parentheses ’( )’ indicate grouping. Ellipses ’. . . ’ indicate obvious repetitions. Each syntax definition has been named Definition #, where ’#’ is an unique number. This has been done so they can be easily referred to in later chapters.
A.1
Programs and Modules
A program in HW-HUME starts with the program keyword. Definition 1
A.2
hprogrami
::=
program hdeclsi
Declaration Language
Each declaration in HW-HUME is separated by a semi colon ’;’. Definition 2
hdeclsi
::=
hdecl0 i ; ... ; hdecln i
n>0
Compared to HUME only a restricted set of types are allowed in HW-HUME . The type declaration is allowed to declare a new data, stream together with box and wire declarations are allowed. hdecli Definition 3
::= | | |
type htypeidi hvaridi = htypei stream hiodesi hboxdecli hwiringdecli
HW-HUME supports both input streams specified by from and output streams specified by to. Definition 4
hiodesi
::=
hstreamidi ( from | to ) hstringi 70
A.3
Types
Definition 5
htypei
::= |
hexprtypei stream hexprtypei
- stream type
An expression type can either be a base type, or a tuple of types. In the latter case it cannot be an empty tuple.
Definition 6
::= |
hexprtypei
- base type - tuple
hbasetypei ( htypei , htypesi )
In the list of types each type is separated by a comma ’,’. The list can however be empty, i.e. consist of 0 items. Definition 7
htypesi
::=
htype0 i , . . . , htypen i
n>0
HW-HUME supports a subset of the types found in full HUME . Only word, int and char are supported. For the two first types the number of bits required must be specified. hbasetypei Definition 8
::= | |
word hprecisioni int hprecisioni char
In the word and int types, the number of bits that may be used for the representation must be a number between 1 and 64 inclusively. Definition 9
A.4
::=
hprecisioni
1 | ... | 64
Expression Language
The expression language is stripped down to only include variables, constants and tuples. Hence function and constructor applications are removed. The same applies to local definitions, arithmetic, case expression and conditionals. Also types coercions , timeouts and exceptions are removed. Lists and vector are not allowed either. Macro expansions are not supported, neither are ignored output. Empty tuples are not allowed either. hexpri Definition 10
::= | | |
hconstanti hvaridi ( hexpri , hexprsi ) ( hexpri )
- variable/constant - tuple - grouping
In an expression list, each expression is separated by a comma. The list can be empty. Definition 11
hexprsi
::=
hexpr0 i , . . . , hexprn i
n>0
The matches are only used in the box body in HW-HUME . Each match is separated by a vertical bar ’|’, and at least one must be present. Definition 12
::=
hmatchesi
hmatch0 i | . . . | hmatchn i
n>0
Each match is formed by a pattern that must be matched and an expression separated by an arrow. Definition 13
::=
hmatchi
hpatti → hexpri
As with expressions, patterns are stripped down to only variables, constants and tuples. hpatti Definition 14
::= | | |
hconstanti hvaridi ( hpatti , hpattsi ) ( hpatti )
- variable - tuple pattern - grouping
Each pattern is separated by a comma ’,’ and the list of pattern may be empty. Definition 15
A.5
hpattsi
::=
hpatt0 i , . . . , hpattn i
n>0
Coordination Language
The coordination layer is built up by boxes and wiring.
A.5.1 Boxes A box declaration in HW-HUME consists of the same elements as in full HUME . It starts with the box keyword followed by the id of the box, the box prelude, and at the end the body of the box.
Definition 16
hboxdecli
::=
box hboxidi hpreludei hbodyi
As in full HUME, the prelude defines the input and output types of the box, each specified in an inoutlist.
Definition 17
hpreludei
::=
in ( hinouti , hinoutlisti ) out ( hinouti , hinoutlisti )
The inoutlist contains a set of inout items, each separated by a comma ’,’. The list must have at least one inout item. Definition 18
hinoutlisti
::=
hinout0 i , . . . , hinoutn i
n>0
The inout definition has been changed slightly, compared to the one found for full HUME in [25]. This is to be able to express the translation semantics, when translating to PROMELA . The difference is the extra varidlist element. An inout element may consist of several varid elements, but at least one.
Definition 19
hinouti
::=
hvaridi , hvaridlisti :: hexprtypei
In the varidlist each varid element is separated by a comma ’,’ and the list may be empty. Definition 20
::=
hvaridlisti
hvarid0 i , . . . , hvaridn i
n>0
In the body of the box, it is first specified whether fair or unfair matching is used. Fair matching is specified by using the fair keyword, and unfair matching is specified by the match keyword. This is followed by a boxmatches element. Definition 21
hbodyi
::=
( match | fair ) hboxmatchesi
The boxmatches element is identical to the matches element defined in definition 12. Definition 22
::=
hboxmatchesi
hmatchi | hmatchesi
A.5.2 Wiring The other part of the coordination layer are the wiring declarations. The allowed wiring declarations are a subtype of what is allowed in full HUME [25]. The legal constructs are the instantiate sentence to instantiate a template, together with the template declaration and wire declaration. Replications of boxes are not allowed, nor are macros or initial declarations. Repeated wiring declarations are also illegal. ::= | |
hwiringdecli Definition 23
instantiate hwireidi as hboxidi [ * hintconsti ] htemplatedecli hwiredecli
Template declarations are performed in the same way as box declarations with the only difference being that the box keyword is replaced by the template keyword. Definition 17 defines the prelude, while definition 21 defines the body. Definition 24
htemplatedecli
::=
template htemplateidi hpreludei hbodyi
The wire declaration starts with the wire keyword. This is followed by the id of the wire, which must be the same as the id of the corresponding box. Next the sources of the input of the corresponding box, followed by the destinations of the output of the box. Definition 25
hwiredecli
::=
wire hwireidi hsourcesi hdestsi
The sources consist of a link element followed by link list element, inside parentheses. This definition is changed compared to full HUME [25]. Definition 26
hsourcesi
::=
( hlinki , hlinklisti )
The dests has the same syntax as the sources element.
Definition 27
::=
hdestsi
( hlinki , hlinklisti )
The linklist element is not in the full HUME specification. It is a list of link elements, where each element is separated by a comma ’,’. The list may be an empty list. Definition 28
hlinklisti
::=
hlink0 i , . . . , hlinkn i
n>0
The link element is made up by a link specification element and a link properties element. Definition 29
hlinki
::=
hlinkspeci hlinkpropsi
A link specification is either a connection, which is to a box, or it is a stream identification, that is the name of the stream.
Definition 30
hlinkspeci
::= |
hconnectioni hstreamidi
In a connection a dot notation ’.’ is used to find the correct variable in the correct box. The box is identified by it’s unique id and the variable by it’s unique id in the box. Definition 31
hconnectioni
::=
hboxidi . hvaridi
The linkprops element is made of 0 or more linkprop elements - hence it may be empty. Definition 32
hlinkpropsi
::=
hlinkprop0 i . . . hlinkpropn i
n>0
The only allowed linkprop element is to set the initial value. This is done by using the initially keyword. Definition 33
hlinkpropi
::=
initially hexpri
Appendix B
Translation Rules for Hw-Hume B.1 Introduction This chapter describes the translation rules from HW-HUME to PROMELA. The syntax used to describe the semantics in the translation is based on [28]. The syntax is as follows: Rule #
Ruletype ~ hHW-HUME codei 7→ hPROMELA codei | Reference ~ hargumentsi
Each semantic rule has a number, indicated by ‘#’. This is used to refer to the rule in the text. The rule is also of a certain rule type, so the rules of the same kind can be grouped together. The HW-HUME code is inside the semantic brackets ‘~ ’. The corresponding PROMELA code is on the right hand side of the arrow. This side can also contain references to other rules, specified by the rule type, and the arguments inside the semantic brackets ‘~ ’. Terminals in the text are marked with bold text, and a special font is used to reference rules and rule types. E.g. when in the text it is stated that Ruletype2 is used, it indicates that the rule with that set of arguments of the specified rule type is called. If several rules have the same parameters, both are used unless specified otherwise. In some rules an item with the form helement hii i might appear. In this case hii represents the relative position of the element. For instance in a tuple it can represent the position of the element. The text also contains references to the abstract syntax. Each syntax definition had the name definition followed by the definition number. The HW-HUME abstract syntax is defined in appendix A.
B.1.1
Structure of the Promela Program
Figure B.1 shows the structure of the PROMELA program. All the channels must be declared first in the file. The channels are used for the interprocess communication. This is described in section B.5. The next step is to create all the processes. They are the PROMELA representation of a HW-HUME box1 .
The process declaration is explained in section B.6.
In HW-HUME each process executes sequentially while PROMELA processes execute concurrently. A special control process, forcing the PROMELA model to execute the same way as HW-HUME, is 1
Note that templates are instantiated into boxes. This is handles by the Hume parser, and is not considered.
75
1. Channel Declaration 1.1 Control Channels
1.2 Interprocess Channels
2. Process Declaration
3. Control Process Declaration
4. Stream Process Declaration 4.1 Input Streams
4.2 Output Streams
5. Init Process Declaration
Figure B.1: The Structure of the Translation
therefore created. This is explained in section B.7. HW-HUME supports input streams and output streams. Input streams are replaced by a simulator process that simulates the user inputs. As in HW-HUME, a process is used to represent an output stream. Section B.8 describes these processes. Section B.9 describes the declaration of the init process that instantiates all the processes, and initialises the channels with an initial value if it is specified in HW-HUME.
B.2 Data Types In model checking memory usage is one of the biggest problems. Therefore it is important to use the smallest data types possible. However, the data types must also correspond to the HW-HUME data types. The semantic rules for translating data types from HW-HUME to PROMELA is defined by
Types :
Types : HW-HUME Data Types ,→ PROMELA Data Types Figure 2.1 in chapter 2 contains the base types in HUME. Figure 3.1 in chapter 3 displays the base types in PROMELA. HW-HUME only contains a subset of the base types found in HUME. These are defined in definition 8 on page 71. A word is a positive integer value, where the number of bits must be a specified value ranging from ‘1’ to ‘64’ inclusively. If the value is one bit, the PROMELA type bit is used. Rule 1
Types ~ word 1 7→ bit
For values up to one byte (8 bits) the PROMELA type byte is used. It is a positive integer value of 8 bits.
Rule 2
Types ~ word 2 | . . . | 8 7→ byte
If the bit size of the integer is between 9 and 16 bits, the short value is used. Rule 3
Types ~ word 9 | . . . | 16 7→ short
For any values bigger than 16 bits, the PROMELA int value is used. It is only 32 bits, so for any values where the bit size is bigger, the values will not correspond. SPIN will automatically truncate the value to ‘0’ if the value exceeds 32 bits. Rule 4
Types ~ word 17 | . . . | 64 7→ int
A different approach would be to represent a word bigger than 32 bits with a typedef, containing two values, or just use two values. The problem is that this will complicate all other operations, without helping the main issue, which is to mainly model check the interaction between the boxes in HW-HUME. The approach formalised in rule 4 will be closer to the HW-HUME model. Rule 5 to 7 defines the semantics for translating integers. In HW-HUME an integer is constructed by specifying int followed by the bit size of the integer. Like with the word type, it is important to keep the type representation as small as possible. The PROMELA type bit is used for 1 bit integers. Rule 5
Types ~ int 1 7→ bit
PROMELA has a 16 bit integer representation called short. This is used for bit sizes ranging from 2 to 16 bits. Note that the type byte that was used for the word type cannot be used since it can only hold positive integers. Rule 6
Types ~ int 2 | .. | 16 7→ short
The largest possible PROMELA representation of an integer is a 32 bit int. Like for word, the HWHUME int type can use up to 64 bits. This problem is solved the same way as with the word type, i.e. truncate the value to ‘0’ if it exceeds 32 bits. Rule 7
Types ~ int 17 | .. | 64 7→ int
There is no representation for characters in the PROMELA language, as there is in HW-HUME. Removing all characters will take away too much from the PROMELA model compared to the HW-HUME model, and will not give a satisfying result. Each character has a special code called ASCII code or Unicode, which is a numeric value. Representing the character with the ASCII code will give a satisfying PROMELA model, that corresponds with the model in HW-HUME. A Unicode value uses 16 bit, which can be represented by a PROMELA short type. Rule 8
Types ~ char 7→ short
Tuples are the only structured type allowed in HW-HUME. There can either be represented by declaring a new structured type in PROMELA using a typedef declaration, or as a channel. Tuples are only used when boxes are communicating, which means the best result is achieved by using channels. In channels each type is separated by a comma, therefore to translate a tuple, each item in the tuple must be translated independently, and a list of the translated items, separated by a comma must be returned. In a tuple the items are enclosed by parentheses. These are removed.
Rule 9
Types ~
( hexprtypei ) 7→
Types ~
hexprtypei
The tuple is then recursively traversed, and each type is individually translated, divided by a comma. The full list is returned. Rule 10
Types ~ 7→
htypei , htypesi htypei , Types ~ htypesi
Types ~
B.3 Values The semantic rules Types is concerned with translating the declaration of the types. An instance of a type contains a value, which must be translated to a correct PROMELA representation. The semantic rules for this translation are defined by Values :
Values : HW-HUME Values ,→ PROMELA Values The values in HW-HUME are either numeric or characters. The two numeric values, i.e. int and word, will be using the same values in PROMELA as in HW-HUME , regardless of size. SPIN will automatically truncate the value to 0, when it is out of bounds. Rule 11
Values ~
hinti 7→ hinti
Rule 12
Values ~
hwordi 7→ hwordi
Characters, on the other hand, cannot be used directly in PROMELA. Rule 8 states that the Unicode value is used to represent the character in PROMELA, which uses a 16 bit short for representation. Consequently the HW-HUME char must be translated to a short. Rule 13
Values ~
hchari 7→ hshorti
In HW-HUME there are two exceptions to rule 13. These are the escape sequences, which do not have a Unicode value, and must be given an unique value. The valid escape sequences in HW-HUME are newline ‘\n’ and tabulator ‘\t’. Since a Unicode value is always positive, these types will be given the values ‘-1’ and ‘-2’ respectively. These two rules override rule 13. Rule 14
Values ~
‘\n’ 7→ −1
Rule 15
Values ~
‘\t’ 7→ −2
When it is possible variables will have the same names in PROMELA as in HW-HUME. In some cases the names have to be changed slightly to be valid PROMELA.
Names
is applied to ensure that the
name is valid. Rule 16
Values ~
hvaridi 7→
Names ~
hvaridi
If the value is a tuple it is enclosed by parentheses. These are removed in rule 17. Rule 17
Values ~
( htypesi ) 7→
Values ~
htypesi
A tuple can contain several values. If this is the case each value will be translated independently. A list of all translated types, separated by a comma, is then returned as rule 18 formalises. Rule 18
Values ~
htypei , htypesi 7→
Values ~
htypei , Values ~ htypesi
B.4 Names Some names allowed in HW-HUME are ineligible in PROMELA. This can be names used for boxes, wiring, variables, and so on. PROMELA names.
Names denotes the semantics for the translating the names into valid
Names : HUME Names ,→ PROMELA Names There are two different cases where the HW-HUME name is disallowed in PROMELA. The first case is the set of terminals (keywords), which in PROMELA differs from the set of terminals in HW-HUME. PROMELA includes the following set of terminals: hterminali ::= active | assert | atomic | bit | bool | break | byte | chan | c code | c decl | c expr | c state | c track | chan | D proctype | do | d step | else | empty | enabled | eval | false | fi | full | goto | hidden | if | init | inline | int | len | local | mtype | nempty | never | nfull | notrace | np | od | of | pc value | pid | printf | printm | priority | proctype | provided | run | short | show | skip | timeout | trace | true | typedef | unless | unsigned | xr | xs All that has to be done to translate a terminal to a non-terminal is to append a character to the name, providing the new word is not a terminal. If ‘1’ is appended to the end of a terminal, this will not happen since there are no terminals ending in ‘1’. Rule 19
Names ~
hterminali 7→ hterminali1
HW-HUME allows the use of a single quotation mark in a name. In PROMELA names quotation marks are eligible, and so need to be handled. Rule 20 replaces each quotation mark with the letter ‘q’ to make it valid. Rule 20
Names ~
hstringi’hstringi 7→ hstringiqhstringi
B.5 Channels Channels are used in two semantically different cases, control channels and interprocess communication.
ControlChan constitutes the communication with the control process that uses semaphores
to enforce the HW-HUME execution model into the PROMELA model (Section B.5.1). Channels are also used for the interprocess communication specified by the wiring in HW-HUME. Chan constitutes the semantics for these channels, and is defined in section B.5.2.
B.5.1
Control Channels
A control process is used to convert the HW-HUME execution model into the PROMELA model. The control process communicates with each process using a synchronous channel. This section contains the semantics for the channels, and
ControlProc
in section B.7 contains the semantics for the
control process. Each channel is a synchronous channel that contains an enumerated type (mtype). Each channel has the following syntax:
chan < i d > c o n t r o l = [ 0 ] o f { mtype } ;
The hidi element represents the name of the process, extracted from a wire or stream declaration.
ControlChan denotes the semantics of the control channels.
ControlChan : HUME ,→ PROMELA Channel One channel must be created for each process, including the stream processes. The message sent over the channels is of type mtype, which is the enumerated type in PROMELA. The execution model found in HW-HUME is reached by using a control process that sends a ‘BEGIN’ message using the synchronous control channel to a process when it is the process’ turn to execute. When the process has finished one run, it returns an ‘END’ message back to the control process using the same channel. Then the process is blocked until it receives a new ‘BEGIN’ message. This implies that the enumerated type holds two values ‘BEGIN’ and ‘END’ and is declared as follows:
mtype = { BEGIN , END } ;
The wire declaration is used to create a control channel for a HW-HUME box. For a stream, the stream declaration is used. In addition the mtype must be declared. Recursion is used by iterating through all declarations to ensure that all the channels are created. To be sure that the mtype is declared only once , the first run declares it and calls the rule that traverses the declarations. Rule 21
ControlChan ~ hdeclsi
7→ mtype = { BEGIN , END }; ControlChan ~ dec hdeclsi
If a wire declaration is found the correct rule has to be applied. Recursion is used to ensure that the other declarations are found. Rule 22
ControlChan ~ dec hwiredecli; hdeclsi 7→ ControlChan ~ hwiredecli ControlChan ~ dec hdeclsi
A control channel must also be created for stream declarations. Like the previous rule, the rule is recursive to make sure that all channels are created. Rule 23
ControlChan ~ dec hstreamdecli; hdeclsi 7→ ControlChan ~ hstreamdecli ControlChan ~ dec hdeclsi
The following rule defines the creation of a channel from a wire declaration. The name of the wire is used to ensure that the channel name is unique.
Names is used to ensure that the name is valid
PROMELA. Rule 24
ControlChan ~ wire hwireidi hsourcesi hdestsi 7→ chan Names ~ hwireidi control = [ 0 ] of { mtype };
Control channels must also be created for each input and output stream process. As the previous rule used the wire name, so the stream name is used to make sure that the name is unique. Rule 25 and 26 create the control channels for input and output streams respectively. Rule 25
ControlChan ~ stream hstreamidi from hstringi 7→ chan Names ~ hstreamidi control = [ 0 ] of { mtype };
Rule 26
ControlChan ~ stream hstreamidi to hstringi 7→ chan Names ~ hstreamidi control = [ 0 ] of { mtype };
B.5.2
Interprocess Communication
A HW-HUME program consist of a set of boxes. The boxes are connected to each other or to streams by using wiring declarations. In PROMELA interprocess communication is achieved using channels. Each channel created from a box declaration has the following syntax (the stream channels will have a different syntax, shown later):
chan < b o x i d> < v a r i d > = [ 1 ] o f < e x p r t y p e >;
In HW-HUME each box has a corresponding wire declaration, which defines the source of the inputs and the destination of the outputs. In addition, the box specifies the inputs and outputs in its prelude. This suggests that there are four different sources for creating the channels in PROMELA. The problem with using the wire declaration is that it doesn’t specify the types sent over the channel. This implies that only the input and output of the box can be used. In the translation the output of the box has been chosen. For each variable in each box output-element, a channel is created. The semantic rules for creating the channels used for interprocess communication is denoted by Chan .
Chan : HW-HUME Interprocess Communication ,→ PROMELA Channels First all the box declarations must be found, and the correct rule must be applied to it. In rule 27 this is accomplished by recursively iterating all declarations. Rule 27
Chan ~ hboxdecli; hdeclsi 7→ Chan ~ hboxdecli Chan ~ hdeclsi
In each box declaration only the unique name of the box, together with the output-items are required to create the channels, as formalised in rule 28. Rule 28
Chan ~ 7→
box hboxidi in ( hinoutlist1 i ) out ( hinoutlist2 i ) hbodyi hboxidi hinoutlist2 i
Chan ~
Definition 18 defines the syntax for the list with the out-items. Each of these items is separated by a comma. As rule 29 shows, recursion is used to iterate through each item in the list. The correct rule is then applied to each item separately. Rule 29
Chan ~ hboxidi hinouti , hinoutlisti 7→ Chan ~ hboxidi hinouti Chan ~ hboxidi hinoutlisti
Each output-element has a list of minimum one variable name, and the expression type, separated by two colons ‘::’. A channel must be created for each variable, therefore each variable must be translated separately. The box name and type is also required. Rule 30 iterates the list and calls the correct rule with the specified arguments.
Rule 30
Chan ~ hboxidi hvaridi , hvaridlisti :: hexprtypei 7→ Chan ~ hboxidi hvaridi hexprtypei Chan ~ hboxidi hvaridlisti::hexprtypei
Rule 31 creates the PROMELA channel. It has the syntax specified in the beginning of the section. Names is used to get a legal PROMELA name for the box name and variable name, while Types is used to get the corresponding PROMELA data type.
Rule 31
Chan ~ hboxidi hvaridi hexprtypei 7→ chan Names ~ hboxidi Names ~ = [1] of { Types ~ h exprtype i };
hvaridi
In addition to the communication between boxes in HW-HUME, there are communication links to the streams. In PROMELA the streams are represented as processes, and channels must be created between the process that uses the stream process, and the stream process itself. Note that in HWHUME the relationship to a stream is a 1:1 relationship. This implies that only one box can be wired to a stream. Since the channels are created from the output of HW-HUME boxes, the channel used by an output stream process is already created. Hence channels are only created for the input stream processes. The channel created from an input stream has the following syntax:
chan < s t r e a m i d> o u t = [ 1 ] o f < e x p r t y p e >;
The name of the channel is the stream followed by ‘ out’, thus the name of stream is required. The correct expression type is also required. This is found in the prelude of the box that uses the stream. Rule 32 finds all input streams using recursion. To be able to create the channel the type is required. This is defined in the box declaration that uses the stream. To find the type
Stream
defined in
section B.8 is used. Rule 32
Chan ~ stream hstreamidi from hstringi; hdeclsi 7→ Chan ~ stream Stream ~ stream hstreamidi from hstringi; hdeclsi
The inputs in rule 33, except the stream keyword, are returned when using Stream . The rule creates
the PROMELA code using the defined syntax. It uses Names to ensure that the stream name is a valid
PROMELA name, and Types to get the PROMELA type corresponding to the one found in HW-HUME . Rule 33
Chan ~ stream hwireidi hstreamidi hvaridi hexprtypei 7→ chan Names ~ hstreamidi out = [1] of { Types ~ hexprtypei };
B.6 Processes This section declares the rules for translating HW-HUME boxes into PROMELA processes.
Proc de-
notes the semantics for this translation.
Proc : HW-HUME Boxes ,→ PROMELA Processes It is a cumbersome process to translate the HW-HUME boxes into PROMELA processes, and thus it has been divided into three different parts, giving the process the following syntax:
< p r o c e s s p r e l u d e >{
The process prelude, declared in section B.6.1, creates the signature of the process. The variable declaration declares the variables, if the process contains variables, and process body is concerned with creating the main body of the process. The two last parts are created in section B.6.2 and B.6.3 respectively. Rule 35 formalises this, while rule 34 traverses all declarations to obtain all the box declarations.
Prelude denotes the creation of the process prelude, Vars
the variable declaration,
and Body the creation of the main body of the process. Rule 34
Rule 35
B.6.1
Proc ~ Proc ~ 7→
hboxdecli; hdeclsi 7→
Proc ~ hboxdecli Proc ~ hdeclsi
hboxdecli Prelude ~ hboxdecli { Vars ~ hboxdecli Body ~ hboxdecli }
Process Prelude
The signature or prelude of the process is divided into two different parts. This first defines the process name and then declares the formal parameters of the process. The process prelude has the following syntax: p r o c t y p e < p r o c e s s i d > ( chan < p a r a m e t e r l i s t > )
The process name is the same as the box name, and all parameters are channels.
Prelude denotes
the semantics for the process prelude.
Prelude : HW-HUME Box ,→ PROMELA Process Prelude The creation of the process name and the formal parameter declaration are separated out into two different parts, as shown in rule 36. The next section describes the first part, and the section after describes the second part. Rule 36
Prelude ~ hboxdecli 7→ Prelude ~ name hboxdecli Prelude ~
param hboxdecli
Name Definition The name of a PROMELA process is the name of the corresponding HW-HUME box. To ensure that the name is a valid PROMELA name, Names is applied. To declare that it is a process, the proctype keyword starts the declaration. Rule 37 formalises this. Rule 37
Prelude ~ name box hboxidi hpreludei hbodyi
7→ proctype Names ~ hboxidi
Defining Parameters The parameterlist is created based on the input and output elements in the prelude of a HW-HUME box. Rule 38 extracts the prelude from the box declaration. Rule 38
Prelude ~
param box hboxidi hpreludei hbodyi 7→ Prelude ~ hpreludei
Rule 39 shows the creation of the parameterlist in PROMELA. All parameters are channels - hence the list must start with the chan keyword. The input channels, i.e. the channels that are read from, are created from the input element in the prelude of a HW-HUME box, while the output channels, which are written to, are created from the output element in the prelude. In addition, each PROMELA process also includes a channel called ‘control’, used to coerce the HW-HUME execution model onto the PROMELA model. Each item in the parameterlist is separated by a comma and the parameterlist is enclosed by parentheses. Rule 39
Prelude ~
in ( hinoutlist1 i ) out (hinoutlist2 i) 7→ ( chan Prelude ~ in hinoutlist1 i , Prelude ~ out hinoutlist2 i , control )
The input channels are created from the list of input items in the HW-HUME box prelude. Each input item is separated by a comma. Rule 40 traverses the list and manages each input separately. In the parameterlist for the PROMELA process each channel is also separated by a comma. Rule 40
Prelude ~ in hinouti , hinoutlisti 7→ Prelude ~ in hinouti , Prelude ~
in hinoutlisti
Only the variable name is used to declare a channel. Rule 41 extracts all variable names from the input-element. Rule 41
Prelude ~ in hvaridi , hvaridlisti :: hexprtypei 7→ Prelude ~ in hvaridi , Prelude ~ in hvaridlisti :: hexprtypei
The input channels will be given the name in n , where n is a numeric value reflecting the variable’s relative position in the input list starting with ‘1’. E.g. if a box has three inputs the list “in1, in2, in3” is generated. This is illustrated in rule 42. Rule 42
Prelude ~
in hvaridhii i 7→ inhii
The output channels are created the same way as input channels, with the only differences being that the list of output items is used instead and the name starts with ‘out’. Rule 43 is the output version of rule 40.
Rule 43
Prelude ~ out hinouti , hinoutlisti 7→ Prelude ~ out hinouti , Prelude ~
out hinoutlisti
In same way as the previous rule corresponded to rule 40, rule 44 correspond to rule 41. Rule 44
Prelude ~ out hvaridi , hvaridlisti :: hexprtypei 7→ Prelude ~ out hvaridi , Prelude ~ out hvaridlisti :: hexprtypei
Each output channel are given the name out n , where n reflects the relative position, the same way as it does for input channels. This is formalised in rule 45. Rule 45
B.6.2
Prelude ~ out hvaridhii i
7→ outhii
Variable Declarations
In HW-HUME variables are declared in the pattern matches. This cannot be done in PROMELA, since variables cannot be used before they are declared. The variables have to be declared before the process enters its main loop. The variables are declared by going through all pattern matches. If a variable is found, and it is not already declared, the process prelude is used to declare it. The semantics for creating the variables are denoted by Vars .
Vars : HW-HUME ,→ PROMELA Variable Declaration To declare a variable the variable name and data type must be known. In HW-HUME the variable name is declared in a pattern match, which is in the box body, and the data type is declared in the box prelude. Rule 46 extracts these elements from the box declaration. Rule 46
Vars ~ box hboxidi hpreludei hbodyi 7→ Vars ~ hpreludei hbodyi
Rule 47 extract the list with the input-items from the prelude. The output items are not required since variables are declared in the pattern matches. The boxmatches element is extracted from the body. Rule 47
Vars ~ 7→
in ( hinoutlist1 i ) out ( hinoutlist2 i ( match | fair ) hboxmatchesi ) Vars ~ hinoutlist1 i hboxmatchesi
When declaring the variables, the data type of the variable in the prelude is used. For a variable declaration in a pattern match in HW-HUME, the expression type in the same position must be found. This implies that for all patterns the corresponding expression type must be obtained. First each input element is extracted. Rule 48
Vars ~ hinouti , hinoutlisti hboxmatchesi 7→ Vars ~ hinouti hboxmatchesi Vars ~
hinoutlisti hboxmatchesi
In each input element all expression types are located by traversing the list of variables.
Vars ~ Rule 49
7→
hvaridi , hvaridlisti :: hexprtypei hboxmatchesi hexprtypei hboxmatchesi hvaridlisti :: hexprtypei hboxmatchesi
Vars ~ Vars ~
The next step is to iterate through all the matches, as performed in rule 50. Rule 50
Vars ~ 7→
hexprtypei hmatchi | hmatchesi Vars ~ hexprtypei hmatchi Vars ~ hexprtypei hmatchesi
A match is built up by a pattern that the input is compared with, and if they match, an expression generates the output. The pattern and expression are separated by an arrow ‘→’. Only the pattern is required, which rule 51 extracts from the match. Rule 51
Vars ~
hexprtypei hpatti → hexpri 7→
Vars ~
hexprtypei hpatti
The pattern may be a tuple, enclosed by parentheses. If that is the case, the parentheses are removed.
Rule 52
Vars ~
hexprtypei ( hpatti ) 7→ Vars ~ hexprtypei hpatti
In rule 53 hii and h ji reflects the respective positions of the expression type and the pattern. The rule finds the pattern that matches the expression. If the current pattern is not in the correct position, the rule checks the next pattern. If it matches, the rule that creates the PROMELA code is called. if [ hii ≡ h ji ]
Rule 53
else
Vars ~
hexprtypehii i hpatth ji i , hpattsi 7→ Vars ~ hexprtypehii i hpatth ji i
Vars ~
hexprtypehii i hpatth ji i , hpattsi 7→ Vars ~ hexprtypehii i hpattsi
Definition 14 defines the syntax of a pattern. A pattern can be of a variable type. It is only if this is the case that the variable is declared. A variable can only be declared once, which rule 54 takes care of. Note that the declarations are per process, and not for the entire model. This means the same declarations are allowed in different processes. Rule 54
B.6.3
if [ hnot declaredi ]
Vars ~
hexprtypei hvaridi 7→
Types ~
hexprtypei Names ~ hvaridi ;
Process Body
The body of a HW-HUME box consists of a set of matches that are compared to the inputs of the box, and generates output based on the input. There are two semantically different approaches in the order of the matches. Fair matching is the first and is introduced by the fair keyword. The last selected match is always compared first with the inputs. Unfair matching or sequential matching is performed in a top to bottom order. It is introduced by the match keyword. Regardless of the match type the PROMELA process representing a HW-HUME box must be synchronised with the control process to coerce the same execution order as in HW-HUME. The general PROMELA code for a HW-HUME box body is:
start : c o n t r o l ?BEGIN ; < F a i r M a t c h i n g > | < U n f a i r M a t c h i n g> finish : c o n t r o l !END; goto s t a r t ;
The synchronisation with the control process is achieved by receiving a ‘BEGIN’ message prior to each run, and sending an ‘END’ message to the synchronous control channel. The ‘start’ label and the ‘goto’ statement ensures infinite repetitions. The ‘finish’ label is used to exit the matching part if the input does not match any of the input. The semantics of the process body is denoted by Body :
Body : HUME ,→ PROMELA Process Body Rule 55 has the box declaration as an argument. Both the prelude and the body elements are required to create the PROMELA code. The rule extracts these elements, and generates the PROMELA code that is independent of the matching form.
Body ~
box hboxidi hpreludei hbodyi 7→ start: control?BEGIN; Body ~ hpreludei hbodyi finish: control!END; goto start;
Rule 55
Fair and unfair matching have completely different semantics. Therefore the semantics of the PROMELA code differs.
Fair
handles the fair matching, and Unfair handles unfair matching. This
is formalised in the following two rules. Rule 56
Body ~
Rule 57
Body ~
hpreludei fair hboxmatchesi 7→ Fair ~ hpreludei fair hboxmatchesi
hpreludei match hboxmatchesi 7→ Unfair ~ hpreludei unfair hboxmatchesi
Fair Matching In fair matching the last pattern matched is chosen first to be matched with the inputs. In PROMELA this can be represented by the non-deterministic if clause. The if clause includes a set of options, where one of the options that satisfies the condition is randomly chosen. The first statement in the option is called the guard condition. If it succeeds the option is satisfied, and the rest of the statements in that option are executed. The syntax of a PROMELA process main body using fair matching is as follows:
if : : < match1> : : < match2> ... : : < matchn> : : e l s e goto f i n i s h fi ;
In the code, each match has two colons as prefix. If no match succeeds, the PROMELA process will be blocked until one does. In HW-HUME it will simply do nothing, and give the control to the next box. In the next run it will start at the beginning again. To gain the same behaviour in PROMELA, the goto statement has been used together with the else keyword. The process will exit the if statement, and go to the ‘finish’ label, which is just after the if statement, if all other matches fails.
Fair
denotes
the semantics for fair matching.
Fair : HW-HUME Fair Matches ,→ PROMELA Nondeterministic Rule 58 creates the if clause enclosing all the matches. The rule also calls the rule that creates the PROMELA code for each match. To end the if clause fi must be used. Rule 58
Fair ~ hpreludei fair hboxmatchesi 7→ if Fair ~ hpreludei hboxmatchesi
::else goto finish fi;
A boxmatches element consists of one or more match elements, each separated by a vertical bar ‘|’. Definition 22 defines that the boxmatches-element is built up of a match and a matches element, where the latter consist of zero or more match-elements. Rule 59 obtains all match-elements, and handle them separately. Rule 59
Fair ~ hpreludei hmatchi | hmatchesi 7→ Fair ~ hpreludei hmatchi Fair ~ hpreludei hmatchesi
The PROMELA code for one specific match is identical for both fair and unfair matching. In both cases
Match
is used. Rule 60 uses
Match
to create the code. Each match has a double colon
prefix, to separate them from each other in the if clause. Rule 60
Fair ~ hpreludei hmatchi
7→ ::
Match ~
hpreludei hmatchi
Unfair Matching When using unfair matching, the matches are selected in a top to bottom order, which gives it a deterministic nature. In PROMELA there is no deterministic selection structure - hence it has to be manually implemented. This can be achieved by using a set of if-else clauses, where each if clause has exactly one option, including a match, and the else clause contains another if-else clause with exactly one option, which holds the next match. One if-else clause will then be created for all matches, except the last one which only has an if clause. The following PROMELA code illustrates this with two matches as example. Like in Fair , if none of the matches succeeds the process control is redirected to the ‘finish’ label.
if : : < match1> : : else if : : < match2> : : e l s e goto f i n i s h fi ; fi ;
Unfair
denotes the semantics for the unfair matching.
Unfair : HW-HUME Unfair Matches ,→ PROMELA Deterministic The semantics for unfair matches are more cumbersome than for fair matches. The first match is different from the rest, since it doesn’t start with an else clause. Rule 61 uses Match to create the PROMELA code for the first match, and calls the rule that creates the PROMELA code for the rest of the matches. Rule 61
Unfair ~ hpreludei match hmatchi | hmatchesi 7→ if :: Match ~ hpreludei hmatchi Unfair ~ hpreludei hmatchesi fi;
Rule 62 and 63 creates the PROMELA code for the rest of the matches. This is achieved by recursively iterating the match elements. Note that the fi statement ends the if clause. Note that if the matcheselement is not empty, the PROMELA code for the succeeding matches must be generated before the fi statement of one match. Rule 62
Unfair ~ hpreludei hmatchi | hmatchesi 7→ :: else if :: Match ~ hpreludei hmatchi Unfair ~ hpreludei hmatchesi
fi;
Rule 63 creates the PROMELA code for the last match, when the matches element is empty. The case with no matches is handled here by forcing the process control to the ‘finish’ label with the goto statement. Rule 63
Unfair ~ hpreludei hmatchi 7→ :: else if :: Match ~ hpreludei hmatchi
:: else goto finish fi;
Matches Tuples complicate the translation of box matches. The problem is that both in the pattern matches and the expressions that generates the output, the expression type is not specified. There is then no way to tell whether a pattern/expression is part of a tuple or not. In “PROMELA for HW-HUME” values in a tuple are written to the same channel, which implies that the knowledge of the expression type is required. A consequence is that the prelude, where the expression type is defined, must be used. Each match has the following PROMELA syntax:
( i n 1 ?[< p a t t 1 > ] & & . . . & & inm ?[< p a t t n > ] ) −> i n 1 ?< p a t t > ; . . . ; i n n ?< p a t t n >; o u t 1 !< e x p r 1 > ; . . . ; o u t i !< e x p r j >;
In the guard condition of a PROMELA match, enclosed by the parentheses, each channel is tested to see if the read operation succeeds. This is achieved by enclosing the right hand side of the read operator ‘?’ in square brackets ‘[ ]’. Note that the number of input channels (‘m’), and the number of patterns (‘n’), might differ due to the use of tuples. If the guard condition succeeds, the values are read from the tuples and the output is sent to the output. The number of output channels (‘i’) and expressions (‘j’) may also differ.
Match denotes the semantics for the matches.
Match : HW-HUME Matches ,→ PROMELA Matches Rule 64 generates the PROMELA code for a match. As input it takes the box prelude, which consist of the list of input-items and the list of output-items, together with the HW-HUME match item. The PROMELA code is divided into three parts. First the guard condition is created using Patt . The guard condition checks if the read operations on the input channels are possible. The guard condition is enclosed by parenthesis. The guard condition is separated from the rest of the statements by an arrow. If the guard condition succeeds, the channels are read from, and the output is sent to the output channels. Reading and omitting values from the input channels and sending the output to the output channels are accomplished using Exp . For all operations the process prelude must be used. For checking and reading from channels the list with the input-elements is required, and to generate the output, the list of output-elements is needed. The rule extracts the correct element in the three different cases.
Match ~
in ( hinoutlist1 i ) out ( hinoutlist2 i hpatti → hexpri 7→ ( Patt ~ hinoutlist1 i hpatti ) → Exp ~ hinoutlist1 i hpatti Exp ~ hinoutlist2 i hexpri
Rule 64
Pattern Matching The pattern matching section is concerned with creating the guard condition. The guard condition has the following syntax in PROMELA: ( i n 1 ?[< p a t t 1 > ] & & . . . & & inm ?[< p a t t n > ] )
The code was explained in the previous section (Match ). The semantics for pattern matches are
denoted by Patt .
Patt : HW-HUME Patterns ,→ PROMELA Guard Condition If the pattern consist of more than one input element, it is surrounded by parenthesis, which are removed in rule 65. Rule 65
Patt ~
hinoutlisti ( hpatti ) 7→
Patt ~
hinoutlisti hpatti
To create the PROMELA code, the expression type in the input element list in the process prelude is first obtained. The list of patterns is then traversed to find the corresponding pattern. This approach will handle the “tuple-problem” described earlier. Rule 66 iterates recursively through the input element list, and handles each input element individually. Rule 66
Patt ~ 7→
hinouti , hinoutlisti hpatti Patt ~ hinouti hpatti Patt ~ hinoutlisti hpatti
Each input element includes a list of one or more variable name elements. Rule 67 recursively separates out each of them. In the guard condition each statement is separated by two ampersands ‘&&’, as the rule shows.
Patt ~
hvaridi , hvaridlisti :: hexprtypei hpatti 7 → Patt ~ hvaridi :: hexprtypei hpatti && Patt ~ hvaridlisti :: hexprtypei hpatti
Rule 67
Rule 68 creates the PROMELA code that checks one channel. The channel name is ‘in’ followed by a number reflecting the relative position of the variable name in the process prelude. A different rule creates the expression on the right hand side of the receive operator ‘?’ since it might be a tuple. Since the channel is only checked, and the values are not omitted from the channel, the expression on the right hand side is enclosed by square brackets. Rule 68
Patt ~
hvaridhii i :: hexprtypei hpatti 7→ inhii ? [ Patt ~ hexprtypei hpatti ]
If the expression type is a tuple, each type is considered separately. In the created PROMELA code a comma will separate each element. Rule 69 illustrates this by using recursion when traversing the type-element list. Rule 69
Patt ~ htypei , htypesi hpatti 7→ Patt ~ htypei hpatti , Patt ~ htypesi hpatti
If the expression type is not a tuple, it must be a base type. If this is the case the pattern corresponding to the type must be found. Rule 70 uses recursion to find the pattern. The rule recursively iterates through the pattern-list. If it finds the pattern corresponding to the expression type, Values is used to translate the HW-HUME pattern to the PROMELA representation. If does not correspond, the pattern is checked using recursion. Note that hii represents the position of the base type in the prelude, and h ji represents the position in the pattern. if [ hii ≡ h ji ]
Rule 70
else
Patt ~ hbasetypehii i hpatth ji i , hpattsi
7→ Values ~ hpatth ji i
Patt ~ hbasetypehii i hpatth ji i , hpattsi
7→ Patt ~ hbasetypehii i hpattsi
Expressions In this section the PROMELA code on the right hand side of the arrow in a match is created. Both the PROMELA code that reads the values from the input channels, and the code to write to the output channels. The semantics are denoted by Exp .
Exp : HW-HUME Expressions ,→ PROMELA Expressions The first thing to do is to read the values from the input channel. The rules here will be almost identical to all the rules in
Patt .
The only difference is that each statement is separated by a
semicolon instead of the two ampersands, and the square brackets enclosing the values are removed. This will give the PROMELA code the following syntax: i n 1 ?< p a t t 1 > ; . . . ; inm?< p a t t n >
Like for rule 65 the parenthesis surrounding the patterns are removed if they exist. Rule 71
Exp ~
hinoutlisti ( hpatti ) 7→
Exp ~
hinoutlisti hpatti
Rule 72 is identical to rule 66. Rule 72
Exp ~
hinouti , hinoutlisti hpatti 7→ Exp ~ hinouti hpatti Exp ~ hinoutlisti hpatti
When reading from channels each operation is separated by a semicolon, compared to two ampersands like in Patt . This is the only difference between rule 73 and rule 67.
Exp ~ 7→
Rule 73
hvaridi , hvaridlisti :: hexprtypei hpatti Exp ~ hvaridi :: hexprtypei hpatti ; Exp ~ hvaridlisti :: hexprtypei hpatti
Rule 74 removes the square brackets surrounding the pattern. This is the only difference from rule 68. It uses Patt to fetch the correct PROMELA values from the pattern. Rule 74
Exp ~
hvaridhii i :: hexprtypei hpatti 7→ inhii ?
Patt ~ hexprtypei hpatti
Creating the output channels is a similar operation as used in Patt . The main difference is that the pattern element is replaced by an expression element, which is similar. The list of input elements is replaced by the list of output elements. Each statement is separated with a semicolon and not two ampersands. The channel name starts with ‘out’ and not ‘in’, and the read operator ‘?’ is replaced with the write operator ‘!’. The syntax is as follows: o u t 1 !< e x p r 1 > ; . . . ; outm !< e x p r n >;
As for rule 65, which removed the parentheses surrounding the patterns if they exists, rule 75 removes the parentheses enclosing the expression. Rule 75
Exp ~
hinoutlisti ( hexpri ) 7→
Exp ~
hinoutlisti hexpri
Rule 76 iterates recursively through the list of output elements the same way as rule 66 does with input elements. Rule 76
Exp ~
hinouti , hinoutlisti hexpri 7→ Exp ~ hinouti hexpri Exp ~ hinoutlisti hexpri
Each statement is separated by a semicolon. Rule 77 obtains each variable name in the outputelement list, and separates them with a semicolon. The rule is similar to rule 67.
Exp ~ 7→
Rule 77
hvaridi , hvaridlisti :: hexprtypei hexpri Exp ~ hvaridi :: hexprtypei hexpri ; Exp ~ hvaridlisti :: hexprtypei hexpri
Rule 78 creates the PROMELA code that writes to the output channel. The channel name is ‘out’ followed by a number representing the relative position in output-element list. The send operator ‘!’ sends the right hand side of the operator to the channel of the left hand side. Rule 78
Exp ~
hvaridhii i :: hexprtypei hexpri 7→ outhii !
Exp ~ hexprtypei hexpri
Rules 79 and 80 find the PROMELA representation of the expression. The only difference between the two rules and rules 69 and 70 in Patt is that ‘pattern’ is replaced by ‘expression’ in the arguments to the rule. Rule 79
Exp ~ htypei , htypesi hexpri 7→ Exp ~ htypei hexpri , Exp ~ htypesi hexpri if [ hii ≡ h ji ]
Rule 80
else
Exp ~ hbasetypehii i hexprh ji i , hexprsi
7→ Values ~ hexprh ji i
Exp ~ hbasetypehii i hexprh ji i , hexprsi
7→ Exp ~ hbasetypehii i hexprsi
B.7 The Control Process In HW-HUME each box executes sequentially, starting with the first declared box. It finishes one run, and then the next declared box finishes one run. When the last declared box has finished its run, the first starts the next run. This is explained in detail in section 2.7. In SPIN the next statement to be executed is the next statement in a randomly selected process. When performing a full verification all possible execution trails are tried. The SPIN execution model is explained in detail in section 3.9.2. The control process is a process which by using rendezvous communication implement semaphores that coerce the HW-HUME execution model into the PROMELA model. The stream processes also implements the execution model. The control process has the PROMELA syntax: a c t i v e proctype C o n t r o l ( ) { do : : [ for each p r o c e s s ] c o n t r o l ! BEGIN ; < b o x i d> c o n t r o l ?END; [ f o r e a c h o u t p u t stream ] < s t r e a m i d> c o n t r o l ! BEGIN ; < s t r e a m i d> c o n t r o l ?END; od ; }
The main body of the process is inside a do loop, which it never leaves, and therefore the process will never terminate. Inside the loop a ‘BEGIN’ message is first sent to the first channel, which
is the control channel to the first process. The control process then receives an ‘END’ message back on the same channel. Since a rendezvous channel is used, the control process is blocked until it receives the message. When it is received it means that the process has finished one run. A ‘BEGIN’ message is then sent to the next process, and so on. Note that the order of the processes is important. The order must be the same as the order they are declared in the HW-HUME source code. When all processes, including the stream processes, have finished one run, the first process starts the second run, and so on. This will repeat itself infinitely. The PROMELA processes now executes sequentially, like HW-HUME boxes. When declaring the control process the proctype uses the active keyword as a prefix which will instantiate one process.
ControlProc denotes the semantics for the
control process.
ControlProc : HW-HUME ,→ PROMELA Control Process For each wire and stream declaration, a control channel must be set up in the program loop. Recursion is used to find these declarations. First the control process signature and do loop must be created. Rule 81 creates these and calls the rule that creates the main body. Rule 81
ControlProc ~
hdeclsi 7→ active proctype Control(){ do ::
ControlProc ~ control hdeclsi
od; }
Each time a wire declaration is found the rule to set up a channel is called. Rule 82
ControlProc ~ control hwiredecli ; hdeclsi 7→ ControlProc ~ hwiredecli ControlProc ~ control hdeclsi
As in the previous rule, each time a stream declaration is located, the correct rule to create the PROMELA code is called. Rule 83
ControlProc ~ control hstreamdecli ; hdeclsi 7→ ControlProc ~ hstreamdecli ControlProc ~ control hdeclsi
For each wire declaration a control channel has been created in section B.5.1. The name of the channel is the wire name with postfix ‘ control’.
Names is used to ensure that the name is a valid
PROMELA name. First the ‘BEGIN’ message is sent to the channel, before the process waits for an ‘END’ message on the channel, as shown in rule 84.
Rule 84
ControlProc ~ wire hwireidi hsourcesi hdestsi 7→ Names ~ hwireidi control ! BEGIN ; Names ~ hwireidi control ? END ;
Rule 85 and 86 achieves the same for streams as rule 84 did for channels. The rules uses the stream name, together with Names which ensures the name is valid PROMELA .
Rule 85
ControlProc ~ stream hstreamidi from hstringi 7→ Names ~ hstreamidi control ! BEGIN ; Names ~ hstreamidi control ? END ;
Rule 86
ControlProc ~ stream hstreamidi to hstringi 7→ Names ~ hstreamidi control ! BEGIN ; Names ~ hstreamidi control ? END ;
B.8 Stream Processes HW-HUME allows both input and output streams. To be able to model check the PROMELA model it must be in a closed environment, meaning that input from the user is not allowed. As a result the user input is replaced by a process that simulates user input. Section B.8.1 describes this process. Output streams cannot manipulate the model, and are therefore allowed. To make the PROMELA model as analogous as possible to the HW-HUME model, the output stream is represented as a process. Section B.8.2 describes the output streams. To be able to create both types of streams, elements in the stream declaration, the wire declaration that wires the stream to a box, and the box declaration that uses the stream are required.
Stream denotes the semantics to find the required elements.
Stream : HW-HUME ,→ Stream Rules The initial rule accepts as argument a stream declaration, together with the all the other declarations. It then iterates through all declarations after wire declarations, and calls the next rule with the wire declaration added to the argument list. From the stream declaration the name of the stream is extracted, together with the ‘from | to’ element that indicates the type of stream.
Rule 87
Stream ~ stream hstreamidi ( from | to ) hstringi; hwiredecli; hdeclsi 7→ Stream ~ ( from | to ) hstreamidi hwiredecli hdeclsi Stream ~ stream hstreamidi ( from | to ) hstringi; hdeclsi
If the stream is an input stream, indicated by the ‘from’ keyword, the sources element is obtained from the stream. Rule 88
Stream ~ from hstreamidi wire hwireidi hsourcesi hdestsi hdeclsi 7→ Stream ~ from hstreamidi hwireidi hsourcesi hdeclsi
If the stream is an output stream, the destinations elements is obtained. Output streams are identified by the ‘to’ keyword. Rule 89
Stream ~ to hstreamidi wire hwireidi hsourcesi hdestsi hdeclsi 7→ Stream ~ to hstreamidi hwireidi hdestsi hdeclsi
Both sources and destinations elements contains a list of minimum one link elements, enclosed by parentheses. These are removed. Rule 90
Stream ~ ( from | to ) hstreamidi hwireidi ( hlinki , hlinklisti ) hdeclsi 7→ Stream ~ ( from | to ) hstreamidi hwireidi hlinki , hlinklisti hdeclsi
Rule 91 iterates through the list with all link elements. Each link element is treated separately.
Rule 91
Stream ~ ( from | to ) hstreamidihwireidi hlinki , hlinklisti hdeclsi 7→ Stream ~ ( from | to ) hstreamidi hwireidi hlinki hdeclsi Stream ~ ( from | to ) hstreamidi hwireidi hlinklisti hdeclsi
A link element is either a connection, i.e. a reference to an input/output variable in a box, or a stream name. Only if the link is a stream, and the name of stream is equivalent to the name of the stream in stream declaration, does processing continue.
if [ hstreamid1 i ≡ hstreamid2 i ]
Rule 92
Stream ~ ( from | to ) hstreamid1 i hwireidi hstreamid2 i hdeclsi 7→ Stream ~ ( from | to ) hwireidi hstreamid 2 i hdeclsi
After the wire declaration elements are extracted, the correct box declaration must be obtained. This is achieved in rule 93, which traverses the declarations after box declarations. Each time a box declaration is found the next rule is called, with the box declaration appended to the argument list.
Rule 93
Stream ~ ( from | to ) hwireidi hstreamidi hboxdecli; hdeclsi 7→ Stream ~ ( from | to ) hwireidi hstreamidi hboxdecli Stream ~ ( from | to ) hwireidi hstreamidi hdeclsi
If the box name is the same as the name of the wire, then the box is the box that corresponds to the wire. Only then will processing continue. Only the prelude is required from the box declaration, and this is extracted. if [ hwireidi ≡ hboxidi ]
Rule 94
Stream ~ ( from | to ) hwireidi hstreamidi box hboxidi hpreludei hbodyi 7→ Stream ~ ( from | to ) hwireidi hstreamidi hpreludei
The prelude consists of the declaration of the input and output elements. If the stream is an input stream, indicated by the ‘from’ keyword, the input elements are extracted. This is formalised in rule 95. Rule 95
Stream ~ from hwireidi hstreamidi in ( hinoutlist 1 i ) out ( hinoutlist2 i ) 7→ Stream ~ hwireidi hstreamidi hinoutlist 1 i
Output streams are indicated by the ‘to’ keyword. In this case the output elements must be extracted from the prelude, like rule 96 illustrates. Rule 96
Stream ~ to hwireidi hstreamidi in ( hinoutlist1 i ) out ( hinoutlist2 i ) 7→ Stream ~ hwireidi hstreamidi hinoutlist 2 i
The list with the input or output elements is traversed in 97. Each element is dealt with individually.
Rule 97
Stream ~ hwireidi hstreamidi hinouti , hinoutlisti 7→ Stream ~ hwireidi hstreamidi hinouti Stream ~ hwireidi hstreamidi hinoutlisti
In the input and output elements, each variable is handled independently. The expression type is also required.
Rule 98
Stream ~ hwireidi hstreamidi hvaridi , hvaridlisti :: hexprtypei 7→ Stream ~ hwireidi hstreamidi hvaridi :: hexprtypei Stream ~ hwireidi hstreamidi hvaridlisti :: hexprtypei
hii and h ji in rule 99 reflect the relative position in the list. If these values are equal the rule returns all arguments. If they are not equal, nothing is returned. if [ hii ≡ h ji ]
Rule 99
Stream ~ hwireidi hstreamidhii i hvaridi hexprtypeh ji i 7→ hwireidi hstreamidhii i hvaridi hexprtypeh ji i
B.8.1
Input Streams
To be able to model check a model, the model has to be closed from its environment. By closed it is implied that the model cannot accept any input from the environment, i.e. the environment cannot manipulate the model. To be able to verify a model all possible runs must be tested. Since there is no way to control the user inputs, this will be impossible. The solution when the HW-HUME model requires input from the user is to create a process that simulates the input. The simulation process in PROMELA has the syntax: a c t i v e proctype process name ( ) {
InStream denotes the semantics for simulating the HW-HUME input stream in PROMELA.
InStream : HW-HUME Input Stream ,→ PROMELA Input Stream Process The rule that creates the simulator (rule 100) accepts an input stream, together with a list of all the other declarations as arguments. Since the simulator has not got any parameters, the active keyword is used as a prefix in the process signature. This will instantiate one process. The process has the same name as the stream.
Names
ensures that the name is valid PROMELA . Rule 101 creates the
body. To extract all the elements needed, rule 100 uses Stream .
Rule 100
InStream ~ stream hstreamidi from hstringi; hdeclsi 7→ active proctype Names ~ hstreamidi (){ Instream ~ Stream ~ stream hstreamidi from hstringi; hdeclsi InStream ~ hdeclsi
}
The body of the simulator is created in rule 101. As an argument it accepts the elements created by
Stream . In the body the output channel and the variables must be declared. Rule 102 and rule 103 respectively declares these. The stream processes also follow the HW-HUME execution model, i.e. they executes in a sequential order, which means that a ‘BEGIN’ message must be received from the control process before each run, and an ‘END’ message must be returned after. The control channels are already declared in section B.5.1. The name of the channel is the stream name followed by ‘ out’.
Names ensures that it uses a
valid PROMELA name. Labels and the goto statement is used in the body, and an if statement is used to check if the output can be written to. The main body is created in rule 106.
Rule 101
InStream ~ hwireidi hstreamidi hvaridi hexprtypei 7→ InStream ~ chan hstreamidi InStream ~ vars hexprtypei start: Names ~ hstreamidi control ? BEGIN; if :: InStream ~ body hexprtypei ::else goto finish fi; finish: Names ~ hstreamidi control ! END; goto start;
Channel Declaration In rule 102 the name of the stream is used to refer the variable out to the correct channel. The channel has the name of the stream followed by ‘ out’.
Names
ensures that the name is valid
PROMELA. Rule 102
Instream ~ chan hstreamidi 7→ chan out = Names ~ hstreamidi out;
Variable Declaration The simulator uses variables when simulating an input stream. The simulator creates the variables corresponding to the type of the input variable in the box that actually uses the stream. The rule accepts this variable as an argument. Since only numeric values are used in “PROMELA for HW-HUME”, different input are simulated in each run by incrementing each variable by ‘1’. The name of the variable is var, followed by a number representing the relative position of the variable, starting at ‘1’. The variable’s initial value is set to ‘0’, as shown in rule 103. Rule 103
InStream ~ vars hbasetypehii i 7→ Types ~ hbasetypehii i varhii = 0;
If the variable is a tuple it is enclosed by parentheses. These are then removed. A variable is created for each of the types in the tuple, as the following two rules formalises. Rule 104
InStream ~ vars ( htypei , htypesi ) 7→ InStream ~ vars htypei InStream ~ vars htypesi
Rule 105
InStream ~ vars htypei , htypesi 7→ InStream ~ vars htypei InStream ~ vars htypesi
Body Definition The main body of the process body is divided into three parts. First the process checks if the channel is empty. This is applied by using the built-in ‘empty()’ function, which returns true if the channel is empty. If it succeeds the current value of the variable(s) are sent over the channel, as shown in rule 108. The last part is to increment all variables by one. Rule 110 denotes this operation. Each operation is separated by a semicolon.
InStream ~ body hexprtypei Rule 106
7→ ( empty( out ) ) → out ! InStream ~ send hexprtypei ; InStream ~ inc hexprtypei ;
For each value, var followed the an integer indicated the variables position, is used to send the current value of the specified variable to the stream.
Rule 107
InStream ~ send hbasetypehii i 7→ varhii
If the variable is a tuple, each value is considered separately, and these are separated by commas. Rule 108
InStream ~ send ( htypei , htypesi ) 7→ InStream ~ send htypei , InStream ~ send htypesi
Rule 109
InStream ~ send htypei , htypesi 7→ InStream ~ send htypei , InStream ~ send htypesi
The last part of the main body of the process body increments the values by one. The ‘hvarnamei++’ assignment is allowed in PROMELA [18], and is used for each of the variables. A semicolon separates each assignment. Rule 110
InStream ~ inc hbasetypehii i 7→ Types ~ hbasetypehii i varhii++;
For tuples each value is dealt with independently. Rule 111
InStream ~ inc ( htypei , htypesi ) 7→ InStream ~ inc htypei InStream ~ inc htypesi
Rule 112
InStream ~ inc htypei , htypesi 7→ InStream ~ inc htypei InStream ~ inc htypesi
B.8.2
Output Streams
An output stream in HW-HUME is a finite state automaton, which a box is wired to. The same model is used in the PROMELA representation of HW-HUME. Since output streams cannot manipulate the model, they are also allowed in SPIN’s verification mode. In PROMELA all output streams, regardless of their destinations in HW-HUME, are written to standard output. Since HW-HUME is translated to PROMELA to be able to model check it, the destination of the stream is unimportant. The only thing that is important that is exists. The syntax of a PROMELA output stream is quite similar to an input stream. The main difference is in the main body. a c t i v e proctype process name ( ) {
The creation of the PROMELA output stream process from a HW-HUME output stream is denoted by
OutStream .
OutStream : HW-HUME Output Stream ,→ PROMELA Output Stream Process Rule 113 creates the output stream. The only difference compared to an input stream is that the rule accepts an input stream as an argument, instead of an output stream, together with the rest of the declarations. The active prefix is used to instantiate a process, and Names is used to create a valid PROMELA name. As for the input stream rule (rule 100), it uses Stream to extract the required
elements. Note that the rule iterates through all declarations so all output stream declarations are gained and translated.
Rule 113
OutStream ~ stream hstreamidi to hstringi; hdeclsi 7→ active proctype Names ~ hstreamidi (){ Outstream ~ Stream ~ stream hstreamidi to hstringi; hdeclsi OutStream ~ hdeclsi
}
The elements Stream extracts from the declarations are used as arguments to rule 114. As for input streams (rule 101) the channel and variables are first declared. The stream process uses the same execution model as “normal” processes - by synchronising with a rendezvous channel to the control process.
Names is used to obtain the correct name. Labels, the goto statement and the if clause are
used for control flow. Rule 119 creates the main body.
Rule 114
OutStream ~ hwireidi hstreamidi hvaridi hexprtypei 7→ OutStream ~ chan hwireidi hvaridi OutStream ~ vars hexprtypei start: Names ~ hstreamidi control ? BEGIN; if :: OutStream ~ body hexprtypei :: else goto finish fi; finish: Names ~ hstreamidi control ! END; goto start;
Channel Declaration In rule 115 the variable in is defined and declared to reference the input channel. This is defined by the box name and variable that writes to the output stream. This channel is already created (section B.5.2). The rule uses Names to ensure that the name is correct. Rule 115
Outstream ~ chan hwireidi hvaridi 7→ chan in = Names ~ hwireidi Names ~
hvaridi ;
Variable Declaration The rules for creating the variables are almost identical to the rules that create the variables for the input stream process (rule 103 - 105). The only difference is that in rule 116 the variables are not given an initial value. Rule 116
OutStream ~ vars hbasetypehii i 7→ Types ~ hbasetypehii i varhii;
Rule 117
OutStream ~ vars ( htypei , htypesi ) 7→ OutStream ~ vars htypei OutStream ~ vars htypesi
Rule 118
OutStream ~ vars htypei , htypesi 7→ OutStream ~ vars htypei OutStream ~ vars htypesi
Body Definition The semantics of the body of the output stream are completely different from the input stream. The body is divided into two parts. First the values that are to be written to the standard-output are read from the channel, and assigned to the declared variables. Then the values are printed to the screen. This is illustrated in rule 119.
Rule 119
OutStream ~ body hexprtypei 7→ OutStream ~ readchan hexprtypei OutStream ~ print hexprtypei
When reading from the channel, the process first checks if it is possible. This is achieved by using square brackets around the variable. This is called the guard condition. If it succeeds, the expressions on the hand right side of the arrow ‘→’ in rule 120 are executed. The channel is then actually read from, and the values in the channel are assigned to the variables. A semicolon is used at the end of each expression to separate it from the next.
Rule 120
OutStream ~ readchan hexprtypei 7→ ( in ? [ OutStream ~ read hexprtypei ] ) → in ? OutStream ~ read hexprtypei ;
Rule 121 obtains the correct name of a base type. The name is var, followed by a number indicating the relative position of the variable. Rule 121
OutStream ~ read hbasetypehii i 7→
varhii
The type in the channel may be a tuple, in which case rules 122 and 123 traverse the tuple to extract the different types. Each value is considered separately, separated by a comma. This will form a list on the right hand side of the read operator ‘?’. Rule 122
OutStream ~ read ( htypei , htypesi ) 7→ OutStream ~ read htypei , OutStream ~ read htypesi
Rule 123
OutStream ~ read htypei , htypesi 7→ OutStream ~ read htypei , OutStream ~ read htypesi
The last part of the output stream body is where the values read from the channel are printed to standard-output. This is achieved by using the built in ‘printf()’ function. It is a statement that is always executable. The parameters for the ‘printf()’ function are a string followed by a list of variables. The variables are referred to in the string using conversion specifications [18]. Rule 124 creates the print statement. To force each printing to be on separate lines it uses the newline escape sequence ‘\n’. The rule uses rules 125 - 127 to create the references, and rules 121 - 123 to create the variable list.
Rule 124
OutStream ~ print hexprtypei 7→ printf(” OutStream ~ refs hexprtypei \n” , OutStream ~ read hexprtypei );
Rule 125 creates a reference in the string in the argument of the PROMELA ‘printf()’ function. For each base type it returns ‘%d’, which is the conversion specification for an integer.
Rule 125
OutStream ~ refs hbasetypei 7→
%d
If the type is a tuple, each item is independently translated. Rule 126
OutStream ~ refs ( htypei , htypesi ) 7→ OutStream ~ vars htypei OutStream ~ vars htypesi
Rule 127
OutStream ~ refs htypei , htypesi 7→ OutStream ~ refs htypei OutStream ~ refs htypesi
B.9 The Init Process By using the init keyword in PROMELA , a process where the behaviour is active in the initial system state is declared. This can be compared to the main method found in C/C++ and JAVA. In the HW-HUME to PROMELA translation two distinct operations must be accomplished in the initial system state. Firstly all the channels must be given their initial value if one is specified in HW-HUME. The second objective is to instantiate all the processes with the correct channels as parameters. The PROMELA syntax of the init process is as follows: init {
The process is separated into the two specified parts. instantiates the processes.
Init
ChanInit initialises the channels and ProcInst
denotes the semantic for the entire init process.
Init : HW-HUME ,→ PROMELA Initialisation In Init all channels are first initialised, followed by the instantiation of the processes, as shown in rule 128. The rule starts with the init keyword. The rules are enclosed by brackets ‘{ }’ that hold the body of the init process. Rule 128
Init ~ hdeclsi 7→
init { Init ~ chan hdeclsi Init ~ proc hdeclsi }
To be able to initialise the channels, all the wire declarations are necessary. These are obtained by recursively traversing all declarations. This is shown rule 129, where
ChanInit
are used for
creating the PROMELA code. Rule 129
Init ~ chan hwiredecli; hdeclsi 7→ ChanInit ~
When all channels are initialised,
Init
hwiredecli Init ~ chan hdeclsi
instantiates the processes. To be able to do so, the wire
declarations, together with the corresponding box declaration are required. Rule 130 finds all wire declarations using recursion, and calls the rule to find the corresponding box declaration.
Rule 130
Init ~ proc hwiredecli; hdeclsi 7→ Init ~ proc hwiredecli hdeclsi Init ~ proc hdeclsi
Using recursion on the declarations, rule 131 finds all box declarations, and calls the rule that checks if the box declaration corresponds to the wire declaration. Rule 131
Init ~ proc hwiredecli hboxdecli; hdeclsi 7→ Init ~ proc hwiredecli hboxdecli Init ~ proc hwiredecli hdeclsi
If the name of the wire is the same as the box name, they correspond.
ProcInst
is then used to
instantiate the processes. If they don’t match, nothing happens. if [ hwireidi ≡ hboxidi ]
Rule 132
B.9.1
Init ~ wire hwireidi hsourcesi hdestsi box hboxidi hpreludei hbodyi 7→ ProcInst ~ wire hwireidi hsourcesi hdestsi box hboxidi hpreludei hbodyi
Initialisation of Channels
In HW-HUME inputs to boxes can be given initial values in the wire declaration. This is a link property specified by the initially keyword followed by the initial value (Please see definition 25, 32 and 33). In PROMELA the initial values are set using the send operator ‘!’ on the channel, followed by the PROMELA representation of the value.
ChanInit denotes the semantics for this initialisation.
ChanInit : HUME Wire Initialisation ,→ PROMELA Channel Initialisation Rule 133 accepts a wire declaration as parameter. Since the initial value is specified in the input of a channel, only the element including the sources is required. Rule 133
ChanInit ~ wire hwireidi hsourcesi hdestsi
7→ ChanInit ~ hsourcesi
The element that holds all the sources is a least of at list one link element, enclosed by parentheses. Rule 134 removes the parentheses. Rule 134
ChanInit ~ ( hlinki , hlinklisti ) 7→ ChanInit ~
hlinki , hlinklisti
The list of the link element is traversed, and each link-element is considered individually, as shown in rule 135. Rule 135
ChanInit ~ hlinki , hlinklisti 7→ ChanInit ~ hlinki ChanInit ~
hlinklisti
Rule 136 creates the PROMELA code that initialises a channel. Note that there is no rule to handle link-elements where the ‘initially’ keyword is not present - hence no PROMELA code is generated in that case. If initially is present rule 136 uses
Names
on the box and variable name to obtain the
valid PROMELA name. The two elements are separated by an underscore ‘ ’. To initialise the channel the PROMELA version of the value, created with the help of Values , is sent to the channel using the send operator ‘!’. A semicolon is used at the end of the statement to separate it from the next. Rule 136
ChanInit ~ hboxidi.hvaridi initially hexpri 7→ Names ~ hboxidi Names ~ hvaridi
!
Values ~
hexpri ;
B.9.2
Instantiate Processes
To be able to specify the parameters when creating a new process the run operator must be used. It takes as arguments the name of the already declared proctype, and a list of parameters. A process identified by the specified name, with the specified arguments, is then created. Each PROMELA process instantiation will then have the following syntax. run p r o c e s s n a m e ( chan
, < output > , < control > );
All parameters are channels. The process has a set of input channels that are read from, a set of output channels that are written to, and a control channel to synchronise with the other processes. To be able to create the processes, references to all input and output channels must be obtained. Since the output channels are generated based on the variables in the output-element list of a HWHUME box, the box declaration is used to find the output channels. The source element in the wire declaration specifies the source box and variables of the inputs. This is used to create the input channels. The control channel is created based on the box/wire name.
ProcInit
denotes the
semantics for creating the processes.
ProcInit : HW-HUME ,→ PROMELA Process Instantiation Rule 137 accepts the box declaration and corresponding wire declaration as arguments. The rule extracts the prelude from the box declaration, which is used to create the output channels. Rule 137
ProcInst ~ box hboxidi hpreludei hbodyi hwiredecli 7→ ProcInst ~ hpreludei hwiredecli
Rule 138 extracts the name and the source element from the wire declaration. The latter is used to obtain the input channels. Rule 138
ProcInst ~ hpreludei wire hwireidi hsourcesi hdestsi 7→ ProcInst ~ hpreludei hwireidi hsourcesi
Rule 139 creates the PROMELA code. The run operator is used to create a process in PROMELA. The wire name is used, together with Names , to instantiate the correct process. The chan keyword in the parameterlist indicates that channels are used as parameters. This is followed by references to the input and the output channels. At the end of the parameterlist is the reference to the control channel. Each control channel has the process name followed by ‘ control’. The correct process name is created using Names .
ProcInst ~ Rule 139
hpreludei hwireidi hsourcesi 7 → run Names ~ hwireidi ( chan ProcInit ~ hsourcesi ProcInit ~ hwireidi hpreludei Names ~ hwireidi control )
Rule 140 - 144 creates the input channels. Rule 140 uses the sources elements, which consist of a set of link elements, enclosed by parentheses. The rule removes the parentheses. Rule 140
ProcInst ~
( hlinki , hlinklisti ) 7→ ProcInst ~ hlinki , hlinklisti
The list of link elements is traversed recursively. The correct PROMELA channel is then obtained individually, as illustrated in rule 141. Rule 141
ProcInst ~
hlinki , hlinklisti 7→ ProcInst ~ hlinki , ProcInst ~ hlinklisti
Only the link specification is required from the link-element. Rule 142 extracts this element from the link-element. Rule 142
ProcInst ~
hlinkspeci hlinkpropi 7→
ProcInst ~
hlinkspeci
The link specification can either be a connection or a stream name. Rule 143 generates the PROMELA name of the channel. This is done using the name of box and the variable, separated by an underscore.
Names is used to obtain a valid PROMELA name.
Rule 143
ProcInst ~
hboxidi.hvaridi 7→
Names ~
hboxidi
Names ~
hvaridi
In the case of the link specification being a stream name, the PROMELA name of the channel is the stream name followed by ‘ out’. As rule 144 shows, Names is used to ensure that the stream name is a valid PROMELA name. Rule 144
ProcInst ~
hstreamidi 7→
Names ~
hstreamidi out
Rule 145 - 148 creates the output channels. Rule 145 accepts as arguments the name of the wire and the prelude of the box. In the prelude only the list with the output elements is required. This is extracted by the rule. Rule 145
ProcInst ~ hwireidi in ( hinoutlist1 i ) out (hinoutlist2 i) 7→ ProcInst ~ hwireidi hinoutlist2 i
Rule 146 uses recursion to separate each output-element in the list. The channels for each such element are found separately. Rule 146
ProcInst ~ hwireidi hinouti , hinoutlisti 7→ ProcInst ~ hwireidi hinouti , ProcInst ~
hwireidi hinoutlisti
An output element may have several variables. The channels for each variable must be found. Rule 147 finds each variable, and calls the method that creates the PROMELA code.
Rule 147
ProcInst ~ hwireidi hvaridi , hvaridlisti :: hexprtypei 7→ ProcInst ~ hwireidi hvaridi :: hexprtypei , ProcInst ~ hwireidi hvaridlisti :: hexprtypei
Rule 148 generates the PROMELA code. When the channels are created they are given the name of the box and the variable, separated by an underscore.
Names
ensures that the names are valid
PROMELA. Rule 148 uses this to find the channel. Rule 148
ProcInst ~ hwireidi hvaridi::hexprtypei 7→ Names ~ hwireidi Names ~ hvaridi
Appendix C
User Guidelines for the Translator As the use case in figure 5.1 on page 46 shows, the program has four different options. This appendix contains the user guidelines for running the program with the different options. The general syntax for running the JAVA program is: $ java hwhpromela [ -r | -g | -v ]
C.1
java hwhpromela [-r | -g | -v]
Generating Promela Code
One option is to only translate the HW-HUME code into PROMELA code. To perform this operation the program must be executed without specifying any of the optimal arguments: $ java hwhpromela
106
$ j a v a hwhpromela h a l f . hume −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− Translation Successful −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− File Generated : h a l f . pml T r a n s l a t i o n Time : 2 3 6 ms −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
C.2
Random Simulation
To run a random simulation on the generated PROMELA code the ‘-r’ argument must be provided: $ java hwhpromela -r model.hume The simulation is terminated by terminating the ‘hwhpromela’ program, achieved by pressing ‘CtrlC’. The program uses SPIN to run the simulation. This implies that the result is equivalent to first translate the HW-HUME program followed by running SPIN as illustrated below: $ java hwhpromela model.hume $ spin model.pml The following example shows the beginning of the output when performing a random simulation of the half adder in ’hwhpromela’:
$ j a v a hwhpromela − r h a l f . hume 0 0 −1 1 0 −1 1 0 −1 0 1 −1 0 0 −1 1 0 −1 1 0 −1 0 1 −1 0 0 −1 1 0 −1 . . .
C.3
Verifying Model
If the user wishes to verify the model after the translation, which would normally be the reason for the translation, the ‘-v’ argument must be applied:
$ java hwhpromela -v model.hume The verification is also terminated by pressing ‘Ctrl-C’. In the verification the PROMELA code is first translated to ANSI C, then compiled using the ‘cc’ compiler in UNIX and at the generated C program is then executed. Issuing the following commands is equivalent to running ‘hwhpromela’ with the ‘-v’ argument: $ $ $ $
java hwhpromela model.hume spin -a model.pml cc -o pan pan.c ./pan
Appendix H includes the output from verifying a set of HW-HUME examples.
C.4
Guided Simulation
The last option is to run a guided simulation on a previously failed verification. A trail created by the failed verification is used. In ‘hwhpromela’, a guided simulation is achieved with the ‘-g’ argument. $ java hwhpromela -g model.hume The simulation is also terminated by pressing ‘Ctrl-C’. When using this option no code is translated. The result is therefore equivalent to running the guided simulation in SPIN directly. $ spin -t -p model.pml
Appendix D
Hume Examples This appendix explains the use of HUME with an example of a simple counter. The features in the example are explained in chapter 2. n
gen n -> (n+1,(n,'\n')) n'
shown output
std_out
Figure D.1: A Hume Counter
Figure D.1 illustrates a counter in HUME. It consists of one box that takes a number as input. The number, incremented by one, is sent back to the input in addition to the standard output. The example is from ‘The Hume Manual’ [24]. The following listing shows the complete HUME code for the counter: 1 2 3 4 5 6 7 8 9 10 11
program stream o u t p u t t o ” s t d o u t ” ; box i n c in ( n : : i n t 6 4 ) o u t ( n ’ : : i n t 6 4 , shown : : ( i n t 6 4 , char ) ) match n −> ( n +1,( n , ’ \ n ’ ) ) ; wire i n c ( i n c . n ’ i n i t i a l l y 0 ) ( i n c . n , o u t p u t ) ;
Line 3 declares that output is associated with standard output ‘std out’. Line 5 - 9 declares the inc box. Line 5 specifies that the unique name of the box is ‘inc’. Line 6 declares that the box has a 64 bit integer as input called ‘n’. Line 7 declares the outputs. ‘n’‘ 109
is a 64 bit integer, and ‘shown’ is a tuple consisting of a 64 bit integer and a character. Line 8 declares the start of the matches, and that unfair matching is used. Line 9 holds the only match in the model. The input is assigned to the variable ‘n’, if there is an input. Next the right hand side is evaluated. Output ‘n’‘ is is the input incremented by one. The tuple ’shown’ holds the old value of ‘n’, together with the newline escape sequence character. Line 11 is the wire declaration for the box. It defines that the source of the input of the box is the ‘n’‘ variable in the same box. It also sets the initial value of the input to be zero ‘0’. The first output, ‘n’‘, is wired to the ‘n’ input in the same box. The tuple ‘shown’ is wired to ‘output’, which is the standard output.
D.1 Running the Program The output below is generated when the the program is run in continuous mode. This is achieved with the hume inc.hume command. The program is stopped by pressing Ctrl-C. Note that the line numbers are not part of the HUME output. $ hume i n c . hume HUME 0 . 1 Tuesday 0 8 June , 2 0 0 4 , 1 6 : 3 1 RUNNING 0 1 2 3 4 5 6 7 ... hume : i n t e r r u p t e d
HUME can also be run in stepped mode. In this mode some extra information is printed out together with the the defined outputs. All boxes execute one run, and wait for the user to press the ‘enter’ button. Stepped mode is achieved by the ‘-t’ argument. The command hume -t inc.hume run the example in stepped mode, and generates the following output: 1 2 3 4 5 6 7 8 9 10 11 12 13 14
$ hume − t i n c . hume HUME 0 . 1 Tuesday 0 8 June , 2 0 0 4 , 1 6 : 3 1 STEPPING module stream o u t p u t t o ” s t d o u t ” ; box i n c in ( ” n ” : : i n t 6 4 ) out ( ” n ’ ” : : i n t 6 4 , ” shown ” : : ( i n t 6 4 , char ) ) unfair n −> ((+ n 1 ) , ( n ,’\ n ’ ) ) ; wire i n c ( inc . n ’ i n i t i a l l y 0)
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
( inc . n , output ) 0 i n c : RUNNABLE wires : inc . n ’ :1 NEXT> 1 i n c : RUNNABLE wires : inc . n ’ :2 NEXT> 2 i n c : RUNNABLE wires : inc . n ’ :3 NEXT> 3 i n c : RUNNABLE wires : inc . n ’ :4 hume : i n t e r r u p t e d
Appendix E
Promela Examples This appendix includes two examples of PROMELA models. The examples can be used together with chapter 3 that describes the PROMELA language.
E.1 A Simple Baker Example The following code is a very simple PROMELA model consisting of two interacting processes. One process is the baker that bakes a cake, and the other process is a customer that eats the cake. They interact in a sequential manner, i.e. first a cake is baked, then it is eaten, then a new cake is baked and so on. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
mtype = { B a k i n g , E a t i n g } ; mtype t u r n = B a k i n g ; a c t i v e proctype Baker ( ) { do : : ( t u r n == Baking ) −> p r i n t f ( ” B a k e r : B a k i n g Cake \ n ” ) ; turn = Eating ; od ; } a c t i v e proctype Customer ( ) { do : : ( t u r n == E a t i n g ) −> p r i n t f ( ” C u s t o m e r : E a t i n g Cake \ n ” ) ; t u r n = Baking ; od ; }
Line 1 declares that the enumerated type, mtype, holds the two values ’Baking’ and ’Eating’. Line 2 creates a global variable ’turn’ of the enumerated type, and initialises it to ’Baking’. Lines 4 - 10 declare the ’Baker’ process. It runs in a infinite loop. First it waits for it’s turn. The process is blocked on line 6 until ’turn’ holds the value ’Baking’. When this happens, it prints out the “Baker: Baking Cake” message, sets the ’turn’ variable to ’Eating’ and returns to line
112
6 where it is blocked until ’turn’ is set to ’Baking’ again. By using the active keyword in the process prelude one process is initially created. Lines 12 - 18 declare the ’Customer’ process. It is similar to the ’Baker’ process. It uses the same global ’turn’ variable to check if a cake is ready to be eaten. When it is, it prints out the message “Customer: Eating Cake”, sets the ’turn’ value to ’Baking’ and is blocked again on line 14 until ’turn’ is set to ’Eating’. The program can be run in a random simulation mode by using the spin command. When running the example in a random simulation mode using SPIN, the following output is generated:
$ s p i n b a k e r . pml Baker : Baking Customer : Baker : Baking Customer : Baker : Baking Customer : Baker : Baking Customer : Baker : Baking Customer : Baker : Baking Customer : Baker : Baking Customer : . . .
Cake Eating Cake Eating Cake Eating Cake Eating Cake Eating Cake Eating Cake Eating
Cake Cake Cake Cake Cake Cake Cake
Figure E.1 illustrates the use of XSPIN with the example. XSPIN is used to validate a linear temporal formula (LTL) expressing that when a baker bakes a cake it will eventually be eaten by a customer. If ‘p’ is defined as a baker is baking a cake (‘turn’ is set to baking) and ‘q’ expresses that the customer is eating the cake (‘turn’ is set to eating), this can expressed as follows in LTL:
(p →
q)
In figure E.1 this is expressed and verified in XSPIN using the LTL editor which is included in the XSPIN tool. The formula is entered, and the required variables are defined. First the LTL formula is translated into a never claim. Then it is verified. Note the desired behaviour is verified. This is the behaviour that should be valid for all executions. An error behaviour is the behaviour that should never happen in any executions.
E.2 A More Advanced Baker Example The next example introduces another baker and three more customers. To synchronise the process to make sure that only one baker or one customer is active at a given time, a single variable is not enough. The mtype is extended by adding another value ‘None’, indicating that nobody is currently active. A variable ‘who’ is introduced, and contains the pid number of the process who is currently active. To ensure that only one process is active a given time, two inline definitions have been
Figure E.1: The LTL Editor in XSpin
created. On lines 5 to 7 an inline declaration that requests a lock is created. Each process must call this before it can execute. When the process is finished it uses the inline declaration on lines 9 to 11. There the process releases the lock. All processes include a local assertion, which checks that the ‘who’ variable, which holds the current active processor, holds the process number to itself. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
mtype = { B a k i n g , E a t i n g , None } ; mtype t u r n = B a k i n g ; p i d who ; i nl i ne requestLock ( x , y , z ) { a t o m i c { x = = y − > x = z ; who = }
pid }
inline releaseLock (x , y ){ a t o m i c { x = y ; who = 0 } } a c t i v e [ 2 ] proctype Baker ( ) { do : : r e q u e s t L o c k ( t u r n , B a k i n g , None ) − > p r i n t f ( ” B a k e r %d : B a k i n g Cake \ n ” , a s s e r t ( who = = p i d ) ; releaseLock ( turn , Eating ) od ; }
pid );
22 23 24 25 26 27 28 29
a c t i v e [ 3 ] proctype Customer ( ) { do : : r e q u e s t L o c k ( t u r n , E a t i n g , None ) − > p r i n t f ( ” C u s t o m e r %d : E a t i n g Cake \ n ” , a s s e r t ( who = = p i d ) ; r e l e a s e L o c k ( t u r n , Baking ) od ; }
pid ) ;
The process that is currently ‘active’ prints out its process number, and whether it is baking or eating. The following output is extracted from a random simulation of the example: $ s p i n b a k e r . pml B a k e r 0 : B a k i n g Cake C u s t o m e r 3 : E a t i n g Cake B a k e r 1 : B a k i n g Cake C u s t o m e r 3 : E a t i n g Cake B a k e r 1 : B a k i n g Cake C u s t o m e r 3 : E a t i n g Cake B a k e r 0 : B a k i n g Cake C u s t o m e r 2 : E a t i n g Cake B a k e r 0 : B a k i n g Cake C u s t o m e r 3 : E a t i n g Cake B a k e r 0 : B a k i n g Cake C u s t o m e r 3 : E a t i n g Cake B a k e r 1 : B a k i n g Cake C u s t o m e r 3 : E a t i n g Cake B a k e r 1 : B a k i n g Cake C u s t o m e r 4 : E a t i n g Cake
Appendix F
Hw-Hume Examples Chapter 6 evaluates the translation rules and the ‘hwhpromela’ program, which implements the rules. The evaluation is based on the translation and verification of a set of HW-HUME examples. The translation and verification is done with the ‘hwhpromela’ translator. This appendix contains the HW-HUME source code used in the examples in chapter 6. Please note that in the source code listings, the line numbers are not part of the HW-HUME source code:
F.1 Example 1: A Half Adder Example 1 is the half adder that has been used for illustrations throughout the thesis. It has been constructed by using an ‘xor’ and an ‘and’ gate. t y p e B i t = word 1 ; box gen in ( t : : i n t 6 4 ) out ( t ’ : : i n t 6 4 , x , y : : B i t ) match 0 −> (1,0,0) | 1 −> (2,0,1) | 2 −> (3,1,0) | 3 −> (0,1,1); box f a n o u t in ( x , y : : Bit ) o u t ( x1 , y1 , x2 , y2 : : B i t ) match (x , y ) −> ( x , y , x , y ); box x o r in ( x , y : : Bit ) out ( z : : B i t ) match (0,0) −> 0 | (0,1) −> 1 | (1,0) −> 1 | (1,1) −> 0; box and in ( x , y : : Bit ) out ( z : : B i t )
116
match (0,0) (0,1) (1,0) (1,1)
−> −> −> −>
0 | 0 | 0 | 1;
box show in ( z , c : : Bit ) o u t ( z c : : ( B i t , B i t , char ) ) match ( z , c ) −> ( z , c ,’\ n ’ ) ; stream o u t p u t t o ” s t d o u t ” ; wire wire wire wire wire
gen ( gen . t ’ i n i t i a l l y 0 ) ( gen . t , f a n o u t . x , f a n o u t . y ) ; f a n o u t ( gen . x , gen . y ) ( x o r . x , x o r . y , and . x , and . y ) ; x o r ( f a n o u t . x1 , f a n o u t . y1 ) ( show . z ) ; and ( f a n o u t . x2 , f a n o u t . y2 ) ( show . c ) ; show ( x o r . z , and . z ) ( o u t p u t ) ;
F.2 Example 2: An XOR and an AND Gate Forming a Deadlock The second example is the ‘xor’ and an ‘and’ gate which forms a deadlock. This deadlock illustrated in figure 6.4 on page 51. The following listing contains the source code of the HW-HUME implementation creating the deadlock: t y p e B i t = word 1 ; box gen in ( t : : i n t 6 4 ) out ( t ’ : : i n t 6 4 , x , y : : B i t ) match 0 −> (1,0,0) | 1 −> (2,0,1) | 2 −> (3,1,0) | 3 −> (0,1,1); box x o r in ( x , y : : Bit ) o u t ( z1 , z2 : : B i t ) match (0,0) −> (0,0) | (0,1) −> (1,1) | (1,0) −> (1,1) | (1,1) −> (0,0); box and in ( x , y : : Bit ) o u t ( z1 , z2 : : B i t ) match (0,0) −> (0,0) | (0,1) −> (0,0) | (1,0) −> (0,0) | (1,1) −> (1,1); box show in ( z , c : : Bit )
o u t ( z c : : ( B i t , B i t , char ) ) match ( z , c ) −> ( z , c ,’\ n ’ ) ; stream o u t p u t t o ” s t d o u t ” ; wire wire wire wire
gen ( gen . t ’ i n i t i a l l y 0 ) ( gen . t , x o r . x , and . x ) ; x o r ( gen . x , and . z2 ) ( show . z , and . y ) ; and ( gen . y , x o r . z2 ) ( show . c , x o r . y ) ; show ( x o r . z1 , and . z1 ) ( o u t p u t ) ;
F.3 Example 3: Full Adder from Truth Table The third example is a full adder created by using a HW-HUME box to represent a truth table. Figure 6.8 on page 52 models the adder as it is implemented in HW-HUME. The following listing contains the HW-HUME source code: type B i t = i n t 1 ; box gen in ( t : : i n t 6 4 ) out ( t ’ : : i n t 6 4 , x , y , c : : B i t ) match 0 −> (1,0,0,0) | 1 −> (2,0,1,0) | 2 −> (3,1,0,0) | 3 −> (4,1,1,0) | 4 −> (5,0,0,1) | 5 −> (6,0,1,1) | 6 −> (7,1,0,1) | 7 −> (0,1,1,1); box a d d e r in ( x , y , c : : Bit ) out ( s , c ’ : : B i t ) match (0,0,0) −> (0,0) (0,1,0) −> (1,0) (1,0,0) −> (1,0) (1,1,0) −> (0,1) (0,0,1) −> (1,0) (0,1,1) −> (0,1) (1,0,1) −> (0,1) (1,1,1) −> (1,1)
| | | | | | | ;
box show in ( s , c : : Bit ) o u t ( s c : : ( B i t , B i t , char ) ) match ( s , c ) −> ( s , c ,’\ n ’ ) ; stream o u t p u t t o ” s t d o u t ” ; w i r e gen ( gen . t ’ i n i t i a l l y 0 ) ( gen . t , a d d e r . x , a d d e r . y , a d d e r . c ) ; w i r e a d d e r ( gen . x , gen . y , gen . c ) ( show . s , show . c ) ; w i r e show ( a d d e r . s , a d d e r . c ’ ) ( o u t p u t ) ;
F.4 Example 4: Full Adder as Half Adders and OR Gates The forth example is also an implementation of a full adder. However, in this case it is implemented by using two ‘half adders’ and an ‘or’ gate. The adder is modelled in figure 6.9 on page 53. The following source code contains the implementation of the adder: type B i t = i n t 1 ; box gen in ( t : : i n t 6 4 ) out ( t ’ : : i n t 6 4 , x , y , c : : B i t ) match 0 −> (1,0,0,0) | 1 −> (2,0,1,0) | 2 −> (3,1,0,0) | 3 −> (4,1,1,0) | 4 −> (5,0,0,1) | 5 −> (6,0,1,1) | 6 −> (7,1,0,1) | 7 −> (0,1,1,1); template h a l f 2 in ( x , y : : Bit ) out ( s , c : : B i t ) match (0,0) −> (0,0) | (0,1) −> (1,0) | (1,0) −> (1,0) | (1,1) −> (0,1); i n s t a n t i a t e h a l f 2 as h ∗ 2 ; box o r in ( x , y : : Bit ) out ( z : : B i t ) match (0,0) −> 0 | (0,1) −> 1 | (1,0) −> 1 | (1,1) −> 1; box show in ( s , c : : Bit ) o u t ( s c : : ( B i t , B i t , char ) ) match ( s , c ) −> ( s , c ,’\ n ’ ) ; stream o u t p u t t o ” s t d o u t ” ; wire wire wire wire wire
gen ( gen . t ’ i n i t i a l l y 0 ) ( gen . t , h1 . x , h1 . y , h2 . x ) ; h1 ( gen . x , gen . y ) ( h2 . y , o r . x ) ; h2 ( gen . c , h1 . s ) ( show . s , o r . y ) ; o r ( h1 . c , h2 . c ) ( show . c ) ; show ( h2 . s , o r . z ) ( o u t p u t ) ;
F.5 Example 5: Full Adder as XOR, AND and OR Gates The fifth example is the last implementation of a full adder. It is created by using ‘xor’, ‘and’ and ‘or’ gates as illustrated in figure 6.10 on page 53. The following listing contains the HW-HUME source code of the adder: type B i t = i n t 1 ; box gen in ( t : : i n t 6 4 ) out ( t ’ : : i n t 6 4 , x , y , c : : B i t ) match 0 −> (1,0,0,0) | 1 −> (2,0,1,0) | 2 −> (3,1,0,0) | 3 −> (4,1,1,0) | 4 −> (5,0,0,1) | 5 −> (6,0,1,1) | 6 −> (7,1,0,1) | 7 −> (0,1,1,1); template fanout in ( x , y : : Bit ) o u t ( x1 , y1 , x2 , y2 : : B i t ) match (x , y ) −> ( x , y , x , y ); i n s t a n t i a t e f a n o u t as f ∗2; template xor in ( x , y : : Bit ) out ( z : : B i t ) match (0,0) −> 0 | (0,1) −> 1 | (1,0) −> 1 | (1,1) −> 0; i n s t a n t i a t e xor as x ∗2; t e m p l a t e and in ( x , y : : Bit ) out ( z : : B i t ) match (0,0) −> 0 | (0,1) −> 0 | (1,0) −> 0 | (1,1) −> 1; i n s t a n t i a t e and a s a ∗ 2 ; box o r in ( x , y : : Bit ) out ( z : : B i t ) match (0,0) −> 0 | (0,1) −> 1 | (1,0) −> 1 | (1,1) −> 1;
box show in ( s , c : : Bit ) o u t ( s c : : ( B i t , B i t , char ) ) match ( s , c ) −> ( s , c ,’\ n ’ ) ; stream o u t p u t t o ” s t d o u t ” ; wire wire wire wire wire wire wire wire wire
gen ( gen . t ’ i n i t i a l l y 0 ) ( gen . t , f 1 . x , f 1 . y , f 2 . x ) ; f 1 ( gen . x , gen . y ) ( x1 . x , x1 . y , a1 . x , a1 . y ) ; x1 ( f 1 . x1 , f 1 . y1 ) ( f 2 . y ) ; a1 ( f 1 . x2 , f 1 . y2 ) ( o r . x ) ; f 2 ( gen . c , x1 . z ) ( x2 . x , x2 . y , a2 . x , a2 . y ) ; x2 ( f 2 . x1 , f 2 . y1 ) ( show . s ) ; a2 ( f 2 . x2 , f 2 . y2 ) ( o r . y ) ; o r ( a1 . z , a2 . z ) ( show . c ) ; show ( x2 . z , o r . z ) ( o u t p u t ) ;
F.6 Connecting Adders This section contains the source code when connected adders to created multi bit adders. This is described in section 6.7. Figure 6.11 illustrates the connection, by showing a two bit adder. The following sections include the source code of a two, three, four and five bit adder.
F.6.1 Example 6: A Two Bit Adder The following listing contains the HW-HUME source code of a two bit adder: type B i t = i n t 1 ; box gen1 in ( t : : i n t 6 4 ) out ( t ’ : : i n t 6 4 , x , y , c : : B i t ) match 0 −> (1,0,0,0) | 1 −> (2,0,1,0) | 2 −> (3,1,0,0) | 3 −> (4,1,1,0) | 4 −> (5,0,0,1) | 5 −> (6,0,1,1) | 6 −> (7,1,0,1) | 7 −> (0,1,1,1); box gen2 in ( t : : i n t 6 4 ) out ( t ’ : : i n t 6 4 , x , y : : B i t ) match 0 −> (1,0,0) | 1 −> (2,0,1) | 2 −> (3,1,0) | 3 −> (0,1,1) ; template fanout in ( x , y : : Bit ) o u t ( x1 , y1 , x2 , y2 : : B i t ) match
(x , y ) −> ( x , y , x , y ); i n s t a n t i a t e f a n o u t as f ∗4; template xor in ( x , y : : Bit ) out ( z : : B i t ) match (0,0) −> 0 | (0,1) −> 1 | (1,0) −> 1 | (1,1) −> 0; i n s t a n t i a t e xor as x ∗4; t e m p l a t e and in ( x , y : : Bit ) out ( z : : B i t ) match (0,0) −> 0 | (0,1) −> 0 | (1,0) −> 0 | (1,1) −> 1; i n s t a n t i a t e and a s a ∗ 4 ; template or in ( x , y : : Bit ) out ( z : : B i t ) match (0,0) −> 0 | (0,1) −> 1 | (1,0) −> 1 | (1,1) −> 1; i n s t a n t i a t e or as o ∗2; box show in ( s1 , s2 , c : : B i t ) o u t ( s s c : : ( B i t , B i t , B i t , char ) ) match ( a , b , c ) −> ( a , b , c ,’\ n ’ ) ; stream o u t p u t t o ” s t d o u t ” ; wire wire wire wire wire wire wire wire
gen1 ( gen1 . t ’ i n i t i a l l y 0 ) ( gen1 . t , f 1 . x , f 1 . y , f 2 . x ) ; f 1 ( gen1 . x , gen1 . y ) ( x1 . x , x1 . y , a1 . x , a1 . y ) ; x1 ( f 1 . x1 , f 1 . y1 ) ( f 2 . y ) ; a1 ( f 1 . x2 , f 1 . y2 ) ( o1 . x ) ; f 2 ( gen1 . c , x1 . z ) ( x2 . x , x2 . y , a2 . x , a2 . y ) ; x2 ( f 2 . x1 , f 2 . y1 ) ( show . s 1 ) ; a2 ( f 2 . x2 , f 2 . y2 ) ( o1 . y ) ; o1 ( a1 . z , a2 . z ) ( f 4 . x ) ;
wire wire wire wire wire wire wire wire
gen2 ( gen2 . t ’ i n i t i a l l y 0 ) ( gen2 . t , f 3 . x , f 3 . y ) ; f 3 ( gen2 . x , gen2 . y ) ( x3 . x , x3 . y , a3 . x , a3 . y ) ; x3 ( f 3 . x1 , f 3 . y1 ) ( f 4 . y ) ; a3 ( f 3 . x2 , f 3 . y2 ) ( o2 . x ) ; f 4 ( o1 . z , x3 . z ) ( x4 . x , x4 . y , a4 . x , a4 . y ) ; x4 ( f 4 . x1 , f 4 . y1 ) ( show . s 2 ) ; a4 ( f 4 . x2 , f 4 . y2 ) ( o2 . y ) ; o2 ( a3 . z , a4 . z ) ( show . c ) ;
w i r e show ( x2 . z , x4 . z , o2 . z ) ( o u t p u t ) ;
F.6.2 Example 7: A Three Bit Adder The following listing contains the HW-HUME source code of a three bit adder: type B i t = i n t 1 ; box gen1 in ( t : : i n t 6 4 ) out ( t ’ : : i n t 6 4 , x , y , c : : B i t ) match 0 −> (1,0,0,0) | 1 −> (2,0,1,0) | 2 −> (3,1,0,0) | 3 −> (4,1,1,0) | 4 −> (5,0,0,1) | 5 −> (6,0,1,1) | 6 −> (7,1,0,1) | 7 −> (0,1,1,1); box gen2 in ( t : : i n t 6 4 ) out ( t ’ : : i n t 6 4 , x , y : : B i t ) match 0 −> (1,0,0) | 1 −> (2,0,1) | 2 −> (3,1,0) | 3 −> (0,1,1) ; box gen3 in ( t : : i n t 6 4 ) out ( t ’ : : i n t 6 4 , x , y : : B i t ) match 0 −> (1,0,0) | 1 −> (2,0,1) | 2 −> (3,1,0) | 3 −> (0,1,1) ; template fanout in ( x , y : : Bit ) o u t ( x1 , y1 , x2 , y2 : : B i t ) match (x , y ) −> ( x , y , x , y ); i n s t a n t i a t e f a n o u t as f ∗6; template xor in ( x , y : : Bit ) out ( z : : B i t ) match (0,0) −> 0 | (0,1) −> 1 | (1,0) −> 1 | (1,1) −> 0; i n s t a n t i a t e xor as x ∗6; t e m p l a t e and
in ( x , y : : Bit ) out ( z : : B i t ) match (0,0) −> 0 | (0,1) −> 0 | (1,0) −> 0 | (1,1) −> 1; i n s t a n t i a t e and a s a ∗ 6 ; template or in ( x , y : : Bit ) out ( z : : B i t ) match (0,0) −> 0 | (0,1) −> 1 | (1,0) −> 1 | (1,1) −> 1; i n s t a n t i a t e or as o ∗3; box show in ( s1 , s2 , s3 , c : : B i t ) o u t ( s s c : : ( B i t , B i t , B i t , B i t , char ) ) match ( a , b , c , carry ) −> ( a , b , c , carry ,’\ n ’ ) ; stream o u t p u t t o ” s t d o u t ” ; wire wire wire wire wire wire wire wire
gen1 ( gen1 . t ’ i n i t i a l l y 0 ) ( gen1 . t , f 1 . x , f 1 . y , f 2 . x ) ; f 1 ( gen1 . x , gen1 . y ) ( x1 . x , x1 . y , a1 . x , a1 . y ) ; x1 ( f 1 . x1 , f 1 . y1 ) ( f 2 . y ) ; a1 ( f 1 . x2 , f 1 . y2 ) ( o1 . x ) ; f 2 ( gen1 . c , x1 . z ) ( x2 . x , x2 . y , a2 . x , a2 . y ) ; x2 ( f 2 . x1 , f 2 . y1 ) ( show . s 1 ) ; a2 ( f 2 . x2 , f 2 . y2 ) ( o1 . y ) ; o1 ( a1 . z , a2 . z ) ( f 4 . x ) ;
wire wire wire wire wire wire wire wire
gen2 ( gen2 . t ’ i n i t i a l l y 0 ) ( gen2 . t , f 3 . x , f 3 . y ) ; f 3 ( gen2 . x , gen2 . y ) ( x3 . x , x3 . y , a3 . x , a3 . y ) ; x3 ( f 3 . x1 , f 3 . y1 ) ( f 4 . y ) ; a3 ( f 3 . x2 , f 3 . y2 ) ( o2 . x ) ; f 4 ( o1 . z , x3 . z ) ( x4 . x , x4 . y , a4 . x , a4 . y ) ; x4 ( f 4 . x1 , f 4 . y1 ) ( show . s 2 ) ; a4 ( f 4 . x2 , f 4 . y2 ) ( o2 . y ) ; o2 ( a3 . z , a4 . z ) ( f 6 . x ) ;
wire wire wire wire wire wire wire wire
gen3 ( gen3 . t ’ i n i t i a l l y 0 ) ( gen3 . t , f 5 . x , f 5 . y ) ; f 5 ( gen3 . x , gen3 . y ) ( x5 . x , x5 . y , a5 . x , a5 . y ) ; x5 ( f 5 . x1 , f 5 . y1 ) ( f 6 . y ) ; a5 ( f 5 . x2 , f 5 . y2 ) ( o3 . x ) ; f 6 ( o2 . z , x5 . z ) ( x6 . x , x6 . y , a6 . x , a6 . y ) ; x6 ( f 6 . x1 , f 6 . y1 ) ( show . s 3 ) ; a6 ( f 6 . x2 , f 6 . y2 ) ( o3 . y ) ; o3 ( a5 . z , a6 . z ) ( show . c ) ;
w i r e show ( x2 . z , x4 . z , x6 . z , o3 . z ) ( o u t p u t ) ;
F.6.3 Example 8: A Four Bit Adder The following listing contains the HW-HUME source code of a four bit adder: type B i t = i n t 1 ; box gen1 in ( t : : i n t 6 4 ) out ( t ’ : : i n t 6 4 , x , y , c : : B i t ) match 0 −> (1,0,0,0) | 1 −> (2,0,1,0) | 2 −> (3,1,0,0) | 3 −> (4,1,1,0) | 4 −> (5,0,0,1) | 5 −> (6,0,1,1) | 6 −> (7,1,0,1) | 7 −> (0,1,1,1); box gen2 in ( t : : i n t 6 4 ) out ( t ’ : : i n t 6 4 , x , y : : B i t ) match 0 −> (1,0,0) | 1 −> (2,0,1) | 2 −> (3,1,0) | 3 −> (0,1,1) ; box gen3 in ( t : : i n t 6 4 ) out ( t ’ : : i n t 6 4 , x , y : : B i t ) match 0 −> (1,0,0) | 1 −> (2,0,1) | 2 −> (3,1,0) | 3 −> (0,1,1) ; box gen4 in ( t : : i n t 6 4 ) out ( t ’ : : i n t 6 4 , x , y : : B i t ) match 0 −> (1,0,0) | 1 −> (2,0,1) | 2 −> (3,1,0) | 3 −> (0,1,1) ; template fanout in ( x , y : : Bit ) o u t ( x1 , y1 , x2 , y2 : : B i t ) match (x , y ) −> ( x , y , x , y ); i n s t a n t i a t e f a n o u t as f ∗8; template xor in ( x , y : : Bit ) out ( z : : B i t ) match (0,0) −> 0 | (0,1) −> 1 | (1,0) −> 1 | (1,1) −> 0;
i n s t a n t i a t e xor as x ∗8; t e m p l a t e and in ( x , y : : Bit ) out ( z : : B i t ) match (0,0) −> 0 | (0,1) −> 0 | (1,0) −> 0 | (1,1) −> 1; i n s t a n t i a t e and a s a ∗ 8 ; template or in ( x , y : : Bit ) out ( z : : B i t ) match (0,0) −> 0 | (0,1) −> 1 | (1,0) −> 1 | (1,1) −> 1; i n s t a n t i a t e or as o ∗4; box show in ( s1 , s2 , s3 , s4 , c : : B i t ) o u t ( s s c : : ( B i t , B i t , B i t , B i t , B i t , char ) ) match ( a , b , c , d , carry ) −> ( a , b , c , d , carry ,’\ n ’ ) ; stream o u t p u t t o ” s t d o u t ” ; wire wire wire wire wire wire wire wire
gen1 ( gen1 . t ’ i n i t i a l l y 0 ) ( gen1 . t , f 1 . x , f 1 . y , f 2 . x ) ; f 1 ( gen1 . x , gen1 . y ) ( x1 . x , x1 . y , a1 . x , a1 . y ) ; x1 ( f 1 . x1 , f 1 . y1 ) ( f 2 . y ) ; a1 ( f 1 . x2 , f 1 . y2 ) ( o1 . x ) ; f 2 ( gen1 . c , x1 . z ) ( x2 . x , x2 . y , a2 . x , a2 . y ) ; x2 ( f 2 . x1 , f 2 . y1 ) ( show . s 1 ) ; a2 ( f 2 . x2 , f 2 . y2 ) ( o1 . y ) ; o1 ( a1 . z , a2 . z ) ( f 4 . x ) ;
wire wire wire wire wire wire wire wire
gen2 ( gen2 . t ’ i n i t i a l l y 0 ) ( gen2 . t , f 3 . x , f 3 . y ) ; f 3 ( gen2 . x , gen2 . y ) ( x3 . x , x3 . y , a3 . x , a3 . y ) ; x3 ( f 3 . x1 , f 3 . y1 ) ( f 4 . y ) ; a3 ( f 3 . x2 , f 3 . y2 ) ( o2 . x ) ; f 4 ( o1 . z , x3 . z ) ( x4 . x , x4 . y , a4 . x , a4 . y ) ; x4 ( f 4 . x1 , f 4 . y1 ) ( show . s 2 ) ; a4 ( f 4 . x2 , f 4 . y2 ) ( o2 . y ) ; o2 ( a3 . z , a4 . z ) ( f 6 . x ) ;
wire wire wire wire wire wire wire wire
gen3 ( gen3 . t ’ i n i t i a l l y 0 ) ( gen3 . t , f 5 . x , f 5 . y ) ; f 5 ( gen3 . x , gen3 . y ) ( x5 . x , x5 . y , a5 . x , a5 . y ) ; x5 ( f 5 . x1 , f 5 . y1 ) ( f 6 . y ) ; a5 ( f 5 . x2 , f 5 . y2 ) ( o3 . x ) ; f 6 ( o2 . z , x5 . z ) ( x6 . x , x6 . y , a6 . x , a6 . y ) ; x6 ( f 6 . x1 , f 6 . y1 ) ( show . s 3 ) ; a6 ( f 6 . x2 , f 6 . y2 ) ( o3 . y ) ; o3 ( a5 . z , a6 . z ) ( f 8 . x ) ;
w i r e gen4 ( gen4 . t ’ i n i t i a l l y 0 ) ( gen4 . t , f 7 . x , f 7 . y ) ; w i r e f 7 ( gen4 . x , gen4 . y ) ( x7 . x , x7 . y , a7 . x , a7 . y ) ; w i r e x7 ( f 7 . x1 , f 7 . y1 ) ( f 8 . y ) ;
wire wire wire wire wire
a7 ( f 7 . x2 , f 7 . y2 ) ( o4 . x ) ; f 8 ( o3 . z , x7 . z ) ( x8 . x , x8 . y , a8 . x , a8 . y ) ; x8 ( f 8 . x1 , f 8 . y1 ) ( show . s 4 ) ; a8 ( f 8 . x2 , f 8 . y2 ) ( o4 . y ) ; o4 ( a7 . z , a8 . z ) ( show . c ) ;
w i r e show ( x2 . z , x4 . z , x6 . z , x8 . z , o4 . z ) ( o u t p u t ) ;
F.6.4 Example 9: A Five Bit Adder The following listing contains the HW-HUME source code of a five bit adder: type B i t = i n t 1 ; box gen1 in ( t : : i n t 6 4 ) out ( t ’ : : i n t 6 4 , x , y , c : : B i t ) match 0 −> (1,0,0,0) | 1 −> (2,0,1,0) | 2 −> (3,1,0,0) | 3 −> (4,1,1,0) | 4 −> (5,0,0,1) | 5 −> (6,0,1,1) | 6 −> (7,1,0,1) | 7 −> (0,1,1,1); box gen2 in ( t : : i n t 6 4 ) out ( t ’ : : i n t 6 4 , x , y : : B i t ) match 0 −> (1,0,0) | 1 −> (2,0,1) | 2 −> (3,1,0) | 3 −> (0,1,1) ; box gen3 in ( t : : i n t 6 4 ) out ( t ’ : : i n t 6 4 , x , y : : B i t ) match 0 −> (1,0,0) | 1 −> (2,0,1) | 2 −> (3,1,0) | 3 −> (0,1,1) ; box gen4 in ( t : : i n t 6 4 ) out ( t ’ : : i n t 6 4 , x , y : : B i t ) match 0 −> (1,0,0) | 1 −> (2,0,1) | 2 −> (3,1,0) | 3 −> (0,1,1) ; box gen5 in ( t : : i n t 6 4 ) out ( t ’ : : i n t 6 4 , x , y : : B i t ) match 0 −> (1,0,0) |
1 −> (2,0,1) | 2 −> (3,1,0) | 3 −> (0,1,1) ; template fanout in ( x , y : : Bit ) o u t ( x1 , y1 , x2 , y2 : : B i t ) match (x , y ) −> ( x , y , x , y ); i n s t a n t i a t e f a n o u t as f ∗10; template xor in ( x , y : : Bit ) out ( z : : B i t ) match (0,0) −> 0 | (0,1) −> 1 | (1,0) −> 1 | (1,1) −> 0; i n s t a n t i a t e xor as x ∗10; t e m p l a t e and in ( x , y : : Bit ) out ( z : : B i t ) match (0,0) −> 0 | (0,1) −> 0 | (1,0) −> 0 | (1,1) −> 1; i n s t a n t i a t e and a s a ∗ 1 0 ; template or in ( x , y : : Bit ) out ( z : : B i t ) match (0,0) −> 0 | (0,1) −> 1 | (1,0) −> 1 | (1,1) −> 1; i n s t a n t i a t e or as o ∗5; box show in ( s1 , s2 , s3 , s4 , s5 , c : : B i t ) o u t ( s s c : : ( B i t , B i t , B i t , B i t , B i t , B i t , char ) ) match ( a , b , c , d , e , carry ) −> ( a , b , c , d , e , carry ,’\ n ’ ) ; stream o u t p u t t o ” s t d o u t ” ; wire wire wire wire wire wire wire wire
gen1 ( gen1 . t ’ i n i t i a l l y 0 ) ( gen1 . t , f 1 . x , f 1 . y , f 2 . x ) ; f 1 ( gen1 . x , gen1 . y ) ( x1 . x , x1 . y , a1 . x , a1 . y ) ; x1 ( f 1 . x1 , f 1 . y1 ) ( f 2 . y ) ; a1 ( f 1 . x2 , f 1 . y2 ) ( o1 . x ) ; f 2 ( gen1 . c , x1 . z ) ( x2 . x , x2 . y , a2 . x , a2 . y ) ; x2 ( f 2 . x1 , f 2 . y1 ) ( show . s 1 ) ; a2 ( f 2 . x2 , f 2 . y2 ) ( o1 . y ) ; o1 ( a1 . z , a2 . z ) ( f 4 . x ) ;
w i r e gen2 ( gen2 . t ’ i n i t i a l l y 0 ) ( gen2 . t , f 3 . x , f 3 . y ) ;
wire wire wire wire wire wire wire
f 3 ( gen2 . x , gen2 . y ) ( x3 . x , x3 . y , a3 . x , a3 . y ) ; x3 ( f 3 . x1 , f 3 . y1 ) ( f 4 . y ) ; a3 ( f 3 . x2 , f 3 . y2 ) ( o2 . x ) ; f 4 ( o1 . z , x3 . z ) ( x4 . x , x4 . y , a4 . x , a4 . y ) ; x4 ( f 4 . x1 , f 4 . y1 ) ( show . s 2 ) ; a4 ( f 4 . x2 , f 4 . y2 ) ( o2 . y ) ; o2 ( a3 . z , a4 . z ) ( f 6 . x ) ;
wire wire wire wire wire wire wire wire
gen3 ( gen3 . t ’ i n i t i a l l y 0 ) ( gen3 . t , f 5 . x , f 5 . y ) ; f 5 ( gen3 . x , gen3 . y ) ( x5 . x , x5 . y , a5 . x , a5 . y ) ; x5 ( f 5 . x1 , f 5 . y1 ) ( f 6 . y ) ; a5 ( f 5 . x2 , f 5 . y2 ) ( o3 . x ) ; f 6 ( o2 . z , x5 . z ) ( x6 . x , x6 . y , a6 . x , a6 . y ) ; x6 ( f 6 . x1 , f 6 . y1 ) ( show . s 3 ) ; a6 ( f 6 . x2 , f 6 . y2 ) ( o3 . y ) ; o3 ( a5 . z , a6 . z ) ( f 8 . x ) ;
wire wire wire wire wire wire wire wire
gen4 ( gen4 . t ’ i n i t i a l l y 0 ) ( gen4 . t , f 7 . x , f 7 . y ) ; f 7 ( gen4 . x , gen4 . y ) ( x7 . x , x7 . y , a7 . x , a7 . y ) ; x7 ( f 7 . x1 , f 7 . y1 ) ( f 8 . y ) ; a7 ( f 7 . x2 , f 7 . y2 ) ( o4 . x ) ; f 8 ( o3 . z , x7 . z ) ( x8 . x , x8 . y , a8 . x , a8 . y ) ; x8 ( f 8 . x1 , f 8 . y1 ) ( show . s 4 ) ; a8 ( f 8 . x2 , f 8 . y2 ) ( o4 . y ) ; o4 ( a7 . z , a8 . z ) ( f 1 0 . x ) ;
wire wire wire wire wire wire wire wire
gen5 ( gen5 . t ’ i n i t i a l l y 0 ) ( gen5 . t , f 9 . x , f 9 . y ) ; f 9 ( gen5 . x , gen5 . y ) ( x9 . x , x9 . y , a9 . x , a9 . y ) ; x9 ( f 9 . x1 , f 9 . y1 ) ( f 1 0 . y ) ; a9 ( f 9 . x2 , f 9 . y2 ) ( o5 . x ) ; f 1 0 ( o4 . z , x9 . z ) ( x10 . x , x10 . y , a10 . x , a10 . y ) ; x10 ( f 1 0 . x1 , f 1 0 . y1 ) ( show . s 5 ) ; a10 ( f 1 0 . x2 , f 1 0 . y2 ) ( o5 . y ) ; o5 ( a9 . z , a10 . z ) ( show . c ) ;
w i r e show ( x2 . z , x4 . z , x6 . z , x8 . z , x10 . z , o5 . z ) ( o u t p u t ) ;
F.7 Example 10: Debugging with Spin Example ten is used to illustrate the possibilities when using SPIN to model check HW-HUME programs. There are two versions of the HW-HUME source code. The first version, listed in section F.7.1, contains an error, and in the second version, listed in section F.7.2, the error has been corrected.
F.7.1 The First Version of the Counter The following listing contains the HW-HUME of the first version of the counter. The example contains an error. t y p e B i t = word 1 ; box c l o c k in ( a : : Bit ) out ( a ’ : : B i t ) match a −> 1;
template d i g i t in ( a , clk : : Bit ) out ( c l k ’ , q : : B i t ) match (0,0) −> (0,0) | (1,0) −> (0,1) | (0,1) −> (0,1) | (1,1) −> (1,0) ; i n s t a n t i a t e d i g i t as d ∗3; template fanout in ( x : : Bit ) o u t ( x1 , x2 : : B i t ) match a −> ( a , a ); i n s t a n t i a t e f a n o u t as f ∗3; box show i n ( d1 , d2 , d3 : : B i t ) o u t ( show : : ( word 3 , char ) ) match (0,0,0) −> (0,’\n ’ ) | (1,0,0) −> (1,’\n ’ ) | (0,1,0) −> (2,’\n ’ ) | (1,1,0) −> (3,’\n ’ ) | (0,0,1) −> (4,’\n ’ ) | (1,1,0) −> (5,’\n ’ ) | (0,1,1) −> (6,’\n ’ ) | (1,1,1) −> (7,’\n ’) ; stream o u t p u t t o ” s t d o u t ” ; wire wire wire wire wire wire wire wire
c l o c k ( d3 . c l k ’ i n i t i a l l y 1 ) ( d1 . c l k ) ; d1 ( f 1 . x1 , c l o c k . a ’ ) ( d2 . c l k , f 1 . x ) ; d2 ( f 2 . x1 , d1 . c l k ’ ) ( d3 . c l k , f 2 . x ) ; d3 ( f 3 . x1 , d2 . c l k ’ ) ( c l o c k . a , f 3 . x ) ; f 1 ( d1 . q i n i t i a l l y 0 ) ( d1 . a , show . d1 ) ; f 2 ( d2 . q i n i t i a l l y 0 ) ( d2 . a , show . d2 ) ; f 3 ( d3 . q i n i t i a l l y 0 ) ( d3 . a , show . d3 ) ; show ( f 1 . x2 , f 2 . x2 , f 3 . x2 ) ( o u t p u t ) ;
F.7.2 The Second Version of the Counter In the second version of the counter, the error has been fixed. The following listing contains the error free source code. t y p e B i t = word 1 ; box c l o c k in ( a : : Bit ) out ( a ’ : : B i t ) match a −> 1;
template d i g i t
in ( a , clk : : Bit ) out ( c l k ’ , q : : B i t ) match (0,0) −> (0,0) | (1,0) −> (0,1) | (0,1) −> (0,1) | (1,1) −> (1,0) ; i n s t a n t i a t e d i g i t as d ∗3; template fanout in ( x : : Bit ) o u t ( x1 , x2 : : B i t ) match a −> ( a , a ); i n s t a n t i a t e f a n o u t as f ∗3; box show i n ( d1 , d2 , d3 : : B i t ) o u t ( show : : ( word 3 , char ) ) match (0,0,0) −> (0,’\n ’ ) | (1,0,0) −> (1,’\n ’ ) | (0,1,0) −> (2,’\n ’ ) | (1,1,0) −> (3,’\n ’ ) | (0,0,1) −> (4,’\n ’ ) | (1,0,1) −> (5,’\n ’ ) | (0,1,1) −> (6,’\n ’ ) | (1,1,1) −> (7,’\n ’) ; stream o u t p u t t o ” s t d o u t ” ; wire wire wire wire wire wire wire wire
c l o c k ( d3 . c l k ’ i n i t i a l l y 1 ) ( d1 . c l k ) ; d1 ( f 1 . x1 , c l o c k . a ’ ) ( d2 . c l k , f 1 . x ) ; d2 ( f 2 . x1 , d1 . c l k ’ ) ( d3 . c l k , f 2 . x ) ; d3 ( f 3 . x1 , d2 . c l k ’ ) ( c l o c k . a , f 3 . x ) ; f 1 ( d1 . q i n i t i a l l y 0 ) ( d1 . a , show . d1 ) ; f 2 ( d2 . q i n i t i a l l y 0 ) ( d2 . a , show . d2 ) ; f 3 ( d3 . q i n i t i a l l y 0 ) ( d3 . a , show . d3 ) ; show ( f 1 . x2 , f 2 . x2 , f 3 . x2 ) ( o u t p u t ) ;
Appendix G
Translation Examples This appendix holds the PROMELA source code created in the examples used in chapter 6. In that chapter the evaluation of the rules and ‘hwhpromela’ program is performed. The source code is the result of translating the HW-HUME source code using ‘hwhpromela’. The HW-HUME code is listed in appendix F. Due to the size of the generated PROMELA code, only example one, three and four have been included. Note that the code has been slightly modified compared to the code ‘hwhpromela’ generated. This modification only includes removal of white space to save space and some additional new lines.
G.1 Example 1: The Half Adder The first example is the half adder that has been used throughout the entire thesis. The slightly modified PROMELA code generated from ‘hwhpromela’ is listed below: mtype = { BEGIN , END } ; chan o u t p u t c o n t r o l = [ 0 ] o f { mtype } ; chan g e n c o n t r o l = [ 0 ] o f { mtype } ; chan f a n o u t c o n t r o l = [ 0 ] o f { mtype } ; chan x o r c o n t r o l = [ 0 ] o f { mtype } ; chan a n d c o n t r o l = [ 0 ] o f { mtype } ; chan s h o w 1 c o n t r o l = [ 0 ] o f { mtype } ; chan g e n t q = [ 1 ] o f { i n t } ; chan g e n x = [ 1 ] o f { b i t } ; chan g e n y = [ 1 ] o f { b i t } ; chan f a n o u t x 1 = [ 1 ] o f { b i t } ; chan f a n o u t y 1 = [ 1 ] o f { b i t } ; chan f a n o u t x 2 = [ 1 ] o f { b i t } ; chan f a n o u t y 2 = [ 1 ] o f { b i t } ; chan x o r z = [ 1 ] o f { b i t } ; chan a n d z = [ 1 ] o f { b i t } ; chan s h o w 1 z c = [ 1 ] o f { b i t , b i t , s h o r t } ; p r o c t y p e gen ( chan i n 1 , o u t 1 , o u t 2 , o u t 3 , control ) { start : c o n t r o l ?BEGIN ; if : : ( in1 ? [ 0 ] ) − > in1 ? 0 ; out1 ! 1 ; out2 ! 0 ; out3 ! 0 ; : : else if : : ( in1 ? [ 1 ] ) − > in1 ? 1 ; out1 ! 2 ; out2 ! 0 ; out3 ! 1 ; : : else if
132
: : ( in1 ? [ 2 ] ) − > in1 ? 2 ; out1 ! 3 ; out2 ! 1 ; out3 ! 0 ; : : else if : : ( in1 ? [ 3 ] ) − > in1 ? 3 ; out1 ! 0 ; out2 ! 1 ; out3 ! 1 ; : : e l s e goto f i n i s h fi ; fi ; fi ; fi ; finish : c o n t r o l !END; goto s t a r t ; } p r o c t y p e f a n o u t ( chan i n 1 , i n 2 , o u t 1 , o u t 2 , o u t 3 , o u t 4 , control ) { bit x ; bit y ; start : c o n t r o l ?BEGIN ; if : : ( in1 ? [ x ] && in2 ? [ y ] ) − > in1 ?x ; in2 ?y ; out1 ! x ; out2 ! y ; out3 ! x ; out4 ! y ; : : e l s e goto f i n i s h fi ; finish : c o n t r o l !END; goto s t a r t ; } p r o c t y p e x o r ( chan i n 1 , i n 2 , o u t 1 , control ) { start : c o n t r o l ?BEGIN ; if : : ( in1 ?[0] && in2 ? [ 0 ] ) − > in1 ? 0 ; in2 ? 0 ; out1 ! 0 ; : : else if : : ( in1 ?[0] && in2 ? [ 1 ] ) − > in1 ? 0 ; in2 ? 1 ; out1 ! 1 ; : : else if : : ( in1 ?[1] && in2 ? [ 0 ] ) − > in1 ? 1 ; in2 ? 0 ; out1 ! 1 ; : : else if : : ( in1 ?[1] && in2 ? [ 1 ] ) − > in1 ? 1 ; in2 ? 1 ; out1 ! 0 ; : : e l s e goto f i n i s h fi ; fi ; fi ; fi ; finish : c o n t r o l !END; goto s t a r t ; } p r o c t y p e and ( chan i n 1 , i n 2 , o u t 1 , control ) { start : c o n t r o l ?BEGIN ; if : : ( in1 ?[0] && in2 ? [ 0 ] ) − > in1 ? 0 ; in2 ? 0 ; out1 ! 0 ; : : else if : : ( in1 ?[0] && in2 ? [ 1 ] ) − > in1 ? 0 ; in2 ? 1 ; out1 ! 0 ; : : else if : : ( in1 ?[1] && in2 ? [ 0 ] ) − > in1 ? 1 ; in2 ? 0 ; out1 ! 0 ; : : else if : : ( in1 ?[1] && in2 ? [ 1 ] ) − > in1 ? 1 ; in2 ? 1 ; out1 ! 1 ; : : e l s e goto f i n i s h fi ; fi ; fi ;
fi ; finish : c o n t r o l !END; goto s t a r t ; } p r o c t y p e show1 ( chan i n 1 , i n 2 , o u t 1 , control ) { bit z ; bit c ; start : c o n t r o l ?BEGIN ; if : : ( in1 ? [ z ] && in2 ? [ c ] ) − > in1 ? z ; in2 ? c ; out1 ! z , c , − 1 ; : : e l s e goto f i n i s h fi ; finish : c o n t r o l !END; goto s t a r t ; } a c t i v e proctype C o n t r o l ( ) { do : : g e n c o n t r o l ! BEGIN ; g e n c o n t r o l ?END; f a n o u t c o n t r o l ! BEGIN ; f a n o u t c o n t r o l ?END; x o r c o n t r o l ! BEGIN ; x o r c o n t r o l ?END; a n d c o n t r o l ! BEGIN ; a n d c o n t r o l ?END; s h o w 1 c o n t r o l ! BEGIN ; s h o w 1 c o n t r o l ?END; o u t p u t c o n t r o l ! BEGIN ; o u t p u t c o n t r o l ?END; od ; } a c t i v e proctype o u t p u t ( ) { chan i n = s h o w 1 z c ; b i t var1 ; b i t var2 ; short var3 ; start : o u t p u t c o n t r o l ?BEGIN ; if : : ( in ?[ var1 , var2 , var3 ] ) − > in ? var1 , var2 , var3 ; p r i n t f ( ” % d %d %d \ n ” , v a r 1 , v a r 2 , v a r 3 ) : : e l s e goto f i n i s h fi ; finish : o u t p u t c o n t r o l !END; goto s t a r t ; } init { gen tq !0; run gen ( g e n t q , run f a n o u t ( g e n x fanout run x o r ( f a n o u t x 1 run and ( f a n o u t x 2 run show1 ( x o r z , }
gen tq , gen x , gen y , g e n c o n t r o l ) ; , gen y , fanout x1 , fanout y1 , fanout x2 , y2 , fanout control ) ; , fanout y1 , xor z , xor control ) ; , fanout y2 , and z , a n d c o n t r o l ) ; and z , show1 zc , s h o w 1 c o n t r o l ) ;
G.2 Example 3: Full Adder from Truth Table The following listing is the PROMELA represention of example three. The example is a full adder implemented as a truth table. It is a slightly modified version of the code generated from ‘hwhpromela’. The only modifications applied to it, are the removal of white space, and some newline insertions. mtype = { BEGIN , END } ; chan o u t p u t c o n t r o l = [ 0 ] o f { mtype } ; chan g e n c o n t r o l = [ 0 ] o f { mtype } ; chan a d d e r c o n t r o l = [ 0 ] o f { mtype } ; chan s h o w 1 c o n t r o l = [ 0 ] o f { mtype } ; chan g e n t q = [ 1 ] o f { i n t } ; chan g e n x = [ 1 ] o f { b i t } ; chan g e n y = [ 1 ] o f { b i t } ; chan g e n c = [ 1 ] o f { b i t } ; chan a d d e r s = [ 1 ] o f { b i t } ; chan a d d e r c q = [ 1 ] o f { b i t } ; chan s h o w 1 s c = [ 1 ] o f { b i t , b i t , s h o r t } ; p r o c t y p e gen ( chan i n 1 , o u t 1 , o u t 2 , o u t 3 , o u t 4 , control ) { start : c o n t r o l ?BEGIN ; if : : ( in1 ? [ 0 ] ) − > in1 ? 0 ; out1 ! 1 ; out2 ! 0 ; out3 ! 0 ; out4 ! 0 ; : : else if : : ( in1 ? [ 1 ] ) − > in1 ? 1 ; out1 ! 2 ; out2 ! 0 ; out3 ! 1 ; out4 ! 0 ; : : else if : : ( in1 ? [ 2 ] ) − > in1 ? 2 ; out1 ! 3 ; out2 ! 1 ; out3 ! 0 ; out4 ! 0 ; : : else if : : ( in1 ? [ 3 ] ) − > in1 ? 3 ; out1 ! 4 ; out2 ! 1 ; out3 ! 1 ; out4 ! 0 ; : : else if : : ( in1 ? [ 4 ] ) − > in1 ? 4 ; out1 ! 5 ; out2 ! 0 ; out3 ! 0 ; out4 ! 1 ; : : else if : : ( in1 ? [ 5 ] ) − > in1 ? 5 ; out1 ! 6 ; out2 ! 0 ; out3 ! 1 ; out4 ! 1 ; : : else if : : ( in1 ? [ 6 ] ) − > in1 ? 6 ; out1 ! 7 ; out2 ! 1 ; out3 ! 0 ; out4 ! 1 ; : : else if : : ( in1 ? [ 7 ] ) − > in1 ? 7 ; out1 ! 0 ; out2 ! 1 ; out3 ! 1 ; out4 ! 1 ; : : e l s e goto f i n i s h fi ; fi ; fi ; fi ; fi ; fi ; fi ; fi ; finish : c o n t r o l !END; goto s t a r t ; }
p r o c t y p e a d d e r ( chan i n 1 , i n 2 , i n 3 , o u t 1 , o u t 2 , control ) { start : c o n t r o l ?BEGIN ; if : : ( in1 ?[0] && in2 ?[0] && in3 ? [ 0 ] ) − > in1 ? 0 ; in2 ? 0 ; in3 ?0; out1 ! 0 ; out2 ! 0 ; : : else if : : ( in1 ?[0] && in2 ?[1] && in3 ? [ 0 ] ) − > in1 ? 0 ; in2 ? 1 ; in3 ?0; out1 ! 1 ; out2 ! 0 ; : : else if : : ( in1 ?[1] && in2 ?[0] && in3 ? [ 0 ] ) − > in1 ? 1 ; in2 ? 0 ; in3 ?0; out1 ! 1 ; out2 ! 0 ; : : else if : : ( in1 ?[1] && in2 ?[1] && in3 ? [ 0 ] ) − > in1 ? 1 ; in2 ? 1 ; in3 ?0; out1 ! 0 ; out2 ! 1 ; : : else if : : ( in1 ?[0] && in2 ?[0] && in3 ? [ 1 ] ) − > in1 ? 0 ; in2 ? 0 ; in3 ?1; out1 ! 1 ; out2 ! 0 ; : : else if : : ( in1 ?[0] && in2 ?[1] && in3 ? [ 1 ] ) − > in1 ? 0 ; in2 ? 1 ; in3 ?1; out1 ! 0 ; out2 ! 1 ; : : else if : : ( in1 ?[1] && in2 ?[0] && in3 ? [ 1 ] ) − > in1 ? 1 ; in2 ? 0 ; in3 ?1; out1 ! 0 ; out2 ! 1 ; : : else if : : ( in1 ?[1] && in2 ?[1] && in3 ? [ 1 ] ) − > in1 ? 1 ; in2 ?1; in3 ?1; out1 ! 1 ; out2 ! 1 ; : : e l s e goto f i n i s h fi ; fi ; fi ; fi ; fi ; fi ; fi ; fi ; finish : c o n t r o l !END; goto s t a r t ; } p r o c t y p e show1 ( chan i n 1 , i n 2 , o u t 1 , control ) { bit s ; bit c ; start : c o n t r o l ?BEGIN ; if : : ( in1 ? [ s ] && in2 ? [ c ] ) − > in1 ? s ; in2 ? c ; out1 ! s , c , − 1 ; : : e l s e goto f i n i s h fi ; finish : c o n t r o l !END; goto s t a r t ; }
a c t i v e proctype C o n t r o l ( ) { do : : g e n c o n t r o l ! BEGIN ; g e n c o n t r o l ?END; a d d e r c o n t r o l ! BEGIN ; a d d e r c o n t r o l ?END; s h o w 1 c o n t r o l ! BEGIN ; s h o w 1 c o n t r o l ?END; o u t p u t c o n t r o l ! BEGIN ; o u t p u t c o n t r o l ?END; od ; } a c t i v e proctype o u t p u t ( ) { chan i n = s h o w 1 s c ; b i t var1 ; b i t var2 ; short var3 ; start : o u t p u t c o n t r o l ?BEGIN ; if : : ( in ?[ var1 , var2 , var3 ] ) − > in ? var1 , var2 , var3 ; p r i n t f ( ” % d %d %d \ n ” , v a r 1 , v a r 2 , v a r 3 ) : : e l s e goto f i n i s h fi ; finish : o u t p u t c o n t r o l !END; goto s t a r t ; } init { gen run run run }
tq !0; gen ( g e n t q , g e n t q , g e n x , g e n y , g e n c , g e n c o n t r o l ) ; adder ( gen x , gen y , gen c , adder s , adder cq , a d d e r c o n t r o l ) ; show1 ( a d d e r s , a d d e r c q , s h o w 1 s c , s h o w 1 c o n t r o l ) ;
G.3 Example 4: Full Adder as Half Adders and OR Gates Example four is the last example included in this appendix. The full adder is here represented using ‘half adders’ and ‘or’ gates. The slightly modified PROMELA version is listed below: mtype = { BEGIN , END } ; chan o u t p u t c o n t r o l = [ 0 ] o f { mtype } ; chan g e n c o n t r o l = [ 0 ] o f { mtype } ; chan h 1 c o n t r o l = [ 0 ] o f { mtype } ; chan h 2 c o n t r o l = [ 0 ] o f { mtype } ; chan o r c o n t r o l = [ 0 ] o f { mtype } ; chan s h o w 1 c o n t r o l = [ 0 ] o f { mtype } ; chan g e n t q = [ 1 ] o f { i n t } ; chan g e n x = [ 1 ] o f { b i t } ; chan g e n y = [ 1 ] o f { b i t } ; chan g e n c = [ 1 ] o f { b i t } ; chan o r z = [ 1 ] o f { b i t } ; chan s h o w 1 s c = [ 1 ] o f { b i t , b i t , s h o r t } ; chan h 1 s = [ 1 ] o f { b i t } ; chan h 1 c = [ 1 ] o f { b i t } ; chan h 2 s = [ 1 ] o f { b i t } ; chan h 2 c = [ 1 ] o f { b i t } ; p r o c t y p e gen ( chan i n 1 , o u t 1 , o u t 2 , o u t 3 , o u t 4 , start :
control ) {
c o n t r o l ?BEGIN ; if : : ( in1 ? [ 0 ] ) − > in1 ? 0 ; out1 ! 1 ; out2 ! 0 ; out3 ! 0 ; out4 ! 0 ; : : else if : : ( in1 ? [ 1 ] ) − > in1 ? 1 ; out1 ! 2 ; out2 ! 0 ; out3 ! 1 ; out4 ! 0 ; : : else if : : ( in1 ? [ 2 ] ) − > in1 ? 2 ; out1 ! 3 ; out2 ! 1 ; out3 ! 0 ; out4 ! 0 ; : : else if : : ( in1 ? [ 3 ] ) − > in1 ? 3 ; out1 ! 4 ; out2 ! 1 ; out3 ! 1 ; out4 ! 0 ; : : else if : : ( in1 ? [ 4 ] ) − > in1 ? 4 ; out1 ! 5 ; out2 ! 0 ; out3 ! 0 ; out4 ! 1 ; : : else if : : ( in1 ? [ 5 ] ) − > in1 ? 5 ; out1 ! 6 ; out2 ! 0 ; out3 ! 1 ; out4 ! 1 ; : : else if : : ( in1 ? [ 6 ] ) − > in1 ? 6 ; out1 ! 7 ; out2 ! 1 ; out3 ! 0 ; out4 ! 1 ; : : else if : : ( in1 ? [ 7 ] ) − > in1 ? 7 ; out1 ! 0 ; out2 ! 1 ; out3 ! 1 ; out4 ! 1 ; : : e l s e goto f i n i s h fi ; fi ; fi ; fi ; fi ; fi ; fi ; fi ; finish : c o n t r o l !END; goto s t a r t ; } p r o c t y p e o r ( chan i n 1 start : c o n t r o l ?BEGIN ; if : : ( in1 ?[0] && in2 : : else if : : ( in1 ?[0] : : else if ::( ::
, in2 , out1 ,
control ) {
? [ 0 ] ) − > in1 ? 0 ; in2 ? 0 ; out1 ! 0 ; && in2 ? [ 1 ] ) − > in1 ? 0 ; in2 ? 1 ; out1 ! 1 ; in1 ?[1] && in2 ? [ 0 ] ) − > in1 ? 1 ; in2 ? 0 ; out1 ! 1 ; else if : : ( in1 ?[1] && in2 ? [ 1 ] ) − > in1 ? 1 ; in2 ? 1 ; out1 ! 1 ; : : e l s e goto f i n i s h fi ;
fi ; fi ; fi ; finish : c o n t r o l !END; goto s t a r t ; } p r o c t y p e show1 ( chan i n 1 , i n 2 , o u t 1 , bit s ; bit c ; start :
control ) {
c o n t r o l ?BEGIN ; if : : ( in1 ? [ s ] && in2 ? [ c ] ) − > in1 ? s ; in2 ? c ; out1 ! s , c , − 1 ; : : e l s e goto f i n i s h fi ; finish : c o n t r o l !END; goto s t a r t ; } p r o c t y p e h1 ( chan i n 1 start : c o n t r o l ?BEGIN ; if : : ( in1 ?[0] && in2 : : else if : : ( in1 ?[0] : : else if ::( ::
, in2 , out1 , out2 ,
control ) {
? [ 0 ] ) − > in1 ? 0 ; in2 ? 0 ; out1 ! 0 ; out2 ! 0 ; && in2 ? [ 1 ] ) − > in1 ? 0 ; in2 ? 1 ; out1 ! 1 ; out2 ! 0 ; in1 ?[1] && in2 ? [ 0 ] ) − > in1 ? 1 ; in2 ? 0 ; out1 ! 1 ; out2 ! 0 ; else if : : ( in1 ?[1] && in2 ? [ 1 ] ) − > in1 ? 1 ; in2 ?1; out1 ! 0 ; out2 ! 1 ; : : e l s e goto f i n i s h fi ;
fi ; fi ; fi ; finish : c o n t r o l !END; goto s t a r t ; } p r o c t y p e h2 ( chan i n 1 start : c o n t r o l ?BEGIN ; if : : ( in1 ?[0] && in2 : : else if : : ( in1 ?[0] : : else if ::( ::
, in2 , out1 , out2 ,
control ) {
? [ 0 ] ) − > in1 ? 0 ; in2 ? 0 ; out1 ! 0 ; out2 ! 0 ; && in2 ? [ 1 ] ) − > in1 ? 0 ; in2 ? 1 ; out1 ! 1 ; out2 ! 0 ; in1 ?[1] && in2 ? [ 0 ] ) − > in1 ? 1 ; in2 ? 0 ; out1 ! 1 ; out2 ! 0 ; else if : : ( in1 ?[1] && in2 ? [ 1 ] ) − > in1 ? 1 ; in2 ?1; out1 ! 0 ; out2 ! 1 ; : : e l s e goto f i n i s h fi ;
fi ; fi ; fi ; finish : c o n t r o l !END; goto s t a r t ; } a c t i v e proctype C o n t r o l ( ) { do : : g e n c o n t r o l ! BEGIN ; g e n c o n t r o l ?END; h 1 c o n t r o l ! BEGIN ; h 1 c o n t r o l ?END; h 2 c o n t r o l ! BEGIN ; h 2 c o n t r o l ?END; o r c o n t r o l ! BEGIN ; o r c o n t r o l ?END; s h o w 1 c o n t r o l ! BEGIN ; s h o w 1 c o n t r o l ?END; o u t p u t c o n t r o l ! BEGIN ; o u t p u t c o n t r o l ?END; od ;
} a c t i v e proctype o u t p u t ( ) { chan i n = s h o w 1 s c ; b i t var1 ; b i t var2 ; short var3 ; start : o u t p u t c o n t r o l ?BEGIN ; if : : ( in ?[ var1 , var2 , var3 ] ) − > in ? var1 , var2 , var3 ; p r i n t f ( ” % d %d %d \ n ” , v a r 1 , v a r 2 , v a r 3 ) : : e l s e goto f i n i s h fi ; finish : o u t p u t c o n t r o l !END; goto s t a r t ; } init { gen run run run run run }
tq !0; gen ( g e n t q , g e n t q , g e n x , g e n y , g e n c , g e n c o n t r o l ) ; or ( h1 c , h2 c , or z , o r c o n t r o l ) ; show1 ( h 2 s , o r z , s h o w 1 s c , s h o w 1 c o n t r o l ) ; h1 ( g e n x , g e n y , h 1 s , h 1 c , h 1 c o n t r o l ) ; h2 ( g e n c , h 1 s , h 2 s , h 2 c , h 2 c o n t r o l ) ;
Appendix H
Verification Result This appendix contains the verification result, when verifying the PROMELA model translated from HW-HUME using ‘hwhpromela’. The verifications are conducted in chapter 6. The HW-HUME source code is listed in appendix F while the a few of the PROMELA translations are listed in appendix G. Due the size of the PROMELA code, only a selected range of the source code is included. Please note that the line numbers in the listings are not part of the verification output.
H.1 Example 1: Half Adder The half adder source code is listed in section G.1. When verifying the example with ‘hwhpromela’, the following output is generated: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
$ j a v a hwhpromela − v h a l f . hume ( Spin Version 4 . 1 . 3 −− 24 A p r i l 2 0 0 4 ) + P a r t i a l Order Reduction Full s t a t e s p a c e search for : never claim assertion violations acceptance cycles i n v a l i d end s t a t e s
− ( none s p e c i f i e d ) + − ( not s e le c t e d ) +
S t a t e −vector 1 5 6 byte , depth reached 2 7 5 , e r r o r s : 0 217 s t a t e s , stored 1 s t a t e s , matched 2 1 8 t r a n s i t i o n s ( = s t o r e d +m a t c h e d ) 0 atomic s t e p s hash c o n f l i c t s : 0 ( r e s o l v e d ) ( max s i z e 2 ˆ 1 8 s t a t e s ) u n r e a c h e d i n p r o c t y p e gen l i n e 4 5 , s t a t e 3 7 , ” − end −” ( 1 of 3 7 s t a t e s ) unreached in proctype f a n o u t l i n e 6 4 , s t a t e 1 5 , ” − end −” ( 1 of 1 5 s t a t e s ) unreached in proctype xor l i n e 9 0 , s t a t e 3 3 , ” − end −” ( 1 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e and l i n e 1 1 6 , s t a t e 3 3 , ” − end −”
141
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
( 1 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e show1 l i n e 1 3 5 , s t a t e 1 2 , ” − end −” ( 1 of 1 2 s t a t e s ) unreached in proctype C o n t r o l l i n e 1 5 0 , s t a t e 1 6 , ” − end −” ( 1 of 1 6 s t a t e s ) unreached in proctype o u t p u t l i n e 1 7 1 , s t a t e 1 1 , ” − end −” ( 1 of 1 1 s t a t e s ) unreached in proctype : i n i t : ( 0 of 7 s t a t e s ) −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− T r a n s l a t i o n S u c c e s s f u l : V e r i f i c a t i o n Completed −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− Fi le Generated : h a l f . pml T r a n s l a t i o n Time : 4 0 9 ms V e r i f i c a t i o n Time : 3 3 1 0 ms T o t a l Running Time : 3 7 1 9 ms −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
Line 1 shows the command applied to ‘hwhpromela’ to verify the half adder. Line 2 lists the name of the generated file, which is ‘half.pml’. The meaning of the output in line 6 to 17 is already described in chapter 6. Line 18 is only interesting when using algorithms other than the default. The rest of the verification output lists all the unreached states. Since this is a full space search that ran to completion, this means that these transitions are unreachable and constitute dead code in the model [18]. As the listing illustrates, all the processes except the init process, have one unreachable state, which is the end of the code for the process. This makes sense this since all processes have an infinite number of runs, and will never exit the process - hence it will never reach the end of it.
H.2 Example 2: An XOR and an AND Gate Forming a Deadlock The following output is generated when validating example two. Line 14 specifies that the example contains a deadlock, and line 3 states the filename of the generated trail. Lines 23 to 30 inclusively contain the statistics of the time consumption and is not part of the SPIN output. It is created by the ‘hwhpromela’ program. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
$ j a v a hwhpromela − v d e a d l o c k . hume pan : i n v a l i d end s t a t e ( a t d e p t h 4 6 ) pan : w r o t e d e a d l o c k . pml . t r a i l ( Spin Version 4 . 1 . 3 −− 24 A p r i l 2 0 0 4 ) Warning : S e a r c h n o t c o m p l e t e d + P a r t i a l Order Reduction Full s t a t e s p a c e search for : never claim assertion violations acceptance cycles i n v a l i d end s t a t e s
− ( none s p e c i f i e d ) + − ( not s e le c t e d ) +
S t a t e −vector 1 3 2 byte , depth reached 4 6 , e r r o r s : 1 36 s t a t e s , stored 0 s t a t e s , matched
17 18 19 20 21 22 23 24 25 26 27 28 29 30
3 6 t r a n s i t i o n s ( = s t o r e d +m a t c h e d ) 0 atomic s t e p s hash c o n f l i c t s : 0 ( r e s o l v e d ) ( max s i z e 2 ˆ 1 8 s t a t e s )
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− T r a n s l a t i o n S u c c e s s f u l : V e r i f i c a t i o n Completed −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− Fi le Generated : d e a d l o c k . pml T r a n s l a t i o n Time : 2 4 6 ms V e r i f i c a t i o n Time : 3 1 0 7 ms T o t a l Running Time : 3 3 5 3 ms −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
H.3 Example 3: Full Adder from Truth Table When validating example three, which is the full adder created by using a truth table, the output listed below is generated. Line 11 specifies that the verification completed successfully and without any errors. Lines 37 to 44 inclusively hold the time statistics from the verification, generated by ‘hwhpromela’. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
$ j a v a hwhpromela − v a d d e r 1 . hume ( Spin Version 4 . 1 . 3 −− 24 A p r i l 2 0 0 4 ) + P a r t i a l Order Reduction Full s t a t e s p a c e search for : never claim assertion violations acceptance cycles i n v a l i d end s t a t e s
− ( none s p e c i f i e d ) + − ( not s e le c t e d ) +
S t a t e −vector 1 2 0 byte , depth reached 3 7 1 , e r r o r s : 0 301 s t a t e s , stored 1 s t a t e s , matched 3 0 2 t r a n s i t i o n s ( = s t o r e d +m a t c h e d ) 0 atomic s t e p s hash c o n f l i c t s : 0 ( r e s o l v e d ) ( max s i z e 2 ˆ 1 8 s t a t e s ) u n r e a c h e d i n p r o c t y p e gen l i n e 5 2 , s t a t e 7 7 , ” − end −” ( 1 of 7 7 s t a t e s ) unreached in proctype adder l i n e 9 0 , s t a t e 7 7 , ” − end −” ( 1 of 7 7 s t a t e s ) u n r e a c h e d i n p r o c t y p e show1 l i n e 1 0 9 , s t a t e 1 2 , ” − end −” ( 1 of 1 2 s t a t e s ) unreached in proctype C o n t r o l l i n e 1 2 2 , s t a t e 1 2 , ” − end −” ( 1 of 1 2 s t a t e s ) unreached in proctype o u t p u t l i n e 1 4 3 , s t a t e 1 1 , ” − end −” ( 1 of 1 1 s t a t e s ) unreached in proctype : i n i t : ( 0 of 5 s t a t e s )
36 37 38 39 40 41 42 43 44
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− T r a n s l a t i o n S u c c e s s f u l : V e r i f i c a t i o n Completed −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− Fi le Generated : a d d e r 1 . pml T r a n s l a t i o n Time : 5 0 8 ms V e r i f i c a t i o n Time : 3 0 9 3 ms T o t a l Running Time : 3 6 0 1 ms −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
H.4 Example 4: Full Adder as Half Adders and OR Gates Example four is a full adder created by using ‘half adders’ and ‘or’ gates. The output generated when validating the adder, is listed below. Line 11 states that no errors were found, and lines 46 to 53 inclusively contain the time statistics generated by ‘hwhpromela’. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
$ j a v a hwhpromela − v a d d e r 2 . hume ( Spin Version 4 . 1 . 3 −− 24 A p r i l 2 0 0 4 ) + P a r t i a l Order Reduction Full s t a t e s p a c e search for : never claim assertion violations acceptance cycles i n v a l i d end s t a t e s
− ( none s p e c i f i e d ) + − ( not s e le c t e d ) +
S t a t e −vector 1 5 6 byte , depth reached 5 1 9 , e r r o r s : 0 413 s t a t e s , stored 1 s t a t e s , matched 4 1 4 t r a n s i t i o n s ( = s t o r e d +m a t c h e d ) 0 atomic s t e p s hash c o n f l i c t s : 0 ( r e s o l v e d ) ( max s i z e 2 ˆ 1 8 s t a t e s ) u n r e a c h e d i n p r o c t y p e gen l i n e 5 7 , s t a t e 7 7 , ” − end −” ( 1 of 7 7 s t a t e s ) unreached in proctype or l i n e 7 2 , s t a t e 1 8 , ” in1 ?1” l i n e 7 2 , s t a t e 1 9 , ” in2 ?1” l i n e 7 2 , s t a t e 2 0 , ” out1 !1” l i n e 8 3 , s t a t e 3 3 , ” − end −” ( 4 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e show1 l i n e 1 0 2 , s t a t e 1 2 , ” − end −” ( 1 of 1 2 s t a t e s ) u n r e a c h e d i n p r o c t y p e h1 l i n e 1 2 8 , s t a t e 3 7 , ” − end −” ( 1 of 3 7 s t a t e s ) u n r e a c h e d i n p r o c t y p e h2 l i n e 1 5 4 , s t a t e 3 7 , ” − end −” ( 1 of 3 7 s t a t e s ) unreached in proctype C o n t r o l l i n e 1 6 9 , s t a t e 1 6 , ” − end −” ( 1 of 1 6 s t a t e s ) unreached in proctype o u t p u t l i n e 1 9 0 , s t a t e 1 1 , ” − end −”
42 43 44 45 46 47 48 49 50 51 52 53
( 1 of 1 1 s t a t e s ) unreached in proctype : i n i t : ( 0 of 7 s t a t e s ) −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− T r a n s l a t i o n S u c c e s s f u l : V e r i f i c a t i o n Completed −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− Fi le Generated : a d d e r 2 . pml T r a n s l a t i o n Time : 3 1 2 ms V e r i f i c a t i o n Time : 4 1 2 6 ms T o t a l Running Time : 4 4 3 8 ms −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
H.5 Example 5: Full Adder as XOR, AND and OR Gates In example five the adder has been created by connecting a set of ‘xor’,‘and’ and ‘or’ gates. The output shown below was generated from the verification in SPIN. The verification succeeded without any errors, as line 11 illustrates. The time statistics generated by ‘hwhpromela’ are listed on line 57 to 64 inclusively. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
$ j a v a hwhpromela − v a d d e r 3 . hume ( Spin Version 4 . 1 . 3 −− 24 A p r i l 2 0 0 4 ) + P a r t i a l Order Reduction Full s t a t e s p a c e search for : never claim assertion violations acceptance cycles i n v a l i d end s t a t e s
− ( none s p e c i f i e d ) + − ( not s e le c t e d ) +
S t a t e −vector 2 5 6 byte , depth reached 8 7 1 , e r r o r s : 0 693 s t a t e s , stored 1 s t a t e s , matched 6 9 4 t r a n s i t i o n s ( = s t o r e d +m a t c h e d ) 0 atomic s t e p s hash c o n f l i c t s : 0 ( r e s o l v e d ) ( max s i z e 2 ˆ 1 8 s t a t e s ) u n r e a c h e d i n p r o c t y p e gen l i n e 6 9 , s t a t e 7 7 , ” − end −” ( 1 of 7 7 s t a t e s ) unreached in proctype or l i n e 8 4 , s t a t e 1 8 , ” in1 ?1” l i n e 8 4 , s t a t e 1 9 , ” in2 ?1” l i n e 8 4 , s t a t e 2 0 , ” out1 !1” l i n e 9 5 , s t a t e 3 3 , ” − end −” ( 4 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e show1 l i n e 1 1 4 , s t a t e 1 2 , ” − end −” ( 1 of 1 2 s t a t e s ) unreached in proctype f1 l i n e 1 3 3 , s t a t e 1 5 , ” − end −” ( 1 of 1 5 s t a t e s ) unreached in proctype f2 l i n e 1 5 2 , s t a t e 1 5 , ” − end −” ( 1 of 1 5 s t a t e s ) u n r e a c h e d i n p r o c t y p e x1
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
l i n e 1 7 8 , s t a t e 3 3 , ” − end −” ( 1 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e x2 l i n e 2 0 4 , s t a t e 3 3 , ” − end −” ( 1 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e a1 l i n e 2 3 0 , s t a t e 3 3 , ” − end −” u n r e a c h e d i n p r o c t y p e a2 l i n e 2 5 6 , s t a t e 3 3 , ” − end −” ( 1 of 3 3 s t a t e s ) unreached in proctype C o n t r o l l i n e 2 7 5 , s t a t e 2 4 , ” − end −” ( 1 of 2 4 s t a t e s ) unreached in proctype o u t p u t l i n e 2 9 6 , s t a t e 1 1 , ” − end −” ( 1 of 1 1 s t a t e s ) unreached in proctype : i n i t : ( 0 of 1 1 s t a t e s ) −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− T r a n s l a t i o n S u c c e s s f u l : V e r i f i c a t i o n Completed −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− Fi le Generated : a d d e r 3 . pml T r a n s l a t i o n Time : 3 4 3 ms V e r i f i c a t i o n Time : 4 9 9 0 ms T o t a l Running Time : 5 3 3 3 ms −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
H.6 Connecting Adders Examples six to nine are used to test the translation and verification on bigger models. The models are created on the basis of example five. Several such adders are connected together to create two, three, four and five bit adders.
H.6.1 Example 6: A Two Bit Adder In example six, two adders are connected to create a two bit adder. As line 11 states SPIN handled the size, and the model verified without any errors. Lines 85 to 92 inclusively hold the time statistics generated by ‘hwhpromela’. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
$ j a v a hwhpromela − v t w o b i t a d d e r . hume ( Spin Version 4 . 1 . 3 −− 24 A p r i l 2 0 0 4 ) + P a r t i a l Order Reduction Full s t a t e s p a c e search for : never claim assertion violations acceptance cycles i n v a l i d end s t a t e s
− ( none s p e c i f i e d ) + − ( not s e le c t e d ) +
S t a t e −vector 4 5 6 byte , depth reached 1 5 9 4 , e r r o r s : 0 1272 s t a t e s , s t o r e d 1 s t a t e s , matched 1 2 7 3 t r a n s i t i o n s ( = s t o r e d +m a t c h e d ) 0 atomic s t e p s
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
hash c o n f l i c t s : 0 ( r e s o l v e d ) ( max s i z e 2 ˆ 1 8 s t a t e s ) u n r e a c h e d i n p r o c t y p e gen1 l i n e 9 3 , s t a t e 7 7 , ” − end −” ( 1 of 7 7 s t a t e s ) u n r e a c h e d i n p r o c t y p e gen2 l i n e 1 1 9 , s t a t e 3 7 , ” − end −” ( 1 of 3 7 s t a t e s ) u n r e a c h e d i n p r o c t y p e show1 l i n e 1 3 9 , s t a t e 1 3 , ” − end −” ( 1 of 1 3 s t a t e s ) unreached in proctype f1 l i n e 1 5 8 , s t a t e 1 5 , ” − end −” ( 1 of 1 5 s t a t e s ) unreached in proctype f2 l i n e 1 7 7 , s t a t e 1 5 , ” − end −” ( 1 of 1 5 s t a t e s ) unreached in proctype f3 l i n e 1 9 6 , s t a t e 1 5 , ” − end −” ( 1 of 1 5 s t a t e s ) unreached in proctype f4 l i n e 2 1 5 , s t a t e 1 5 , ” − end −” ( 1 of 1 5 s t a t e s ) u n r e a c h e d i n p r o c t y p e x1 l i n e 2 4 1 , s t a t e 3 3 , ” − end −” ( 1 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e x2 l i n e 2 6 7 , s t a t e 3 3 , ” − end −” ( 1 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e x3 l i n e 2 9 3 , s t a t e 3 3 , ” − end −” ( 1 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e x4 l i n e 3 1 9 , s t a t e 3 3 , ” − end −” ( 1 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e a1 l i n e 3 4 5 , s t a t e 3 3 , ” − end −” ( 1 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e a2 l i n e 3 7 1 , s t a t e 3 3 , ” − end −” ( 1 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e a3 l i n e 3 9 7 , s t a t e 3 3 , ” − end −” ( 1 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e a4 l i n e 4 2 3 , s t a t e 3 3 , ” − end −” ( 1 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e o1 l i n e 4 3 8 , s t a t e 1 8 , ” in1 ?1” l i n e 4 3 8 , s t a t e 1 9 , ” in2 ?1” l i n e 4 3 8 , s t a t e 2 0 , ” out1 !1” l i n e 4 4 9 , s t a t e 3 3 , ” − end −” ( 4 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e o2 l i n e 4 6 4 , s t a t e 1 8 , ” in1 ?1” l i n e 4 6 4 , s t a t e 1 9 , ” in2 ?1” l i n e 4 6 4 , s t a t e 2 0 , ” out1 !1” l i n e 4 7 5 , s t a t e 3 3 , ” − end −” ( 4 of 3 3 s t a t e s ) unreached in proctype C o n t r o l l i n e 5 0 2 , s t a t e 4 0 , ” − end −” ( 1 of 4 0 s t a t e s )
79 80 81 82 83 84 85 86 87 88 89 90 91 92
unreached in proctype o u t p u t l i n e 5 2 4 , s t a t e 1 1 , ” − end −” ( 1 of 1 1 s t a t e s ) unreached in proctype : i n i t : ( 0 of 2 0 s t a t e s ) −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− T r a n s l a t i o n S u c c e s s f u l : V e r i f i c a t i o n Completed −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− Fi le Generated : t w o b i t a d d e r . pml T r a n s l a t i o n Time : 3 9 4 ms V e r i f i c a t i o n Time : 8 2 9 7 ms T o t a l Running Time : 8 6 9 1 ms −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
H.6.2 Example 7: A Three Bit Adder The three bit adder in example seven is created by appending another adder to example six. By doing so, an even bigger model is created. However, as line 12 in the following output shows, the verification succeeded without any errors. Lines 113 to 120 inclusively show the time statistics generated by ‘hwhpromela’. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
$ j a v a hwhpromela − v t h r e e b i t a d d e r . hume h i n t : t h i s s e a r c h i s more e f f i c i e n t i f pan . c i s c o m p i l e d −DSAFETY ( Spin Version 4 . 1 . 3 −− 24 A p r i l 2 0 0 4 ) + P a r t i a l Order Reduction Full s t a t e s p a c e search for : never claim assertion violations acceptance cycles i n v a l i d end s t a t e s
− ( none s p e c i f i e d ) + − ( not s e le c t e d ) +
S t a t e −vector 6 5 2 byte , depth reached 2 3 1 7 , e r r o r s : 0 1851 s t a t e s , s t o r e d 1 s t a t e s , matched 1 8 5 2 t r a n s i t i o n s ( = s t o r e d +m a t c h e d ) 0 atomic s t e p s hash c o n f l i c t s : 0 ( r e s o l v e d ) ( max s i z e 2 ˆ 1 8 s t a t e s ) u n r e a c h e d i n p r o c t y p e gen1 line 117, state 77, ( 1 of 7 7 s t a t e s ) u n r e a c h e d i n p r o c t y p e gen2 line 143, state 37, ( 1 of 3 7 s t a t e s ) u n r e a c h e d i n p r o c t y p e gen3 line 169, state 37, ( 1 of 3 7 s t a t e s ) u n r e a c h e d i n p r o c t y p e show1 line 190, state 14, ( 1 of 1 4 s t a t e s ) unreached in proctype f1 line 209, state 15, ( 1 of 1 5 s t a t e s ) unreached in proctype f2 line 228, state 15,
” − end −”
” − end −”
” − end −”
” − end −”
” − end −”
” − end −”
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
( 1 of 1 5 s t a t e s ) unreached in proctype f3 line 247, state 15, ( 1 of 1 5 s t a t e s ) unreached in proctype f4 line 266, state 15, ( 1 of 1 5 s t a t e s ) unreached in proctype f5 line 285, state 15, ( 1 of 1 5 s t a t e s ) unreached in proctype f6 line 304, state 15, ( 1 of 1 5 s t a t e s ) u n r e a c h e d i n p r o c t y p e x1 line 330, state 33, ( 1 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e x2 line 356, state 33, ( 1 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e x3 line 382, state 33, ( 1 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e x4 line 408, state 33, ( 1 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e x5 line 434, state 33, ( 1 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e x6 line 460, state 33, ( 1 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e a1 line 486, state 33, ( 1 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e a2 line 512, state 33, ( 1 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e a3 line 538, state 33, ( 1 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e a4 line 564, state 33, ( 1 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e a5 line 590, state 33, ( 1 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e a6 line 616, state 33, ( 1 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e o1 line 631, state 18, line 631, state 19, line 631, state 20, line 642, state 33, ( 4 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e o2 line 657, state 18, line 657, state 19, line 657, state 20, line 668, state 33, ( 4 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e o3 line 683, state 18,
” − end −”
” − end −”
” − end −”
” − end −”
” − end −”
” − end −”
” − end −”
” − end −”
” − end −”
” − end −”
” − end −”
” − end −”
” − end −”
” − end −”
” − end −”
” − end −”
” in1 ?1” ” in2 ?1” ” out1 !1” ” − end −”
” in1 ?1” ” in2 ?1” ” out1 !1” ” − end −”
” in1 ?1”
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
l i n e 6 8 3 , s t a t e 1 9 , ” in2 ?1” l i n e 6 8 3 , s t a t e 2 0 , ” out1 !1” l i n e 6 9 4 , s t a t e 3 3 , ” − end −” ( 4 of 3 3 s t a t e s ) unreached in proctype C o n t r o l l i n e 7 2 9 , s t a t e 5 6 , ” − end −” ( 1 of 5 6 s t a t e s ) unreached in proctype o u t p u t l i n e 7 5 2 , s t a t e 1 1 , ” − end −” ( 1 of 1 1 s t a t e s ) unreached in proctype : i n i t : ( 0 of 2 9 s t a t e s ) −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− T r a n s l a t i o n S u c c e s s f u l : V e r i f i c a t i o n Completed −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− Fi le Generated : t h r e e b i t a d d e r . pml T r a n s l a t i o n Time : 4 1 4 ms V e r i f i c a t i o n Time : 1 1 4 5 8 ms T o t a l Running Time : 1 1 8 7 2 ms −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
H.6.3 Example 8: A Four Bit Adder In example eight another adder is appended to the previous example, creating a four bit adder. As line 12 shows, the verification completed successfully, without any errors. Lines 134 to 141 inclusively hold the time statistics ‘hwhpromela’ created. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
$ j a v a hwhpromela − v f o u r b i t a d d e r . hume h i n t : t h i s s e a r c h i s more e f f i c i e n t i f pan . c i s c o m p i l e d −DSAFETY ( Spin Version 4 . 1 . 3 −− 24 A p r i l 2 0 0 4 ) + P a r t i a l Order Reduction Full s t a t e s p a c e search for : never claim assertion violations acceptance cycles i n v a l i d end s t a t e s
− ( none s p e c i f i e d ) + − ( not s e le c t e d ) +
S t a t e −vector 8 4 8 byte , depth reached 3 0 4 0 , e r r o r s : 0 2430 s t a t e s , s t o r e d 1 s t a t e s , matched 2 4 3 1 t r a n s i t i o n s ( = s t o r e d +m a t c h e d ) 0 atomic s t e p s hash c o n f l i c t s : 0 ( r e s o l v e d ) ( max s i z e 2 ˆ 1 8 s t a t e s ) u n r e a c h e d i n p r o c t y p e gen1 line 141, state 77, ( 1 of 7 7 s t a t e s ) u n r e a c h e d i n p r o c t y p e gen2 line 167, state 37, ( 1 of 3 7 s t a t e s ) u n r e a c h e d i n p r o c t y p e gen3 line 193, state 37, ( 1 of 3 7 s t a t e s ) u n r e a c h e d i n p r o c t y p e gen4 line 219, state 37,
” − end −”
” − end −”
” − end −”
” − end −”
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
( 1 of 3 7 s t a t e s ) u n r e a c h e d i n p r o c t y p e show1 line 241, state 15, ( 1 of 1 5 s t a t e s ) unreached in proctype f1 line 260, state 15, ( 1 of 1 5 s t a t e s ) unreached in proctype f2 line 279, state 15, ( 1 of 1 5 s t a t e s ) unreached in proctype f3 line 298, state 15, ( 1 of 1 5 s t a t e s ) unreached in proctype f4 line 317, state 15, ( 1 of 1 5 s t a t e s ) unreached in proctype f5 line 336, state 15, ( 1 of 1 5 s t a t e s ) unreached in proctype f6 line 355, state 15, ( 1 of 1 5 s t a t e s ) unreached in proctype f7 line 374, state 15, ( 1 of 1 5 s t a t e s ) unreached in proctype f8 line 393, state 15, ( 1 of 1 5 s t a t e s ) u n r e a c h e d i n p r o c t y p e x1 line 419, state 33, ( 1 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e x2 line 445, state 33, ( 1 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e x3 line 471, state 33, ( 1 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e x4 line 497, state 33, ( 1 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e x5 line 523, state 33, ( 1 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e x6 line 549, state 33, ( 1 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e x7 line 575, state 33, ( 1 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e x8 line 601, state 33, ( 1 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e a1 line 627, state 33, ( 1 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e a2 line 653, state 33, ( 1 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e a3 line 679, state 33, ( 1 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e a4 line 705, state 33,
” − end −”
” − end −”
” − end −”
” − end −”
” − end −”
” − end −”
” − end −”
” − end −”
” − end −”
” − end −”
” − end −”
” − end −”
” − end −”
” − end −”
” − end −”
” − end −”
” − end −”
” − end −”
” − end −”
” − end −”
” − end −”
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
( 1 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e a5 l i n e 7 3 1 , s t a t e 3 3 , ” − end −” ( 1 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e a6 l i n e 7 5 7 , s t a t e 3 3 , ” − end −” ( 1 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e a7 l i n e 7 8 3 , s t a t e 3 3 , ” − end −” ( 1 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e a8 l i n e 8 0 9 , s t a t e 3 3 , ” − end −” ( 1 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e o1 l i n e 8 2 4 , s t a t e 1 8 , ” in1 ?1” l i n e 8 2 4 , s t a t e 1 9 , ” in2 ?1” l i n e 8 2 4 , s t a t e 2 0 , ” out1 !1” l i n e 8 3 5 , s t a t e 3 3 , ” − end −” ( 4 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e o2 l i n e 8 5 0 , s t a t e 1 8 , ” in1 ?1” l i n e 8 5 0 , s t a t e 1 9 , ” in2 ?1” l i n e 8 5 0 , s t a t e 2 0 , ” out1 !1” l i n e 8 6 1 , s t a t e 3 3 , ” − end −” ( 4 of 3 3 s t a t e s ) u n r e a c h e d i n p r o c t y p e o4 l i n e 9 0 2 , s t a t e 1 8 , ” in1 ?1” l i n e 9 0 2 , s t a t e 1 9 , ” in2 ?1” l i n e 9 0 2 , s t a t e 2 0 , ” out1 !1” l i n e 9 1 3 , s t a t e 3 3 , ” − end −” ( 4 of 3 3 s t a t e s ) unreached in proctype C o n t r o l l i n e 9 5 6 , s t a t e 7 2 , ” − end −” ( 1 of 7 2 s t a t e s ) unreached in proctype o u t p u t l i n e 9 8 0 , s t a t e 1 1 , ” − end −” ( 1 of 1 1 s t a t e s ) unreached in proctype : i n i t : ( 0 of 3 8 s t a t e s ) −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− T r a n s l a t i o n S u c c e s s f u l : V e r i f i c a t i o n Completed −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− Fi le Generated : f o u r b i t a d d e r . pml T r a n s l a t i o n Time : 5 9 7 ms V e r i f i c a t i o n Time : 1 5 9 4 2 ms T o t a l Running Time : 1 6 5 3 9 ms −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
H.6.4 Example 9: A Five Bit Adder Example nine appends another adder to the four bit adder in example eight, and by doing so, creates a five bit adder. As line 16 in the following output shows, the verification then failed. Line 2 of the output states that the reason for the failure is the size of the state vector. To verify the example the maximum size of it must be increased, which is a configuration issue in SPIN. Lines 25 to 32 inclusively hold the time statistics ‘hwhpromela’ generated.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
$ j a v a hwhpromela − v f i v e b i t a d d e r . hume pan : e r r o r , VECTORSZ t o o s m a l l , r e c o m p i l e pan . c w i t h −DVECTORSZ=N w i t h N>1028 pan : a b o r t i n g ( a t d e p t h 4 3 ) pan : w r o t e f i v e b i t a d d e r . pml . t r a i l ( Spin Version 4 . 1 . 3 −− 24 A p r i l 2 0 0 4 ) Warning : S e a r c h n o t c o m p l e t e d + P a r t i a l Order Reduction Full s t a t e s p a c e search for : never claim assertion violations acceptance cycles i n v a l i d end s t a t e s
− ( none s p e c i f i e d ) + − ( not s e le c t e d ) +
S t a t e −vector 1 0 2 8 byte , depth reached 4 3 , e r r o r s : 1 44 s t a t e s , stored 0 s t a t e s , matched 4 4 t r a n s i t i o n s ( = s t o r e d +m a t c h e d ) 0 atomic s t e p s hash c o n f l i c t s : 0 ( r e s o l v e d ) ( max s i z e 2 ˆ 1 8 s t a t e s )
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− T r a n s l a t i o n S u c c e s s f u l : V e r i f i c a t i o n Completed −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− Fi le Generated : f i v e b i t a d d e r . pml T r a n s l a t i o n Time : 7 7 0 ms V e r i f i c a t i o n Time : 1 7 8 6 6 ms T o t a l Running Time : 1 8 6 3 6 ms −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
H.7 Example 10: Debugging with Spin Example ten is used to show the possibilities gained by using SPIN to model check HW-HUME programs. First it uses ‘hwhpromela’ and SPIN to obtain and correct an error injected into the HW-HUME model. The model is a three bit counter. The example also illustrates the use of linear temporal logic to specify the order of events, and verify that the model corresponds to the specification.
H.7.1 The Counter with an Error Injected The first version of the counter example had an error injected. Line 14 in the following output, shows that SPIN found the error. 1 2 3 4 5 6 7 8
$ j a v a hwhpromela − v c o u n t e r . hume pan : i n v a l i d end s t a t e ( a t d e p t h 5 2 8 ) pan : w r o t e c o u n t e r . pml . t r a i l ( Spin Version 4 . 1 . 3 −− 24 A p r i l 2 0 0 4 ) Warning : S e a r c h n o t c o m p l e t e d + P a r t i a l Order Reduction Full s t a t e s p a c e search for :
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
never claim assertion violations acceptance cycles i n v a l i d end s t a t e s
− ( none s p e c i f i e d ) + − ( not s e le c t e d ) +
S t a t e −vector 2 0 8 byte , depth reached 5 2 8 , e r r o r s : 1 412 s t a t e s , stored 0 s t a t e s , matched 4 1 2 t r a n s i t i o n s ( = s t o r e d +m a t c h e d ) 0 atomic s t e p s hash c o n f l i c t s : 0 ( r e s o l v e d ) ( max s i z e 2 ˆ 1 8 s t a t e s )
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− T r a n s l a t i o n S u c c e s s f u l : V e r i f i c a t i o n Completed −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− Fi le Generated : c o u n t e r . pml T r a n s l a t i o n Time : 3 4 2 ms V e r i f i c a t i o n Time : 4 3 7 0 ms T o t a l Running Time : 4 7 1 2 ms −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
H.7.2 The Updated Counter By using the error trail in a guided simulation, the source of the error was found and the HWHUME model was corrected. The following listing shows the output from the updated version of the counter. As line 11 states, the counter did not include any errors. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
$ j a v a hwhpromela − v c o u n t e r . hume ( Spin Version 4 . 1 . 3 −− 24 A p r i l 2 0 0 4 ) + P a r t i a l Order Reduction Full s t a t e s p a c e search for : never claim assertion violations acceptance cycles i n v a l i d end s t a t e s
− ( none s p e c i f i e d ) + − ( not s e le c t e d ) +
S t a t e −vector 2 0 8 byte , depth reached 7 4 5 , e r r o r s : 0 583 s t a t e s , stored 1 s t a t e s , matched 5 8 4 t r a n s i t i o n s ( = s t o r e d +m a t c h e d ) 0 atomic s t e p s hash c o n f l i c t s : 0 ( r e s o l v e d ) ( max s i z e 2 ˆ 1 8 s t a t e s ) unreached in proctype clock l i n e 4 4 , s t a t e 1 1 , ” − end −” ( 1 of 1 1 s t a t e s ) u n r e a c h e d i n p r o c t y p e show1 l i n e 8 2 , s t a t e 6 9 , ” − end −” ( 1 of 6 9 s t a t e s ) u n r e a c h e d i n p r o c t y p e d1 l i n e 9 1 , s t a t e 4 , ” in2 ?0” l i n e 9 3 , s t a t e 1 0 , ” in2 ?0” l i n e 9 3 , s t a t e 1 1 , ” out1 !0” l i n e 1 0 8 , s t a t e 3 7 , ” − end −”
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
( 4 of 3 7 s t a t e s ) u n r e a c h e d i n p r o c t y p e d2 l i n e 1 3 4 , s t a t e 3 7 , ” − end −” ( 1 of 3 7 s t a t e s ) u n r e a c h e d i n p r o c t y p e d3 l i n e 1 6 0 , s t a t e 3 7 , ” − end −” ( 1 of 3 7 s t a t e s ) unreached in proctype f1 l i n e 1 7 8 , s t a t e 1 2 , ” − end −” ( 1 of 1 2 s t a t e s ) unreached in proctype f2 l i n e 1 9 6 , s t a t e 1 2 , ” − end −” ( 1 of 1 2 s t a t e s ) unreached in proctype f3 l i n e 2 1 4 , s t a t e 1 2 , ” − end −” ( 1 of 1 2 s t a t e s ) unreached in proctype C o n t r o l l i n e 2 3 2 , s t a t e 2 2 , ” − end −” ( 1 of 2 2 s t a t e s ) unreached in proctype o u t p u t l i n e 2 5 2 , s t a t e 1 1 , ” − end −” ( 1 of 1 1 s t a t e s ) unreached in proctype : i n i t : ( 0 of 1 3 s t a t e s ) −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− T r a n s l a t i o n S u c c e s s f u l : V e r i f i c a t i o n Completed −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− Fi le Generated : c o u n t e r . pml T r a n s l a t i o n Time : 3 4 7 ms V e r i f i c a t i o n Time : 4 4 2 1 ms T o t a l Running Time : 4 7 6 8 ms −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
H.7.3 Specifying Behaviour SPIN is much more powerful than to just find deadlocks. Certain required behaviour can be specified, and SPIN can be used to check if the model violates this behaviour. In this example the behaviour is specified by using linear temporal logic (LTL), where the order of events can be reasoned. LTL can be used to specify both desired behaviour and error behaviour. The next section uses both ways to specify the same behaviour. The requirement is that when the counter reaches seven it will eventually be set to zero. Desired Behaviour The desired behaviour is that the counter should always be set to zero, when the counter reaches one. The following output is the output generated when using XSPIN to specify and validate the behaviour. Lines 1 and 2 declare the two events, and line 4 holds the desired LTL property. In order to validate an LTL property, SPIN translates the LTL property into a never claim. Lines 10 to 20 show the generated never claim. Note that since the claim specifies what should not happen the LTL property on line 4 is negated in the claim on line 6. Line 39 declares that the verification completed successfully. Since ‘hwhpromela’ was not used, no time statistics were created.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
# define p ( value == 7) # define q ( value == 0) /∗ ∗ F o r m u l a As Typed : [ ] ( p − > <> q ) ∗ The Never Claim Below C o r r e s p o n d s ∗ To The N e g a t e d F o r m u l a ! ( [ ] ( p − > <> q ) ) ∗ ( f o r m a l i z i n g v i o l a t i o n s of the o r i g i n a l ) ∗/ never { T0 init :
/∗ !([]
( p −>
<>
q )) ∗/
if : : ( ! ( ( q ) ) & & ( p ) ) − > goto a c c e p t S 4 : : ( 1 ) − > goto T 0 i n i t fi ; accept S4 : if : : ( ! ( ( q ) ) ) − > goto a c c e p t S 4 fi ; } # i f d e f NOTES Use Load t o open a f i l e o r a t e m p l a t e . # endif # i f d e f RESULT w a r n i n g : f o r p . o . r e d u c t i o n t o be v a l i d t h e n e v e r c l a i m must be s t u t t e r −invarian t ( n e v e r c l a i m s g e n e r a t e d from LTL f o r m u l a e a r e s t u t t e r − i n v a r i a n t ) d e p t h 1 3 3 1 : Claim r e a c h e d s t a t e 9 ( l i n e 2 9 3 ) ( Spin Version 4 . 1 . 3 −− 24 A p r i l 2 0 0 4 ) + P a r t i a l Order Reduction Full s t a t e s p a c e search for : never claim assertion violations acceptance cycles i n v a l i d end s t a t e s
+ + ( i f within scope of claim ) + ( fairness disabled ) − ( d i s a b l e d by n e v e r c l a i m )
S t a t e −vector 2 1 2 byte , depth reached 1 3 4 6 , e r r o r s : 0 658 s t a t e s , stored ( 7 2 4 v i s i t e d ) 130 s t a t e s , matched 8 5 4 t r a n s i t i o n s ( = v i s i t e d +m a t c h e d ) 0 atomic s t e p s hash c o n f l i c t s : 0 ( r e s o l v e d ) ( max s i z e 2 ˆ 1 9 s t a t e s ) S t a t s on memory u s a g e ( i n M e g a b y t e s ) : 0.145 e q u i v a l e n t memory u s a g e f o r s t a t e s ( s t o r e d ∗( S t a t e −vector + overhead ) ) 0.284 a c t u a l memory u s a g e f o r s t a t e s ( unsuccessful compression : 196.29%) S t a t e −vector as s t o r e d = 4 2 4 byte + 8 byte overhead 2.097 memory u s e d f o r h a s h t a b l e ( − w19 ) 0.320 memory u s e d f o r DFS s t a c k ( − m10000 ) 2.622 t o t a l a c t u a l memory u s a g e unreached in proctype clock l i n e 4 8 , ” pan . ” , s t a t e 1 1 , ” − end −” ( 1 of 1 1 s t a t e s ) u n r e a c h e d i n p r o c t y p e show1 l i n e 8 6 , ” pan . ” , s t a t e 6 9 , ” − end −” ( 1 of 6 9 s t a t e s ) u n r e a c h e d i n p r o c t y p e d1
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
l i n e 9 5 , ” pan . ” , s t a t e 4 , ” in2 ?0” l i n e 9 7 , ” pan . ” , s t a t e 1 0 , ” in2 ?0” l i n e 9 7 , ” pan . ” , s t a t e 1 1 , ” out1 !0” l i n e 1 1 2 , ” pan . ” , s t a t e 3 7 , ” − end −” ( 4 of 3 7 s t a t e s ) u n r e a c h e d i n p r o c t y p e d2 ” , s t a t e 3 7 , ” − end −” l i n e 1 3 8 , ” pan . ( 1 of 3 7 s t a t e s ) u n r e a c h e d i n p r o c t y p e d3 l i n e 1 6 4 , ” pan . ” , s t a t e 3 7 , ” − end −” ( 1 of 3 7 s t a t e s ) unreached in proctype f1 l i n e 1 8 2 , ” pan . ” , s t a t e 1 2 , ” − end −” ( 1 of 1 2 s t a t e s ) unreached in proctype f2 l i n e 2 0 0 , ” pan . ” , s t a t e 1 2 , ” − end −” ( 1 of 1 2 s t a t e s ) unreached in proctype f3 l i n e 2 1 8 , ” pan . ” , s t a t e 1 2 , ” − end −” ( 1 of 1 2 s t a t e s ) unreached in proctype C o n t r o l ” , s t a t e 2 2 , ” − end −” l i n e 2 3 6 , ” pan . ( 1 of 2 2 s t a t e s ) unreached in proctype o u t p u t l i n e 2 5 6 , ” pan . ” , s t a t e 1 2 , ” − end −” ( 1 of 1 2 s t a t e s ) unreached in proctype : i n i t : ( 0 of 1 3 s t a t e s ) unreached in proctype : never : l i n e 2 9 6 , ” pan . ” , s t a t e 1 1 , ” − end −” ( 1 of 1 1 s t a t e s ) 0 . 0 2 u s e r 0 . 0 0 s y s t e m 0 : 0 0 . 0 2 e l a p s e d 68%CPU ( 0 a v g t e x t +0 a v g d a t a 0 m a x r e s i d e n t ) k 0 i n p u t s +0 o u t p u t s ( 1 3 2 m a j o r +637 m i n o r ) p a g e f a u l t s 0 swaps # endif
Error Behaviour When specifying desired behaviour, the behaviour that should always happen is defined. When specifying error behaviour the events that should never occur is defined. The error behaviour in the counter example is that the counter is eventually not set to zero when it reaches seven. The following output is generated by XSPIN when verifying the error behaviour. Line 1 and 2 holds the two events, and line 4 holds the LTL property. In lines 7 to 17 the never claim is created. Note that since this is an error behaviour the LTL property is not negated on line 7. Line 36 shows that the verification completed successfully without any errors. Since XSPIN, and not ‘hwhpromela’, was used, the time statistics were not created. 1 2 3 4 5 6 7 8
# define p ( value == 7) # define q ( value == 0) /∗ ∗ F o r m u l a As Typed : < > ∗/ never { T0 init :
/∗ (<>
!
( p −>
!
<>
( p −>
q)) ∗/
<>
q)
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
if : : ( ! ( ( q ) ) & & ( p ) ) − > goto a c c e p t S 4 : : ( 1 ) − > goto T 0 i n i t fi ; accept S4 : if : : ( ! ( ( q ) ) ) − > goto a c c e p t S 4 fi ; } # i f d e f NOTES Use Load t o open a f i l e o r a t e m p l a t e . # endif # i f d e f RESULT w a r n i n g : f o r p . o . r e d u c t i o n t o be v a l i d t h e n e v e r c l a i m must be s t u t t e r −invarian t ( n e v e r c l a i m s g e n e r a t e d from LTL f o r m u l a e a r e s t u t t e r − i n v a r i a n t ) d e p t h 1 3 3 1 : Claim r e a c h e d s t a t e 9 ( l i n e 2 9 0 ) ( Spin Version 4 . 1 . 3 −− 24 A p r i l 2 0 0 4 ) + P a r t i a l Order Reduction Full s t a t e s p a c e search for : never claim assertion violations acceptance cycles i n v a l i d end s t a t e s
+ + ( i f within scope of claim ) + ( fairness disabled ) − ( d i s a b l e d by n e v e r c l a i m )
S t a t e −vector 2 1 2 byte , depth reached 1 3 4 6 , e r r o r s : 0 658 s t a t e s , stored ( 7 2 4 v i s i t e d ) 130 s t a t e s , matched 8 5 4 t r a n s i t i o n s ( = v i s i t e d +m a t c h e d ) 0 atomic s t e p s hash c o n f l i c t s : 0 ( r e s o l v e d ) ( max s i z e 2 ˆ 1 9 s t a t e s ) S t a t s on memory u s a g e ( i n M e g a b y t e s ) : 0.145 e q u i v a l e n t memory u s a g e f o r s t a t e s ( s t o r e d ∗( S t a t e −vector + overhead ) ) 0.284 a c t u a l memory u s a g e f o r s t a t e s ( unsuccessful compression : 196.29%) S t a t e −vector as s t o r e d = 4 2 4 byte + 8 byte overhead 2.097 memory u s e d f o r h a s h t a b l e ( − w19 ) 0.320 memory u s e d f o r DFS s t a c k ( − m10000 ) 2.622 t o t a l a c t u a l memory u s a g e unreached in proctype clock l i n e 4 8 , ” pan . ” , s t a t e 1 1 , ” − end −” ( 1 of 1 1 s t a t e s ) u n r e a c h e d i n p r o c t y p e show1 l i n e 8 6 , ” pan . ” , s t a t e 6 9 , ” − end −” ( 1 of 6 9 s t a t e s ) u n r e a c h e d i n p r o c t y p e d1 l i n e 9 5 , ” pan . ” , s t a t e 4 , ” in2 ?0” l i n e 9 7 , ” pan . ” , s t a t e 1 0 , ” in2 ?0” l i n e 9 7 , ” pan . ” , s t a t e 1 1 , ” out1 !0” l i n e 1 1 2 , ” pan . ” , s t a t e 3 7 , ” − end −” ( 4 of 3 7 s t a t e s ) u n r e a c h e d i n p r o c t y p e d2 l i n e 1 3 8 , ” pan . ” , s t a t e 3 7 , ” − end −” ( 1 of 3 7 s t a t e s ) u n r e a c h e d i n p r o c t y p e d3 l i n e 1 6 4 , ” pan . ” , s t a t e 3 7 , ” − end −” ( 1 of 3 7 s t a t e s )
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
unreached in proctype f1 l i n e 1 8 2 , ” pan . ” , s t a t e 1 2 , ” − end −” ( 1 of 1 2 s t a t e s ) unreached in proctype f2 l i n e 2 0 0 , ” pan . ” , s t a t e 1 2 , ” − end −” ( 1 of 1 2 s t a t e s ) unreached in proctype f3 l i n e 2 1 8 , ” pan . ” , s t a t e 1 2 , ” − end −” ( 1 of 1 2 s t a t e s ) unreached in proctype C o n t r o l l i n e 2 3 6 , ” pan . ” , s t a t e 2 2 , ” − end −” ( 1 of 2 2 s t a t e s ) unreached in proctype o u t p u t ” , s t a t e 1 2 , ” − end −” l i n e 2 5 6 , ” pan . ( 1 of 1 2 s t a t e s ) unreached in proctype : i n i t : ( 0 of 1 3 s t a t e s ) unreached in proctype : never : l i n e 2 9 3 , ” pan . ” , s t a t e 1 1 , ” − end −” ( 1 of 1 1 s t a t e s ) 0 . 0 1 u s e r 0 . 0 2 s y s t e m 0 : 0 0 . 0 4 e l a p s e d 68%CPU ( 0 a v g t e x t +0 a v g d a t a 0 m a x r e s i d e n t ) k 0 i n p u t s +0 o u t p u t s ( 1 3 2 m a j o r +637 m i n o r ) p a g e f a u l t s 0 swaps # endif