Using Formal Methods to Create Instruction Set Architectures

Preview:

Citation preview

Using Formal Methods to

Create Instruction Set

Architectures

Steve Wright

Bristol University

Department of

COMPUTER SCIENCE

Steve Wright

• Chartered Software Engineer.

• 8 years at Rolls-Royce.

• 2 years at STMicroelectronics.

• 7 years at Airbus.

• Now at University of Bristol.

ISA Applications

Objective

Formally construct all possible

outcomes for an instruction

set during program execution.

Normal Operation

“I'm completely operational,

and all

my circuits are

functioning perfectly.”

Actions easy to identify.

Failure Conditions

“Open the pod bay doors, HAL.”

“I'm sorry Dave, I'm afraid

I can't do that.”

Harder to identify.

Formal Methods

• Define “events”: “actions” predicated by“guards”.

• Use set theory to prove that one or moreevents is subset of a single more abstract

event.

• “Model Checking” needed to prove thatrefined events fully implement abstract.

ISA Common Properties

• Binary image in contiguous memory.

• Instructions selected by “ProgramCounter”.

• All operations as bit-manipulationsbetween registers.

• Register data stored across multiplecontiguous memory locations.

Top-level Abstraction

RUNNING/FAILED/HALTED state and instruction:

Iterate =

BEGIN

act1: inst :∈ INST

act2: status :∈ STATE

END

First Refinement

Loading

REFINES Iterate

WHEN

grd1: status = LOADING

THEN

act1: inst :∈ Inst

act2: status :∈ { LOADING, RUNNING}

END

Running

REFINES Iterate

WHEN

grd1: status = RUNNING

THEN

act1: inst :∈ Inst // Instruction is updated

act3: status :∈ { RUNNING, HALTED, FAILED}

END

Halted // Explicit deadlock achieved

REFINES Iterate

WHEN

grd1: status = HALTED

THEN

skip

END

Failed // Explicit deadlock achieved

REFINES Iterate

WHEN

grd1: status = FAILED

THEN

skip

END

Create state machine to switch states RUNNING/FAILED/HALTED:

=

32nd(!) Refinement

NopOk

REFINES NopOk

ANY

op

opVal

nextInstPtr

WHERE

grd6: op : DataByte

grd7: op = mem(instPtr)

grd5: opVal : 0..255

grd2: opVal = DataByte2Int(op)

grd1: opVal = 16

grd3: instPtr <= 99992

grd4: statusCode = 2

grd8: nextInstPtr : -2147483647.. 2147483647

grd9: nextInstPtr = instPtr + 1

THEN

act1: instPtr := nextInstPtr

END

For example, the humble NOP:

Proof Obligations

status = RUNNING

status ∈{LOADING,RUNNING,HALTED,FAILED}

Proof Obligations

∀x · x∈MemArrayDom

(memArrayDataLongmemIndex ↦DataBytes2DataLong(resByte(0)↦resByte(1) ↦resByte(2) ↦resByte(3))})(x) =

DataBytes2DataLong((memArrayDataBytememIndex↦resByte(0)}memIndex+1 ↦resByte(1)}memIndex+2↦resByte(2)}memIndex+3 ↦resByte(3)})(x)↦(memArrayDataBytememIndex ↦resByte(0)}memIndex+1↦resByte(1)}memIndex+2 ↦resByte(2)}memIndex+3↦resByte(3)})(x+1) ↦(memArrayDataBytememIndex↦resByte(0)}memIndex+1 ↦resByte(1)}memIndex+2↦resByte(2)}memIndex+3 ↦resByte(3)})(x+2)↦(memArrayDataBytememIndex ↦resByte(0)}memIndex+1↦resByte(1)}memIndex+2 ↦resByte(2)}memIndex+3↦resByte(3)})(x+3))

Tool Support

RODIN

• Integrated Development Environment for Event-B.

• Eclipse-based.

• Windows, Linux and Mac.

• Free, open-source.

• Extensible via Java plug-ins.

“MIDAS” Example Machines

• Stack and register machines.

• 35 instructions.

• “Modified Harvard” memoryarchitecture.

• Stack and Register Variants

MIDAS Events

35 instructions ⇒ 112 events

i.e. Many more failure cases than OKcases.

VM Auto-generation

NopOk

REFINES NopOk

ANY

op

opVal

nextInstPtr

WHERE

grd6: op : DataSmall

grd7: op = mem(instPtr)

grd5: opVal : DataSmallNat

grd2: opVal= DataSmall2Nat(op)

grd1: opVal = 16

grd3: instPtr <= 99994

grd4: statusCode = 2

grd8: nextInstPtr : DataLargeNat

grd9: nextInstPtr = instPtr + 1

THEN

act1: instPtr := nextInstPtr

END

/* Event5 [NopOk] */

BOOL NopOk(void){

/* Local variable declarations */

DataLargeNat nextInstPtr;

DataSmall op;

DataSmallNat opVal;

/* Guard 1 */

op = mem[instPtr];

DataSmall2Nat(op,&opVal);

if(opVal!=16) return BFALSE;

/* Guard 2 */

if(instPtr>99994) return BFALSE;

/* Guard 3 */

if(statusCode!=2) return BFALSE;

/* Local assignments in actions */

nextInstPtr = (instPtr+1);

/* Actions */

instPtr = nextInstPtr;

/* Report hit */

ReportEventbEvent("NopOk",5);

return BTRUE;}

> B2C >

Compiled Target Executable

int x;

for(x=0;x<10;x++) {

/* Do nothing */

}

.L3:

# Addsi [fp] [fp] 1

# imm push 1

psh.si.im 1

# indirect push [fp]

psh.si.in fp

ari.si.add

# indirect pop [fp]

pop.si.in fp

pop.si.di void

pop.si.di void

.L2:

# Cmp [fp] 9

# CondBra [fp] 9 le

# imm push 9

psh.si.im 9

# indirect push [fp]

psh.si.in fp

cmp.si.le

pop.si.di void

pop.si.di void

# bra.tr .L3

psh.ad.im .L3

jmp.ad.tr

pop.ad.di void

> GCC >

Program Execution

Future Work

• Expand Event-B to enhance the

process.

• Model checking (dead-

lock/determinism).

• Apply to existing ISAs.

Summary

• EventB can capture generic

properties and refine to example.

• RODIN allows refinement to

executable.

Questions

?

Recommended