module Sham where

import Data.Bits
import Data.Word
import Hardware.Chalk
import Control.Applicative
import Control.Monad (liftM2)

data Reg = R0 | R1 | R2 | R3 deriving (Show, Eq, Read)

type Regs = (Int, Int, Int, Int) 

initRegs :: Regs
initRegs = (0,0,0,0)

regFile ::
  Signal Reg                    -- write port
  -> Signal Int                 -- write val
  -> Signal Reg                 -- first read port
  -> Signal Reg                 -- second read port
  -> Signal (Int, Int)          -- read port outputs and next state
regFile wr val rd1 rd2 = component "RegisterFile" $ res
  where
  rf = pure regStep <*> wr <*> val <*> rd1 <*> rd2 <*> delay initRegs rstate
  (res, rstate) = splitView rf

splitView :: Circuit (a, b) -> (Circuit a, Circuit b)
splitView c = (fmap fst c, fmap snd c)

regStep :: Reg -> Int -> Reg -> Reg -> Regs -> ((Int, Int), Regs)
regStep wr x rd1 rd2 regs =
  let regs' = updateReg (wr,x) regs
  in ((lookupReg rd1 regs', lookupReg rd2 regs'), regs')  

updateReg (R0,x) (a,b,c,d) = (x,b,c,d)
updateReg (R1,x) (a,b,c,d) = (a,x,c,d)
updateReg (R2,x) (a,b,c,d) = (a,b,x,d)
updateReg (R3,x) (a,b,c,d) = (a,b,c,x)

lookupReg R0 (a,b,c,d) = a
lookupReg R1 (a,b,c,d) = b
lookupReg R2 (a,b,c,d) = c
lookupReg R3 (a,b,c,d) = d


delayed :: Circuit a -> Circuit a 
delayed c = delay (first c) c

activity :: (a -> a -> b) -> Circuit a -> Circuit b
activity f c = pure f <*> delayed c <*> c

rf :: Circuit ((Int, Int), Regs)
rf = undefined

bitChange :: Circuit Int
bitChange = activity m rf
  where
  m :: ((Int, Int), Regs) ->((Int, Int), Regs) -> Int
  m 
  bitDiff :: Int -> Int -> Int
  bitDiff x y = count (complement (xor (bit x) (bit y) :: Word32))
  count = undefined