module ChipModel where
import Monad(liftM)
import State
import qualified FunFM as FM
import Algorithms
import Memories
import MemMonads
import Protected
import Nat
import MemoryState
type Channel = Nat
type Packet = (Channel,Data)
type Regs = FM.FM RegFile
type ChipState = (Memory,Regs)
type Algs = Channel -> Alg
chip :: Algs -> ChipState -> [Packet] -> [Packet]
chip algs state ps = fst (runS (manyPackets algs ps) state)
{-P: {-#cert:Separation#-} {-#cert:ISaySeparation#-}
assert Separation =
All algs . All ch . All state . All ps .
{pick ch (chip algs state ps)} === {chip algs state (pick ch ps)}
pick :: Channel -> [Packet] -> [Packet]
pick ch = filter (sameChannel ch)
sameChannel :: Channel -> Packet -> Bool
sameChannel ch p = fst p == ch
-}
manyPackets :: Algs -> [Packet] -> StateM ChipState [Packet]
manyPackets algs = mapM (onePacket algs)
onePacket :: Algs -> Packet -> StateM ChipState Packet
onePacket algs (chan,ws) =
do regfile <- liftM (\regs->FM.lookup regs chan) (inSnd load)
(ws',regfile') <- inFst (doPacket (algs chan) ws regfile)
finishPacket chan ws' regfile'
doPacket :: Alg -> Data -> RegFile -> StateM Memory (Data,RegFile)
doPacket alg ws regf =
do r <- mallocM (len ws)
update (storeList (base r) ws)
let code = alg (base r) regf
doPacket2 code r regf
doPacket2 :: Code -> Range -> RegFile -> StateM Memory (Data,RegFile)
doPacket2 code r regf = saferun >>= doPacket3 r
where
saferun = runProtected regf (inRange r) run
run = runAlg code
doPacket3 :: Range -> RegFile -> StateM Memory (Data,RegFile)
doPacket3 r regf' =
do ws <- liftM (loadRange r) load
freeM r
return (ws,regf')
finishPacket :: Channel -> Data -> RegFile -> StateM ChipState Packet
finishPacket ch ws regf =
do inSnd (update (FM.update ch regf))
return (ch,ws)
initRegs :: Regs
initRegs = FM.empty initRegFile
initChip :: ChipState
initChip = (initMem,initRegs)
{-P:
property StateIndependent =
{| m | All s1 . All s2 . {fst (runS m s1)} === {fst (runS m s2)} |}
property GoodAlg =
{| alg | All ws . All regf . StateIndependent {doPacket alg ws regf} |}
regfile :: Channel -> ChipState -> RegFile
regfile ch state = FM.lookup (snd state) ch
property Invariant =
{| state1, state2, ch | {regfile ch state1} === {regfile ch state2} |}
assert CondSeparation = {-#cert:CondSeparation#-} {-#cert:ISayCondSeparation#-}
All algs . All ch . All state1 . All state2 . All ps .
GoodAlg {algs ch} ==>
Invariant state1 state2 ch ==>
{pick ch (chip algs state1 ps)} === {chip algs state2 (pick ch ps)}
{-#cert:AllGoodAlg#-} {-#cert:ISayAllGoodAlg#-}
assert AllGoodAlg = All alg . GoodAlg alg
{-#cert:SameState#-} {-#cert:ISaySameState#-}
assert SameState = All state . All ch . Invariant state state ch
-}