ivy/test/test_a.ivy

338 строки
9.4 KiB
XML

#lang ivy1.7
################################################################################
# ivy Origin protocol model
#
# Copyright 2017-2018 Asgeir Eiriksson (asgeir.eiriksson@gmail.com)
#
# - write this to look as close to the SMV model structure as possible
# to investigate how well ivy matches the typical hardware design
# paradigm
#
# - this would enable moving the same model between ivy, SMV and verilog
#
# - why do we need the back-and-forth between tools/paradigms capability?
#
# 1) analyze liveness within smv
# 2) refine the design within smv in both directions, i.e. increase
# abstraction e.g. similar to the BRD* to IRD* proc handling,
# and to formally verify the actual hardware design
# 3) prove memory consistency model within ivy
# 4) generate executable model within ivy
# 5) mixed sw/fw/hw designs with ivy
#
# TODO
#
# 1) change action to ph, both in the smv model
# 2) module p_mod "individual msg_req_rsp : msg_req_rsp_type" looks like it
# might be moved to net, but maybe not
# 3) change the SMV defines to lower case to better match ivy
#
################################################################################
type proc
type data_type
type addr_type
type state_type = {inv,shd,cex,dex}
type dstate_type = {uown,shrd,excl,busys,busye}
type msg_req_rsp_type = {idle_r_r,erply,espec,nack,rdsh,rdex,srply,sspec,upack,upgrd,wack,wb,wbbak}
type msg_rpl_type = {idle_rpl,eack,eresp,sack,sresp}
type msg_req_type = {idle_req,irdex,irdsh}
type msg_trf_type = {idle_trf,dngrd,xfer}
type ph_type = {req_rsp_ph1,req_rsp_ph2,req_rsp_ph3,rpl_ph,req_ph,trf_ph,store_ph}
type send_type = {send_ex,send_evct,send_rdsh,send_none}
module req_rsp_type = {
individual kind : msg_req_rsp_type
individual data : data_type
}
module req_type = {
individual kind : msg_req_type
individual src : proc
individual dst : proc
}
module rpl_type = {
individual kind : msg_rpl_type
individual src : proc
individual dst : proc
individual data : data_type
}
module trf_type = {
individual kind : msg_trf_type
individual src : proc
individual data : data_type
}
module rrb_type = {
individual v : bool
individual a : bool
individual r : bool
}
module wrb_type = {
individual v : bool
individual a : bool
}
module irb_type = {
individual i : bool
individual kind : msg_req_type
individual src : proc
}
################################################################################
# proc issues requests and pesses responses, interventions and store
# requests
#
################################################################################
## ****
module p_mod = {
individual state(A:addr_type) : state_type
instantiate rrb(A:addr_type) : rrb_type
instantiate irb(A:addr_type) : irb_type
instantiate wrb(A:addr_type) : wrb_type
individual data(A:addr_type) : data_type
individual wr : bool
individual error : bool
individual ivack : bool
action p_rec(p:proc,a:addr_type,ph:ph_type,send:send_type,store:bool,store_data:data_type) = {
error := true;
if ph=rpl_ph & net.ivack(p,a) {
net.ivack(p,a) := false;
if (exists X. net.ivack(X,a)) | (exists Y. net.ivec(Y,a)) | (exists P. pi(P).irb(a).i & pi(P).irb(a).kind=idle_req) {
net.last_ivack := false;
} else {
net.last_ivack := true;
};
ivack := true;
} else {
net.last_ivack := false;
ivack := false;
};
if ph=req_rsp_ph1 & ~rrb(a).v & ~wrb(a).v & state(a)=inv & send=send_rdsh {
rrb(a).v := true;
rrb(a).r := false;
rrb(a).a := false;
net.req_rsp(p,a).kind := rdsh;
error := false;
}
else if ph=req_rsp_ph1 & ~rrb(a).v & ~wrb(a).v & state(a)=inv & send=send_ex {
rrb(a).v := true;
rrb(a).r := false;
rrb(a).a := false;
net.req_rsp(p,a).kind := rdex;
error := false;
}
else {
error := false;
}
}
}
## ****
object d = {
individual dstate(A:addr_type) : dstate_type
individual ptr(A:addr_type) : proc
individual pptr(A:addr_type) : proc
individual tmp_pptr : proc
individual pptr_vld(A:addr_type) : bool
relation owner(X:proc,A:addr_type)
individual mem(A:addr_type) : data_type
individual mem_real(A:addr_type) : data_type
individual error : bool
individual shrd_only : bool
individual excl_owner : bool
################################################################################
# directory receives proc requests and ownership transfer messages
# and responds with response messages and optionally invalidates and
# interventions
#
################################################################################
action dir_rec(p:proc,a:addr_type,ph:ph_type) = {
error := true;
tmp_pptr := ptr(a);
shrd_only := ~(exists P. owner(P,a) & p~=P);
excl_owner := p=ptr(a);
if ph=req_rsp_ph2 & net.req_rsp(p,a).kind=rdsh & dstate(a)=uown {
dstate(a) := shrd;
owner(p,a) := true;
net.req_rsp(p,a).kind := srply;
net.req_rsp(p,a).data := mem(a);
pptr_vld(a) := false;
error := false;
}
else if ph=req_rsp_ph2 & net.req_rsp(p,a).kind=rdsh & dstate(a)=excl & excl_owner {
dstate(a) := shrd;
owner(p,a) := true;
net.req_rsp(p,a).kind := srply;
net.req_rsp(p,a).data := mem(a);
pptr(a) := ptr(a);
pptr_vld(a) := true;
error := false;
}
else {
error := false;
}
}
after dir_rec {
assert ~error
}
}
## ****
################################################################################
#
################################################################################
module network = {
instantiate req_rsp(X:proc,A:addr_type) : req_rsp_type
instantiate req(X:proc,A:addr_type) : req_type
instantiate rpl(A:addr_type) : rpl_type
instantiate trf(A:addr_type) : trf_type
individual binv(A:addr_type) : bool
individual inval(A:addr_type) : bool
individual store_data : data_type
individual last_ivack : bool
individual ivec(X:proc,A:addr_type) : bool
individual ivack(X:proc,A:addr_type) : bool
action step(p:proc,a:addr_type,ph:ph_type,send:send_type,store:bool) = {
if ph=req_rsp_ph1 { # proc issues new request
call pi(p).p_rec(p,a,ph,send,store,store_data)
} else if ph=req_rsp_ph2 { # directory receives request/owner-ship transfer
call d.dir_rec(p,a,ph)
} else if ph=req_rsp_ph3 { # proc receives response
call pi(p).p_rec(p,a,ph,send,store,store_data)
} else if ph=rpl_ph & net.rpl(a).dst=p { # proc receives intervention/invalidate response
if net.rpl(a).kind~= idle_rpl & net.rpl(a).dst=p {
call pi(p).p_rec(p,a,ph,send,store,store_data)
} else if net.ivack(p,a) {
call pi(d.ptr(a)).p_rec(p,a,ph,send,store,store_data)
}
} else if ph=req_ph { # proc receives intervention/invalidate request
call pi(p).p_rec(p,a,ph,send,store,store_data)
} else if ph=trf_ph { # directory receives ownership transfer message
call d.dir_rec(p,a,ph)
} else if ph=store_ph { # proc writes/dirties a cex cache line
call pi(p).p_rec(p,a,ph,send,store,store_data)
}
}
#
action step0(p:proc,a:addr_type,send:send_type,store:bool) = {
call pi(p).p_rec(p,a,req_rsp_ph1,send,store,store_data)
}
action step1(p:proc,a:addr_type,send:send_type,store:bool) = {
call d.dir_rec(p,a,req_rsp_ph2)
}
action step2(p:proc,a:addr_type,send:send_type,store:bool) = {
call pi(p).p_rec(p,a,req_rsp_ph3,send,store,store_data)
}
action step3(p:proc,a:addr_type,send:send_type,store:bool) = {
if net.rpl(a).dst=p {
if net.rpl(a).kind~= idle_rpl & net.rpl(a).dst=p {
call pi(p).p_rec(p,a,rpl_ph,send,store,store_data)
} else if net.ivack(p,a) {
call pi(d.ptr(a)).p_rec(p,a,rpl_ph,send,store,store_data)
}
}
}
action step4(p:proc,a:addr_type,send:send_type,store:bool) = {
call pi(p).p_rec(p,a,req_ph,send,store,store_data)
}
action step5(p:proc,a:addr_type,send:send_type,store:bool) = {
call d.dir_rec(p,a,trf_ph)
}
action step6(p:proc,a:addr_type,send:send_type,store:bool) = {
call pi(p).p_rec(p,a,store_ph,send,store,store_data)
}
}
after init {
net.req_rsp(P,A).kind := idle_r_r;
net.req(P,A).kind := idle_req;
net.ivec(P,A) := false;
net.ivack(P,A) := false;
net.inval(A) := false;
net.binv(A) := false;
pi(X).state(A) := inv;
pi(X).rrb(A).v := false;
d.dstate(A) := uown;
d.owner(X,A) := false;
d.pptr_vld(A) := false;
d.mem_real(A) := d.mem(A);
net.rpl(A).kind := idle_rpl;
net.trf(A).kind := idle_trf
}
################################################################################
#
################################################################################
instantiate pi(X:proc) : p_mod
#instantiate dir : dir_mod
instantiate net : network
################################################################################
#
################################################################################
conjecture (net.req_rsp(P,A).kind~=rdsh)
#export net.step
export net.step0
export net.step1
export net.step2
export net.step3
export net.step4
export net.step5
export net.step6