Skip to content

first version of full port ord_live.lean port (from ord_live.ivy) has issues #5

Description

@asgeir386
/-
 Purpose: port the Apple open-source ord_live.ivy ordering model to Veil

 The following is a test case with the features required for the (safety property part) of the model:
   1) event structure
   2) global issue time LClockType
   3) arrival clocks
   4) ordering check relation: prevents from Ken McMillans FMCAD 2016 paper

 Initially will only port the inductive invariant and safety properties, but when liveness
 properties become available in Veil will port that portion of the model too

 Location of the model in the Ivy repository:
  https://github.com/kenmcmil/ivy/blob/master/doc/examples/apple/ord_live.ivy
 Reference:
  Ken McMillan, "Toward liveness proofs at scale", CAV2024 uses this model

  CURRENT ISSUES:

  Only run with one export (plus initial state) at a time so I comment out all actions except one for
  each run and I frequently exit vscode and re-invoke (because I saw some issues when I
  didn't do that e.g. veil/lean would get stuck)

  Changed 'if-then-else' to sequence of 'if' because the 'if-then-else' part seems to have worse performance

  Didn't get match (see selectOpAck) to work with enum, i.e. this would decrease the nesting level
  compared to e.g. the let op_ack in step_north

  1. step_north
     - doesn't complete and aborts when (I think) it runs out of memory e.g. I've seen 80G in top -o cpu
     - I remember that this action on and off has caused issues in Ivy when I modified it)
  2. had a typo where perform was an action instead of procedure and with all other actions commented out
     except 'after_init' this caused an issue
     - is it legal in veil to call an action from another action?
  3. simplified min t derivation in step_south for run-time reasons
     - cvc5 and z3 support minimizing natively i.e. the minimizing construct that is used in ord_live.ivy
  4. step_if_fabric
     - inv_77 fails but no CTI is created only a WP
     - separate issue: inv_10 says that all the evs_* functions are in the initial state, for time 0, but
       the CTI ignore this part and start at time 0 i.e. violate inv_10 (not a majore issue)
  5. step_memc
     - simp` failed: maximum number of steps exceeded
  6. step_cf_fabric
     - semantic difference between veil and ivy (see comment below for step_cf_fabric)
     - get error in #gen_spec step to the effect that something can't be proven after exhaustive search

 The inductive invariants pass for step_south, dramc_step_rd and dramc_step_wr
-/
import Veil

veil module ord_live

set_option maxRecDepth 16384
set_option maxHeartbeats 10000000
set_option synthInstance.maxHeartbeats 80000

type Proc
type mem_type
type addr_type

enum OpType       = {write,read,wr_cmp,rrsp,nop}
enum mem_loc_type = {mem_loc_init,mem_memc,pio_memc}

enum op_ack_type  = {nGnRnE,nGnRE,nGRE,GRE,normal}

enum LocType      = {init_l,cf_mem_l,cf_pio_l,cf_cmp_l,if_l,memc_l,dramc_l,arm_l}

enum ph_type      = {nop_ph,wr_ph,rd_ph,cpl_ph}

/- global issue time-/
type LClockType

instantiate LClock : TotalOrderWithZero LClockType


/- mem_c arrival time-/
type        tar_clock_type

instantiate tar_clock     : TotalOrderWithZero tar_clock_type

type tar_cf_clock_type
instantiate tar_cf_clock     : TotalOrderWithZero tar_cf_clock_type

individual ltime     : LClockType                -- maximum issue time
individual lt_tar_cf : tar_cf_clock_type         -- maximum arrival time cf
function   lt_tar    : mem_type → tar_clock_type -- maximum arrival time dramc

/- break out evs fields as a workaround (for now) -/

function evs_p            : LClockType → Proc
function evs_m            : LClockType → mem_type
function evs_a            : LClockType → addr_type
function evs_req          : LClockType → OpType
function evs_cmp          : LClockType → OpType
function evs_op_ack       : LClockType → op_ack_type
function evs_mem_loc      : LClockType → mem_loc_type
function evs_l_req        : LClockType → LocType
function evs_l_cmp        : LClockType → LocType
function evs_serialized   : LClockType → Bool

function evs_lt_tar       : LClockType → tar_clock_type    -- lt when reaches target: write->wr_cmp or read->rrsp
function evs_lt_arr       : LClockType → tar_clock_type
function evs_lt_arr_cf    : LClockType → tar_cf_clock_type

relation wr  : Proc → mem_type → addr_type → LClockType → Bool
relation rd  : Proc → mem_type → addr_type → LClockType → Bool

relation rsp : Proc → mem_type → addr_type → LClockType → Bool

#gen_state
ghost relation cmp_active (T:LClockType) := evs_l_cmp T=cf_mem_l ∨ evs_l_cmp T=cf_pio_l ∨ evs_l_cmp T=cf_cmp_l  ∨ evs_l_cmp T=if_l ∨ evs_l_cmp T=memc_l ∨ evs_l_cmp T=dramc_l ∨ evs_l_cmp T=arm_l

theory ghost relation lt   (x y : LClockType) := (LClock.le x y ∧ x ≠ y)
theory ghost relation le   (x y : LClockType) := (LClock.le x y)
theory ghost relation next (x y : LClockType) := (lt x y ∧ ∀ z, lt x z → LClock.le y z)

theory ghost relation lt_arr_cf_c   (x y : tar_cf_clock_type) := (tar_cf_clock.le x y ∧ x ≠ y)
theory ghost relation le_arr_cf_c   (x y : tar_cf_clock_type) := (tar_cf_clock.le x y)
theory ghost relation arr_cf_c_next (x y : tar_cf_clock_type) := (lt_arr_cf_c x y ∧ ∀ z, lt_arr_cf_c x z → tar_cf_clock.le y z)

theory ghost relation lt_arr_c   (x y : tar_clock_type) := (tar_clock.le x y ∧ x ≠ y)
theory ghost relation le_arr_c   (x y : tar_clock_type) := (tar_clock.le x y)
theory ghost relation arr_c_next (x y : tar_clock_type) := (lt_arr_c x y ∧ ∀ z, lt_arr_c x z → tar_clock.le y z)

ghost relation pnd_or_ser_wr(P:Proc)(M:mem_type)(A:addr_type)(T:LClockType) := (wr P M A T) ∨ (evs_cmp T)=wr_cmp ∧ (evs_p T)=P ∧ (evs_m T)=M ∧ (evs_a T)=A ∧ (evs_serialized T)
ghost relation pnd_or_ser_rd(P:Proc)(M:mem_type)(A:addr_type)(T:LClockType) := (rd P M A T) ∨ (evs_cmp T)=rrsp ∧ (evs_p T)=P ∧ (evs_m T)=M ∧ (evs_a T)=A ∧ (evs_serialized T)

infix:50 "<" => lt
infix:50 "<" => lt_arr_cf_c
infix:50 "<" => lt_arr_c

infix:50 "≤" => le
infix:50 "≤" => le_arr_cf_c
infix:50 "≤" => le_arr_c

-- instance : Zero LClockType        := ⟨LClock.zero⟩
-- instance : Zero tar_clock_type    := ⟨tar_clock.zero⟩
-- instance : Zero tar_cf_clock_type := ⟨tar_cf_clock.zero⟩

ghost relation same_addr(x y : LClockType) := (evs_m x) = (evs_m y) ∧ (evs_a x) = (evs_a y)

ghost relation both_normal(T0 T1 : LClockType) := (evs_op_ack T0)=normal  ∧ (evs_op_ack T1)=normal
ghost relation both_nGnR(T0 T1 : LClockType)   := ((evs_op_ack T0)=nGnRnE ∨ (evs_op_ack T0)=nGnRE) ∧ ((evs_op_ack T1)=nGnRnE ∨ (evs_op_ack T1)=nGnRE)
ghost relation both_nGR(T0 T1 : LClockType)     := ((evs_op_ack T0)=nGRE   ∨ (evs_op_ack T0)=GRE)   ∧ ((evs_op_ack T1)=nGRE   ∨ (evs_op_ack T1)=GRE)
ghost relation nGR(OP_ACK : op_ack_type)       := (OP_ACK=nGRE    ∨ OP_ACK=GRE)
ghost relation nGnR(OP_ACK : op_ack_type)      := (OP_ACK=nGnRE   ∨ OP_ACK=nGnRnE)

ghost relation dev(T:LClockType)           := (evs_op_ack T)=nGRE ∨ (evs_op_ack T)=GRE ∨ (evs_op_ack T)=nGnRnE ∨ (evs_op_ack T)=nGnRE
ghost relation pio(T:LClockType)           := dev T ∧ (evs_mem_loc T)=pio_memc

ghost relation same_attr(x y : LClockType) := both_nGnR (x) (y) ∨ both_nGR (x) (y) ∨ both_normal (x) (y)
--


-- in the actual model the prevents has evs_p T = evs_p t (but want to bring out failure in test case)


ghost relation mem_memc_exception(T0 T1 :LClockType) := (evs_cmp T0)=rrsp ∧ (evs_cmp T1)=rrsp ∧
                                                       (evs_m T0)=(evs_m T1) ∧ (evs_a T0)=(evs_a T1) ∧ (same_attr T0 T1) ∧
                                                       (evs_mem_loc T0)=mem_memc ∧ (evs_mem_loc T1)=mem_memc

ghost relation prevents (T1 : LClockType) := (∀ T0,
                                 ((evs_req T0)≠nop ∨ (evs_cmp T0)≠nop) ∧ ((¬(evs_serialized T0) ∧ (evs_serialized T1) ∨ (evs_l_cmp T0)≠init_l ∧ (evs_l_cmp T1)=init_l)
                                     ∧ (T0<T1) ∨
                                     (evs_l_req T1)≠init_l ∧ (evs_serialized T0) ∧ (T1<T0)
                                 )
                               ∧ (evs_p T0)=(evs_p T1)
                               ∧ (evs_m T0)=(evs_m T1) ∧ (evs_a T0)=(evs_a T1) ∧ (same_attr T0 T1)
                               ∧ ¬(mem_memc_exception T0 T1))

-- ghost relation prevents(t : LClockType) := ∀ T, lt LClock.zero t ∧ (lt T ltime → ¬ (evs_l_req T = dramc_l ∧ lt t T))

after_init {
  ltime            := LClock.zero       -- maximum issue time
  lt_tar_cf        := tar_cf_clock.zero
  lt_tar M         := tar_clock.zero

  wr P M A T       := false
  rd P M A T       := false
  rsp P M A T      := false

  evs_req T        := nop
  evs_cmp T        := nop
  evs_op_ack T     := normal
  evs_serialized T := true
  evs_l_req T      := init_l
  evs_l_cmp T      := init_l
  evs_mem_loc T    := mem_loc_init

  evs_lt_arr T     := tar_clock.zero
  evs_lt_tar T     := tar_clock.zero
  evs_lt_arr_cf T  := tar_cf_clock.zero
}

procedure succ (n : LClockType) {
   let k :| next n k
   return k
}

procedure succ_lt_arr_cf (n : tar_cf_clock_type) {
   let k :| arr_cf_c_next n k
   return k
}

procedure succ_lt_arr (n : tar_clock_type) {
   let k :| arr_c_next n k
   return k
}

procedure perform_grd (t:LClockType)  {
-- update the global memory state

  let m := (evs_m t)

  let next_lt_tar_m ← succ_lt_arr (lt_tar m)
  -- assert ¬ (evs_serialized t)

  if (evs_req t)=read then
    evs_l_req t     := init_l

    evs_req t       := nop

    evs_cmp t       := rrsp

    lt_tar (evs_m t) := next_lt_tar_m
    evs_lt_tar t     :=  lt_tar (evs_m t)

  if (evs_req t)=write then
-- serialize at current global time
    evs_serialized t := true

    evs_l_req t      := init_l

    evs_cmp t        := wr_cmp
    evs_req t        := nop

    lt_tar (evs_m t) := next_lt_tar_m
    evs_lt_tar t     := lt_tar (evs_m t)

  }
-- forward messages to dramc and keep them in order
-----------------------------------------------------------------------------------

--
-------------------------------------------------------------------------------------

action dramc_step_rd(m:mem_type) {
  let t :| (evs_l_req t = dramc_l) ∧ ∀ p a tt, ((rd p m a tt ∧ evs_req tt=read ∨ wr p m a tt ∧ evs_req tt=write) ∧ (evs_l_req tt) = dramc_l) → ((evs_lt_arr t)<(evs_lt_arr tt) ∨ t=tt)

  let ordpip := (evs_req t)=write

  if (evs_l_req t)=dramc_l ∧ ¬ordpip then
    rsp (evs_p t) (evs_m t) (evs_a t) t := true

    perform_grd t

    -- assert ¬ prevents t

    evs_l_cmp t := memc_l
  }

/-
action dramc_step_wr(m:mem_type) {
  let t :| (evs_l_req t=dramc_l) ∧ ∀ p a tt, ((rd p m a tt ∧ evs_req tt=read ∨ wr p m a tt ∧ evs_req tt=write) ∧ (evs_l_req tt)=dramc_l) → ((evs_lt_arr t)<(evs_lt_arr tt) ∨ t=tt)

  let ordpip := (evs_req t)=read

  if (evs_l_req t)=dramc_l ∧ ¬ordpip then
    perform_grd t

    evs_l_cmp t := memc_l

    assert ¬ prevents t
  }
-/
-- create new requests
-----------------------------------------------------------------------------

procedure create (p : Proc)(m : mem_type)(a : addr_type)(req : OpType)(l_req : LocType)(op_ack:op_ack_type)(mem_loc:mem_loc_type) {
  evs_p       ltime    := p
  evs_m       ltime    := m
  evs_a       ltime    := a
  evs_req     ltime    := req
  evs_l_req   ltime    := l_req
  evs_op_ack  ltime    := op_ack
  evs_mem_loc ltime    := mem_loc

  evs_lt_arr_cf ltime  := tar_cf_clock.zero

  evs_serialized ltime := false
}


/-
def selectOpAck (mem_loc : mem_loc_type) (choose : op_ack_type) : op_ack_type :=
    match mem_loc, choose with
    | mem_memc,GRE                  => GRE
    | mem_memc,nGRE                 => nGRE
    | mem_memc,normal               => normal
    | mem_memc, _                   => normal
    | _, _                          => choose
-/

/-
action step_north (ph : ph_type)(p : Proc)(m : mem_type)(a : addr_type)(choose_op_ack : op_ack_type)(mem_loc_arg : mem_loc_type) {
  let next_ltime ← succ ltime
  -- determine next arrival time larger than arr_mem_c_max
  let next_arr_cf ←  succ_lt_arr_cf lt_tar_cf
--  let OrdPip := ∃ T, (evs_l_req T = cf_mem_l ∧ evs_p T = evs_p t) ∧ lt T t

  let dram_new := true
  let pio_new  := false

  let wr_new   := ph=wr_ph
  let rd_new   := ph=rd_ph

  let devb     := false

 -- let t :| (evs_req t=read ∨ evs_req t=write ∨ evs_cmp t=rrsp ∨ evs_cmp t=wr_cmp) ∧ evs_m t=m ∧ evs_a t=a

  let t :| ∃ P, wr P m a t ∨ rd P m a t

  let op_ack :=
    if (evs_req t=read ∨ evs_req t=write ∨ evs_cmp t=rrsp ∨ evs_cmp t=wr_cmp) ∧ evs_m t=m ∧ evs_a t=a then
      if evs_mem_loc t=mem_memc then
        if choose_op_ack=normal ∨ choose_op_ack=GRE ∨ choose_op_ack=nGRE then
          choose_op_ack
        else
          normal  -- pick one
      else
        if choose_op_ack=nGnRnE ∨ choose_op_ack=nGnRE ∨ choose_op_ack=GRE ∨ choose_op_ack=nGRE then
          choose_op_ack
        else
          nGnRnE
    else
      normal

  let mem_loc_arg := if mem_loc_arg=mem_memc then mem_memc else pio_memc

  let mem_loc :=
    if (evs_req t=read ∨ evs_req t=write ∨ evs_cmp t=rrsp ∨ evs_cmp t=wr_cmp) ∧ evs_m t=m ∧ evs_a t=a then
      evs_mem_loc t
    else
      if op_ack=normal then
        mem_memc
      else
        if op_ack=nGnRnE ∨ op_ack=nGnRE then
          pio_memc
        else
          mem_loc_arg

--  let op_ack :=
--    if ((evs_req t)=read ∨ (evs_req t)=write ∨ (evs_cmp t)=rrsp ∨ (evs_cmp t)=wr_cmp) ∧ (evs_m t)=m ∧ (evs_a t)=a then
--      selectOpAck (evs_mem_loc t) choose_op_ack
--    else
--      normal
--  let ordser_wr := false
  let ordser_wr :=  ∃ M A T, wr_new ∧ devb ∧ nGnR op_ack ∧ wr p M A T  ∧ (evs_req T=write ∨ evs_cmp T=wr_cmp  ∧ cmp_active T)  ∧ dev T  ∧ nGnR (evs_op_ack T)  ∧ pio_new ∧ ¬(M=m ∧ A=a) ∨
                             wr_new ∧ devb ∧ nGnR op_ack ∧ rd p M A T ∧ (evs_req T=read ∨ evs_cmp T=rrsp ∧ cmp_active T) ∧ dev T ∧ nGnR (evs_op_ack T) ∨
                             wr_new ∧ devb ∧ nGnR op_ack ∧ rd p M A T ∧ (evs_req T=read ∨ evs_cmp T=rrsp ∧ cmp_active T) ∧ dev T ∧ nGR (evs_op_ack T) ∨
                             wr_new ∧ devb ∧ nGR op_ack  ∧ rd p M A T ∧ (evs_req T=read ∨ evs_cmp T=rrsp ∧ cmp_active T) ∧ dev T ∧ nGnR (evs_op_ack T) ∨
                             wr_new ∧ devb ∧ nGR op_ack  ∧ rd p M A T ∧ (evs_req T=read ∨ evs_cmp T=rrsp ∧ cmp_active T) ∧ dev T ∧ nGR (evs_op_ack T) ∨
                             wr_new ∧ ¬devb ∧ wr p m a T ∧ (evs_req T=write ∨ evs_cmp T=wr_cmp ∧ cmp_active T) ∧ ¬(dev T) ∧ dram_new ∨
                             wr_new ∧ ¬devb ∧ wr p m a T ∧ (evs_req T=write ∨ evs_cmp T=wr_cmp ∧ cmp_active T) ∧ ¬(dev T) ∧ pio_new ∨
                             wr_new ∧ ¬devb ∧ rd p M A T ∧ (evs_req T=read ∨ evs_cmp T=rrsp ∧ cmp_active T) ∧ ¬(dev T)

  let ordser_rd := ∃ M A T, rd_new ∧ devb ∧ nGnR op_ack ∧ wr p M A T ∧ (evs_req T=write ∨ evs_cmp T=wr_cmp ∧ cmp_active T) ∧ dev T ∧ nGnR (evs_op_ack T) ∧ dram_new ∨
                            rd_new ∧ devb ∧ nGnR op_ack ∧ wr p M A T ∧ (evs_req T=write ∨ evs_cmp T=wr_cmp ∧ cmp_active T) ∧ dev T ∧ nGnR (evs_op_ack T) ∧ pio_new ∨
                            rd_new ∧ devb ∧ nGnR op_ack ∧ rd p M A T ∧ (evs_req T=read ∨ evs_cmp T=rrsp ∧ cmp_active T) ∧ dev T ∧ nGnR (evs_op_ack T) ∧ pio_new ∧ ¬(M=m ∧ A=a) ∨
                            rd_new ∧ devb ∧ nGR op_ack ∧ wr p m a T ∧ (evs_req T=write ∨ evs_cmp T=wr_cmp ∧ cmp_active T) ∧ dev T ∧ nGR (evs_op_ack T) ∧ dram_new ∨
                            rd_new ∧ devb ∧ nGR op_ack ∧ wr p m a T ∧ (evs_req T=write ∨ evs_cmp T=wr_cmp ∧ cmp_active T) ∧ dev T ∧ nGR (evs_op_ack T) ∧ pio_new ∨
                            rd_new ∧ ¬devb ∧ wr p m a T ∧ (evs_req T=write ∨ evs_cmp T=wr_cmp ∧ cmp_active T) ∧ ¬(dev T) ∧ dram_new ∨
                            rd_new ∧ ¬devb ∧ wr p m a T ∧ (evs_req T=write ∨ evs_cmp T=wr_cmp ∧ cmp_active T) ∧ ¬(dev T) ∧ pio_new ∨
                            rd_new ∧ ¬devb ∧ rd p m a T ∧ (evs_req T=read ∨ evs_cmp T=rrsp ∧ cmp_active T) ∧ ¬(dev T) ∧ dram_new ∨
                            rd_new ∧ ¬devb ∧ rd p m a T ∧ (evs_req T=read ∨ evs_cmp T=rrsp ∧ cmp_active T) ∧ ¬(dev T) ∧ pio_new

  if wr_new ∧ ¬ordser_wr ∧ mem_loc=mem_memc then
    ltime := next_ltime -- increment max issue time

    create p m a write cf_mem_l op_ack mem_loc

    wr p m a ltime := true

  if wr_new ∧ ¬ordser_wr ∧ mem_loc=pio_memc then
      ltime := next_ltime -- increment max issue time

      create p m a write cf_pio_l op_ack mem_loc

      wr p m a ltime := true

  if rd_new ∧ ¬ordser_rd ∧ mem_loc=mem_memc then
    ltime := next_ltime -- increment max issue time

    create p m a read cf_mem_l op_ack mem_loc

    lt_tar_cf           := next_arr_cf
    evs_lt_arr_cf ltime := next_arr_cf

    rd p m a ltime := true

  if rd_new ∧ ¬ordser_rd ∧ mem_loc=pio_memc then
      ltime := next_ltime -- increment max issue time

      create p m a read cf_pio_l op_ack mem_loc

      wr p m a ltime := true
}
-/
/-
  XXX when procedure is replaced with action bad things happen
  - comment out all other actions, and then only the initial state check remains, but the build doesn't complete
    in reasonable time
-/
procedure perform (t:LClockType) {
-- update the global memory state
  if evs_cmp t=rrsp then
      -- serialize at current global time
      evs_serialized t := true

  evs_l_cmp  t := init_l
}
/-
action step_south (ph:ph_type)(pp:Proc) {

  /- XXX this is code corresponding to ord_live.ivy but didn't work, or at least took a long time so re-wrote it with equivalent expression -/
  -- let t :| evs_l_cmp t≠init_l ∧ evs_p t=pp ∧ (evs_cmp t=wr_cmp ∨ evs_cmp t=rrsp) ∧ ∀ tt, evs_p tt=pp ∧ (evs_cmp tt=wr_cmp ∨ evs_cmp tt=rrsp) ∧ evs_l_cmp tt≠init_l → (lt t tt ∨ t=tt)

  let t :| ¬evs_serialized t ∧ evs_p t=pp ∧ ∀ tt, ¬evs_serialized tt ∧ evs_p tt=pp → (lt t tt ∨ tt=t)

  let m := evs_m t
  let a := evs_a t

  if ph=cpl_ph ∧ evs_l_cmp t=arm_l ∧ evs_cmp t=rrsp then
    perform t

    assert ¬ prevents t

    rsp pp m a t  := false
    rd  pp m a t  := false

  if ph=cpl_ph ∧ evs_l_cmp t=arm_l ∧ evs_cmp t=wr_cmp then
    perform t

    assert ¬ prevents t

    wr pp m a t    := false

}
-/
-- forward messages to memc and keep messages from same arm instance in-order
--------------------------------------------------------------------------------------
-- 1) uncomment tcmp argument, 2) comment out let for cmp and tcmp
/-
action step_cf_fabric (ph:ph_type)(sel_memc:Bool) { -- (tcmp : LClockType) {

  let min_rd_mem :| (evs_l_req min_rd_mem=cf_mem_l) ∧  sel_memc ∧ ∀ t, evs_req t=read  ∧ evs_l_req t=cf_mem_l   → (lt_arr_cf_c (evs_lt_arr_cf min_rd_mem) (evs_lt_arr_cf t) ∨ min_rd_mem=t)
  let min_rd_pio :| (evs_l_req min_rd_pio=cf_pio_l) ∧ ¬sel_memc ∧ ∀ t, (evs_req t=read  ∧ evs_l_req t=cf_pio_l) → (lt min_rd_pio t ∨ min_rd_pio=t)

  let min_wr_mem :| (evs_l_req min_wr_mem=cf_mem_l) ∧  sel_memc ∧ ∀ t, (evs_req t=write ∧ evs_l_req t=cf_mem_l) → (lt min_wr_mem t ∨ min_wr_mem=t)
  let min_wr_pio :| (evs_l_req min_wr_pio=cf_pio_l) ∧ ¬sel_memc ∧ ∀ t, (evs_req t=write ∧ evs_l_req t=cf_pio_l) → (lt min_wr_pio t ∨ min_wr_pio=t)

  let new_rd  := ph=rd_ph ∧ (sel_memc ∧ evs_l_req min_rd_mem=cf_mem_l ∨ ¬ sel_memc ∧ evs_l_req min_rd_pio=cf_pio_l)
  let new_wr  := ph=wr_ph ∧ (sel_memc ∧ evs_l_req min_wr_mem=cf_mem_l ∨ ¬ sel_memc ∧ evs_l_req min_wr_pio=cf_pio_l)

  let t :=
    if ph=wr_ph then
      if sel_memc then
        min_wr_mem
      else
        min_wr_pio
    else
      if sel_memc then
        min_rd_mem
      else
        min_rd_pio

  let p    := evs_p t

  /- the following two lines are redundant compared to ivy model i.e. including tcmp as an argument in
     action is sufficient -/
  let cmp  := ph=cpl_ph ∧ ∃ tcmp, (evs_cmp tcmp=rrsp ∨ evs_cmp tcmp=wr_cmp) ∧ evs_l_cmp tcmp=cf_cmp_l
  let tcmp :| ∃ tcmp, (evs_cmp tcmp=rrsp ∨ evs_cmp tcmp=wr_cmp) ∧ evs_l_cmp tcmp=cf_cmp_l

  let ordpip0 := new_rd ∧ ∃ M A T, rd p M A T ∧ evs_req T=read  ∧ (evs_l_req T=cf_mem_l ∨ evs_l_req T=cf_pio_l) ∧ evs_mem_loc t=evs_mem_loc T ∧ evs_mem_loc t=mem_memc ∧ lt_arr_cf_c (evs_lt_arr_cf T) (evs_lt_arr_cf t)
  let ordpip1 := new_wr ∧ ∃ M A T, wr p M A T ∧ evs_req T=write ∧ (evs_l_req T=cf_mem_l ∨ evs_l_req T=cf_pio_l) ∧ evs_mem_loc t=evs_mem_loc T ∧ evs_mem_loc t=mem_memc ∧ lt T t
  let ordpip2 := new_rd ∧ ∃ M A T, rd p M A T ∧ evs_req T=read  ∧ (evs_l_req T=cf_mem_l ∨ evs_l_req T=cf_pio_l) ∧ evs_mem_loc t=evs_mem_loc T ∧ evs_mem_loc t=pio_memc ∧ lt T t
  let ordpip3 := new_wr ∧ ∃ M A T, wr p M A T ∧ evs_req T=write ∧ (evs_l_req T=cf_mem_l ∨ evs_l_req T=cf_pio_l) ∧ evs_mem_loc t=evs_mem_loc T ∧ evs_mem_loc t=pio_memc ∧ lt T t

  let ordpip := ordpip0 ∨ ordpip1 ∨ ordpip2 ∨ ordpip3

  if (new_rd ∨ new_wr) ∧ ¬ ordpip ∧ evs_mem_loc t=mem_memc then
    evs_l_req t := memc_l

  if (new_rd ∨ new_wr) ∧ ¬ ordpip ∧ evs_mem_loc t=pio_memc then
    evs_l_req t := if_l

  if cmp then
    evs_l_cmp tcmp := arm_l

}
-/
-- if switching fabric (rudimentary)
--------------------------------------------------------------------------------------

/- XXX inv_77 fails but no CTI is created only a WP -/
/-
action step_if_fabric (ph:ph_type)(m:mem_type)(a:addr_type)(p:Proc)(tcmp:LClockType) {

  let min_rd_issue :| (evs_l_req min_rd_issue=if_l) ∧ ∀ t, (evs_req t=read  ∧ evs_l_req t=if_l) → (lt min_rd_issue t ∨ min_rd_issue = t)
  let min_wr_issue :| (evs_l_req min_wr_issue=if_l) ∧ ∀ t, (evs_req t=write ∧ evs_l_req t=if_l) → (lt min_wr_issue t ∨ min_wr_issue = t)

  let new_rd  := ph=rd_ph ∧ evs_l_req min_rd_issue=if_l
  let new_wr  := ph=wr_ph ∧ evs_l_req min_wr_issue=if_l

  let t       := if ph=wr_ph then min_wr_issue else min_rd_issue

  let cmp     := ph=cpl_ph ∧ evs_l_cmp tcmp=if_l

  let ordpip0 := new_rd ∧ ∃ M A T, rd p M A T ∧ evs_req T=read  ∧ evs_l_req T=if_l ∧ lt T t -- processed
  let ordpip1 := new_wr ∧ ∃ M A T, wr p M A T ∧ evs_req T=write ∧ evs_l_req T=if_l ∧ lt T t -- processed

  let ordpip := ordpip0 ∨ ordpip1

  if (new_rd ∨ new_wr) ∧ ¬ ordpip  ∧ (evs_mem_loc t=mem_memc ∨ evs_mem_loc t=pio_memc) then
      evs_l_req t := memc_l

  if cmp then
    evs_l_cmp tcmp := cf_cmp_l

}
-/

/- XXX `simp` failed: maximum number of steps exceeded -/
/-
action step_memc(ph:ph_type)(p:Proc)(m:mem_type)(a:addr_type)(tcmp:LClockType) {

let next_arr_c ←  succ_lt_arr (lt_tar m)


let rd_bp := ∃ T, evs_req T=read ∧ evs_m T=m ∧ evs_a T=a ∧ evs_l_req T=dramc_l
let wr_bp := ∃ T, evs_req T=write ∧ evs_m T=m ∧ evs_a T=a ∧ evs_l_req T=dramc_l

let t_rd :| (evs_l_req t_rd=memc_l) ∧ ∀ p t, evs_l_req t=memc_l ∧ rd p m a t → (lt t_rd t ∨ t_rd=t)
let t_wr :| (evs_l_req t_wr=memc_l) ∧ ∀ p t, evs_l_req t=memc_l ∧ wr p m a t → (lt t_wr t ∨ t_wr=t)

if ph=rd_ph ∧ evs_l_req t_rd=memc_l ∧ evs_mem_loc t_rd=mem_memc ∧ ¬ rd_bp then
  evs_l_req t_rd   := dramc_l

  lt_tar m         := next_arr_c
  evs_lt_arr t_rd  := next_arr_c

if ph=wr_ph ∧ evs_l_req t_wr=memc_l ∧ evs_mem_loc t_wr=mem_memc ∧ ¬ wr_bp then
  evs_l_req t_wr   := dramc_l

  lt_tar m         := next_arr_c
  evs_lt_arr t_wr  := next_arr_c

if ph=rd_ph ∧ evs_l_req t_rd=memc_l ∧ evs_mem_loc t_rd=pio_memc then

  rsp (evs_p t_rd) (evs_m t_rd) (evs_a t_rd) t_rd  := true

  perform_grd t_rd

  evs_l_cmp t_rd := memc_l

  assert ¬ prevents t_rd

if ph=wr_ph ∧ evs_l_req t_wr=memc_l ∧ evs_mem_loc t_wr=pio_memc then

  perform_grd t_wr

  evs_l_cmp t_wr := memc_l

  assert ¬ prevents t_wr

if ph=cpl_ph ∧ evs_l_cmp tcmp=memc_l ∧ (evs_cmp tcmp=rrsp ∨ evs_cmp tcmp=wr_cmp) ∧ evs_mem_loc tcmp=mem_memc then
  evs_l_cmp tcmp := cf_cmp_l

if ph=cpl_ph ∧ evs_l_cmp tcmp=memc_l ∧ (evs_cmp tcmp=rrsp ∨ evs_cmp tcmp=wr_cmp) ∧ evs_mem_loc tcmp=pio_memc then
  evs_l_cmp tcmp := if_l

}
-/

invariant [only_write] ((evs_req T)=nop ∨ (evs_req T)=write)

----
invariant [inv_0] (evs_req T)=read ∧ (evs_l_req T)=cf_mem_l ∧ (evs_mem_loc T)=mem_memc ∧ T=ltime -> (evs_lt_arr_cf T)=lt_tar_cf

invariant [inv_1] (evs_req T)=read ∧ (evs_l_req T)=cf_mem_l ∧ (evs_mem_loc T)=mem_memc -> evs_lt_arr_cf T ≠ tar_cf_clock.zero
invariant [inv_2] (evs_req T)=read ∧ (evs_l_req T)=cf_mem_l ∧ (evs_mem_loc T)=mem_memc -> (evs_lt_arr_cf T)≤lt_tar_cf

invariant [inv_3] (evs_cmp T)=rrsp ∧ (evs_mem_loc T)=mem_memc -> (evs_lt_arr_cf T)≤lt_tar_cf

invariant [inv_4] (evs_lt_arr_cf T) ≤ lt_tar_cf

invariant [inv_5] (
           (evs_req T0)=read ∧ (evs_l_req T0)=cf_mem_l ∧ (evs_mem_loc T0)=mem_memc ∧
           (evs_req T1)=read ∧ (evs_l_req T1)=cf_mem_l ∧ (evs_mem_loc T1)=mem_memc ∧
           T0<T1
          )
          ->
          (evs_lt_arr_cf T0)<(evs_lt_arr_cf T1)
----

invariant [inv_6] (ltime=T ∧ ¬(T=LClock.zero)) -> ¬((evs_req T)=nop ∧ (evs_cmp T)=nop)

invariant [inv_7] (ltime<T ∨ T=LClock.zero) -> (evs_lt_arr T)=tar_clock.zero ∧ (evs_lt_arr_cf T)=tar_cf_clock.zero
invariant [inv_8] ltime=LClock.zero         -> lt_tar_cf=tar_cf_clock.zero

invariant [inv_9] ((evs_req T)=nop ∧ (evs_cmp T)=nop ∨ (evs_req T)=write ∨  (evs_cmp T)=wr_cmp ∨ ((evs_req T)=read ∨ (evs_cmp T)=rrsp) ∧ ¬((evs_mem_loc T)=mem_memc))
           ->
           (evs_lt_arr_cf T)=tar_cf_clock.zero

invariant [inv_10] (evs_req LClock.zero)=nop ∧ (evs_l_req LClock.zero)=init_l ∧ (evs_cmp LClock.zero)=nop ∧ (evs_l_cmp LClock.zero)=init_l ∧ (evs_lt_arr LClock.zero)=tar_clock.zero ∧ (evs_lt_arr_cf LClock.zero)=tar_cf_clock.zero

invariant [inv_11] ((evs_req T)=write ∨ (evs_req T)=read ∨ (evs_cmp T)=wr_cmp ∨ (evs_cmp T)=rrsp) ∧ (evs_mem_loc T)=pio_memc
           ->
          (evs_lt_arr T)=tar_clock.zero

invariant [inv_12] ((evs_req T)=write ∨ (evs_req T)=read) ∧ (evs_m T)=M ∧ (evs_a T)=A ∧ (evs_l_req T)=dramc_l
           ->
            ¬((evs_lt_arr T)=tar_clock.zero)

invariant [inv_13] ((evs_req T)=write ∨ (evs_req T)=read) ∧ (evs_m T)=M ∧ (evs_a T)=A ∧ ¬((evs_l_req T)=dramc_l)
           ->
           (evs_lt_arr T)=tar_clock.zero

invariant [inv_14] (evs_req T)=read  -> (evs_l_cmp T)=init_l
invariant [inv_15] (evs_req T)=write -> (evs_l_cmp T)=init_l

invariant [inv_16]  (evs_req T)=nop -> (evs_l_req T)=init_l

invariant [inv_17] ((evs_req T)=read ∨ (evs_req T)=write ∨ (evs_req T)=nop)
invariant [inv_18] ((evs_cmp T)=rrsp ∨ (evs_cmp T)=wr_cmp ∨ (evs_cmp T)=nop)

invariant [inv_19] (evs_req T)≠nop -> (evs_cmp T)=nop
invariant [inv_20] (evs_cmp T)≠nop -> (evs_req T)=nop

invariant [inv_21] (∀ P M A, ¬((wr P M A T) ∨ (rd P M A T))) -> ((evs_l_req T)=init_l ∧ (evs_l_cmp T)=init_l)

invariant [inv_22] (((evs_req T)=write ∨ (evs_req T)=read) ∧ (evs_mem_loc T)=mem_memc ∧ (evs_l_req T)=dramc_l)
           ->
           ¬((lt_tar (evs_m T))<(evs_lt_arr T))

invariant [inv_23] (((evs_cmp T)=wr_cmp ∨ (evs_cmp T)=rrsp) ∧ (evs_mem_loc T)=mem_memc)
           ->
           (evs_lt_arr T)<(evs_lt_tar T)

invariant [inv_24] (
            ((evs_req T0)=write ∧ (evs_l_req T0)=dramc_l ∨ (evs_req T0)=read ∧ (evs_l_req T0)=dramc_l) ∧ (evs_mem_loc T0)=mem_memc ∧
            ((evs_cmp T1)=wr_cmp ∨ (evs_cmp T1)=rrsp) ∧ (evs_mem_loc T1)=mem_memc ∧ (evs_l_cmp T1)=dramc_l ∧
            (evs_m T0)=(evs_m T1) ∧
            T0≠T1
           )
           ->
           ((evs_lt_arr T0)≠(evs_lt_tar T1) ∧ (evs_lt_arr T0)≠(evs_lt_arr T1))

invariant [inv_25] (
            ((evs_req T0)=write ∧ (evs_l_req T0)=dramc_l ∨ (evs_cmp T0)=wr_cmp ∨ (evs_req T0)=read ∧ (evs_l_req T0)=dramc_l ∨ (evs_cmp T0)=rrsp) ∧ (evs_mem_loc T0)=mem_memc ∧
            ((evs_req T1)=write ∧ (evs_l_req T1)=dramc_l ∨ (evs_cmp T1)=wr_cmp ∧ (evs_l_cmp T1)=dramc_l ∨ (evs_req T1)=read ∧ (evs_l_req T1)=dramc_l ∨ (evs_cmp T1)=rrsp ∧ (evs_l_cmp T1)=dramc_l) ∧ (evs_mem_loc T1)=mem_memc ∧
            (evs_m T0)=(evs_m T1) ∧
            T0≠T1
           )
           ->
           (
            (evs_lt_arr T0)≠(evs_lt_arr T1) ∧
            (((evs_cmp T0)=wr_cmp ∨ (evs_cmp T0)=rrsp) -> (evs_lt_tar T0)≠(evs_lt_arr T1)) ∧
            (((evs_cmp T1)=wr_cmp ∨ (evs_cmp T1)=rrsp) -> (evs_lt_arr T0)≠(evs_lt_tar T1))
           )

invariant [inv_26] (
            ((evs_cmp T0)=wr_cmp ∨ (evs_cmp T0)=rrsp) ∧ (evs_mem_loc T0)=mem_memc ∧
            ((evs_cmp T1)=wr_cmp ∨ (evs_cmp T1)=rrsp) ∧ (evs_mem_loc T1)=mem_memc ∧
            (evs_m T0)=(evs_m T1) ∧
            T0≠T1
           )
           ->
           ((evs_lt_arr T0)≠(evs_lt_arr T1) ∧ (evs_lt_tar T0)≠(evs_lt_tar T1))

invariant [inv_27] ¬(
            (evs_req T0)=write ∧ (evs_cmp T1)=rrsp ∧
            (evs_mem_loc T0)=mem_memc ∧ (evs_mem_loc T1)=mem_memc ∧
            (evs_m T0)=(evs_m T1) ∧
            (evs_a T0)=(evs_a T1) ∧
            (evs_l_req T0)=dramc_l ∧
            ((evs_lt_arr T0)<(evs_lt_arr T1))
            )

invariant [inv_28] (
            (evs_req T0)=read ∧ (evs_cmp T1)=rrsp ∧
            (evs_p T0)=(evs_p T1) ∧
            (evs_mem_loc T0)=mem_memc ∧ (evs_mem_loc T1)=mem_memc ∧
            (evs_m T0)=(evs_m T1) ∧
            (evs_a T0)=(evs_a T1) ∧
            (same_attr T0 T1) ∧
            T0<T1
            )
            ->
            ((evs_lt_arr T0)<(evs_lt_arr T1))

-- No RR or WW to same address in mem_memc from arm (normal)
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

invariant [inv_29] ¬(
            ((evs_req T0)=read ∧ (evs_req T1)=read ∨ (evs_req T0)=write ∧ (evs_req T1)=write) ∧
            (evs_op_ack T0)=normal ∧
            (evs_p T0)=(evs_p T1) ∧
            (evs_mem_loc T0)=mem_memc ∧ (evs_mem_loc T1)=mem_memc ∧
            (evs_m T0)=(evs_m T1) ∧
            (evs_a T0)=(evs_a T1) ∧
            (same_attr T0 T1) ∧
            T0<T1
            )

-- RR and WW to same address in mem_memc stay in order
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

invariant [inv_30] (
            ((evs_req T0)=write ∧ (evs_req T1)=write ∨ (evs_req T0)=read ∧ (evs_req T1)=read) ∧
            (evs_mem_loc T0)=mem_memc ∧ (evs_mem_loc T1)=mem_memc ∧
            (evs_p T0)=(evs_p T1) ∧
            (evs_m T0)=(evs_m T1) ∧
            (evs_a T0)=(evs_a T1) ∧
            (evs_l_req T0)=dramc_l ∧ (evs_l_req T1)=dramc_l ∧
            (same_attr T0 T1) ∧
            T0<T1
           )
           ->
           (
            ((evs_lt_arr T0)<(evs_lt_arr T1))
           )

invariant [inv_31] ((evs_cmp T)=wr_cmp ∨ (evs_cmp T)=rrsp) -> ¬((lt_tar (evs_m T))<(evs_lt_tar T))

invariant [inv_32] (
            ((evs_cmp T0)=wr_cmp ∨ (evs_cmp T0)=rrsp) ∧
            ((evs_cmp T1)=wr_cmp ∨ (evs_cmp T1)=rrsp) ∧
            (evs_m T0)=(evs_m T1) ∧
            T0≠T1
           )
           ->
           ((evs_lt_tar T0)≠(evs_lt_tar T1))

invariant [inv_33] (
            (evs_cmp T0)=wr_cmp ∧ (evs_cmp T1)=rrsp ∧
            (evs_p T0)=(evs_p T1) ∧
            (evs_m T0)=(evs_m T1) ∧
            (evs_a T0)=(evs_a T1) ∧
            (same_attr T0 T1) ∧
            T0<T1
           )
           ->
           (
            ((evs_lt_tar T0) < (evs_lt_tar T1))
           )

invariant [inv_34] (
             (evs_req T0)=read ∧ (evs_req T1)=read ∧
             (evs_p T0)=(evs_p T1) ∧
             (evs_mem_loc T0)=pio_memc ∧ (evs_mem_loc T1)=pio_memc ∧
             (evs_m T0)=(evs_m T1) ∧
             (evs_a T0)=(evs_a T1) ∧
             (same_attr T0 T1) ∧
             T0<T1
           )
           ->
           (
            (evs_l_req T0)=cf_pio_l       ∧ ((evs_l_req T1)=cf_pio_l) ∨
            (evs_l_req T0)=if_l       ∧ ((evs_l_req T1)=if_l  ∨ (evs_l_req T1)=cf_pio_l) ∨
            (evs_l_req T0)=memc_l      ∧ ((evs_l_req T1)=memc_l ∨ (evs_l_req T1)=if_l ∨ (evs_l_req T1)=cf_pio_l)
           )

invariant [inv_35] (((evs_cmp T)=wr_cmp ∨ (evs_cmp T)=rrsp) ∧ (evs_serialized T))
           ->
           (
            (evs_mem_loc T)=mem_memc ∨
            (evs_mem_loc T)=pio_memc
           )
--
----------------------------------------------------------------------------------------------------------------------------------------------------------------

invariant [inv_36] (evs_req T)=write -> ¬(evs_serialized T)
invariant [inv_37] (evs_req T)=read  -> ¬(evs_serialized T)

invariant [inv_38] ((evs_req T)=nop   ∧ (evs_cmp T)=wr_cmp) -> (evs_serialized T)

invariant [inv_39] (evs_serialized T) -> ((evs_req T)=nop ∨ (evs_cmp T)=nop ∨ (evs_cmp T)=rrsp ∨ (evs_cmp T)=wr_cmp)

invariant [inv_40] (((evs_cmp T)=wr_cmp ∨ (evs_cmp T)=rrsp))
           ->
           (
            ((evs_cmp T)=wr_cmp ∨ (evs_cmp T)=rrsp ∧ ¬(evs_serialized T)) ∧ (
            (evs_mem_loc T)=mem_memc ∧ ((evs_l_cmp T)=dramc_l ∨ (evs_l_cmp T)=memc_l ∨ (evs_l_cmp T)=cf_cmp_l ∨ (evs_l_cmp T)=arm_l) ∨
            (evs_mem_loc T)=pio_memc ∧ ((evs_l_cmp T)=memc_l ∨ (evs_l_cmp T)=if_l ∨ (evs_l_cmp T)=cf_cmp_l ∨ (evs_l_cmp T)=arm_l)
            ) ∨

            (evs_serialized T) ∧ ((evs_cmp T)=rrsp ∨ (evs_cmp T)=wr_cmp) ∧ (evs_l_cmp T)=init_l
           )

invariant [inv_41] (((evs_req T)=write ∨ (evs_req T)=read))
           ->
           (
            (evs_mem_loc T)=mem_memc ∧ ((evs_l_req T)=dramc_l ∨ (evs_l_req T)=memc_l ∨ (evs_l_req T)=cf_mem_l) ∨
            (evs_mem_loc T)=pio_memc ∧ ((evs_l_req T)=memc_l ∨ (evs_l_req T)=if_l ∨ (evs_l_req T)=cf_pio_l)
           )

invariant [inv_42] ¬(
            ((evs_req T0)=write ∧ (evs_cmp T1)=wr_cmp ∧ (evs_l_cmp T1)=init_l ∨ ((evs_req T0)=read ∨ (evs_cmp T0)=rrsp) ∧ (evs_cmp T1)=rrsp) ∧
            ¬(evs_serialized T0) ∧ (evs_serialized T1) ∧
            (evs_p T0)=(evs_p T1) ∧
            (evs_m T0)=(evs_m T1) ∧
            (evs_a T0)=(evs_a T1) ∧
            (same_attr T0 T1) ∧
            T0<T1
           )

invariant [inv_43] ¬(evs_serialized T) -> ¬((evs_mem_loc T)=mem_loc_init)

-- initialized to mem_loc_init, but once used has same mapping for all agents

invariant [inv_44] ((evs_req T)=nop ∧ (evs_cmp T)=nop) -> (evs_mem_loc T)=mem_loc_init

invariant [inv_45] (((evs_req T0)≠nop ∨ (evs_cmp T0)≠nop) ∧ ((evs_req T1)≠nop ∨ (evs_cmp T1)≠nop) ∧ (evs_m T0)=(evs_m T1) ∧ (evs_a T0)=(evs_a T1))
           ->
           (
            (evs_mem_loc T0)=(evs_mem_loc T1)
           )

invariant [inv_46] (((evs_req T0)≠nop ∨ (evs_cmp T0)≠nop) ∧ ((evs_req T1)≠nop ∨ (evs_cmp T1)≠nop) ∧ (evs_m T0)=(evs_m T1) ∧ (evs_a T0)=(evs_a T1))
           ->
           (
            (evs_mem_loc T0)=mem_memc ∨ (evs_mem_loc T0)=pio_memc
           )

invariant [inv_47] (((evs_req T)≠nop ∨ (evs_cmp T)≠nop) ∧ ¬(dev T)) -> (evs_op_ack T)=normal

invariant [inv_48] (((evs_req T)≠nop ∨ (evs_cmp T)≠nop) ∧ (dev T)) -> (((evs_op_ack T)=nGnRE ∨ (evs_op_ack T)=nGnRnE) ∨ ((evs_op_ack T)=GRE ∨ (evs_op_ack T)=nGRE))

invariant [inv_49] ¬(
             (evs_req T0)=read ∧ ((evs_req T1)=read ∨ (evs_cmp T1)=rrsp) ∧ ¬(evs_serialized T0) ∧ ¬(evs_serialized T1) ∧
             (evs_p T0)=(evs_p T1) ∧
             (evs_mem_loc T0)=mem_memc ∧ (evs_mem_loc T1)=mem_memc ∧
             (evs_m T0)=(evs_m T1) ∧ (evs_a T0)=(evs_a T1) ∧
             (both_normal T0 T1) ∧
             T0<T1
           )

invariant [inv_50] ((evs_req T)=nop ∨ (evs_cmp T)=nop ∨ (evs_req T)=write ∨ (evs_cmp T)=wr_cmp ∨ (evs_req T)=read ∨ (evs_cmp T)=rrsp)

invariant [inv_51] (wr P M A T)  -> T≠LClock.zero
invariant [inv_52] (rd P M A T)  -> T≠LClock.zero

invariant [inv_53] (evs_mem_loc T)=pio_memc -> (dev T)

invariant [inv_54] (((wr P M A T) ∨ (rd P M A T)) ∧ (dev T)) -> (((evs_op_ack T)=nGRE ∨ (evs_op_ack T)=GRE) ∨ ((evs_op_ack T)=nGnRnE ∨ (evs_op_ack T)=nGnRE))
invariant [inv_55] (((wr P M A T) ∨ (rd P M A T)) ∧ ¬(dev T)) -> (evs_op_ack T)=normal

invariant [inv_56] ¬((pnd_or_ser_wr P M1 A1 T1) ∧ (rd P M0 A0 T0) ∧ (same_attr T0 T1) ∧ M0=M1 ∧ A0=A1 ∧ T0<T1)

invariant [inv_57] ¬((pnd_or_ser_rd P M1 A1 T1) ∧ (wr P M0 A0 T0) ∧ T0<T1 ∧  (dev T0) ∧  (dev T1) ∧ (both_nGnR T0 T1))

invariant [inv_58] ¬((pnd_or_ser_rd P M1 A1 T1) ∧ (wr P M0 A0 T0) ∧ T0<T1 ∧  (dev T0) ∧  (dev T1) ∧ (both_nGR T0 T1) ∧ (same_addr T0 T1))

-- Never >1 to Normal to/from same address

invariant [inv_59] ¬((pnd_or_ser_rd P M A T1) ∧ (rd P M A T0) ∧ T0<T1 ∧ ¬(dev T0) ∧ ¬(dev T1))
invariant [inv_60] ¬((pnd_or_ser_rd P M A T1) ∧ (wr P M A T0) ∧ T0<T1 ∧ ¬(dev T0) ∧ ¬(dev T1))
invariant [inv_61] ¬((pnd_or_ser_wr P M A T1) ∧ (rd P M A T0) ∧ T0<T1 ∧ ¬(dev T0) ∧ ¬(dev T1))
invariant [inv_62] ¬((pnd_or_ser_wr P M A T1) ∧ (wr P M A T0) ∧ T0<T1 ∧ ¬(dev T0) ∧ ¬(dev T1))

----------------------------------------------------------------------------------------------------------------------------------------------------------------
-- SECTION: ref
--
-- lt keeps track of the largest value of the logical time value. Starts at
--        value 0 and is then incremented when each write/read is issued
--

invariant [inv_63] (T=LClock.zero ∨ ltime<T) -> ((evs_req T)=nop ∧ (evs_cmp T)=nop ∧ (evs_serialized T))

invariant [inv_64] (wr P M A T)
           <->
           (((evs_req T)=write ∧ ¬(evs_serialized T) ∨ (evs_cmp T)=wr_cmp ∧ (evs_l_cmp T)≠init_l ∧ (evs_serialized T)) ∧ (evs_p T)=P ∧ (evs_m T)=M ∧ (evs_a T)=A)

------

invariant [inv_65] ((rd P M A T) ∧ ¬(rsp P M A T))
           <->
           ((evs_req T)=read ∧ ¬(evs_serialized T) ∧ (evs_p T)=P ∧ (evs_m T)=M ∧ (evs_a T)=A)

invariant [inv_66] ((rd P M A T) ∧ (rsp P M A T))
           <->
           ((evs_cmp T)=rrsp ∧ ¬(evs_serialized T) ∧ (evs_p T)=P ∧ (evs_m T)=M ∧ (evs_a T)=A)

invariant [inv_67] (evs_req T)=read ->  ¬(evs_serialized T)

------

invariant [inv_68] ((evs_cmp T)=rrsp ∧ ¬(evs_serialized T)) -> (evs_l_cmp T) ≠ dramc_l

----------------------------------------------------------------------------------------------------------------------------------------------------------------
-- SECTION: arm

invariant [inv_69] (((evs_req T)=read ∨ (evs_cmp T)=rrsp) ∧ (dev T))  -> ((evs_op_ack T)=nGnRnE ∨ (evs_op_ack T)=nGnRE ∨ (evs_op_ack T)=nGRE ∨ (evs_op_ack T)=GRE)
invariant [inv_70] (((evs_req T)=read ∨ (evs_cmp T)=rrsp) ∧ ¬(dev T)) -> (evs_op_ack T)=normal

invariant [inv_71] (((evs_req T)=write ∨ (evs_cmp T)=wr_cmp) ∧ (dev T)) -> ((evs_op_ack T)=nGnRnE ∨ (evs_op_ack T)=nGnRE ∨ (evs_op_ack T)=nGRE ∨ (evs_op_ack T)=GRE)
invariant [inv_72] (((evs_req T)=write ∨ (evs_cmp T)=wr_cmp) ∧ ¬(dev T)) -> (evs_op_ack T)=normal

-- PIO writes (to same address) can be pipelined and stay in order

invariant [inv_73] (
            ((evs_req T0)=write ∨ (evs_cmp T0)=wr_cmp) ∧
            ((evs_req T1)=write ∨ (evs_cmp T1)=wr_cmp) ∧
            (evs_p T0)=(evs_p T1) ∧
            (evs_m T0)=(evs_m T1) ∧
            (evs_a T0)=(evs_a T1) ∧
            (same_attr T0 T1) ∧
            T0<T1
           )
           ->
           ¬((evs_serialized T1) ∧ ¬(evs_serialized T0))

invariant [inv_74] (
            ((evs_req T0)=write ∧ (evs_req T1)=write ∨ (evs_req T0)=read ∧ (evs_req T1)=read) ∧
            ¬(evs_serialized T0) ∧
            (evs_p T0)=(evs_p T1) ∧
            (evs_m T0)=(evs_m T1) ∧
            (evs_a T0)=(evs_a T1) ∧
            (evs_mem_loc T0)=mem_memc ∧ (evs_mem_loc T1)=mem_memc ∧
            T0<T1
           )
           ->
           (
            (evs_l_req T0)=cf_mem_l  ∧ (evs_l_req T1)=cf_mem_l   ∨
            (evs_l_req T0)=memc_l ∧ ((evs_l_req T1)=memc_l ∨ (evs_l_req T1)=cf_mem_l) ∨
            (evs_l_req T0)=dramc_l  ∧ ((evs_l_req T1)=dramc_l  ∨ (evs_l_req T1)=memc_l ∨ (evs_l_req T1)=cf_mem_l)
           )

invariant [inv_75] ¬(
            (((evs_req T0)=read ∨ (evs_cmp T0)=rrsp) ∧ ((evs_req T1)=write ∨ (evs_cmp T1)=wr_cmp)) ∧
            ¬(evs_serialized T0) ∧
            (evs_p T0)=(evs_p T1) ∧
            (evs_m T0)=(evs_m T1) ∧
            (evs_a T0)=(evs_a T1) ∧
            (evs_mem_loc T0)=pio_memc ∧ (evs_mem_loc T1)=pio_memc ∧
            T0<T1
           )

invariant [inv_76] ¬(
            ((evs_req T0)=write ∧ ((evs_req T1)=read ∨ (evs_cmp T1)=rrsp)) ∧
            (evs_p T0)=(evs_p T1) ∧
            (evs_m T0)=(evs_m T1) ∧
            (evs_a T0)=(evs_a T1) ∧
            (evs_mem_loc T0)=pio_memc ∧ (evs_mem_loc T1)=pio_memc ∧
            (same_attr T0 T1) ∧
            T0<T1
           )

invariant [inv_77] (
            ((evs_req T0)=write ∧ (evs_req T1)=write ∨ (evs_req T0)=read ∧ (evs_req T1)=read) ∧
            (evs_p T0)=(evs_p T1) ∧
            (evs_m T0)=(evs_m T1) ∧
            (evs_a T0)=(evs_a T1) ∧
            (evs_mem_loc T0)=pio_memc ∧ (evs_mem_loc T1)=pio_memc ∧
            T0<T1
           )
           ->
           (
            (evs_l_req T0)=cf_pio_l  ∧ (evs_l_req T1)=cf_pio_l ∨
            (evs_l_req T0)=if_l  ∧ ((evs_l_req T1)=if_l ∨ (evs_l_req T1)=cf_pio_l) ∨
            (evs_l_req T0)=memc_l ∧ ((evs_l_req T1)=memc_l ∨ (evs_l_req T1)=if_l ∨ (evs_l_req T1)=cf_pio_l)
           )

----------------------------------------------------------------------------------------------------------------------------------------------------------------
-- dramc_mod
--

invariant [inv_78] ((evs_req T0)=write ∧ (evs_l_req T0)=dramc_l ∧ (evs_req T1)=write ∧ (evs_l_req T1)=dramc_l ∧ (evs_m T0)=(evs_m T1) ∧ (evs_a T0)=(evs_a T1)) -> T0=T1
invariant [inv_79] ((evs_req T0)=read  ∧ (evs_l_req T0)=dramc_l ∧ (evs_req T1)=read ∧ (evs_l_req T1)=dramc_l ∧ (evs_m T0)=(evs_m T1) ∧ (evs_a T0)=(evs_a T1)) -> T0=T1

------

--RAR

invariant [inv_80] (
            (evs_req T0)=read ∧ ¬(evs_serialized T0) ∧
            (evs_req T1)=read ∧
            (evs_p T0)=(evs_p T1) ∧
            (evs_mem_loc T0)=mem_memc ∧ (evs_mem_loc T1)=mem_memc ∧
            (evs_m T0)=(evs_m T1) ∧
            (evs_a T0)=(evs_a T1) ∧
            T0<T1
           )
           ->
           (
            (evs_req T1)=read ∧ (evs_l_req T1)=cf_mem_l  ∧ (evs_req T0)=read ∧ ((evs_l_req T0)=cf_mem_l ∨ (evs_l_req T0)=memc_l ∨ (evs_l_req T0)=dramc_l) ∨
            (evs_req T1)=read ∧ (evs_l_req T1)=memc_l ∧ (evs_req T0)=read ∧ ((evs_l_req T0)=memc_l ∨ (evs_l_req T0)=dramc_l) ∨
            (evs_req T1)=read ∧ (evs_l_req T1)=dramc_l  ∧ (evs_req T0)=read ∧ (evs_l_req T0)=dramc_l
           )

--WAW
invariant [inv_81] (
            (evs_req T0)=write ∧ ¬(evs_serialized T0) ∧
            (evs_req T1)=write ∧
            (evs_p T0)=(evs_p T1) ∧
            (evs_mem_loc T0)=mem_memc ∧ (evs_mem_loc T1)=mem_memc ∧
            (evs_m T0)=(evs_m T1) ∧
            (evs_a T0)=(evs_a T1) ∧
            T0<T1
           )
           ->
           (
            (evs_l_req T0)=cf_mem_l  ∧ (evs_l_req T1)=cf_mem_l ∨
            (evs_l_req T0)=memc_l ∧ ((evs_l_req T1)=memc_l ∨ (evs_l_req T1)=cf_mem_l) ∨
            (evs_l_req T0)=dramc_l  ∧ ((evs_l_req T1)=dramc_l  ∨ (evs_l_req T1)=memc_l ∨ (evs_l_req T1)=cf_mem_l)
           )
--RAR
invariant [inv_82] (
            (evs_req T0)=read ∧ ¬(evs_serialized T0) ∧
            (evs_cmp T1)=rrsp ∧
            (evs_p T0)=(evs_p T1) ∧
            (evs_mem_loc T0)=mem_memc ∧ (evs_mem_loc T1)=mem_memc ∧
            (evs_m T0)=(evs_m T1) ∧
            (evs_a T0)=(evs_a T1) ∧
            (same_attr T0 T1) ∧
            T0<T1
           )
           ->
           (
            (evs_l_req T0)=dramc_l ∧ ((evs_l_cmp T1)=dramc_l ∨ (evs_l_cmp T1)=memc_l ∨ (evs_l_cmp T1)=cf_mem_l ∨ (evs_l_cmp T1)=arm_l)
           )

--RAR/WAW

-- RR to mem_memc is OrdSer for arm
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

invariant [inv_83] ¬(
             (evs_req T0)=read ∧ (evs_cmp T1)=rrsp ∧
             (evs_p T0)=(evs_p T1) ∧
             (evs_m T0)=(evs_m T1) ∧ (evs_a T0)=(evs_a T1) ∧
             (same_attr T0 T1) ∧
             T0<T1
           )

-- WW to same address stay in order, and therefore can't have wr_cmp for younger before older
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

invariant [inv_84] ¬(
             (evs_req T0)=write ∧ (evs_cmp T0)=nop ∧ (evs_req T1)=nop ∧ (evs_cmp T1)=wr_cmp ∧
             (evs_p T0)=(evs_p T1) ∧
             (evs_m T0)=(evs_m T1) ∧ (evs_a T0)=(evs_a T1) ∧
             (same_attr T0 T1) ∧
             T0<T1
           )

invariant [inv_85] (
            ((evs_req T0)=read ∨ (evs_cmp T0)=rrsp) ∧ (pio T0) ∧
            ((evs_req T1)=read ∨ (evs_cmp T1)=rrsp) ∧ (pio T1) ∧
             (evs_m T0)=(evs_m T1) ∧ (evs_a T0)=(evs_a T1) ∧
             (evs_p T0)=(evs_p T1) ∧
             (same_attr T0 T1) ∧
             T0<T1
           )
           ->
           ¬(¬(evs_serialized T0) ∧ (evs_serialized T1))

invariant [inv_86] (
            ((evs_req T0)=read ∨ (evs_cmp T0)=rrsp) ∧
            ((evs_req T1)=read ∨ (evs_cmp T1)=rrsp) ∧
             (evs_m T0)=(evs_m T1) ∧ (evs_a T0)=(evs_a T1) ∧
             (evs_p T0)=(evs_p T1) ∧
             (same_attr T0 T1) ∧
             T0<T1
           )
           ->
           ¬(¬(evs_serialized T0) ∧ (evs_serialized T1))

#time #gen_spec
--
-- #model_check { LClockType := Fin 5,Proc := Fin 3, tar_clock_type := Fin 3, tar_cf_clock_type := Fin 3, mem_type := Fin 1, addr_type := Fin 1}{ }

#check_invariants

end ord_live

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions