view ModelChecking.agda @ 713:252e15bcbbb8

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Thu, 05 May 2022 21:02:07 +0900
parents 64a86fde1f90
children 75da5f6de47e
line wrap: on
line source

module ModelChecking where

open import Level renaming (zero to Z ; suc to succ)

open import Data.Nat hiding (compare)
open import Data.Nat.Properties as NatProp
open import Data.Maybe
-- open import Data.Maybe.Properties
open import Data.Empty
open import Data.List
-- open import Data.Tree.Binary
-- open import Data.Product
open import Function as F hiding (const)
open import Relation.Binary
open import Relation.Binary.PropositionalEquality
open import Relation.Nullary
open import logic
open import Data.Unit hiding ( _≟_ ;  _≤?_ ; _≤_)
open import Relation.Binary.Definitions

record AtomicNat : Set where
   field
      anid : ℕ       -- memory pointer ( unique id of DataGear )
      value : ℕ

init-AtomicNat : AtomicNat
init-AtomicNat = record { anid = 0 ; value = 0 }

--
-- single process implemenation
--

f_set : {n : Level } {t : Set n} → AtomicNat → (value : ℕ) → ( AtomicNat → t ) → t
f_set a v next = next record a { value = v }

record Phil  : Set  where
   field 
      pid : ℕ
      left right : AtomicNat

init-Phil : Phil
init-Phil = record { pid = 0 ; left = init-AtomicNat ; right = init-AtomicNat }

pickup_rfork : {n : Level} {t : Set n} → Phil → ( Phil → t ) → t
pickup_lfork : {n : Level} {t : Set n} → Phil → ( Phil → t ) → t
eating : {n : Level} {t : Set n} → Phil → ( Phil → t ) → t
putdown_rfork : {n : Level} {t : Set n} → Phil → ( Phil → t ) → t
putdown_lfork : {n : Level} {t : Set n} → Phil → ( Phil → t ) → t
thinking : {n : Level} {t : Set n} → Phil → ( Phil → t ) → t

-- pickup_rfork p next = f_set (Phil.right p) (Phil.pid p) ( λ f → goto C_pickup_lfork record p { right = f } next )

pickup_rfork p next = f_set (Phil.right p) (Phil.pid p) ( λ f → pickup_lfork record p { right = f } next )
pickup_lfork p next = f_set (Phil.left p) (Phil.pid p) ( λ f → eating record p { left = f } next )
eating p next = putdown_rfork p next
putdown_rfork p next = f_set (Phil.right p) 0 ( λ f → putdown_lfork record p { right = f } next )
putdown_lfork p next = f_set (Phil.left p) 0 ( λ f → thinking record p { left = f } next )
thinking p next = next p

run : Phil
run = pickup_rfork record { pid = 1 ; left = record { anid = 1 ; value = 0 } ; right = record { anid = 2 ; value = 0 } } $ λ p → p

--
-- Coda Gear
--

data Code : Set  where
   C_nop : Code
   C_cas_int : Code
   C_putdown_rfork : Code 
   C_putdown_lfork : Code 
   C_thinking : Code 
   C_pickup_rfork : Code 
   C_pickup_lfork : Code 
   C_eating : Code 

--
-- all possible arguments in -APIs
--
record AtomicNat-API : Set where
   field
      next : Code
      fail : Code
      value : ℕ
      impl : AtomicNat

record Phil-API : Set  where
   field 
      next : Code
      impl : Phil

data Error : Set where
   E_panic : Error
   E_cas_fail : Error

--
-- Data Gear
--
data Data : Set where
   D_AtomicNat :  AtomicNat → Data
   D_Phil :      Phil → Data
   D_Error :      Error → Data

   -- A_AtomicNat :  AtomicNat-API → Data
   -- A_Phil :      Phil-API → Data

open import hoareBinaryTree

record Context  : Set  where
   field
      next :      Code 
      fail :      Code

      --  -API list (frame in Gears Agda )
      c_Phil-API :     Phil-API
      c_AtomicNat-API : AtomicNat-API

      mbase :     ℕ
      memory :    bt Data
      error :     Data
      fail_next :      Code

alloc-data : {n : Level} {t : Set n} → ( c : Context ) → ( Context → ℕ → t ) → t
alloc-data {n} {t} c next = next record c { mbase = ( suc ( Context.mbase c ) ) } ( suc ( Context.mbase c ) ) 

update-data : {n : Level} {t : Set n} → ( c : Context ) → ℕ →  Data → ( Context → t ) → t
update-data  c n x next  = insertTree (Context.memory c) n x ( λ bt → next record c { memory = bt } )

