Advertisement
Guest User

Untitled

a guest
Jul 22nd, 2019
77
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.80 KB | None | 0 0
  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
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement