{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE Trustworthy #-}
{-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-}
{-# OPTIONS_HADDOCK show-extensions #-}
module Clash.Explicit.ROM
(
rom
, romPow2
, rom#
)
where
import Data.Array ((!),listArray)
import GHC.Stack (withFrozenCallStack)
import GHC.TypeLits (KnownNat, type (^))
import Prelude hiding (length)
import Clash.Signal.Internal
(Clock (..), KnownDomain, Signal (..), Enable, fromEnable)
import Clash.Sized.Unsigned (Unsigned)
import Clash.Sized.Vector (Vec, length, toList)
import Clash.XException (deepErrorX, seqX, Undefined)
romPow2
:: (KnownDomain dom, KnownNat n, Undefined a)
=> Clock dom
-> Enable dom
-> Vec (2^n) a
-> Signal dom (Unsigned n)
-> Signal dom a
romPow2 :: Clock dom
-> Enable dom
-> Vec (2 ^ n) a
-> Signal dom (Unsigned n)
-> Signal dom a
romPow2 = Clock dom
-> Enable dom
-> Vec (2 ^ n) a
-> Signal dom (Unsigned n)
-> Signal dom a
forall (dom :: Domain) (n :: Nat) a addr.
(KnownDomain dom, KnownNat n, Undefined a, Enum addr) =>
Clock dom
-> Enable dom -> Vec n a -> Signal dom addr -> Signal dom a
rom
{-# INLINE romPow2 #-}
rom
:: (KnownDomain dom, KnownNat n, Undefined a, Enum addr)
=> Clock dom
-> Enable dom
-> Vec n a
-> Signal dom addr
-> Signal dom a
rom :: Clock dom
-> Enable dom -> Vec n a -> Signal dom addr -> Signal dom a
rom = \clk :: Clock dom
clk en :: Enable dom
en content :: Vec n a
content rd :: Signal dom addr
rd -> Clock dom
-> Enable dom -> Vec n a -> Signal dom Int -> Signal dom a
forall (dom :: Domain) (n :: Nat) a.
(KnownDomain dom, KnownNat n, Undefined a) =>
Clock dom
-> Enable dom -> Vec n a -> Signal dom Int -> Signal dom a
rom# Clock dom
clk Enable dom
en Vec n a
content (addr -> Int
forall a. Enum a => a -> Int
fromEnum (addr -> Int) -> Signal dom addr -> Signal dom Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Signal dom addr
rd)
{-# INLINE rom #-}
rom#
:: forall dom n a
. (KnownDomain dom, KnownNat n, Undefined a)
=> Clock dom
-> Enable dom
-> Vec n a
-> Signal dom Int
-> Signal dom a
rom# :: Clock dom
-> Enable dom -> Vec n a -> Signal dom Int -> Signal dom a
rom# _ en :: Enable dom
en content :: Vec n a
content rd :: Signal dom Int
rd =
a -> Signal dom Bool -> Signal dom a -> Signal dom a
forall t (dom :: Domain) (dom :: Domain) (dom :: Domain).
t -> Signal dom Bool -> Signal dom t -> Signal dom t
go
((HasCallStack => a) -> a
forall a. HasCallStack => (HasCallStack => a) -> a
withFrozenCallStack (String -> a
forall a. (Undefined a, HasCallStack) => String -> a
deepErrorX "rom: initial value undefined"))
(Enable dom -> Signal dom Bool
forall (dom :: Domain). Enable dom -> Signal dom Bool
fromEnable Enable dom
en)
((Array Int a
arr Array Int a -> Int -> a
forall i e. Ix i => Array i e -> i -> e
!) (Int -> a) -> Signal dom Int -> Signal dom a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Signal dom Int
rd)
where
szI :: Int
szI = Vec n a -> Int
forall (n :: Nat) a. KnownNat n => Vec n a -> Int
length Vec n a
content
arr :: Array Int a
arr = (Int, Int) -> [a] -> Array Int a
forall i e. Ix i => (i, i) -> [e] -> Array i e
listArray (0,Int
szIInt -> Int -> Int
forall a. Num a => a -> a -> a
-1) (Vec n a -> [a]
forall (n :: Nat) a. Vec n a -> [a]
toList Vec n a
content)
go :: t -> Signal dom Bool -> Signal dom t -> Signal dom t
go o :: t
o (e :: Bool
e :- es :: Signal dom Bool
es) as :: Signal dom t
as@(~(x :: t
x :- xs :: Signal dom t
xs)) =
t
o t -> Signal dom t -> Signal dom t
forall a b. a -> b -> b
`seqX` t
o t -> Signal dom t -> Signal dom t
forall (dom :: Domain) a. a -> Signal dom a -> Signal dom a
:- (Signal dom t
as Signal dom t -> Signal dom t -> Signal dom t
forall a b. a -> b -> b
`seq` if Bool
e then t -> Signal dom Bool -> Signal dom t -> Signal dom t
go t
x Signal dom Bool
es Signal dom t
xs else t -> Signal dom Bool -> Signal dom t -> Signal dom t
go t
o Signal dom Bool
es Signal dom t
xs)
{-# NOINLINE rom# #-}