{-# LANGUAGE CPP #-} module Calculator where import Clash.Prelude hiding (Word) import Clash.Explicit.Testbench import CalculatorTypes (.:) :: (c -> d) -> (a -> b -> c) -> a -> b -> d (f .: g) a b = f (g a b) infixr 9 .: alu :: Num a => OPC a -> a -> a -> Maybe a alu ADD = Just .: (+) alu MUL = Just .: (*) alu (Imm i) = const . const (Just i) alu _ = const . const Nothing pu :: (Num a, Num b) => (OPC a -> a -> a -> Maybe a) -> (a, a, b) -- Current state -> (a, OPC a) -- Input -> ( (a, a, b) -- New state , (b, Maybe a) -- Output ) pu alu (op1,op2,cnt) (dmem,Pop) = ((dmem,op1,cnt-1),(cnt,Nothing)) pu alu (op1,op2,cnt) (dmem,Push) = ((op1,op2,cnt+1) ,(cnt,Nothing)) pu alu (op1,op2,cnt) (dmem,opc) = ((op1,op2,cnt) ,(cnt,alu opc op1 op2)) datamem :: (KnownNat n, Integral i) => Vec n a -- Current state -> (i, Maybe a) -- Input -> (Vec n a, a) -- (New state, Output) datamem mem (addr,Nothing) = (mem ,mem !! addr) datamem mem (addr,Just val) = (replace addr val mem,mem !! addr) topEntity :: Clock System -> Reset System -> Enable System -> Signal System (OPC Word) -> Signal System (Maybe Word) topEntity = exposeClockResetEnable go where go i = val where (addr,val) = (pu alu <^> (0,0,0 :: Unsigned 3)) (mem,i) mem = (datamem <^> initMem) (addr,val) initMem = replicate d8 0 -- See: https://github.com/clash-lang/clash-compiler/pull/2511 {-# CLASH_OPAQUE topEntity #-} testBench :: Signal System Bool testBench = done where testInput = stimuliGenerator clk rst $(listToVecTH [Imm 1::OPC Word,Push,Imm 2,Push,Pop,Pop,Pop,ADD]) expectedOutput = outputVerifier' clk rst $(listToVecTH [Just 1 :: Maybe Word,Nothing,Just 2,Nothing,Nothing,Nothing,Nothing,Just 3]) done = expectedOutput (topEntity clk rst (enableGen) testInput) clk = tbSystemClockGen (not <$> done) rst = systemResetGen