My professor decide to give us math student a code to change into NuSMV and i can't seem to find anywhere else for help and i read the textbook it like 6 pages only and only describe what certain property does. Module main is an example of NuSMV code and he said to use that format example to write the psuedo code. I don't know how to write the while loop and set what to be true? and would flag1 be a state and turn be also another state?
while(true) do
flag1 := true
while flag2 do
if turn=2
flag1 := false;
wait until turn = 1;
flag1 := true
Critical section
turn := 2
flag1 := false;
It looks like you're trying to model Dekker/Dijkstra's algorithm for mutual exclusion among two processes.
The steps of your interest, based on your question, should only be 1-4. I added some more to provide a more complete picture of what can be achieved with NuSMV.
I used a slightly different version of the same algorithm, though the underlying idea is the same.
IDEA: there exists a methodology for converting pseudo-code into a NuSMV model:
Label the entry and exit point of each statement in your code:
-- void p(iflag, turn, id) {
-- l0: while(true) do
-- l1: flag := true
-- l2: while iflag do
-- l3: if turn != id
-- l4: flag := false;
-- l5: wait until turn = id;
-- l6: flag := true
-- l7: // Critical section
-- l8: turn := 1 - id
-- l9: flag := false;
-- }
Note that some statements, e.g. while iflag do
, might have more than one exit point depending on the value of the guard: if iflag
is true, then the exit point is l3, otherwise the exit point is l7.
Create a corresponding module that takes the same inputs and has a state variable which evaluates to the newly introduced labels.
MODULE p(iflag, turn, id)
VAR
state : { l0, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, error };
flag : boolean;
Here, notice that i added the special state error. This is only to ensure that during the definition the transition relation for state we are not leaving out any correct transition step. In general, it should be omitted as it does not belong to the original code.
Define the transition relation for state:
ASSIGN
init(state) := l0;
next(state) := case
state = l0 : l1;
state = l1 : l2;
state = l2 & iflag : l3;
state = l2 & !iflag : l7;
state = l3 & turn != id : l4;
state = l3 & turn = id : l2;
state = l4 : l5;
state = l5 & turn != id : l5;
state = l5 & turn = id : l6;
state = l6 : l2;
state = l7 : l8;
state = l8 : l9;
state = l9 : l0;
TRUE : error; -- if you match this then the above
-- description of transitions are incomplete
esac;
As you can see, I simply connected every entry point with the corresponding exit point. Moreover, wherever more than one exit point is defined for a given entry point I also added other state conditions to determine what line is executed next.
Add the transition relation for flag:
init(flag) := FALSE;
next(flag) := case
state = l1 | state = l6 : TRUE;
state = l4 | state = l9 : FALSE;
TRUE : flag;
esac;
Add some definitions to identify which sections of code the process is executing:
DEFINE
critical_section := (state = l7);
trying_section := (state = l1 | state = l2 | state = l3 |
state = l4 | state = l5 | state = l6);
Create a main module which creates two instances of p:
MODULE main ()
VAR
turn : {0, 1};
p1 : p(p2.flag, turn, 0);
p2 : p(p1.flag, turn, 1);
ASSIGN
init(turn) := 0;
next(turn) := case
p1.state = l8 : 1;
p2.state = l8 : 0;
TRUE : turn;
esac;
Add some very typical mutual exclusion properties to be verified by the model checker:
--*-- PROPERTIES --*--
-- Safety: two processes are never in the critical section at the same time
CTLSPEC AG !(p1.critical_section & p2.critical_section);
-- Liveness: if a process is in the trying section, then sooner or later
-- it will access the critical section.
CTLSPEC AG (p1.trying_section -> AF p1.critical_section);
-- Absence of Starvation
CTLSPEC ! EF AG (p1.trying_section & p2.trying_section);
-- Never in Error State
CTLSPEC AG !(p1.state = error);
Run the tool
~$ NuSMV -int
and check that all properties are verified:
NuSMV > reset; read_model -i dekker.smv; go; check_property
-- specification AG !(p1.critical_section & p2.critical_section) is true
-- specification AG (p1.trying_section -> AF p1.critical_section) is true
-- specification !(EF (AG (p1.trying_section & p2.trying_section))) is true
-- specification AG !(p1.state = error) is true
NOTES:
If you look closely at steps 1 and 3, several states look redundant. For instance, it is always possible to collapse contiguous states that have only one entry and exit points. I'll leave this to you as an exercise.
Notice that I used the synchronous composition of modules for simplicity. In practice the verification would be more meaningful by letting the two processes to be run asynchronously. However, this would require making the model more complex than your question really required, and it is thus beyond the scope of my answer.
If you would like to learn more about NuSMV, you can take a look at its documentation or look at the second part of this course.