--
-- second level stub
--
AtomicInt_cas_stub : {n : Level} {t : Set n} → Context  → ( Code → Context → t ) → t
AtomicInt_cas_stub {_} {t} c next = updateTree (Context.memory c) (AtomicNat.anid ai) ( D_AtomicNat (record ai { value = AtomicNat.value ai } ))
     ( λ bt → next ( Context.fail c ) c  ) -- segmentation fault ( null pointer )
     $ λ now bt → f_cas ai  (AtomicNat.value ai) now bt  where
    api : AtomicNat-API
    api = Context.c_AtomicNat-API c
    ai : AtomicNat
    ai = AtomicNat-API.impl api
    f_cas : AtomicNat → (old : ℕ ) → Data  → bt Data  → t
    f_cas a old (D_AtomicNat now) bt with <-cmp old ( AtomicNat.value now )
    ... | tri≈ ¬a b ¬c  = next (AtomicNat-API.fail api) ( record c { memory = bt ; c_AtomicNat-API = record api { impl = a } }  ) -- update memory
    ... | tri< a₁ ¬b ¬c = next (AtomicNat-API.fail api) c
    ... | tri> ¬a ¬b _  = next (AtomicNat-API.fail api) c
    f_cas a old _ bt    = next ( Context.fail c ) c       -- type error


Phil_putdown_rfork_sub : {n : Level} {t : Set n} → Context  → ( Code → Context → t ) → t
Phil_putdown_rfork_sub c next = next C_cas_int record c { 
    c_AtomicNat-API = record { impl = Phil.right phil ; value =  Phil.pid phil ; fail = C_putdown_lfork ; next = C_putdown_lfork } }  where
    phil : Phil
    phil = Phil-API.impl ( Context.c_Phil-API c )

Phil_putdown_lfork_sub : {n : Level} {t : Set n} → Context  → ( Code → Context → t ) → t
Phil_putdown_lfork_sub c next = next C_cas_int record c { 
    c_AtomicNat-API = record { impl = Phil.left phil ; value =  Phil.pid phil ; fail = C_thinking ; next = C_thinking } }  where
    phil : Phil
    phil = Phil-API.impl ( Context.c_Phil-API c )

Phil_thiking : {n : Level} {t : Set n} → Context  → ( Code → Context → t ) → t
Phil_thiking c next = next C_pickup_rfork c  

Phil_pickup_lfork_sub : {n : Level} {t : Set n} → Context  → ( Code → Context → t ) → t
Phil_pickup_lfork_sub c next = next C_cas_int record c { 
    c_AtomicNat-API = record { impl = Phil.left phil ; value =  Phil.pid phil ; fail = C_pickup_rfork ; next = C_pickup_lfork } }  where
    phil : Phil
    phil = Phil-API.impl ( Context.c_Phil-API c )

Phil_pickup_rfork_sub : {n : Level} {t : Set n} → Context  → ( Code → Context → t ) → t
Phil_pickup_rfork_sub c next = next C_cas_int record c { 
    c_AtomicNat-API = record { impl = Phil.left phil ; value =  Phil.pid phil ; fail = C_pickup_lfork ; next = C_eating } }  where
    phil : Phil
    phil = Phil-API.impl ( Context.c_Phil-API c )

Phil_eating_sub : {n : Level} {t : Set n} → Context  → ( Code → Context → t ) → t
Phil_eating_sub c next =  next C_putdown_rfork c 

code_table :  {n : Level} {t : Set n} → Code → Context → ( Code → Context → t) → t
code_table C_nop  = λ c  next  → next C_nop c
code_table C_cas_int  = AtomicInt_cas_stub
code_table C_putdown_rfork = Phil_putdown_rfork_sub
code_table C_putdown_lfork = Phil_putdown_lfork_sub
code_table C_thinking = Phil_thiking
code_table C_pickup_rfork = Phil_pickup_lfork_sub
code_table C_pickup_lfork = Phil_pickup_rfork_sub
code_table C_eating = Phil_eating_sub

open Context

new :   {n : Level} {t : Set n} →  ( c : Context ) → Data → ( Context → ℕ → t ) → t
new c1 d next =  alloc-data c1 ( λ c1 n → update-data c1  n d (λ c2 → next c2 n ))

step : {n : Level} {t : Set n} → List Context → (List Context → t) → t
step {n} {t} [] next0 = next0 []
step {n} {t} (p ∷ ps) next0 = code_table (Context.next p) p ( λ code np → next0 (ps ++ ( record np { next = code } ∷ [] ))) 

init-context : Context
init-context = record {
      next = C_nop
    ; fail = C_nop
    ; c_Phil-API = record { next = C_nop ; impl = init-Phil } 
    ; c_AtomicNat-API = record { next = C_nop ; fail = C_nop ; value = 0 ; impl = init-AtomicNat } 
    ; mbase = 0
    ; memory = leaf
    ; error = D_Error E_panic
    ; fail_next = C_nop
  }

init-phil-1 : (pid : ℕ ) → (left right : AtomicNat ) → List Context
init-phil-1 pid left right = c ∷ [] where
   c : Context
   c = record init-context { c_Phil-API = record { next = C_thinking ; impl = record  init-Phil { pid = pid ; left = left ; right = right }  } } 

test : List Context
test = step {!!} ( λ ps → ps ) 

test1 : List Context
test1 = step {!!}
  $ λ ps → step ps $ λ ps → ps

-- loop exexution

-- concurrnt execution

-- state db ( binary tree of processes )

-- depth first ececution

-- verify temporal logic poroerries