160 likes | 322 Views
Comparison of Formal Verification Tools for Cache Coherency Protocols. EECS 578 – Fall 2006 Final Project Presentation. Aulihan Teng & Scott McLelland. Outline. Project Overview Protocols Implemented MESI Tokens Murphi SMV Syntax Comparison Results Lessons Learned Conclusion.
E N D
Comparison of Formal Verification Tools for Cache Coherency Protocols EECS 578 – Fall 2006 Final Project Presentation Aulihan Teng & Scott McLelland
Outline • Project Overview • Protocols Implemented • MESI • Tokens • Murphi • SMV • Syntax Comparison • Results • Lessons Learned • Conclusion
Project Overview • Implemented two cache coherency protocols • MESI • Token Coherency • Compared two formal verification tools • SMV (Cadence/CMU) • Murphi (Stanford)
PrRd or PrWr M PrWr/BusWr PrWr/-- BusRd/-- BusWr/-- E PrWr/BusWr PrRd/-- BusWr/-- PrRd/ BusRd (!S) BusRd/-- S BusWr PrRd/ BusRd (S) PrRd/-- BusRd/-- I Cache Coherency Protocol - MESI • MESI • 4 states per cache line • Invalid: this data is invalid • Exclusive: only this cache as a copy (unmodified) • Shared: 2 or more caches may have copies (unmodified) • Modified: only this cache has a copy (modified)
Rules T total tokens for each cache line One owner token per cache line Processor can write a line only if it has all T tokens Processor can read a line if it has >= 1 tokens If message contains owner token, it also contains data Equivalent MOSI states Modified Tokens = T Owner Tokens >= 1 (including owner) Shared Tokens >= 1 (excluding owner) Invalid Tokens = 0 Cache Coherency Protocol – Tokens
Cache Coherency Protocol - Tokens Receiving Messages Receiving Persistent Messages (from others) Sending Messages Activation M t = T Data and not all token(s) Data and token(s) Data and Token(s) Data and all tokens SO 0<t<T P t < T Data and token(s) Data and token(s) Data and all tokens Data and token(s) Data and token(s) Deactivation I t = 0 Activation
Murphi • Developed at Stanford in 1992 by David Dill -> • Murphi Description Language • Collection of conditions/action rules • Rules executed in infinite loop • Formal verifier based on explicit state enumeration • Depth- or breadth-first searches • Uses hash table to record results • State Reduction • Symmetry • Reversible Rules • Repetition Constructors
Murphi Syntax Example Const ProcCount: 2; AddressCount: 2; Type Pid: Scalarset(ProcCount); Address: Scalarset(AddressCount); MessageType: Enum{ReadReq, WriteReq, Data}; BusMessage: Record msg_type: MessageType; p: Pid; a: Address; End; Interconnect: MultiSet[BufferDepth] of BusMessage; ProcState: Record cache: Array[Address] of Record state: Enum{Modified, Exclusive, Shared, Invalid}; v: Value; End; End; CacheLineState: Enum{Uncached, CachedShared, CachedExclusive}; Procedure Send(… p: Pid; a: Address; v: Value; …); Var msg: BusMessage; Begin msg.p := p; msg.a := a; msg.v := v; MultiSetAdd(msg,Bus); End; Ruleset p: Pid Do RuleSet a: Address Do Rule "Request read" (procs[p].cache[a].state = Invalid) ==> Send(p,a); Endrule; … EndRuleset; EndRuleset; … Invariant "Shared entries must agree" Forall a: Address Do Forall p1: Pid; p2: Pid Do ((procs[p1].cache[a].state = Shared) & (procs[p2].cache[a].state = Shared)) -> (procs[p1].cache[a].v = procs[p2].cache[a].v) Endforall Endforall;
SMV • Developed at CMU in 1993 ->Now a Cadence tool • SMV Verification Language • Invariants specified in CTL • Hierarchical specifications using modules • Define initial state and next state for every variable in a module • Formal verification • Optimizes the transition relation for each variable • Represents states with BDDs • Checks for deadlock, liveness, safety, fairness
SMV Syntax Example MODULE main VAR bus: bus(c0.req_proc, c0.req_op, c0.req_addr, c0.req_s, c0.req_val, c1.req_proc, c1.req_op, c1.req_addr, c1.req_s, c1.req_val, mem.req_proc, mem.req_op, mem.req_addr, mem.req_s, mem.req_val); c0: cache(bus.op, bus.proc, bus.val, bus.addr, bus.s, 0); … SPEC --in memory is in shared, some cache has that line in shared AG (!(mem.state0 = cached_shared) | (c0.state0 = shared) | (c1.state0 = shared)) & AG (!(mem.state1 = cached_shared) | (c0.state1 = shared) | (c1.state1 = shared)) … MODULE cache(bus_op, bus_proc, bus_val, bus_addr, bus_s, proc) VAR state0: {modified, exclusive, shared, invalid}; val0: 0..7; … ASSIGN -- val0 init(val0) := {0,1,2,3,4,5,6,7}; next(val0) := case bus_addr = 0 : case bus_op = write : {0,1,2,3,4,5,6,7}; bus_op = data : bus_val; 1 : val0; esac; 1: val0; esac; …
Murphi Ruleset p: Pid Do RuleSet a: Address Do Alias me: procs[p] Do Rule "Request read" (me.Waiting = FALSE) & (me.cache[a].state = Invalid) ==> me.Waiting := TRUE; Send_Read_Request(p,a); Endrule; Rule "Request write" (me.Waiting = FALSE) & (me.cache[a].state = Invalid | me.cache[a].state = Shared) ==> me.Waiting := TRUE; Send_Write_Request(p,a); Endrule; Ruleset v: Value Do Rule "Exlusive to Modified" (me.Waiting = FALSE) & (me.cache[a].state = Exclusive) ==> me.cache[a].v := v; me.cache[a].state := Modified; Endrule; Endruleset; Endalias; Endruleset; Endruleset; SMV init(req_op) := noop; next(req_op) := case (bus_op = read) & ((bus_addr = 0 & (state0 = exclusive | state0 = modified)) | (bus_addr = 1 & (state1 = exclusive | state1 = modified))) : data; new_trans = 1 : case what_line = 0: case (state0 = shared) | (state0 = exclusive) : write; 1 : {read, write}; esac; what_line = 1: case (state1 = shared) | (state1 = exclusive) : write; 1 : {read, write}; esac; esac; waiting = 1: req_op; 1: noop; esac; init(req_addr) := {0,1}; next(req_addr) := case (bus_op = read) & ((bus_addr = 0 & (state0 = exclusive | state0 = modified)) | (bus_addr = 1 & (state1 = exclusive | state1 = modified))) : bus_addr; new_trans = 1 : what_line; 1: req_addr; esac; init(req_proc) := proc; next(req_proc) := case (bus_op = read) & ((bus_addr = 0 & (state0 = exclusive | state0 = modified)) | (bus_addr = 1 & (state1 = exclusive | state1 = modified))) : bus_proc; 1: proc; esac; init(req_val) := {0,1}; next(req_val) := case (bus_op = read) & (bus_addr = 0 & (state0 = exclusive | state0 = modified)) : val0; (bus_op = read) & (bus_addr = 1 & (state1 = exclusive | state1 = modified)) : val1; 1: req_val; Esac; Murphi vs. SMV: MESI Message Sending Rules
Lessons Learned • Protocols are easier to express using rule based action statements • Debugging in SMV is hard without a GUI • SMV does not recognize the keywords true and false • Formal verification tools are valuable in early stages of a project to verify that your ideas are sound
Murphi strengths Multiple variables are assigned next states at once using rule based descriptions Scalarsets allow similar structures to verified at once Array support makes scaling easy Debugging is easier Weaknesses Size limitations Limited documentation SMV strengths More documentation BDD based storage allows more complex designs to be modeled More user defined options at runtime Weaknesses Individual variable next state assignment makes scaling a monumental task Implementation and debugging is more difficult Conclusion