320 likes | 413 Views
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
E N D
Towards the Formal Verification of aJava 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 stackAddr PROGRAM DATA iADD +/- 1 MUX DPRAM stackDataIn ALU HEAP stackDataOut MICROCODED INSTRUCTION EXECUTION CONTROLLER
Microcoded Processor Operation stackAddr iADD sp +/- 1 MUX sp 0 sp-1 0 DPRAM stackDataIn ALU HEAP stackDataOut 0 loadStackVarsAndDec(const 0) MICROCODED INSTRUCTION EXECUTION CONTROLLER
Microcoded Processor Operation stackAddr iADD sp +/- 1 MUX DPRAM stackDataIn x ALU HEAP stackDataOut 0 stackRead MICROCODED INSTRUCTION EXECUTION CONTROLLER
Microcoded Processor Operation stackAddr iADD sp +/- 1 MUX x DPRAM stackDataIn x ALU HEAP stackDataOut 0 writeRegAndStackWrite MICROCODED INSTRUCTION EXECUTION CONTROLLER
Microcoded Processor Operation stackAddr iADD sp-1 sp +/- 1 MUX sp-1 0 sp-2 0 DPRAM stackDataIn x ALU HEAP stackDataOut 0 loadStackVarsAndDec(const 0) MICROCODED INSTRUCTION EXECUTION CONTROLLER
Microcoded Processor Operation stackAddr iADD sp-1 +/- 1 MUX DPRAM stackDataIn y x ALU HEAP stackDataOut 0 stackRead MICROCODED INSTRUCTION EXECUTION CONTROLLER
Microcoded Processor Operation stackAddr iADD sp-1 +/- 1 MUX y DPRAM stackDataIn y ALU HEAP stackDataOut 0 writeRegAndStackWrite MICROCODED INSTRUCTION EXECUTION CONTROLLER
Microcoded Processor Operation stackAddr iADD +/- 1 MUX x x y DPRAM stackDataIn ALU HEAP y stackDataOut dualLoadALU MICROCODED INSTRUCTION EXECUTION CONTROLLER
Microcoded Processor Operation stackAddr iADD +/- 1 MUX x DPRAM stackDataIn x+y ALU HEAP y stackDataOut ALUAdd MICROCODED INSTRUCTION EXECUTION CONTROLLER
Microcoded Processor Operation stackAddr iADD +/- 1 MUX x+y DPRAM stackDataIn x+y HEAP stackDataOut writeALUResult MICROCODED INSTRUCTION EXECUTION CONTROLLER
Microcoded Processor Operation stackAddr iADD +/- 1 MUX sp-2 x+y sp-1 x+y DPRAM stackDataIn ALU HEAP stackDataOut x+y loadStackDataAndInc MICROCODED INSTRUCTION EXECUTION CONTROLLER
Microcoded Processor Operation stackAddr iADD sp-1 +/- 1 MUX DPRAM sp-1 stackDataIn ALU HEAP stackDataOut x+y loadStackAddr MICROCODED INSTRUCTION EXECUTION CONTROLLER
Microcoded Processor Operation stackAddr iADD sp-1 +/- 1 MUX DPRAM stackDataIn ALU HEAP stackDataOut x+y StackWrite MICROCODED INSTRUCTION EXECUTION CONTROLLER
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
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_inibecomes the first step in the execution of the microcoded architecture, andiADDbecomes 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 • We add the invariant iadd_status1 = INACTIVE eqv(SP, stack1, stack) where eqv(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 stackDataOutSet = TRUE eqv(SP, stack1 { SP stackDataOut }, cons(hd(stack) + hd(tl(stack)), tl(tl(stack)))) 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 iadd_status1 = INACTIVE eqv(SP, stack1, stack)
A Correspondence • 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 stackDataOutSet = TRUE eqv(SP, stack1 { SP stackDataOut }, cons(hd(stack) + hd(tl(stack)), tl(tl(stack)))) loadStackDataAndInc = WHEN ALUOutSet = TRUE stackDataOutSet = FALSE THEN SP := SP + 1 || stackDataOut := ALUOutReg || stackDataOutSet :=TRUE|| END
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