Allow editing commands
This commit is contained in:
299
src/Main.elm
299
src/Main.elm
@ -6,11 +6,13 @@ port module Main exposing (..)
|
||||
import Browser
|
||||
import Html exposing (Html, button, div, h1, p, text)
|
||||
import Html.Attributes as HAttr exposing (class, classList, value)
|
||||
import Html.Events exposing (onClick)
|
||||
import Html.Events as HEvent exposing (onClick, onInput)
|
||||
import Html.Lazy exposing (lazy)
|
||||
import Tuple
|
||||
import Array exposing (get)
|
||||
import Html exposing (address)
|
||||
import Json.Decode as JD
|
||||
import Html.Events exposing (targetValue)
|
||||
|
||||
|
||||
|
||||
@ -40,7 +42,7 @@ type alias PC =
|
||||
|
||||
type alias Model =
|
||||
{ pc : PC
|
||||
, uCode : List (Maybe UAction)
|
||||
, uCode : List UAction
|
||||
, autoscroll : Bool
|
||||
}
|
||||
|
||||
@ -59,6 +61,7 @@ type UAction
|
||||
| ActRam2DataBus
|
||||
| ActResetUCounter
|
||||
| ActProgrammCounter2AddressBus
|
||||
| ActNothing
|
||||
|
||||
|
||||
uCodeDescriptions : List ( UAction, String )
|
||||
@ -76,6 +79,7 @@ uCodeDescriptions =
|
||||
, ( ActRam2DataBus, "Ram -> DataBus" )
|
||||
, ( ActResetUCounter, "µCounter = 0" )
|
||||
, ( ActProgrammCounter2AddressBus, "ProgCounter -> AddrBus" )
|
||||
, ( ActNothing, "Empty" )
|
||||
]
|
||||
|
||||
|
||||
@ -94,6 +98,7 @@ uCodeMaps =
|
||||
, ( ActRam2DataBus, actRam2DataBus )
|
||||
, ( ActResetUCounter, actResetUCounter )
|
||||
, ( ActProgrammCounter2AddressBus, actProgrammCounter2AddressBus )
|
||||
, ( ActNothing, (\s -> s))
|
||||
]
|
||||
|
||||
|
||||
@ -125,66 +130,66 @@ initialPC =
|
||||
0
|
||||
|
||||
|
||||
initialUCodes : List (Maybe UAction)
|
||||
initialUCodes : List UAction
|
||||
initialUCodes =
|
||||
[ Just ActProgrammCounter2AddressBus -- 000
|
||||
, Just ActRam2DataBus -- 001
|
||||
, Just ActDataBus2InstructionReg -- 002
|
||||
, Just ActProgrammCounterIncrement -- 003
|
||||
, Just ActInstructionReg2UCounter -- 004
|
||||
, Nothing -- 005
|
||||
, Nothing
|
||||
, Nothing
|
||||
, Nothing
|
||||
, Nothing -- 009
|
||||
[ ActProgrammCounter2AddressBus -- 000
|
||||
, ActRam2DataBus -- 001
|
||||
, ActDataBus2InstructionReg -- 002
|
||||
, ActProgrammCounterIncrement -- 003
|
||||
, ActInstructionReg2UCounter -- 004
|
||||
, ActNothing -- 005
|
||||
, ActNothing
|
||||
, ActNothing
|
||||
, ActNothing
|
||||
, ActNothing -- 009
|
||||
|
||||
-- 010 LOADA
|
||||
, Just ActInstructionReg2AddressBus -- 010
|
||||
, Just ActRam2DataBus -- 011
|
||||
, Just ActDataBus2Accumulator -- 012
|
||||
, Just ActResetUCounter -- 013
|
||||
, Nothing -- 014
|
||||
, Nothing
|
||||
, Nothing
|
||||
, Nothing
|
||||
, Nothing
|
||||
, Nothing -- 019
|
||||
, ActInstructionReg2AddressBus -- 010
|
||||
, ActRam2DataBus -- 011
|
||||
, ActDataBus2Accumulator -- 012
|
||||
, ActResetUCounter -- 013
|
||||
, ActNothing -- 014
|
||||
, ActNothing
|
||||
, ActNothing
|
||||
, ActNothing
|
||||
, ActNothing
|
||||
, ActNothing -- 019
|
||||
|
||||
-- 020 STOA
|
||||
, Just ActAccumulator2DataBus -- 020
|
||||
, Just ActInstructionReg2AddressBus -- 021
|
||||
, Just ActDataBus2Ram -- 022
|
||||
, Just ActResetUCounter -- 023
|
||||
, Nothing --024
|
||||
, Nothing
|
||||
, Nothing
|
||||
, Nothing
|
||||
, Nothing
|
||||
, Nothing -- 029
|
||||
, ActAccumulator2DataBus -- 020
|
||||
, ActInstructionReg2AddressBus -- 021
|
||||
, ActDataBus2Ram -- 022
|
||||
, ActResetUCounter -- 023
|
||||
, ActNothing --024
|
||||
, ActNothing
|
||||
, ActNothing
|
||||
, ActNothing
|
||||
, ActNothing
|
||||
, ActNothing -- 029
|
||||
|
||||
-- 030 INCA
|
||||
, Just ActAccumulatorIncrement -- 030
|
||||
, Just ActResetUCounter -- 031
|
||||
, Nothing -- 032
|
||||
, Nothing
|
||||
, Nothing
|
||||
, Nothing
|
||||
, Nothing
|
||||
, Nothing
|
||||
, Nothing
|
||||
, Nothing -- 039
|
||||
, ActAccumulatorIncrement -- 030
|
||||
, ActResetUCounter -- 031
|
||||
, ActNothing -- 032
|
||||
, ActNothing
|
||||
, ActNothing
|
||||
, ActNothing
|
||||
, ActNothing
|
||||
, ActNothing
|
||||
, ActNothing
|
||||
, ActNothing -- 039
|
||||
|
||||
-- 040 JMP
|
||||
, Just ActInstructionReg2ProgrammCounter -- 040
|
||||
, Just ActResetUCounter -- 041
|
||||
, Nothing -- 042
|
||||
, Nothing
|
||||
, Nothing
|
||||
, Nothing
|
||||
, Nothing
|
||||
, Nothing
|
||||
, Nothing
|
||||
, Nothing -- 049
|
||||
, ActInstructionReg2ProgrammCounter -- 040
|
||||
, ActResetUCounter -- 041
|
||||
, ActNothing -- 042
|
||||
, ActNothing
|
||||
, ActNothing
|
||||
, ActNothing
|
||||
, ActNothing
|
||||
, ActNothing
|
||||
, ActNothing
|
||||
, ActNothing -- 049
|
||||
]
|
||||
|
||||
|
||||
@ -194,6 +199,9 @@ type Msg
|
||||
| MsgReset
|
||||
| MsgAutoscrollUpdate
|
||||
| MsgManualStep UAction
|
||||
| MsgRamEditAddress Int String
|
||||
| MsgRamEditInstr Int String
|
||||
| MsgCuEditAction Int String
|
||||
| MsgLocalSessionRecieve String
|
||||
|
||||
|
||||
@ -223,6 +231,41 @@ update msg model =
|
||||
( { model | pc = instruction model.pc}
|
||||
, Cmd.none )
|
||||
|
||||
MsgRamEditAddress addr may_int ->
|
||||
case String.toInt may_int of
|
||||
Just int ->
|
||||
let
|
||||
(inst,_) = seperateInstructionsEntry ( valueAtInt addr model.pc.ram )
|
||||
new_val = inst * 100000 + int
|
||||
old_pc = model.pc
|
||||
new_pc = { old_pc | ram = (changeAtInt addr new_val old_pc.ram) }
|
||||
in
|
||||
({ model | pc = new_pc }
|
||||
, Cmd.none )
|
||||
_ -> (model, Cmd.none)
|
||||
|
||||
MsgRamEditInstr addr may_int ->
|
||||
case String.toInt may_int of
|
||||
Just int ->
|
||||
let
|
||||
(_,address) = seperateInstructionsEntry ( valueAtInt addr model.pc.ram )
|
||||
new_val = int * 100000 + address
|
||||
old_pc = model.pc
|
||||
new_pc = { old_pc | ram = (changeAtInt addr new_val old_pc.ram) }
|
||||
in
|
||||
({ model | pc = new_pc }
|
||||
, Cmd.none )
|
||||
_ -> ( model, Cmd.none )
|
||||
|
||||
MsgCuEditAction addr may_action ->
|
||||
case string2uAction may_action of
|
||||
Just action ->
|
||||
let
|
||||
newCode = changeAtUCode addr action model.uCode
|
||||
in
|
||||
({ model | uCode = newCode }, Cmd.none)
|
||||
_ -> ( model, Cmd.none )
|
||||
|
||||
MsgAutoscrollUpdate ->
|
||||
( { model | autoscroll = not model.autoscroll }
|
||||
, Cmd.none
|
||||
@ -250,12 +293,12 @@ uStepPC model =
|
||||
uCounter =
|
||||
model.pc.uCounter
|
||||
|
||||
may_instruction : Maybe (Maybe UAction)
|
||||
may_instruction : Maybe UAction
|
||||
may_instruction =
|
||||
valueAt uCounter model.uCode
|
||||
in
|
||||
case may_instruction of
|
||||
Just (Just action) ->
|
||||
Just action ->
|
||||
let
|
||||
possible_instructions =
|
||||
List.filter (\s -> Tuple.first s == action) uCodeMaps
|
||||
@ -284,6 +327,7 @@ uStepPC model =
|
||||
_ ->
|
||||
model
|
||||
|
||||
|
||||
|
||||
view : Model -> Html Msg
|
||||
view model =
|
||||
@ -368,11 +412,30 @@ viewRamContent model =
|
||||
|
||||
val =
|
||||
Tuple.second entry
|
||||
|
||||
(instruction, address) = seperateInstructionsEntry val
|
||||
in
|
||||
Html.tr
|
||||
[ classList [ ( "current", id == model.pc.addressBus ) ] ]
|
||||
[ Html.td [ class "num" ] [ text (addLeadingZero id 3) ]
|
||||
, Html.td [ class "num " ] [ viewInstrEntry val ]
|
||||
, Html.td [ class "num " ]
|
||||
[ Html.input
|
||||
[ HAttr.type_ "number"
|
||||
, HAttr.value (addLeadingZero instruction 3)
|
||||
, onInput (MsgRamEditInstr id)
|
||||
, class "ram-entry"
|
||||
, class "instruction"
|
||||
]
|
||||
[]
|
||||
, Html.input
|
||||
[ HAttr.type_ "number"
|
||||
, HAttr.value (addLeadingZero address 5)
|
||||
, onInput (MsgRamEditAddress id)
|
||||
, class "ram-entry"
|
||||
, class "address"
|
||||
]
|
||||
[]
|
||||
]
|
||||
]
|
||||
in
|
||||
Html.tbody [] (List.map ram2table indexedRam)
|
||||
@ -438,50 +501,41 @@ viewCuUCodeContent model =
|
||||
indexedList =
|
||||
List.indexedMap Tuple.pair model.uCode
|
||||
|
||||
list2table : ( Int, Maybe UAction ) -> Html Msg
|
||||
list2table may_t =
|
||||
list2table : ( Int, UAction ) -> Html Msg
|
||||
list2table t =
|
||||
let
|
||||
id =
|
||||
Tuple.first may_t
|
||||
Tuple.first t
|
||||
|
||||
may_code =
|
||||
Tuple.second may_t
|
||||
code =
|
||||
Tuple.second t
|
||||
in
|
||||
case may_code of
|
||||
Just code ->
|
||||
let
|
||||
possibleDescriptions : List ( UAction, String )
|
||||
possibleDescriptions =
|
||||
List.filter (\s -> Tuple.first s == code) uCodeDescriptions
|
||||
Html.tr
|
||||
[ classList [ ( "current", id == model.pc.uCounter ), ("empty", code == ActNothing) ] ]
|
||||
[ Html.td [ class "num" ] [ text (addLeadingZero id 4) ]
|
||||
, Html.td [] [ viewCuInstrSelect id code ]
|
||||
]
|
||||
|
||||
codeDescription =
|
||||
case List.head possibleDescriptions of
|
||||
Just ( _, description ) ->
|
||||
description
|
||||
|
||||
_ ->
|
||||
"Idk what this is"
|
||||
in
|
||||
Html.tr
|
||||
[ classList [ ( "current", id == model.pc.uCounter ) ] ]
|
||||
[ Html.td [ class "num" ] [ text (addLeadingZero id 3) ]
|
||||
, Html.td [] [ text codeDescription ]
|
||||
]
|
||||
|
||||
Nothing ->
|
||||
Html.tr [ class "empty" ]
|
||||
[ Html.td [ class "num" ] [ text (addLeadingZero id 3) ]
|
||||
, Html.td [] [ text "Empty" ]
|
||||
]
|
||||
in
|
||||
Html.tbody [] (List.map list2table indexedList)
|
||||
|
||||
viewCuInstrSelect : Int -> UAction -> Html Msg
|
||||
viewCuInstrSelect id current =
|
||||
let
|
||||
info2option (action, info) =
|
||||
Html.option [ HAttr.selected (action == current) ] [ text info ]
|
||||
listOptions = List.map info2option uCodeDescriptions
|
||||
in
|
||||
Html.select
|
||||
[ HEvent.on "change" ( JD.map (MsgCuEditAction id) selectCuValueDecoder) ]
|
||||
listOptions
|
||||
|
||||
|
||||
viewAlu : Model -> Html Msg
|
||||
viewAlu model =
|
||||
div [ class "section", class "alu" ]
|
||||
[ h1 [ class "header" ] [ text "ALU" ]
|
||||
, p [] [ text ("Accumulator: " ++ String.fromInt model.pc.accumulator) ]
|
||||
, p [] [ text ("Accumulator: " ++ (addLeadingZero model.pc.accumulator 8)) ]
|
||||
, div [ class "arrow", class "up"]
|
||||
[ div [ class "button" ]
|
||||
[ Html.a [ onClick (MsgManualStep ActDataBus2Accumulator)] [ text "DB -> ALU" ]]
|
||||
@ -514,8 +568,7 @@ viewAddressBus model =
|
||||
viewInstrEntry : Int -> Html Msg
|
||||
viewInstrEntry i =
|
||||
let
|
||||
instruction = i // 100000
|
||||
address = i - instruction*100000
|
||||
(instruction, address) = seperateInstructionsEntry i
|
||||
in
|
||||
text ( (addLeadingZero instruction 3) ++ " " ++ (addLeadingZero address 5) )
|
||||
|
||||
@ -551,21 +604,28 @@ actResetUCounter pc =
|
||||
|
||||
actInstructionReg2UCounter : PC -> PC
|
||||
actInstructionReg2UCounter pc =
|
||||
-- Remove last 5 digits as they are address
|
||||
-- Multiply by ten, because every instruction is 10 uCodes long
|
||||
{ pc | uCounter = pc.instructionReg // 100000 * 10 }
|
||||
let
|
||||
(instruction, address) = seperateInstructionsEntry pc.instructionReg
|
||||
in
|
||||
{ pc | uCounter = instruction * 10}
|
||||
|
||||
|
||||
actInstructionReg2AddressBus : PC -> PC
|
||||
actInstructionReg2AddressBus pc =
|
||||
-- Only bring last 5 digits to AB, because the rest is opcode
|
||||
{ pc | addressBus = pc.instructionReg - pc.instructionReg // 100000 * 100000 }
|
||||
let
|
||||
(instruction, address) = seperateInstructionsEntry pc.instructionReg
|
||||
in
|
||||
{ pc | addressBus = address }
|
||||
|
||||
|
||||
actInstructionReg2ProgrammCounter : PC -> PC
|
||||
actInstructionReg2ProgrammCounter pc =
|
||||
-- Only bring last 5 digits to AB, because the rest is opcode
|
||||
{ pc | programmCounter = pc.instructionReg - pc.instructionReg // 100000 * 100000 }
|
||||
let
|
||||
(instruction, address) = seperateInstructionsEntry pc.instructionReg
|
||||
in
|
||||
|
||||
{ pc | programmCounter = address }
|
||||
|
||||
|
||||
actProgrammCounterIncrement : PC -> PC
|
||||
@ -602,7 +662,7 @@ actDataBus2Ram : PC -> PC
|
||||
actDataBus2Ram pc =
|
||||
let
|
||||
newRam =
|
||||
changeAt pc.addressBus pc.dataBus pc.ram
|
||||
changeAtInt pc.addressBus pc.dataBus pc.ram
|
||||
in
|
||||
{ pc | ram = newRam }
|
||||
|
||||
@ -627,8 +687,17 @@ valueAt n l =
|
||||
List.head (List.drop n l)
|
||||
|
||||
|
||||
changeAt : Int -> Int -> List Int -> List Int
|
||||
changeAt pos newVal list =
|
||||
changeAtInt : Int -> Int -> List Int -> List Int
|
||||
changeAtInt pos newVal list =
|
||||
changeAt pos newVal 0 list
|
||||
|
||||
|
||||
changeAtUCode : Int -> UAction -> List UAction -> List UAction
|
||||
changeAtUCode pos newVal list =
|
||||
changeAt pos newVal ActNothing list
|
||||
|
||||
changeAt : Int -> a -> a ->List a -> List a
|
||||
changeAt pos newVal default list =
|
||||
let
|
||||
before =
|
||||
List.take pos list
|
||||
@ -642,7 +711,7 @@ changeAt pos newVal list =
|
||||
if pos > len then
|
||||
let
|
||||
before2 =
|
||||
List.append before (List.repeat (pos - len) 0)
|
||||
List.append before (List.repeat (pos - len) default)
|
||||
in
|
||||
List.append before2 (newVal :: after)
|
||||
|
||||
@ -674,6 +743,38 @@ addLeadingZero number length =
|
||||
else
|
||||
num_str
|
||||
|
||||
seperateInstructionsEntry : Int -> (Int, Int)
|
||||
seperateInstructionsEntry i =
|
||||
let
|
||||
instruction = i // 100000
|
||||
address = i - instruction*100000
|
||||
in
|
||||
(instruction, address)
|
||||
|
||||
|
||||
uAction2String : UAction -> String
|
||||
uAction2String action =
|
||||
let
|
||||
filtered_list = List.filter (\s -> Tuple.first s == action) uCodeDescriptions
|
||||
in
|
||||
case List.head filtered_list of
|
||||
Just (_,info) -> info
|
||||
Nothing -> "IDK"
|
||||
|
||||
string2uAction : String -> Maybe UAction
|
||||
string2uAction msg =
|
||||
let
|
||||
filtered_list = List.filter (\s -> Tuple.second s == msg) uCodeDescriptions
|
||||
in
|
||||
case List.head filtered_list of
|
||||
Just (action,_) -> Just action
|
||||
_ -> Nothing
|
||||
|
||||
|
||||
selectCuValueDecoder : JD.Decoder String
|
||||
selectCuValueDecoder =
|
||||
JD.field "target" ( JD.field "value" JD.string)
|
||||
|
||||
-- END HELPERS
|
||||
-- GENERAL
|
||||
|
||||
|
Reference in New Issue
Block a user