From d9e4c301d7292bc9d4bd3668163d83449802ccfa Mon Sep 17 00:00:00 2001 From: Gautham Ganapathy Date: Sun, 29 Oct 2023 14:48:01 +0000 Subject: [PATCH] Unconditional jump. Added fix for clamping addresses --- src/TIS100/Tiles/T21.hs | 15 ++++++---- test/Sim/T21.hs | 62 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 65 insertions(+), 12 deletions(-) diff --git a/src/TIS100/Tiles/T21.hs b/src/TIS100/Tiles/T21.hs index 5de97f2..2173e0f 100644 --- a/src/TIS100/Tiles/T21.hs +++ b/src/TIS100/Tiles/T21.hs @@ -174,17 +174,22 @@ instance IsConnectedTile T21 where SUBI v -> incPC $ writeRegOrPort (Register ACC) $ maybeAddSub (flip (-)) (t, Just v) $ readRegOrPort (Register ACC) t SUB src -> incPC $ writeRegOrPort (Register ACC) $ maybeAddSub (flip (-)) (readRegOrPort src t) (readRegOrPort (Register ACC) t) NEG -> incPC $ writeRegOrPort (Register ACC) $ maybeAddSub (-) (t, Just $ Value 0) $ readRegOrPort (Register ACC) t - JMP addr -> t{tileState = (tileState t){pc = addr}} + JMP addr -> t{tileState = (tileState t){pc = clampAddr addr}} JCC cond addr -> case cond of - EZ -> if acc (tileState t) == 0 then t{tileState = (tileState t){pc = addr}} else incPC t - NZ -> if acc (tileState t) /= 0 then t{tileState = (tileState t){pc = addr}} else incPC t - GZ -> if acc (tileState t) > 0 then t{tileState = (tileState t){pc = addr}} else incPC t - LZ -> if acc (tileState t) < 0 then t{tileState = (tileState t){pc = addr}} else incPC t + EZ -> if acc (tileState t) == 0 then t{tileState = (tileState t){pc = clampAddr addr}} else incPC t + NZ -> if acc (tileState t) /= 0 then t{tileState = (tileState t){pc = clampAddr addr}} else incPC t + GZ -> if acc (tileState t) > 0 then t{tileState = (tileState t){pc = clampAddr addr}} else incPC t + LZ -> if acc (tileState t) < 0 then t{tileState = (tileState t){pc = clampAddr addr}} else incPC t JROI v -> addValueToPC (t, Just v) JRO src -> addValueToPC $ readRegOrPort src t + maybeAddSub :: (Value -> Value -> Value) -> (T21, Maybe Value) -> (T21, Maybe Value) -> (T21, Maybe Value) maybeAddSub f (t', Just v1) (_, Just v2) = (t', Just $ f v1 v2) maybeAddSub _ tv _ = tv -- Just to silence the linter + clampAddr :: Address -> Address + clampAddr (Address a) = Address $ max 0 $ min a maxAddr + where + maxAddr = V.length (tileProgram t) - 1 readRegOrPort :: RegisterOrPort -> T21 -> (T21, Maybe Value) readRegOrPort rp t = case rp of diff --git a/test/Sim/T21.hs b/test/Sim/T21.hs index ef5ab34..d47e49e 100644 --- a/test/Sim/T21.hs +++ b/test/Sim/T21.hs @@ -8,8 +8,8 @@ import TIS100.Tiles.T21 import Test.Hspec import Prelude hiding (init, last) -mkT21Tile :: Value -> Value -> [Instruction] -> T21 -mkT21Tile initAcc initBak instns = +mkT21TileWithPC :: Address -> Value -> Value -> [Instruction] -> T21 +mkT21TileWithPC initPc initAcc initBak instns = T21 { tileProgram = V.fromList instns @@ -18,11 +18,14 @@ mkT21Tile initAcc initBak instns = { acc = initAcc , bak = initBak , last = ANY - , pc = 0 + , pc = initPc , runState = Ready } } +mkT21Tile :: Value -> Value -> [Instruction] -> T21 +mkT21Tile = mkT21TileWithPC 0 + testADDSUB :: Bool -> Spec testADDSUB add = describe ("Testing " ++ insName) $ do testADDSUB_ACC @@ -61,10 +64,6 @@ testADD :: Spec testADD = testADDSUB True testSUB :: Spec testSUB = testADDSUB False -testADDI :: Spec -testADDI = testADDSUBI True -testSUBI :: Spec -testSUBI = testADDSUBI False testADDSUBI :: Bool -> Spec testADDSUBI add = do @@ -78,6 +77,39 @@ testADDSUBI add = do f = if add then (+) else (-) insName = if add then "ADDI" else "SUBI" +testADDI :: Spec +testADDI = testADDSUBI True +testSUBI :: Spec +testSUBI = testADDSUBI False + +testUnconditionalJump :: Spec +testUnconditionalJump = describe "Testing JMP" $ do + testUnconditionalJump' "without overflow/underflow" (JMP (Address 5)) (Address 5) + testUnconditionalJump' "underflow" (JMP (Address (-5))) (Address 0) + testUnconditionalJump' "overflow" (JMP (Address 10)) (Address 6) + where + testUnconditionalJump' desc ins tgtAddr = do + let next = step $ init ins + + describe ("Testing " ++ desc) $ do + it "Status" $ do + pc (tileState next) `shouldBe` tgtAddr + + init ins = mkT21TileWithPC 3 2 0 [NOP, NOP, NOP, ins, NOP, NOP, NOP] + +testJEZ :: Spec +testJEZ = undefined +testJGZ :: Spec +testJGZ = undefined +testJLZ :: Spec +testJLZ = undefined +testJNZ :: Spec +testJNZ = undefined +testJMP :: Spec +testJMP = testUnconditionalJump +testJRO :: Spec +testJRO = undefined + testMOVI :: Spec testMOVI = describe "Testing MOVI" $ do let ports = [UP, DOWN, LEFT, RIGHT] @@ -122,6 +154,15 @@ testMOV = describe "Testing MOV" $ do it "Status" $ do runState (tileState next) `shouldBe` WaitingOnRead port Nothing +testNEG :: Spec +testNEG = describe "Testing NEG" $ do + let init = mkT21Tile 10 20 [NEG] + let next = step init + + describe "Testing NEG" $ do + it "Status" $ do + acc (tileState next) `shouldBe` Value (-10) + testNOP :: Spec testNOP = describe "Testing NOPs" $ do testNOP' NOP @@ -150,8 +191,15 @@ simTestsSpec :: Spec simTestsSpec = describe "Intra-T21 tests" $ parallel $ do testADD testADDI + -- testJEZ + -- testJGZ + -- testJLZ + -- testJNZ + testJMP + -- testJRO testMOV testMOVI + testNEG testNOP testSUB testSUBI