Implement cache access operations.
This commit is contained in:
parent
72e134ee79
commit
8de1d82d88
130
src/CacheSim/Cache.elm
Normal file
130
src/CacheSim/Cache.elm
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
module CacheSim.Cache exposing (..)
|
||||||
|
import CacheSim.IntMap exposing (..)
|
||||||
|
|
||||||
|
-- Types that help document code
|
||||||
|
type alias Lru = Int
|
||||||
|
type alias WordAddr = Int
|
||||||
|
type alias BlockAddr = Int
|
||||||
|
type alias BlockSize = Int
|
||||||
|
type alias SetCount = Int
|
||||||
|
type alias SetSize = Int
|
||||||
|
|
||||||
|
-- Cache description, without state
|
||||||
|
type alias CacheModel =
|
||||||
|
{ blockSize : BlockSize
|
||||||
|
, setCount : SetCount
|
||||||
|
, setSize : SetSize
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Types for cache state
|
||||||
|
type CacheSlot = Empty | Used Lru BlockAddr
|
||||||
|
type alias CacheSet = IntMap CacheSlot
|
||||||
|
type alias CacheState = IntMap CacheSet
|
||||||
|
|
||||||
|
type alias Cache = (CacheModel, CacheState)
|
||||||
|
|
||||||
|
type AccessResult = Hit | Miss
|
||||||
|
type alias AccessEffect a =
|
||||||
|
{ result : AccessResult
|
||||||
|
, output : a
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fullyAssociativeCache : BlockSize -> SetSize -> CacheModel
|
||||||
|
fullyAssociativeCache bs ss =
|
||||||
|
{ blockSize = bs
|
||||||
|
, setCount = 1
|
||||||
|
, setSize = ss
|
||||||
|
}
|
||||||
|
|
||||||
|
directMappedCache : BlockSize -> SetCount -> CacheModel
|
||||||
|
directMappedCache bs sc =
|
||||||
|
{ blockSize = bs
|
||||||
|
, setCount = sc
|
||||||
|
, setSize = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
findExistingSlot : BlockAddr -> CacheSet -> Maybe Int
|
||||||
|
findExistingSlot ba =
|
||||||
|
let
|
||||||
|
isExisting cs =
|
||||||
|
case cs of
|
||||||
|
Empty -> False
|
||||||
|
Used l aba -> ba == aba
|
||||||
|
in
|
||||||
|
intMapFind isExisting
|
||||||
|
|
||||||
|
findEmptySlot : CacheSet -> Maybe Int
|
||||||
|
findEmptySlot =
|
||||||
|
let
|
||||||
|
isEmpty cs =
|
||||||
|
case cs of
|
||||||
|
Empty -> True
|
||||||
|
_ -> False
|
||||||
|
in
|
||||||
|
intMapFind isEmpty
|
||||||
|
|
||||||
|
findLruSlot : CacheSet -> Maybe Int
|
||||||
|
findLruSlot cs =
|
||||||
|
let
|
||||||
|
minLru = List.minimum <| List.map cacheSlotLru cs
|
||||||
|
isMin s = Just (cacheSlotLru s) == minLru
|
||||||
|
in
|
||||||
|
intMapFind isMin cs
|
||||||
|
|
||||||
|
cacheSlotLru : CacheSlot -> Lru
|
||||||
|
cacheSlotLru c =
|
||||||
|
case c of
|
||||||
|
Empty -> -1
|
||||||
|
Used l _ -> l
|
||||||
|
|
||||||
|
cacheSlotSetLru : Int -> CacheSlot -> CacheSlot
|
||||||
|
cacheSlotSetLru i c =
|
||||||
|
case c of
|
||||||
|
Empty -> Empty
|
||||||
|
Used _ v -> Used i v
|
||||||
|
|
||||||
|
cacheSlotBumpLru : CacheSlot -> CacheSlot
|
||||||
|
cacheSlotBumpLru c =
|
||||||
|
case c of
|
||||||
|
Empty -> Empty
|
||||||
|
Used l v -> Used (l+1) v
|
||||||
|
|
||||||
|
cacheSetBumpLru : CacheSet -> CacheSet
|
||||||
|
cacheSetBumpLru = List.map cacheSlotBumpLru
|
||||||
|
|
||||||
|
accessCacheSet : CacheModel -> BlockAddr -> CacheSet -> Result String (AccessEffect CacheSet)
|
||||||
|
accessCacheSet cm ba cs =
|
||||||
|
let
|
||||||
|
existingSlotEffect =
|
||||||
|
case findExistingSlot ba cs of
|
||||||
|
Just i -> Ok { result = Hit, output = intMapUpdate i (cacheSlotSetLru 0) <| cacheSetBumpLru cs }
|
||||||
|
Nothing -> emptySlotEffect
|
||||||
|
emptySlotEffect =
|
||||||
|
case findEmptySlot cs of
|
||||||
|
Just i -> Ok { result = Miss, output = intMapPut i (Used 0 ba) <| cacheSetBumpLru cs }
|
||||||
|
Nothing -> lruSlotEffect
|
||||||
|
lruSlotEffect =
|
||||||
|
case findLruSlot cs of
|
||||||
|
Just i -> Ok { result = Miss, output = intMapPut i (Used 0 ba) <| cacheSetBumpLru cs }
|
||||||
|
Nothing -> Err "Unable to find a single spot in the cache set. Is the size nonzero?"
|
||||||
|
in
|
||||||
|
existingSlotEffect
|
||||||
|
|
||||||
|
accessCache : WordAddr -> Cache -> Result String (AccessEffect Cache)
|
||||||
|
accessCache wa c =
|
||||||
|
let
|
||||||
|
(cm, cs) = c
|
||||||
|
blockAddr = wa // cm.blockSize
|
||||||
|
setAddr = modBy cm.setCount blockAddr
|
||||||
|
set = intMapGet setAddr cs
|
||||||
|
setAccess = Maybe.map (accessCacheSet cm blockAddr) set
|
||||||
|
transformAccess { result, output } =
|
||||||
|
{ result = result
|
||||||
|
, output = (cm, intMapPut setAddr output cs)
|
||||||
|
}
|
||||||
|
in
|
||||||
|
case setAccess of
|
||||||
|
Just (Ok ar) -> Ok <| transformAccess ar
|
||||||
|
Just (Err e) -> Err <| "Error accessing cache set: " ++ e
|
||||||
|
Nothing -> Err "Unable to find correct set in cache."
|
Loading…
Reference in New Issue
Block a user