Compare commits
2 Commits
3c0f5d34bf
...
5a28a554a1
Author | SHA1 | Date | |
---|---|---|---|
5a28a554a1 | |||
e6c7638324 |
|
@ -2,15 +2,21 @@ module CacheSim.AccessView exposing (..)
|
||||||
import CacheSim.Cache exposing (..)
|
import CacheSim.Cache exposing (..)
|
||||||
import CacheSim.Hierarchy exposing (..)
|
import CacheSim.Hierarchy exposing (..)
|
||||||
|
|
||||||
type AccessPosition = Down Int | Up Int | Done
|
type AccessPosition = Down Int | Up Int | Preview | End
|
||||||
type alias AccessView = (List (AccessEffect Cache), AccessPosition)
|
type alias AccessView =
|
||||||
|
{ initialState : CacheHierarchy
|
||||||
|
, blockAddr : BlockAddr
|
||||||
|
, accessEffects : List (AccessEffect Cache)
|
||||||
|
, position : AccessPosition
|
||||||
|
}
|
||||||
|
|
||||||
accessPositionForward : Int -> AccessPosition -> AccessPosition
|
accessPositionForward : Int -> AccessPosition -> AccessPosition
|
||||||
accessPositionForward depth av =
|
accessPositionForward depth av =
|
||||||
case av of
|
case av of
|
||||||
Down n -> if n == depth - 1 then Up n else Down (n + 1)
|
Down n -> if n == depth - 1 then Up n else Down (n + 1)
|
||||||
Up n -> if n == 0 then Done else Up (n - 1)
|
Up n -> if n == 0 then Preview else Up (n - 1)
|
||||||
Done -> Done
|
Preview -> End
|
||||||
|
End -> End
|
||||||
|
|
||||||
accessPositionBack : Int -> AccessPosition -> AccessPosition
|
accessPositionBack : Int -> AccessPosition -> AccessPosition
|
||||||
accessPositionBack depth av =
|
accessPositionBack depth av =
|
||||||
|
@ -18,41 +24,43 @@ accessPositionBack depth av =
|
||||||
Down 0 -> Down 0
|
Down 0 -> Down 0
|
||||||
Down n -> Down (n-1)
|
Down n -> Down (n-1)
|
||||||
Up n -> if n == (depth - 1) then Down n else Up (n + 1)
|
Up n -> if n == (depth - 1) then Down n else Up (n + 1)
|
||||||
Done -> Up 0
|
Preview -> Up 0
|
||||||
|
End -> Preview
|
||||||
|
|
||||||
accessPositionDone : AccessPosition -> Bool
|
accessPositionDone : AccessPosition -> Bool
|
||||||
accessPositionDone av =
|
accessPositionDone av =
|
||||||
case av of
|
case av of
|
||||||
Done -> True
|
End -> True
|
||||||
_ -> False
|
_ -> False
|
||||||
|
|
||||||
accessViewForward : AccessView -> AccessView
|
accessViewForward : AccessView -> AccessView
|
||||||
accessViewForward (l, ap) = (l, accessPositionForward (List.length l) ap)
|
accessViewForward av = { av | position = accessPositionForward (List.length av.accessEffects) av.position }
|
||||||
|
|
||||||
accessViewBack : AccessView -> AccessView
|
accessViewBack : AccessView -> AccessView
|
||||||
accessViewBack (l, ap) = (l, accessPositionBack (List.length l) ap)
|
accessViewBack av = { av | position = accessPositionBack (List.length av.accessEffects) av.position }
|
||||||
|
|
||||||
accessViewDone : AccessView -> Bool
|
accessViewDone : AccessView -> Bool
|
||||||
accessViewDone (_, ap) = accessPositionDone ap
|
accessViewDone av = accessPositionDone av.position
|
||||||
|
|
||||||
finalCacheHierarchy : CacheHierarchy -> AccessView -> CacheHierarchy
|
finalCacheHierarchy : AccessView -> CacheHierarchy
|
||||||
finalCacheHierarchy ch (l, ap) =
|
finalCacheHierarchy av =
|
||||||
List.map .output l ++ List.drop (List.length l) ch
|
List.map .output av.accessEffects ++ List.drop (List.length av.accessEffects) av.initialState
|
||||||
|
|
||||||
|
effectiveCacheHierarchy : AccessView -> CacheHierarchy
|
||||||
effectiveCacheHierarchy : CacheHierarchy -> AccessView -> CacheHierarchy
|
effectiveCacheHierarchy av =
|
||||||
effectiveCacheHierarchy c (l, ap) =
|
|
||||||
let
|
let
|
||||||
finalContents = List.map .output l
|
finalContents = List.map .output av.accessEffects
|
||||||
unaccessed = List.drop (List.length l) c
|
unaccessed = List.drop (List.length av.accessEffects) av.initialState
|
||||||
notDone =
|
notDone =
|
||||||
case ap of
|
case av.position of
|
||||||
Done -> []
|
Preview -> []
|
||||||
Down _ -> List.take (List.length l) c
|
End -> []
|
||||||
Up n -> List.take n c
|
Down _ -> List.take (List.length av.accessEffects) av.initialState
|
||||||
|
Up n -> List.take n av.initialState
|
||||||
done =
|
done =
|
||||||
case ap of
|
case av.position of
|
||||||
Done -> finalContents
|
Preview -> finalContents
|
||||||
|
End -> finalContents
|
||||||
Down _ -> []
|
Down _ -> []
|
||||||
Up n -> List.drop n finalContents
|
Up n -> List.drop n finalContents
|
||||||
in
|
in
|
||||||
|
|
|
@ -45,8 +45,13 @@ updateAccess li m =
|
||||||
case xs of
|
case xs of
|
||||||
[] -> Ok []
|
[] -> Ok []
|
||||||
(i::t) ->
|
(i::t) ->
|
||||||
case accessCacheHierarchy i c of
|
case accessCacheHierarchy (i // 4) c of
|
||||||
Ok av -> Result.map ((::) (av, Down 0)) <| process (finalCacheHierarchy c (av, Done)) t
|
Ok av ->
|
||||||
|
let
|
||||||
|
newView = { blockAddr = i, accessEffects = av, position = Down 0, initialState = c }
|
||||||
|
in
|
||||||
|
Result.map ((::) newView)
|
||||||
|
<| process (finalCacheHierarchy newView) t
|
||||||
Err s -> Err s
|
Err s -> Err s
|
||||||
|
|
||||||
accessResult = Maybe.andThen (\h -> Result.toMaybe <| process h li) m.hierarchy
|
accessResult = Maybe.andThen (\h -> Result.toMaybe <| process h li) m.hierarchy
|
||||||
|
@ -59,12 +64,15 @@ updateAccessViewForward : Model -> (Model, Cmd Msg)
|
||||||
updateAccessViewForward m =
|
updateAccessViewForward m =
|
||||||
let
|
let
|
||||||
afterStep = Maybe.map (intMapUpdate 0 accessViewForward) m.accessView
|
afterStep = Maybe.map (intMapUpdate 0 accessViewForward) m.accessView
|
||||||
(newHierarchy, newAccessView) =
|
newAccessView =
|
||||||
case afterStep of
|
case afterStep of
|
||||||
Just ((avs, Done)::[]) -> (Maybe.map (\h -> finalCacheHierarchy h (avs, Done)) m.hierarchy, Nothing)
|
Just (result::xs) ->
|
||||||
Just ((avs, Done)::xs) -> (Maybe.map (\h -> finalCacheHierarchy h (avs, Done)) m.hierarchy, Just xs)
|
case (result.position, xs) of
|
||||||
as_ -> (m.hierarchy, as_)
|
(End, []) -> Nothing
|
||||||
newModel = { m | accessView = newAccessView, hierarchy = newHierarchy }
|
(End, nxs) -> Just nxs
|
||||||
|
_ -> Just (result::xs)
|
||||||
|
as_ -> as_
|
||||||
|
newModel = { m | accessView = newAccessView }
|
||||||
cmd = Cmd.none
|
cmd = Cmd.none
|
||||||
in
|
in
|
||||||
(newModel, cmd)
|
(newModel, cmd)
|
||||||
|
|
|
@ -10,34 +10,31 @@ import Html.Attributes exposing (type_, class, value, for, classList, disabled,
|
||||||
import Html.Events exposing (onInput, onClick)
|
import Html.Events exposing (onInput, onClick)
|
||||||
|
|
||||||
-- Button components, powered by Bootstrap
|
-- Button components, powered by Bootstrap
|
||||||
basicButton : List (Attribute Msg) -> String -> Html Msg
|
button : List (Attribute Msg) -> String -> Html Msg
|
||||||
basicButton attrs s = input ([ type_ "button", value s, class "btn", class "btn-info" ] ++ attrs) []
|
button attrs s = input ([ type_ "button", value s, class "btn"] ++ attrs) []
|
||||||
|
|
||||||
disabledButton : String -> Html Msg
|
basicButton : Msg -> String -> Html Msg
|
||||||
disabledButton = basicButton [ disabled True ]
|
basicButton msg s = button [ onClick msg ] s
|
||||||
|
|
||||||
advancedButton : List (Attribute Msg) -> String -> Msg -> Html Msg
|
disabledButton : List (Attribute Msg) -> String -> Html Msg
|
||||||
advancedButton attrs s m = basicButton (attrs ++ [ onClick m ]) s
|
disabledButton attrs = button (attrs ++ [ disabled True ])
|
||||||
|
|
||||||
button : String -> Msg -> Html Msg
|
|
||||||
button s m = basicButton [ onClick m ] s
|
|
||||||
|
|
||||||
dangerButton : String -> Msg -> Html Msg
|
dangerButton : String -> Msg -> Html Msg
|
||||||
dangerButton = advancedButton [ class "btn-danger" ]
|
dangerButton s m = button [ onClick m, class "btn-danger" ] s
|
||||||
|
|
||||||
primaryButton : String -> Msg -> Html Msg
|
primaryButton : String -> Msg -> Html Msg
|
||||||
primaryButton = advancedButton [ class "btn-primary" ]
|
primaryButton s m = button [ onClick m, class "btn-primary" ] s
|
||||||
|
|
||||||
secondaryButton : String -> Msg -> Html Msg
|
secondaryButton : String -> Msg -> Html Msg
|
||||||
secondaryButton = advancedButton [ class "btn-secondary" ]
|
secondaryButton s m = button [ onClick m, class "btn-secondary" ] s
|
||||||
|
|
||||||
maybeButton : Maybe a -> String -> (a -> Msg) -> Html Msg
|
maybeButton : Maybe a -> List (Attribute Msg) -> String -> (a -> Msg) -> Html Msg
|
||||||
maybeButton m s f =
|
maybeButton m attrs s f =
|
||||||
case m of
|
case m of
|
||||||
Just v -> button s (f v)
|
Just v -> button (attrs ++ [ onClick (f v) ]) s
|
||||||
_ -> disabledButton s
|
_ -> disabledButton attrs s
|
||||||
|
|
||||||
resultButton : Result e a -> String -> (a -> Msg) -> Html Msg
|
resultButton : Result e a -> List (Attribute Msg) -> String -> (a -> Msg) -> Html Msg
|
||||||
resultButton = maybeButton << Result.toMaybe
|
resultButton = maybeButton << Result.toMaybe
|
||||||
|
|
||||||
-- Button wrapper (button group)
|
-- Button wrapper (button group)
|
||||||
|
@ -105,8 +102,8 @@ viewRawCacheModelHierarchy rcmh =
|
||||||
Ok _ -> viewError True ""
|
Ok _ -> viewError True ""
|
||||||
Err e -> viewError False e
|
Err e -> viewError False e
|
||||||
|
|
||||||
newButton = button "Add level" CreateRawModel
|
newButton = primaryButton "Add level" CreateRawModel
|
||||||
useButton = resultButton checkedResult "Use hierarchy" (UseHierarchy << Just)
|
useButton = resultButton checkedResult [ class "btn-primary" ] "Start simulation" (UseHierarchy << Just)
|
||||||
in
|
in
|
||||||
div []
|
div []
|
||||||
[ h2 [] [ text "Cache hierarchy" ]
|
[ h2 [] [ text "Cache hierarchy" ]
|
||||||
|
@ -163,23 +160,21 @@ viewCacheHierarchy ch =
|
||||||
|
|
||||||
viewAccessView : Model -> AccessView -> Html Msg
|
viewAccessView : Model -> AccessView -> Html Msg
|
||||||
viewAccessView m av =
|
viewAccessView m av =
|
||||||
let
|
div []
|
||||||
currentCache = Maybe.withDefault [] m.hierarchy
|
[ h2 [] [ text "Access Simulation" ]
|
||||||
in
|
, p [] [ text ("Simulating access of address " ++ String.fromInt av.blockAddr) ]
|
||||||
div []
|
, buttonWrapper
|
||||||
[ h2 [] [ text "Access Simulation" ]
|
[ primaryButton "Back" AccessViewBack
|
||||||
, buttonWrapper
|
, primaryButton "Forward" AccessViewForward
|
||||||
[ primaryButton "Back" AccessViewBack
|
]
|
||||||
, primaryButton "Forward" AccessViewForward
|
, h3 [] [ text "Access event log" ]
|
||||||
]
|
, viewAccessLog av
|
||||||
, h3 [] [ text "Access event log" ]
|
, h3 [] [ text "Current cache state" ]
|
||||||
, viewAccessLog av
|
, viewCacheHierarchy <| effectiveCacheHierarchy av
|
||||||
, h3 [] [ text "Current cache state" ]
|
]
|
||||||
, viewCacheHierarchy <| effectiveCacheHierarchy currentCache av
|
|
||||||
]
|
|
||||||
|
|
||||||
viewAccessLog : AccessView -> Html Msg
|
viewAccessLog : AccessView -> Html Msg
|
||||||
viewAccessLog (aes, ap) =
|
viewAccessLog av =
|
||||||
let
|
let
|
||||||
resultSpan r =
|
resultSpan r =
|
||||||
span [ classList [ ("badge", True), ("badge-success", r == Hit), ("badge-danger", r == Miss) ] ]
|
span [ classList [ ("badge", True), ("badge-success", r == Hit), ("badge-danger", r == Miss) ] ]
|
||||||
|
@ -189,14 +184,17 @@ viewAccessLog (aes, ap) =
|
||||||
, resultSpan ae.result
|
, resultSpan ae.result
|
||||||
]
|
]
|
||||||
upEvent n ae = div [ class "event" ]
|
upEvent n ae = div [ class "event" ]
|
||||||
[ text <| "Updated L" ++ String.fromInt (List.length aes - n)
|
[ text <| "Updated L" ++ String.fromInt (List.length av.accessEffects - n)
|
||||||
]
|
]
|
||||||
events =
|
events =
|
||||||
case ap of
|
case av.position of
|
||||||
Done -> []
|
Preview -> List.indexedMap downEvent av.accessEffects ++
|
||||||
Down n -> List.indexedMap downEvent <| List.take (n + 1) aes
|
(List.indexedMap upEvent av.accessEffects) ++
|
||||||
Up n -> List.indexedMap downEvent aes ++
|
[ div [ class "event" ] [ text "Access complete. Viewing final cache state." ] ]
|
||||||
(List.indexedMap upEvent <| List.drop n aes)
|
End -> []
|
||||||
|
Down n -> List.indexedMap downEvent <| List.take (n + 1) av.accessEffects
|
||||||
|
Up n -> List.indexedMap downEvent av.accessEffects ++
|
||||||
|
(List.indexedMap upEvent <| List.drop n av.accessEffects)
|
||||||
in
|
in
|
||||||
div [] events
|
div [] events
|
||||||
|
|
||||||
|
@ -204,27 +202,26 @@ viewAccessInput : Model -> Html Msg
|
||||||
viewAccessInput m =
|
viewAccessInput m =
|
||||||
let
|
let
|
||||||
parser =
|
parser =
|
||||||
Parser.map (List.map (\i -> i // 4)) <|
|
Parser.sequence
|
||||||
Parser.sequence
|
{ start = ""
|
||||||
{ start = ""
|
, end = ""
|
||||||
, end = ""
|
, separator = ","
|
||||||
, separator = ","
|
, spaces = Parser.spaces
|
||||||
, spaces = Parser.spaces
|
, item = Parser.int
|
||||||
, item = Parser.int
|
, trailing = Parser.Optional
|
||||||
, trailing = Parser.Optional
|
}
|
||||||
}
|
|
||||||
parseErrorToString _ = "Unable to parse input. Please enter a sequence of numbers separated by commas."
|
parseErrorToString _ = "Unable to parse input. Please enter a sequence of numbers separated by commas."
|
||||||
parseResult = Parser.run (parser |. Parser.end) m.accessInput
|
parseResult = Parser.run (parser |. Parser.end) m.accessInput
|
||||||
checkedResult =
|
checkedResult =
|
||||||
case parseResult of
|
case parseResult of
|
||||||
Ok is -> if is == [] then Err "Please enter at least one number." else Ok is
|
Ok is -> if is == [] then Err "Please enter at least one number." else Ok is
|
||||||
Err e -> Err <| parseErrorToString e
|
Err e -> Err <| parseErrorToString e
|
||||||
accessButton = resultButton checkedResult "Access address" Access
|
accessButton = resultButton checkedResult [ class "btn-primary" ] "Access address" Access
|
||||||
errorHtml =
|
errorHtml =
|
||||||
case checkedResult of
|
case checkedResult of
|
||||||
Ok _ -> viewError True ""
|
Ok _ -> viewError True ""
|
||||||
Err e -> viewError False e
|
Err e -> viewError False e
|
||||||
editHierarchyButton = button "Edit hierarchy" (UseHierarchy Nothing)
|
editHierarchyButton = secondaryButton "Edit hierarchy" (UseHierarchy Nothing)
|
||||||
in
|
in
|
||||||
div []
|
div []
|
||||||
[ h2 [] [ text "Run access simulation" ]
|
[ h2 [] [ text "Run access simulation" ]
|
||||||
|
@ -244,7 +241,7 @@ viewDescription =
|
||||||
, p []
|
, p []
|
||||||
[ text <| "To use the simulator, first create a fitting cache configuration by using the \"Add level\" button,"
|
[ text <| "To use the simulator, first create a fitting cache configuration by using the \"Add level\" button,"
|
||||||
++ " as well as the settings provided by each individual cache level. When the cache is correctly specified, and"
|
++ " as well as the settings provided by each individual cache level. When the cache is correctly specified, and"
|
||||||
++ " no warnings appear, click \"Use hierarchy\" to load the specified hierarchy and begin simulating. To simulate,"
|
++ " no warnings appear, click \"Start simulation\" to load the specified hierarchy and begin simulating. To simulate,"
|
||||||
++ " type a block address into the \"Access address\" field, and click \"Access\". This will bring forward the simulation"
|
++ " type a block address into the \"Access address\" field, and click \"Access\". This will bring forward the simulation"
|
||||||
++ " view, which will allow you to step through the steps of accessing a cache."
|
++ " view, which will allow you to step through the steps of accessing a cache."
|
||||||
]
|
]
|
||||||
|
|
Loading…
Reference in New Issue
Block a user