towards the formal verification of a java processor in event-b
DESCRIPTION
Towards the Formal Verification of a Java Processor in Event-B. Neil Evans and Neil Grant AWE, Aldermaston. Motivation. The Scalable Core processor (Score) is a hardware implementation of a JVM Instruction Set Architecture (ISA) level instructions are Java bytecodes - PowerPoint PPT PresentationTRANSCRIPT
Towards the Formal Verification of a Java Processor in Event-B
Neil Evans and Neil Grant
AWE, Aldermaston
Motivation The Scalable Core processor (Score) is a
hardware implementation of a JVM
Instruction Set Architecture (ISA) level instructions are Java bytecodes
At the lower Microcode Architecture (MA) level, ISA-level programs are executed by an interpreter
Below lies the digital logic of the processor
We aim to prove a correspondence between ISA-level code and its MA-level interpretation
Microcoded Processor Operation
DPRAM
PROGRAMDATA
HEAP
MICROCODED INSTRUCTION EXECUTION CONTROLLER
+/- 1
ALU
stackDataIn
stackAddr
stackDataOutM
UX
iADD
Microcoded Processor Operation
DPRAM
iADD
HEAP
MICROCODED INSTRUCTION EXECUTION CONTROLLER
+/- 1
ALU
stackDataIn
stackAddr
stackDataOutM
UX
sp
0
sp
0
sp-1
0
loadStackVarsAndDec(const 0)
Microcoded Processor Operation
DPRAM
iADD
HEAP
MICROCODED INSTRUCTION EXECUTION CONTROLLER
+/- 1
ALU
sp
0
stackDataIn
stackAddr
stackDataOutM
UX
stackRead
x
Microcoded Processor Operation
DPRAM
iADD
HEAP
MICROCODED INSTRUCTION EXECUTION CONTROLLER
+/- 1
ALUx
sp
0
stackDataIn
stackAddr
stackDataOutM
UX
writeRegAndStackWrite
x
Microcoded Processor Operation
DPRAM
iADD
HEAP
MICROCODED INSTRUCTION EXECUTION CONTROLLER
+/- 1
ALUx
sp
0
stackDataIn
stackAddr
stackDataOutM
UX
sp-1
0
sp-2
0
loadStackVarsAndDec(const 0)
sp-1
Microcoded Processor Operation
DPRAM
iADD
HEAP
MICROCODED INSTRUCTION EXECUTION CONTROLLER
+/- 1
ALUx
sp-1
0
stackDataIn
stackAddr
stackDataOutM
UX
stackRead
y
Microcoded Processor Operation
DPRAM
iADD
HEAP
MICROCODED INSTRUCTION EXECUTION CONTROLLER
+/- 1
ALUy
sp-1
0
stackDataIn
stackAddr
stackDataOutM
UX
writeRegAndStackWrite
y
Microcoded Processor Operation
DPRAM
iADD
HEAP
MICROCODED INSTRUCTION EXECUTION CONTROLLER
+/- 1
ALU
stackDataIn
stackAddr
stackDataOutM
UX
x
y
dualLoadALU
x
y
Microcoded Processor Operation
DPRAM
iADD
HEAP
MICROCODED INSTRUCTION EXECUTION CONTROLLER
+/- 1
ALU
stackDataIn
stackAddr
stackDataOutM
UX
ALUAdd
x
y
x+y
Microcoded Processor Operation
DPRAM
iADD
HEAP
MICROCODED INSTRUCTION EXECUTION CONTROLLER
+/- 1
stackDataIn
stackAddr
stackDataOutM
UX
writeALUResult
x+yx+y
Microcoded Processor Operation
DPRAM
iADD
HEAP
MICROCODED INSTRUCTION EXECUTION CONTROLLER
+/- 1
ALU
stackDataIn
stackAddr
stackDataOutM
UX
sp-2
x+y
loadStackDataAndInc
sp-1
x+y
x+y
Microcoded Processor Operation
DPRAM
iADD
HEAP
MICROCODED INSTRUCTION EXECUTION CONTROLLER
+/- 1
ALU
stackDataIn
stackAddr
stackDataOutM
UX
sp-1
loadStackAddr
sp-1
x+y
Microcoded Processor Operation
DPRAM
iADD
HEAP
MICROCODED INSTRUCTION EXECUTION CONTROLLER
+/- 1
ALU
sp-1
x+y
stackDataIn
stackAddr
stackDataOutM
UX
StackWrite
What we aim to do Ultimately, we want to prove correctness of
the Score processor
In other words, the behaviour dictated by the microcoded instruction execution controller should meet the specification of the JVM
However
Java bytecodes are specified as single-step instructions
The Score processor will execute multiple cycles to achieve the desired behaviour
So we need a formal approach to reconcile these
Possible Approaches
General purpose languages and tools
ACL2 uses Lisp and has theorem proving support
Tailor the tool (by constructing user-defined theories) to solve the problem
Dedicated languages and tools for refinement
The B Method and its tool support (in particular Event-B and the Rodin tool)
Tailor the problem to make it amenable to B refinement checking
Event-B An Event-B model comprises
A static part containing sets, constants, properties
A dynamic part containing state variables, events and an invariant to specify behaviour
An event E is of the form
E = WHEN G(v) THEN S(v) END
where
G(v) is a guard
S(v) is a substitution (ours will be deterministic)
Both of which refer to the state variables
Refinement in Event-B The state can be refined by replacing abstract
representations of objects with more concrete implementation-like representations
Existing events are refined accordingly, but new events can be introduced to give a more fine-grained specification of behaviour
A gluing invariant is defined in the refined model to formalise the relationship between the abstract and concrete representations
However, this relationship is only relevant in certain states
Refinement of iADD
An Abstract Model
SETS Stack Bytecode Status = { ACTIVE, INACTIVE }
CONSTANTS iADD Bytecode null Stack cons N × Stack (Stack – { null }) hd (Stack – { null }) N tl (Stack – { null }) Stack len Stack N PROPERTIES n, s. (n N s Stack hd(cons(n, s)) = n) n, s. (n N s Stack tl(cons(n, s)) = s) len(null) = 0 n, s. (n N s Stack len(cons(n, s)) = 1 + len(s))
An Abstract Model
VARIABLES bytecode iadd_status stack
INVARIANT bytecode Bytecode iadd_status Status stack Stack iadd_status = ACTIVE len(stack) > 1 EVENTS iADD_ini = iADD = WHEN WHEN iadd_status = INACTIVE iadd_status = ACTIVE len(stack) > 1 THEN bytecode = iadd stack := cons(hd(stack) + hd(tl(stack)), tl(tl(stack))) || THEN iadd_status := INACTIVE iadd_status := ACTIVE END END
Concrete Variables
bytecode1 Bytecode iadd_status1 Status stack1 N1 N SP N stackDataIn N stackDataOut N ALURegA N ALURegB N ALUOutReg N stackDataInSet BOOL stackDataOutSet BOOL ALURegASet BOOL ALURegBSet BOOL ALUOutSet BOOL
Refinement of Existing Events iADD_ini becomes the first step in the execution of the
microcoded architecture, and iADD becomes the last
In addition to these, new events are introduced to model the intermediate steps in the execution of the microcoded architecture
iADD_ini = iADD = WHEN WHEN iadd_status1 = INACTIVE iadd_status1 = ACTIVE SP > 1 stackDataOutSet = TRUE bytecode1 = iadd THEN THEN stack1(SP) := stackDataOut || iadd_status1 := ACTIVE iadd_status1 := INACTIVE || END stackDataOutSet := FALSE ||
ALURegASet := FALSE || ALURegBSet := FALSE || ALUOutSet := FALSE END
A Correspondence
A Correspondence We add the invariant
iadd_status1 = INACTIVE eqv(SP, stack1, stack)
whereeqv(n, s, null) = n = 0
eqv(n, s, cons(h, t)) = n > 0 s(n) = h eqv(n-1, s, t)
The refined versions of iADD induces the proof obligation
eqv(SP, stack1 { SP stackDataOut },
cons(hd(stack) + hd(tl(stack)), tl(tl(stack))))
under the assumption stackDataOutSet = TRUE
A Correspondence
iADD = iADD = WHEN WHEN iadd_status1 = ACTIVE iadd_status1 = ACTIVE THEN stackDataOutSet = TRUE stack := cons(hd(stack) + hd(tl(stack)), tl(tl(stack))) || THEN iadd_status := INACTIVE stack1(SP) := stackDataOut || END iadd_status1 := INACTIVE ||
stackDataOutSet := FALSE || ALURegASet := FALSE ||
ALURegBSet := FALSE || ALUOutSet := FALSE END
stackDataOutSet = TRUE eqv(SP, stack1 { SP stackDataOut }, cons(hd(stack) + hd(tl(stack)), tl(tl(stack))))
iadd_status1 = INACTIVE eqv(SP, stack1, stack)
The formula
cannot be proven, so we add it to the invariant
This induces further proof obligations – in this case from an event introduced in the refinement
A Correspondence
loadStackDataAndInc = WHEN ALUOutSet = TRUE stackDataOutSet = FALSE THEN SP := SP + 1 ||
stackDataOut := ALUOutReg || stackDataOutSet := TRUE || END
stackDataOutSet = TRUE eqv(SP, stack1 { SP stackDataOut }, cons(hd(stack) + hd(tl(stack)), tl(tl(stack))))
A Correspondence We work our way backwards through the
sequence of events that lead up to iADD, adding to the invariant along the way, until we reach iADD_ini (and an INACTIVE state)
We are left to prove
This can be derived from an assumption of
eqv(SP - 1, stack1 { SP-1 stack1(SP) + stack1(SP - 1) },cons(hd(stack) + hd(tl(stack)), tl(tl(stack))))
iadd_status1 = INACTIVE eqv(SP, stack1, stack)
Pros This approach of repeatedly generating proof
obligations and adding them to the invariant until no further proof obligations are generated is an automatic process
As a consequence, the proof of correctness is almost entirely automated
Overall, the (unremarkable) nature of this result demonstrates that Event-B refinement is well-suited for this kind of application
Cons One criticism of the concrete model is the
implicit control (ordering of events) specified by the guards:
Constructing the guards in the refined model is quite tricky
The flow of control in the refined model is not obvious
Ideally the formal model should look like the informal thing that it claims to represent
A CSP representation of the control flow (i.e. by taking a CSP||B approach) could help
Conclusion We have seen how an off-the-shelf approach
can be used in the verification of an abstract processor with a microcoded architecture
The approach is typical of Event-B, which demonstrates its suitability
Most proof obligations were discharged automatically (223 out of 234 refinement po’s)
Further work is needed to verify all of the subtleties of the microcoded architecture of the Score processor, and to verify its correctness at the digital logic level