summary refs log tree commit diff
path: root/Simulator.hs
blob: 1718b600939174f5ec2d05f0c25708369758544c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
module Main where

import qualified Data.Sequence as S
import Control.Monad.State
import Data.Word ( Word16 )
import Data.Maybe (isNothing)
import Data.Bits ( Bits((.&.), complement, shiftR) )
import Data.Sequence ((!?))
import Debug.Trace


data Machine = Machine {
    pc :: Int,
    registers :: S.Seq Int,
    memory :: S.Seq Int
} deriving Show

mkMachine :: [String] -> Machine
mkMachine f = Machine 0 (S.replicate 8 0) (S.fromList $ map read f)

data MachineError = Halt | MemoryAccessError deriving (Show,Eq)
execute :: State Machine (Maybe MachineError)
execute = do
    inst <- gets (S.lookup.pc<*>memory)
    -- increment pc
    -- modify $ Machine.((+1).pc)<*>memory<*>registers
    regs <- gets registers
    mem <- gets memory
    pc <- gets $ (+1).pc
    case inst of
        Nothing -> return $ Just MemoryAccessError
        Just inst ->
            let Just regA = S.lookup (inst `shiftR` 19 .&. 0b111) regs
                Just regB = S.lookup (inst `shiftR` 16 .&. 0b111) regs
                destReg = inst .&. 0b111
                offsetField = inst .&. 0b1111111111111111
                wrapAdd x y = (fromIntegral (fromIntegral (x+y) :: Word16) :: Int)
                 in case inst `shiftR` 22 .&. 0b111 of
                -- ADD
                0 -> do
                    put $ Machine pc (S.update destReg (regA+regB) regs) mem
                    return Nothing
                -- NAND
                1 -> do
                    put $ Machine pc (S.update destReg (complement regA.&.regB) regs) mem
                    return Nothing
                -- LW
                2 -> do
                    case S.lookup (wrapAdd offsetField regA) mem of
                        Nothing -> return $ Just MemoryAccessError
                        Just v -> do
                            put $ Machine pc (S.update (inst `shiftR` 16 .&. 0b11) v regs) mem
                            return Nothing
                -- SW
                3 -> do
                    put $ Machine pc regs (S.update (wrapAdd offsetField regA) regB mem)
                    return Nothing
                --- BEQ
                4 -> do
                    if regA==regB then 
                        put $ Machine (wrapAdd offsetField pc)  regs mem
                    else put $ Machine pc regs mem
                    return Nothing
                -- XXX
                5 -> return Nothing
                -- HALT
                6 -> return $ Just Halt
                -- NOOP
                7 -> return Nothing


main :: IO ()
main = do
    input <- getContents
    let m = until ((/=Nothing).evalState execute) (execState execute) $ mkMachine (lines input)
    case evalState execute m of
        Just Halt -> putStrLn "Machine halted"
        Just MemoryAccessError -> putStrLn "Out of bounds memory access"
    print m