Allow editing commands

This commit is contained in:
2020-12-25 17:45:30 +01:00
parent de89a7b8fb
commit 0a15d5bef4
5 changed files with 580 additions and 316 deletions

View File

@ -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