зеркало из https://github.com/microsoft/ivy.git
285 строки
7.7 KiB
XML
285 строки
7.7 KiB
XML
#lang ivy1.1
|
|
|
|
# type of protocol time
|
|
type time
|
|
|
|
relation (T:time < U:time)
|
|
axiom (T < U & U < V) -> (T < V)
|
|
axiom ~(T < T)
|
|
axiom ~(T < U & U < T)
|
|
axiom T < U | T = U | U < T
|
|
|
|
# type of logical time
|
|
type ltime
|
|
|
|
relation lleq(T1:ltime,T2:ltime)
|
|
axiom (lleq(T,U) & lleq(U,V)) -> lleq(T,V)
|
|
axiom lleq(T,T)
|
|
axiom (lleq(T,U) & lleq(U,T)) -> U = T
|
|
axiom lleq(T,U) | lleq(U,T)
|
|
|
|
individual lzero : ltime
|
|
axiom lleq(lzero,T)
|
|
|
|
# type of memory data
|
|
type data
|
|
|
|
# type of memory addresses
|
|
type addr
|
|
|
|
# type of message types
|
|
type mtype = { grant, release }
|
|
|
|
# type of ownership state
|
|
type ownership = { none, shrd, excl }
|
|
|
|
# type of message ID
|
|
type msg_id
|
|
|
|
# memory history
|
|
relation mem(T:ltime, A:addr, D:data)
|
|
|
|
axiom (mem(T,A,D1) & mem(T,A,D2)) -> D1 = D2
|
|
|
|
# message records: set of messages sent
|
|
relation mrec(I:msg_id)
|
|
init ~mrec(I:msg_id)
|
|
|
|
module message = {
|
|
individual type_ : mtype
|
|
relation addr_(A : addr)
|
|
relation data_(D : data)
|
|
relation sent(T : time)
|
|
relation received(T : time)
|
|
individual own : ownership
|
|
relation ltime_(T : ltime)
|
|
|
|
axiom addr_(T) & addr_(U) -> T = U
|
|
axiom data_(T) & data_(U) -> T = U
|
|
axiom sent(T) & sent(U) -> T = U
|
|
axiom received(T) & received(U) -> T = U
|
|
axiom sent(T) & received(U) -> T < U
|
|
axiom ltime_(T) & ltime_(U) -> T = U
|
|
}
|
|
|
|
instantiate msg(I:msg_id) : message
|
|
|
|
# no two messages received at same time
|
|
axiom msg(I):received(T) & msg(J):received(U) & T = U -> I = J
|
|
|
|
individual a : addr
|
|
individual lt : ltime
|
|
individual nlt : ltime
|
|
individual d : data
|
|
individual o : ownership
|
|
individual mid : msg_id
|
|
individual t : time
|
|
individual nt : time
|
|
|
|
macro send_msg(t,mt,a,d,nlt,o) = {
|
|
mid := *;
|
|
assume ~mrec(mid) & msg(mid):sent(t);
|
|
assume msg(mid):type_ = mt;
|
|
assume msg(mid):addr_(a);
|
|
assume msg(mid):data_(d);
|
|
assume msg(mid):ltime_(nlt);
|
|
assume msg(mid):own = o;
|
|
mrec(mid) := true
|
|
}
|
|
|
|
macro receive_msg(t,mt) = {
|
|
mid := *;
|
|
a := *;
|
|
d := *;
|
|
nlt := *;
|
|
o := *;
|
|
assume mrec(mid) & msg(mid):received(t);
|
|
assume mt = msg(mid):type_;
|
|
assume msg(mid):addr_(a);
|
|
assume msg(mid):data_(d);
|
|
assume msg(mid):ltime_(nlt);
|
|
assume msg(mid):own = o;
|
|
mrec(mid) := false
|
|
}
|
|
|
|
module interface = {
|
|
individual own(A:addr) : ownership
|
|
relation mem_clock(A:addr,T:ltime)
|
|
individual local_clock : ltime
|
|
|
|
axiom (mem_clock(A,T) & mem_clock(A,U)) -> T = U
|
|
init mem_clock(A,lzero) & local_clock = lzero & own(A) = none
|
|
|
|
macro release() = {
|
|
a := *;
|
|
nlt := *;
|
|
d := *;
|
|
lt := *;
|
|
assume mem_clock(a,lt);
|
|
assume own(a) ~= none & lleq(lt,nlt);
|
|
mem_clock(a,X) := X=nlt;
|
|
if lleq(local_clock,nlt) {
|
|
local_clock := nlt
|
|
};
|
|
if own(a) = excl {
|
|
assume mem(nlt,a,d)
|
|
};
|
|
own(a) := none;
|
|
o := none
|
|
}
|
|
|
|
macro release_check(a,nlt,d) = {
|
|
lt := *;
|
|
assume mem_clock(a,lt);
|
|
assert own(a) ~= none & lleq(lt,nlt);
|
|
mem_clock(a,X) := X=nlt;
|
|
if lleq(local_clock,nlt) {
|
|
local_clock := nlt
|
|
};
|
|
if own(a) = excl {
|
|
assert mem(nlt,a,d)
|
|
};
|
|
own(a) := none;
|
|
o := none
|
|
}
|
|
|
|
macro grant() = {
|
|
a := *;
|
|
lt := *;
|
|
nlt := *;
|
|
d := *;
|
|
o := *;
|
|
assume o ~= none;
|
|
assume own(a) = none & mem_clock(a,lt) & lleq(lt,nlt);
|
|
mem_clock(a,X) := X=nlt;
|
|
if lleq(local_clock,nlt) {
|
|
local_clock := nlt
|
|
};
|
|
assume mem(nlt,a,d);
|
|
own(a) := o
|
|
}
|
|
|
|
macro grant_check(a,nlt,d,o) = {
|
|
lt := *;
|
|
assume o ~= none;
|
|
assume mem_clock(a,lt);
|
|
assert own(a) = none & lleq(lt,nlt);
|
|
mem_clock(a,X) := X = nlt;
|
|
if lleq(local_clock,nlt) {
|
|
local_clock := nlt
|
|
};
|
|
assert mem(nlt,a,d);
|
|
own(a) := o
|
|
}
|
|
|
|
|
|
}
|
|
|
|
instantiate front : interface
|
|
instantiate back : interface
|
|
|
|
macro front_client() = {
|
|
nt := *;
|
|
assume t < nt;
|
|
instantiate front:release();
|
|
instantiate send_msg(t,release,a,d,nlt,o);
|
|
t := nt
|
|
}
|
|
|
|
macro front_manager() = {
|
|
nt := *;
|
|
assume t < nt;
|
|
instantiate receive_msg(t,grant);
|
|
instantiate front:grant_check(a,nlt,d,o);
|
|
t := nt
|
|
}
|
|
|
|
macro back_manager() = {
|
|
nt := *;
|
|
assume t < nt;
|
|
instantiate back:grant();
|
|
instantiate send_msg(t,grant,a,d,nlt,o);
|
|
t := nt
|
|
}
|
|
|
|
macro back_client() = {
|
|
nt := *;
|
|
assume t < nt;
|
|
instantiate receive_msg(t,release);
|
|
instantiate back:release_check(a,nlt,d);
|
|
t := nt
|
|
}
|
|
|
|
action fc = {
|
|
instantiate front_client()
|
|
}
|
|
|
|
action fm = {
|
|
instantiate front_manager()
|
|
}
|
|
|
|
action bc = {
|
|
instantiate back_client()
|
|
}
|
|
|
|
action bm = {
|
|
instantiate back_manager()
|
|
}
|
|
|
|
action step = {
|
|
if * {
|
|
if * {
|
|
instantiate front_client()
|
|
}
|
|
else {
|
|
instantiate front_manager()
|
|
}
|
|
}
|
|
else {
|
|
if * {
|
|
instantiate back_client()
|
|
}
|
|
else {
|
|
instantiate back_manager()
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
# no two distinct active grant messages with same address
|
|
concept lone_grant(M1,M2,A) = msg(M1):type_ = grant * msg(M2):type_ = grant * M1 ~= M2 * mrec(M1) * mrec(M2) * msg(M1):addr_(A) * msg(M2):addr_(A)
|
|
# grant in channel means address owned at back side
|
|
concept grant_back_own(M,A) = msg(M):addr_(A) * mrec(M) * back:own(A) = none
|
|
# grant in channel means address not owned at front side
|
|
concept grant_front_own(M,A) = msg(M):addr_(A) * mrec(M) * front:own(A) ~= none
|
|
# no two distinct active release messages with same address
|
|
concept lone_release(M1,M2,A) = msg(M1):type_ = release * msg(M2):type_ = release * M1 ~= M2 * mrec(M1) * mrec(M2) * msg(M1):addr_(A) * msg(M2):addr_(A)
|
|
# release in channel means address owned at back side
|
|
concept release_back_own(M,A) = msg(M):addr_(A) * mrec(M) * back:own(A) = none
|
|
# release in channel means address not owned at front side
|
|
concept release_front_own(M,A) = msg(M):addr_(A) * mrec(M) * front:own(A) ~= none
|
|
# no grant and release messages with same address
|
|
concept grant_release(M1,M2,A) = msg(M1):type_ = grant * msg(M2):type_ = release * mrec(M1) * mrec(M2) * msg(M1):addr_(A) * msg(M2):addr_(A)
|
|
# exlusive owned on fron side implies exclusive owned on back side
|
|
concept excl_front_back(A) = front:own(A) = excl * back:own(A) ~= excl
|
|
# shared owned on fron side implies shared owned on back side
|
|
concept shrd_front_back(A) = front:own(A) = shrd * back:own(A) ~= shrd
|
|
# grant messages have correct data
|
|
concept grant_data(A,M,L,D) = mrec(M) * msg(M):type_ = grant * msg(M):addr_(A) * msg(M):ltime_(L) * msg(M):data_(D) * ~mem(L,A,D)
|
|
# release messages have correct data
|
|
concept release_data(A,M,L,D) = mrec(M) * msg(M):type_ = release * msg(M):addr_(A) * msg(M):ltime_(L) * msg(M):data_(D) * ~mem(L,A,D) * back:own(A) = excl
|
|
# a grant message has the same clock as back side
|
|
concept grant_clock_back(A,M,L1,L2) = mrec(M) * msg(M):type_ = grant * msg(M):addr_(A) * msg(M):ltime_(L1) * back:mem_clock(A,L2) * L1 ~= L2
|
|
# a grant message has the same clock >= front side
|
|
concept grant_clock_front(A,M,L1,L2) = mrec(M) * msg(M):type_ = grant * msg(M):addr_(A) * msg(M):ltime_(L1) * front:mem_clock(A,L2) * ~lleq(L2,L1)
|
|
# a release message has the same clock as front side
|
|
concept release_clock_front(A,M,L1,L2) = mrec(M) * msg(M):type_ = release * msg(M):addr_(A) * msg(M):ltime_(L1) * front:mem_clock(A,L2) * L1 ~= L2
|
|
# a release message has the same clock >= front side
|
|
concept release_clock_back(A,M,L1,L2) = mrec(M) * msg(M):type_ = release * msg(M):addr_(A) * msg(M):ltime_(L1) * back:mem_clock(A,L2) * ~lleq(L2,L1)
|
|
# owned front has clock >= back
|
|
concept clock_front_back(A,L1,L2) = front:own(A) ~= none * front:mem_clock(A,L1) * back:mem_clock(A,L2) * ~lleq(L2,L1)
|
|
# non-owned back has clock >= front
|
|
concept clock_back_front(A,L1,L2) = back:own(A) = none * back:mem_clock(A,L1) * front:mem_clock(A,L2) * ~lleq(L2,L1)
|
|
# grant messages have correct ownership
|
|
concept grant_own(A,M) = mrec(M) * msg(M):type_ = grant * msg(M):addr_(A) * msg(M):own ~= back:own(A)
|