Flash2
type id
type cache_state_ = { invalid, shared, exclusive }
type wait_type = { none, get, getX }
module cache_line = {
individual wait : wait_type
relation invmarked
individual state_ : cache_state_
}
module header = {
relation pending
relation local_
relation dirty
relation head
individual hptr : id
relation list
relation real(X:id)
relation upgrade
relation shlist(X:id)
}
module network = {
relation get(S:id,D:id)
relation put(S:id,D:id)
relation getX(S:id,D:id)
relation putX(S:id,D:id)
relation nak(S:id,D:id)
relation fack(S:id,D:id)
relation shwb(S:id,D:id)
}
module wb_network = {
individual proc : id
relation wb
}
individual home : id
instantiate cache(X:id) : cache_line
instantiate dir : header
relation collecting
individual requester : id
instantiate net : network
relation rp_net(X:id)
individual real_owner : id
individual fwd_get : wait_type
instantiate wbnet : wb_network
individual last_WB : id
relation nakc
relation invnet(X:id)
relation invack(X:id)
individual src : id
individual dst : id
after init {
cache(X).state_ := invalid;
cache(X).wait := none;
cache(X).invmarked := false;
dir.pending := false;
dir.dirty := false;
collecting := false;
net.get(X,Y) := false;
net.put(X,Y) := false;
net.getX(X,Y) := false;
net.putX(X,Y) := false;
net.fack(X,Y) := false;
net.shwb(X,Y) := false;
net.nak(X,Y) := false;
dir.list := false;
dir.head := false;
dir.shlist(X) := false;
rp_net(X) := false;
fwd_get := none;
wbnet.wb := false;
real_owner := home;
invnet(X) := false;
invack(X) := false;
nakc := false
}
action pi_Local_Get_dirty = {
assume cache(home).state_ = invalid;
assume cache(home).wait = none;
assume ~dir.pending;
assume dir.dirty;
dir.pending := true;
collecting := false;
cache(home).wait := get;
net.get(home,dir.hptr) := true;
requester := home
}
action pi_Local_Get = {
assume cache(home).state_ = invalid;
assume cache(home).wait = none;
assume ~dir.pending;
assume ~dir.dirty;
assume ~cache(home).invmarked;
dir.local_ := true;
cache(home).state_ := shared
}
action pi_Local_Get_im = {
assume cache(home).state_ = invalid;
assume cache(home).wait = none;
assume ~dir.pending;
assume ~dir.dirty;
assume cache(home).invmarked;
cache(home).invmarked := false
}
action pi_Remote_Get = {
assume src ~= home;
assume cache(src).state_ = invalid;
assume cache(src).wait = none;
cache(src).wait := get;
net.get(src,home) := true;
src := *
}
action ni_Local_Get = { assume net.get(src,home); assume home ~= src; assume ~dir.pending & ~dir.dirty & ~ rp_net(src) & ~cache(src).invmarked; net.get(src,home) := false; net.put(home,src) := true; if (dir.head) { dir.list := true; dir.shlist(src) := true; dir.real := dir.shlist # what is this? } else { dir.head := true; dir.hptr := src } }
action ni_Local_Get = {
assume net.get(src,home);
assume home ~= src;
assume ~dir.pending & ~dir.dirty & ~ rp_net(src) & ~cache(src).invmarked;
net.get(src,home) := false;
net.put(home,src) := true;
dir.head := true;
dir.hptr := src;
dir.shlist(src) := true;
src := *
}
action ni_Local_Get_fwd = {
assume net.get(src,home);
assume home ~= src;
assume ~dir.pending & dir.dirty & ~dir.local_ & src ~= dir.hptr;
net.get(src,home) := false;
dir.pending := true;
net.get(src,dir.hptr) := true;
src := *
}
action ni_Remote_Put = {
assume dst ~= home;
assume net.put(src,dst);
net.put(src,dst) := false;
cache(dst).wait := none;
cache(dst).state_ := shared;
src := *;
dst := *
}
action pi_Remote_Replace = {
assume cache(src).state_=shared & cache(src).wait=none & src ~= home;
cache(src).state_ := invalid;
rp_net(src) := true;
src := *
}
action ni_Replace_list = {
assume rp_net(src);
assume dir.hptr ~= src;
rp_net(src) := false;
dir.shlist(src) := false;
dir.real(src) := false;
src := *
}
action pi_Remote_GetX = {
assume cache(src).state_=invalid & cache(src).wait=none & src ~= home;
cache(src).wait := getX;
net.getX(src,home) := true;
src := *
}
action ni_Local_GetX = {
assume net.getX(src,home);
assume home ~= src;
assume ~dir.pending & ~dir.dirty;
assume ~dir.head | src = dir.hptr;
assume ~dir.head | ~dir.shlist(X) | X = src;
net.getX(src,home) := false;
dir.dirty := true;
dir.head := true;
dir.hptr := src;
dir.real(X) := X = src;
dir.shlist(X) := X = src;
net.putX(home,src) := true;
real_owner := src; # ghost
cache(home).state_ := invalid;
cache(home).invmarked := (cache(home).wait = get & dir.local_) | cache(home).invmarked;
src := *
}
action ni_Local_GetX_nak = {
assume net.getX(src,home);
assume home ~= src;
assume dir.pending | dir.dirty & cache(home).state_ ~= exclusive | src = dir.hptr;
net.getX(src,home) := false;
net.nak(home,src) := true;
src := *
}
action ni_Local_GetX_pend = {
assume net.getX(src,home);
assume home ~= src;
assume ~dir.pending & dir.dirty & ~dir.local_ & src ~= dir.hptr;
net.getX(src,home) := false;
dir.pending := true;
collecting := false;
net.getX(src,dir.hptr) := true;
fwd_get := getX;
requester := src;
src := *
}
action ni_localGetX_inv = {
assume net.getX(src,home);
assume home ~= src;
assume ~dir.pending & ~dir.dirty & ~dir.local_;
assume dir.head;
assume src ~= dir.hptr | (dir.shlist(dst) & dst~=src);
net.getX(src,home) := false;
invnet(X) := X ~= home & X ~= src & dir.shlist(X);
collecting := true;
cache(home).invmarked := (cache(home).wait = get & dir.local_) | cache(home).invmarked;
dir.local_ := false;
dir.dirty := true;
dir.head := true;
dir.hptr := src;
dir.pending := true;
dir.real(X) := X ~= home & X ~= src & dir.shlist(X);
dir.shlist(X) := X = src;
net.putX(home,src) := true;
real_owner := src;
cache(home).state_ := invalid;
src := *;
dst := *
}
action ni_Remote_PutX = {
assume net.putX(src,dst);
assume dst~=home & cache(dst).wait = getX;
net.putX(src,dst) := false;
cache(dst).wait :=none;
cache(dst).invmarked := false;
cache(dst).state_ :=exclusive;
src := *;
dst := *
}
action pi_Remote_PutX = {
assume cache(src).state_ = exclusive & src ~= home; # cache(src).wait=none ???
cache(src).state_ := invalid;
wbnet.proc := src;
wbnet.wb := true;
src := *
}
action ni_Inv = {
assume invnet(dst) & dst~=home;
invnet(dst) := false;
invack(dst) := true;
cache(dst).invmarked := (cache(dst).wait = get) | cache(dst).invmarked;
cache(dst).state_ := invalid;
dst := *
}
action ni_InvAck = {
assume dir.pending & invack(src) & src~=home;
assume dir.real(dst) & dst ~= src;
invack(src) := false;
dir.real(src) := false;
src := *;
dst := *
}
action ni_InvAck_last = {
assume dir.pending & invack(src) & src~=home;
assume ~dir.real(X) | X = src;
dir.pending := false;
collecting := false;
invack(src) := false;
dir.real(src) := false;
if ( dir.local_ & ~ dir.dirty) {
dir.local_ := false
}
}
action ni_WB = {
assume wbnet.wb;
wbnet.wb := false;
dir.dirty := false;
dir.head := false;
dir.shlist(X) := false;
last_WB := wbnet.proc
}
action ni_Remote_GetX_nak = {
assume net.getX(src,dst);
assume dst ~=src & dst ~= home & cache(dst).state_ ~= exclusive;
net.getX(src,dst) := false;
fwd_get := none;
nakc := true;
net.nak(dst,src) := true;
src := *;
dst := *
}
action ni_Remote_GetX_fwd = {
assume net.getX(src,dst);
assume dst ~=src & dst ~= home & cache(dst).state_ = exclusive;
net.getX(src,dst) := false;
cache(dst).state_ := invalid;
fwd_get := none;
net.putX(dst,src) := true;
real_owner := src;
if src~=home {
net.fack(src,home) := true
};
src := *;
dst := *
}
action ni_FAck = {
assume net.fack(src,home);
net.fack(src,home) := false;
dir.pending := false;
if dir.dirty {
dir.hptr := src;
dir.shlist(X) := X = src
};
src := *
}
action ni_Remote_Get_nak = {
assume net.get(src,dst);
assume dst ~=src & dst ~= home & cache(dst).state_ ~= exclusive;
net.get(src,dst) := false;
fwd_get := none;
nakc := true;
net.nak(dst,src) := true;
src := *;
dst := *
}
action ni_Remote_Get_fwd = {
assume net.get(src,dst);
assume dst ~=src & dst ~= home & cache(dst).state_ = exclusive;
net.get(src,dst) := false;
cache(dst).state_ := shared;
fwd_get := none;
net.put(dst,src) := true;
if src~=home {
real_owner := home;
net.shwb(src,home) := true
};
src := *;
dst := *
}
action ni_ShWB = {
assume net.shwb(src,home);
net.shwb(src,home) := false;
dir.pending := false;
dir.dirty := false;
dir.shlist(src) := true;
dir.real(X) := dir.shlist(X);
src := *
}
action ni_NAK_Clear = {
assume nakc;
dir.pending := false;
nakc := false
}
export pi_Local_Get_dirty
export pi_Local_Get
export pi_Local_Get_im
export pi_Remote_Get
export ni_Local_Get
export ni_Local_Get_fwd
export ni_Remote_Put
export pi_Remote_Replace
export ni_Replace_list
export pi_Remote_GetX
export ni_Local_GetX
export ni_Local_GetX_nak
export ni_Local_GetX_pend
export ni_localGetX_inv
export ni_Remote_PutX
export pi_Remote_PutX
export ni_Inv
export ni_InvAck
export ni_InvAck_last
export ni_WB
export ni_Remote_GetX_nak
export ni_Remote_GetX_fwd
export ni_FAck
export ni_Remote_Get_nak
export ni_Remote_Get_fwd
export ni_ShWB
export ni_NAK_Clear
conjecture [coherent]
~(cache(X).state_ = exclusive & cache(X).wait = none &
cache(Y).state_ = exclusive & cache(Y).wait = none &
X ~= Y)
invariant [aux]
((Y = Z | ~net.put(Y,X) | ~net.put(Z,X)) &
(Y = Z | ~net.get(X,Y) | ~net.get(X,Z)) &
(Y = Z | ~net.putX(Y,X) | ~net.putX(Z,X)) &
(Y = Z | ~net.getX(X,Y) | ~net.getX(X,Z)) &
(~net.get(X,Z) | ~net.put(Y,X)) &
(~net.getX(X,Z) | ~net.putX(Y,X)) &
~net.getX(home,Y) &
(dir.shlist(dir.hptr) | ~dir.head) &
(cache.wait(X) = get | ~net.get(X,home)) &
(cache.wait(X) = get | ~net.put(home,X)) &
(~net.put(home,X) | ~rp_net(X)) &
(cache.state_(X) ~= exclusive | cache.wait(X) ~= getX) &
(cache.wait(X) = getX | ~net.getX(X,home)) &
(cache.wait(X) = getX | ~net.putX(home,X)) &
(~net.getX(V1,V0) | cache.wait(V1) ~= none) &
(Y = home | ~net.shwb(X,Y)) &
(cache.state_(V0) = invalid | ~net.get(V0,V1)) &
(cache.state_(V0) = invalid | ~net.put(V1,V0)) &
(cache.wait(V0) = get | ~net.get(V0,V1)) &
(cache.wait(V0) = get | ~net.put(V1,V0)) &
(cache.wait(V0) = getX | ~net.getX(V0,V1)) &
(cache.wait(V0) = getX | ~net.putX(V1,V0)) &
(V1 = home | ~net.fack(V0,V1)))
invariant (cache.state_(V0) = invalid | ~net.get(V0,V1))
invariant (cache.state_(V0) = invalid | ~net.put(V1,V0))
invariant (cache.state_(X) ~= exclusive | cache.wait(X) ~= getX)
invariant (cache.state_(X) ~= exclusive | dir.head)
invariant (cache.state_(X) = invalid | ~invack(X))
invariant (cache.state_(X) ~= shared | cache.wait(X) ~= get)
invariant cache.wait(real_owner) ~= get
invariant (cache.wait(V0) = get | ~net.get(V0,V1))
invariant (cache.wait(V0) = get | ~net.put(V1,V0))
invariant (cache.wait(V0) = getX | ~net.getX(V0,V1))
invariant (cache.wait(V0) = getX | ~net.putX(V1,V0))
invariant (cache.wait(X) = get | ~net.get(X,home))
invariant (cache.wait(X) = get | ~net.put(home,X))
invariant (cache.wait(X) = getX | ~net.getX(X,home))
invariant (cache.wait(X) = getX | ~net.putX(home,X))
invariant (dir.hptr = real_owner | ~dir.dirty | dir.pending)
invariant (dir.hptr = real_owner | ~net.putX(home,X))
invariant (dir.real(X) | X = real_owner | cache.state_(X) = invalid)
invariant (dir.shlist(dir.hptr) | ~dir.head)
invariant (dir.shlist(V0) | V0 = requester | cache.state_(V0) ~= exclusive)
invariant (dir.shlist(V1) | V1 = home | ~net.put(V0,V1))
invariant (dir.shlist(X) | cache.state_(X) ~= exclusive)
invariant (~dir.shlist(X) | dir.head)
invariant (~dir.shlist(X) | ~net.get(X,home))
invariant (dir.shlist(X) | ~net.put(home,X))
invariant (dir.shlist(X) | ~net.putX(home,X))
invariant (dir.shlist(Y) | ~net.put(X,Y))
invariant (dir.shlist(Y) | ~net.put(X,Y) | dir.dirty)
invariant (dir.shlist(Y) | ~net.put(X,Y) | dir.pending)
invariant (~invack(V0) | cache.state_(V0) ~= shared)
invariant (~invack(X) | ~invnet(X))
invariant ~net.fack(requester,home)
invariant ~net.get(home,Y)
invariant ~net.getX(home,Y)
invariant (~net.getX(V1,V0) | cache.wait(V1) ~= none)
invariant (~net.getX(X,Z) | ~net.putX(Y,X))
invariant (~net.get(X,Z) | ~net.put(Y,X))
invariant ~net.put(dir.hptr,V0)
invariant ~net.put(home,X)
invariant (~net.put(home,X) | ~rp_net(X))
invariant (~net.put(V1,V0) | ~rp_net(V0))
invariant ~net.putX(home,X)
invariant (~net.putX(home,X) | dir.head)
invariant ~net.putX(real_owner,X)
invariant (~net.putX(Y,X) | dir.dirty)
invariant (~net.putX(Y,X) | dir.head)
invariant (~net.put(Y,X) | dir.head)
invariant ~net.shwb(X,home)
invariant (real_owner = Y | ~net.putX(X,Y))
invariant (~rp_net(X) | cache.state_(X) ~= shared)
invariant (V0 = home | ~net.putX(V0,V1))
invariant (V0 = real_owner | cache.state_(V0) ~= shared)
invariant (V1 = home | ~net.fack(V0,V1))
invariant (V1 = V0 | ~net.shwb(V0,home) | ~net.shwb(V1,home))
invariant (X = dir.hptr | cache.state_(X) ~= exclusive)
invariant (X = dir.hptr | ~net.putX(home,X))
invariant (X = real_owner | cache.state_(X) ~= exclusive)
invariant (X = real_owner | ~net.fack(X,Y))
invariant (X = requester | Y = home | ~net.getX(X,Y))
invariant (Y = home | ~net.getX(X,Y))
invariant (Y = home | ~net.getX(X,Y) | dir.dirty)
invariant (Y = home | ~net.getX(X,Y) | dir.head)
invariant (Y = home | ~net.get(X,Y) | dir.dirty)
invariant (Y = home | ~net.get(X,Y) | dir.head)
invariant (Y = home | ~net.putX(Y,X))
invariant (Y = home | ~net.putX(Y,X) | dir.dirty)
invariant (Y = home | ~net.putX(Y,X) | dir.head)
invariant (Y = home | ~net.put(Y,X) | dir.dirty)
invariant (Y = home | ~net.shwb(X,Y))
invariant (Y = home | Y = real_owner | ~net.getX(X,Y))
invariant (Y = home | Y = real_owner | ~net.get(X,Y))
invariant (Y = home | Y = real_owner | ~net.putX(Y,X))
invariant (Y = home | Y = real_owner | ~net.put(Y,X))
invariant (Y = Z | ~net.getX(X,Y) | ~net.getX(X,Z))
invariant (Y = Z | ~net.get(X,Y) | ~net.get(X,Z))
invariant (Y = Z | ~net.putX(Y,X) | ~net.putX(Z,X))
invariant (Y = Z | ~net.put(Y,X) | ~net.put(Z,X))