SHARE
TWEET

Untitled

a guest Jul 22nd, 2019 51 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. {-# LANGUAGE DeriveGeneric  #-}
  2. {-# LANGUAGE DeriveAnyClass #-}
  3.  
  4. module CPU where
  5.  
  6. import Clash.Prelude
  7. import Data.Maybe (isJust)
  8. import Control.DeepSeq (NFData)
  9. import GHC.Generics (Generic)
  10.  
  11. data Ready
  12.   = Busy
  13.   | Ready
  14.   deriving (Generic, NFData, Show)
  15.  
  16. data CPUState
  17.   = Idle
  18.   | Waiting Int
  19.   deriving (Generic, NFData, Show)
  20.  
  21. data Instruction
  22.   = Add Int Int
  23.   | Multiply Int Int
  24.   deriving (Generic, NFData, Show)
  25.  
  26.  
  27. doInstr :: Instruction -> Int
  28. doInstr (Add a b)      = a + b
  29. doInstr (Multiply a b) = a * b
  30.  
  31. cpu
  32.   :: (CPUState, Int)
  33.   -- ^ State
  34.   -> Maybe Instruction
  35.   -- ^ Input
  36.   -> ((CPUState, Int), (Maybe Int, Ready))
  37.   -- (New state, output)
  38.  
  39. --  state          input           new state                   output
  40. cpu (Idle, _)      Nothing      = ((Idle, 0),                  (Nothing, Ready))
  41. cpu (Idle, _)      (Just instr) = ((Waiting 0, doInstr instr), (Nothing, Busy))
  42. cpu (Waiting 1, r) _            = ((Idle, 0),                  (Just r, Ready))
  43. cpu (Waiting n, r) _            = ((Waiting (n + 1), r),       (Nothing, Busy))
  44.  
  45.  
  46. -- Example 1: Simple feed some instructions with nothings in between:
  47. instrs1 :: [Maybe Instruction]
  48. instrs1 =
  49.   [ Just (Add 1 2)
  50.   , Nothing
  51.   , Nothing
  52.   , Just (Add 3 5)
  53.   , Nothing
  54.   , Nothing
  55.   , Nothing
  56.   ]
  57.  
  58. sim1 :: IO ()
  59. sim1 = do
  60.   let s = mealy cpu (Idle, 0) (fromList instrs1)
  61.   putStrLn $ show $ sampleN 7 $ s
  62.  
  63.  
  64. -- Example 2: Do the same as example 1, but manipulate the output signal:
  65. sim2 :: IO ()
  66. sim2 = do
  67.   let s = mealy cpu (Idle, 0) (fromList instrs1)
  68.  
  69.   -- Only print first half of tuple:
  70.   putStrLn $ show $ sampleN 7 $ fmap fst s
  71.  
  72.   -- Only print whether cpu outputted a result:
  73.   putStrLn $ show $ sampleN 7 $ fmap (isJust . fst) s
  74.  
  75.  
  76. -- Example 3: Have another circuit drive the cpu
  77. driver
  78.   :: Vec 3 Instruction
  79.   -> Ready
  80.   -> (Vec 3 Instruction, Maybe Instruction)
  81. driver instrs Busy = (instrs, Nothing)
  82. driver instrs Ready = (rotateLeftS instrs d1, Just (head instrs))
  83.  
  84. composed :: SystemClockReset => Signal System (Maybe Int)
  85. composed = cpuResult
  86.   where
  87.     instr = mealy driver (Add 3 5 :> Multiply 10 2 :> Add 7 3 :> Nil) ready
  88.  
  89.     -- If the cpu would directly depend on the driver, and vice-versa we would
  90.     -- create a combinatorial loop which is not computable. In order to prevent
  91.     -- such a loop, we insert a delay with its first value being "Nothing" or
  92.     -- "No instruction".
  93.     instrDelayed = register Nothing instr
  94.  
  95.     cpuOutput = mealy cpu (Idle, 0) instrDelayed
  96.     (cpuResult, ready) = unbundle cpuOutput
  97.  
  98. sim3 :: IO ()
  99. sim3 = putStrLn $ show $ sampleN 7 $ composed
  100.  
  101. -- Example 4: 'composed' should be fully synthesizable by running :vhdl. When
  102. -- I test it on 0.99.3 I get compile errors though..
  103. topEntity
  104.   :: Clock System Source
  105.   -> Reset System Asynchronous
  106.   -> Signal System (Maybe Int)
  107. topEntity clk rst = withClockReset clk rst composed
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Not a member of Pastebin yet?
Sign Up, it unlocks many cool features!
 
Top