Tilelink snoopy
¤
This is an abstract model of simple snoopy cache using TileLink
¤
include tilelink_abstract_spec
¤
Cache line format
¤
module cache_line = {
relation excl_p # has exclusive priv
relation shrd_p # has shared priv
individual data_ : data
init ~excl_p & ~shrd_p
}
¤
The snoopy cache model
¤
module snoopy(id,clnt,mngr,ref) = {
¤
The cache
instantiate cache(A:addr) : cache_line
¤
release action called by the client side not supported
action release(a:addr, d:data, o:ownership) = {
assert false # block it
}
¤
grant action called by the manager side
action grant(a:addr, d:data, o:ownership) = {
if o = excl {
cache(a).excl_p := true
} else {
cache(a).shrd_p := true
};
cache(a).data_ := d
}
¤
request action called by the client side
this just enqueues a request message
action request(a:addr, d:data, mo:otype, lt:ltime) = {
assume mo ~= cas; # don't support for now
if mo = read {
assume cache(a).excl_p | cache(a).shrd_p; # models channel blocking
local d:data {
d := cache(a).data_;
call ref.perform(lt,id); # ghost
call clnt.response(a,d,mo,lt)
}
} else { # mo = write
assume cache(a).excl_p; # models channel blocking
cache(a).data_ := d;
call ref.perform(lt,id); # ghost
call clnt.response(a,d,mo,lt)
}
}
¤
response action called by the client side
not supported
action response(a:addr, d:data, mo:otype, lt:ltime) = {
assume false
}
¤
internal action (step)
this models a release (voluntary or otherwise)
action step = {
local a:addr, d:data, o:ownership {
if * {
assume cache(a).excl_p;
cache(a).excl_p := false;
o := excl
} else {
assume cache(a).shrd_p;
cache(a).shrd_p := false;
o := shrd
};
d := cache(a).data_;
call mngr.release(a,d,o)
}
}
}
¤
Verify the module using the standard testbench
¤
include tilelink_two_port_test_bench
1) supports only one client
axiom fside(I) = client & fside(J) = client -> I = J
axiom ~front.cached(A) & back.cached(A)