2019-05-28 19:26:02 -07:00
|
|
|
module CacheSim.View exposing (..)
|
|
|
|
import CacheSim.Raw exposing (..)
|
|
|
|
import CacheSim.Model exposing (..)
|
2019-05-28 21:01:35 -07:00
|
|
|
import CacheSim.Cache exposing (..)
|
2019-05-28 21:58:15 -07:00
|
|
|
import CacheSim.AccessView exposing (..)
|
2019-05-28 21:01:35 -07:00
|
|
|
import CacheSim.Hierarchy exposing (..)
|
|
|
|
import Html exposing (Html, input, text, div, label, span, h2, h3, table, tr, td)
|
|
|
|
import Html.Attributes exposing (type_, class, value, for, classList, disabled, colspan)
|
2019-05-28 19:49:48 -07:00
|
|
|
import Html.Events exposing (onInput, onClick)
|
|
|
|
|
2019-05-28 20:08:04 -07:00
|
|
|
optionalButton : Bool -> String -> Msg -> Html Msg
|
|
|
|
optionalButton e s m =
|
|
|
|
let
|
|
|
|
events = if e then [ onClick m ] else [ disabled (not e) ]
|
|
|
|
in
|
|
|
|
input ([ type_ "button", value s ] ++ events) []
|
|
|
|
|
2019-05-28 19:49:48 -07:00
|
|
|
button : String -> Msg -> Html Msg
|
|
|
|
button s m = input [ type_ "button", onClick m, value s] []
|
|
|
|
|
|
|
|
buttonWrapper : List (Html Msg) -> Html Msg
|
|
|
|
buttonWrapper = div [ class "button-wrapper" ]
|
2019-05-28 19:26:02 -07:00
|
|
|
|
|
|
|
labeledInput : String -> String -> (String -> Msg) -> Html Msg
|
|
|
|
labeledInput s val f =
|
|
|
|
div [ class "input-group" ]
|
|
|
|
[ span [] [ text s ]
|
|
|
|
, input [ value val, type_ "text", onInput f ] []
|
|
|
|
]
|
|
|
|
|
|
|
|
viewRawCacheModel : Int -> RawCacheModel -> Html Msg
|
|
|
|
viewRawCacheModel level rcm =
|
|
|
|
let
|
|
|
|
updateBlockSize s cm = { cm | blockSize = s}
|
|
|
|
updateSetCount s cm = { cm | setCount = s}
|
|
|
|
updateSetSize s cm = { cm | setSize = s}
|
2019-05-28 19:37:22 -07:00
|
|
|
wrapUpdate f s = ChangeRawModel level (f s)
|
2019-05-28 19:26:02 -07:00
|
|
|
|
2019-05-28 19:49:48 -07:00
|
|
|
deleteButton = button "Delete" (DeleteRawModel level)
|
|
|
|
|
2019-05-28 19:26:02 -07:00
|
|
|
params = div [ class "cache-model-params" ]
|
|
|
|
[ labeledInput "Block size" rcm.blockSize (wrapUpdate updateBlockSize)
|
|
|
|
, labeledInput "Set count" rcm.setCount (wrapUpdate updateSetCount)
|
|
|
|
, labeledInput "Set size" rcm.setSize (wrapUpdate updateSetSize)
|
|
|
|
]
|
|
|
|
in
|
|
|
|
div [ class "cache-model" ]
|
2019-05-28 19:49:48 -07:00
|
|
|
[ h3 [] [ text <| "L" ++ String.fromInt (level + 1) ++ " Cache" ]
|
|
|
|
, buttonWrapper [ deleteButton ]
|
2019-05-28 19:26:02 -07:00
|
|
|
, params
|
|
|
|
]
|
|
|
|
|
|
|
|
viewRawCacheModelHierarchy : RawCacheModelHierarchy -> Html Msg
|
|
|
|
viewRawCacheModelHierarchy rcmh =
|
2019-05-28 19:49:48 -07:00
|
|
|
let
|
|
|
|
models = div [ class "cache-model-levels" ]
|
2019-05-28 21:01:35 -07:00
|
|
|
<| List.indexedMap viewRawCacheModel rcmh
|
2019-05-28 20:08:04 -07:00
|
|
|
translationResult = Result.andThen validateCacheModelHierarchy
|
|
|
|
<| translateRawCacheModelHierarchy rcmh
|
|
|
|
isValid =
|
|
|
|
case translationResult of
|
|
|
|
Ok _ -> True
|
|
|
|
Err _ -> False
|
|
|
|
errorHtml =
|
|
|
|
case translationResult of
|
|
|
|
Ok _ -> viewError True ""
|
|
|
|
Err e -> viewError False e
|
2019-05-28 19:49:48 -07:00
|
|
|
|
|
|
|
newButton = button "Add level" CreateRawModel
|
2019-05-28 20:22:05 -07:00
|
|
|
useButton = case translationResult of
|
|
|
|
Ok cmh -> optionalButton True "Use hierarchy" (UseHierarchy <| Just cmh)
|
|
|
|
Err _ -> optionalButton False "Use hierarchy" (UseHierarchy Nothing)
|
2019-05-28 19:49:48 -07:00
|
|
|
in
|
|
|
|
div [ class "cache-model-hierarchy" ]
|
|
|
|
[ h2 [] [ text "Cache hierarchy" ]
|
2019-05-28 20:08:04 -07:00
|
|
|
, errorHtml
|
|
|
|
, buttonWrapper [ newButton, useButton ]
|
2019-05-28 19:49:48 -07:00
|
|
|
, models
|
|
|
|
]
|
2019-05-28 20:08:04 -07:00
|
|
|
|
2019-05-28 21:01:35 -07:00
|
|
|
viewCache : Int -> Cache -> Html Msg
|
|
|
|
viewCache level (cm, cs) =
|
|
|
|
let
|
|
|
|
slotLabels =
|
|
|
|
List.indexedMap (\i _ -> td [] [ text <| String.fromInt i ])
|
|
|
|
<| List.repeat cm.setSize ()
|
|
|
|
slotLabel = td [ colspan cm.setSize ] [ text "Slot" ]
|
|
|
|
allSlotLabels = List.concat <| List.repeat cm.setCount slotLabels
|
|
|
|
allSlotsLabel = List.repeat cm.setCount slotLabel
|
|
|
|
|
|
|
|
setLabels =
|
|
|
|
List.indexedMap (\i _ -> td [ colspan cm.setSize ] [ text <| String.fromInt i ])
|
|
|
|
<| List.repeat cm.setCount ()
|
|
|
|
setLabel = [ td [ colspan <| cm.setSize * cm.setCount ] [ text "Set" ] ]
|
2019-05-28 21:07:41 -07:00
|
|
|
setRow set =
|
|
|
|
let
|
|
|
|
slotHtml s =
|
|
|
|
case s of
|
|
|
|
Empty -> td [] [ text "" ]
|
|
|
|
Used l a -> td [] [ text <| String.fromInt a ]
|
|
|
|
in
|
|
|
|
List.map slotHtml set
|
|
|
|
cacheRow = List.concat <| List.map setRow cs
|
2019-05-28 21:01:35 -07:00
|
|
|
cacheTable =
|
|
|
|
table []
|
|
|
|
[ tr [ classList [("hidden", cm.setCount == 1)] ] setLabel
|
|
|
|
, tr [ classList [("hidden", cm.setCount == 1)] ] setLabels
|
|
|
|
, tr [ classList [("hidden", cm.setSize == 1)] ] allSlotsLabel
|
|
|
|
, tr [ classList [("hidden", cm.setSize == 1)] ] allSlotLabels
|
2019-05-28 21:07:41 -07:00
|
|
|
, tr [] cacheRow
|
2019-05-28 21:01:35 -07:00
|
|
|
]
|
2019-05-28 21:07:41 -07:00
|
|
|
|
2019-05-28 21:01:35 -07:00
|
|
|
in
|
|
|
|
div [ class "cache" ]
|
|
|
|
[ h3 [] [ text <| "L" ++ String.fromInt level ++ " Cache" ]
|
|
|
|
, cacheTable
|
|
|
|
]
|
|
|
|
|
|
|
|
viewCacheHierarchy : CacheHierarchy -> Html Msg
|
|
|
|
viewCacheHierarchy ch =
|
|
|
|
let
|
|
|
|
levels = div [ class "cache-levels" ]
|
|
|
|
<| List.indexedMap viewCache ch
|
|
|
|
in
|
|
|
|
div [ class "cache-hierarchy" ] <|
|
|
|
|
[ h2 [] [ text <| "Cache hierarchy" ]
|
|
|
|
, levels
|
|
|
|
]
|
|
|
|
|
2019-05-28 21:58:15 -07:00
|
|
|
viewAccessView : Model -> AccessView -> Html Msg
|
|
|
|
viewAccessView m av =
|
|
|
|
let
|
|
|
|
currentCache = Maybe.withDefault [] m.hierarchy
|
|
|
|
in
|
|
|
|
div [ class "access-view" ]
|
2019-05-28 22:51:02 -07:00
|
|
|
[ h2 [] [ text "Access Simulation" ]
|
2019-05-28 22:39:34 -07:00
|
|
|
, buttonWrapper
|
2019-05-28 21:58:15 -07:00
|
|
|
[ button "Forward" AccessViewForward
|
|
|
|
, button "Back" AccessViewBack
|
|
|
|
]
|
2019-05-28 22:51:02 -07:00
|
|
|
, viewAccessLog av
|
|
|
|
, viewCacheHierarchy <| effectiveCacheHierarchy currentCache av
|
2019-05-28 21:58:15 -07:00
|
|
|
]
|
|
|
|
|
2019-05-28 22:51:02 -07:00
|
|
|
viewAccessLog : AccessView -> Html Msg
|
|
|
|
viewAccessLog (aes, ap) =
|
|
|
|
let
|
|
|
|
resultSpan r =
|
|
|
|
case r of
|
|
|
|
Hit -> span [ class "success" ] [ text "HIT" ]
|
|
|
|
Miss -> span [ class "failure" ] [ text "MISS" ]
|
|
|
|
downEvent n ae = div [ class "event" ]
|
|
|
|
[ text <| "L" ++ String.fromInt (n + 1)
|
|
|
|
, resultSpan ae.result
|
|
|
|
]
|
|
|
|
upEvent n ae = div [ class "event" ]
|
|
|
|
[ text <| "Updated L" ++ String.fromInt (n + 1)
|
|
|
|
]
|
|
|
|
events =
|
|
|
|
case ap of
|
|
|
|
Done -> []
|
|
|
|
Down n -> List.indexedMap downEvent <| List.take (n + 1) aes
|
|
|
|
Up n -> List.indexedMap downEvent aes ++
|
|
|
|
(List.indexedMap upEvent <| List.drop n aes)
|
|
|
|
in
|
|
|
|
div [ class "access-log" ]
|
|
|
|
[ h3 [] [ text "Simulation events" ]
|
|
|
|
, div [ class "access-log-events" ] events
|
|
|
|
]
|
|
|
|
|
2019-05-28 22:12:36 -07:00
|
|
|
viewAccessInput : Model -> Html Msg
|
|
|
|
viewAccessInput m =
|
|
|
|
let
|
|
|
|
accessButton =
|
|
|
|
case String.toInt m.accessInput of
|
|
|
|
Just i -> optionalButton True "Access address" (Access i)
|
|
|
|
Nothing -> optionalButton False "Access address" (Access -1)
|
|
|
|
in
|
2019-05-28 22:39:34 -07:00
|
|
|
div [ class "access-input" ]
|
2019-05-28 22:12:36 -07:00
|
|
|
[ labeledInput "Access address" m.accessInput ChangeAccessInput
|
|
|
|
, accessButton
|
|
|
|
]
|
2019-05-28 21:01:35 -07:00
|
|
|
|
2019-05-28 20:08:04 -07:00
|
|
|
viewError : Bool -> String -> Html Msg
|
|
|
|
viewError hide e = span [ classList [ ("hidden", hide) ] ] [ text e ]
|
|
|
|
|
|
|
|
viewBase : Model -> Html Msg
|
|
|
|
viewBase m =
|
2019-05-28 21:01:35 -07:00
|
|
|
let
|
|
|
|
rawView = viewRawCacheModelHierarchy m.rawHierarchy
|
|
|
|
cacheView = Maybe.withDefault [] <| Maybe.map (List.singleton << viewCacheHierarchy) <| m.hierarchy
|
2019-05-28 21:58:15 -07:00
|
|
|
accessView = Maybe.withDefault [] <| Maybe.map (List.singleton << viewAccessView m) <| m.accessView
|
2019-05-28 22:39:34 -07:00
|
|
|
accessInputView = [ viewAccessInput m ]
|
2019-05-28 21:01:35 -07:00
|
|
|
in
|
2019-05-28 22:39:34 -07:00
|
|
|
div [] <| [ rawView ] ++ cacheView ++ accessView ++ accessInputView
|