{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE Trustworthy #-}
{-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-}
{-# OPTIONS_HADDOCK show-extensions #-}
{-# OPTIONS_GHC -fno-do-lambda-eta-expansion #-}
{-# OPTIONS_GHC -fno-cpr-anal #-}
module Clash.Explicit.BlockRam
(
blockRam
, blockRamPow2
, blockRamU
, blockRam1
, ResetStrategy(..)
, readNew
, trueDualPortBlockRam
, RamOp(..)
, blockRam#
, trueDualPortBlockRam#
)
where
import Clash.HaskellPrelude
import Control.Exception (catch, throw)
import Control.Monad (forM_)
import Control.Monad.ST (ST, runST)
import Control.Monad.ST.Unsafe (unsafeInterleaveST, unsafeIOToST, unsafeSTToIO)
import Data.Array.MArray (newListArray)
import qualified Data.List as L
import Data.Either (isLeft)
import Data.Maybe (isJust, fromMaybe)
import GHC.Arr
(STArray, unsafeReadSTArray, unsafeWriteSTArray)
import qualified Data.Sequence as Seq
import Data.Sequence (Seq)
import Data.Tuple (swap)
import GHC.Generics (Generic)
import GHC.Stack (HasCallStack, withFrozenCallStack)
import GHC.TypeLits (KnownNat, type (^), type (<=))
import Unsafe.Coerce (unsafeCoerce)
import Clash.Annotations.Primitive
(hasBlackBox)
import Clash.Class.Num (SaturationMode(SatBound), satSucc)
import Clash.Explicit.Signal (KnownDomain, Enable, register, fromEnable)
import Clash.Signal.Internal
(Clock(..), Reset, Signal (..), invertReset, (.&&.), mux)
import Clash.Promoted.Nat (SNat(..), snatToNum, natToNum)
import Clash.Signal.Bundle (unbundle, bundle)
import Clash.Signal.Internal.Ambiguous (clockPeriod)
import Clash.Sized.Unsigned (Unsigned)
import Clash.Sized.Index (Index)
import Clash.Sized.Vector (Vec, replicate, iterateI)
import qualified Clash.Sized.Vector as CV
import Clash.XException
(maybeIsX, NFDataX(deepErrorX), defaultSeqX, fromJustX, undefined,
XException (..), seqX, isX, errorX)
blockRam
:: ( KnownDomain dom
, HasCallStack
, NFDataX a
, Enum addr )
=> Clock dom
-> Enable dom
-> Vec n a
-> Signal dom addr
-> Signal dom (Maybe (addr, a))
-> Signal dom a
blockRam :: Clock dom
-> Enable dom
-> Vec n a
-> Signal dom addr
-> Signal dom (Maybe (addr, a))
-> Signal dom a
blockRam = \Clock dom
clk Enable dom
gen Vec n a
content Signal dom addr
rd Signal dom (Maybe (addr, a))
wrM ->
let en :: Signal dom Bool
en = Maybe (addr, a) -> Bool
forall a. Maybe a -> Bool
isJust (Maybe (addr, a) -> Bool)
-> Signal dom (Maybe (addr, a)) -> Signal dom Bool
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Signal dom (Maybe (addr, a))
wrM
(Signal dom addr
wr,Signal dom a
din) = Signal dom (addr, a) -> Unbundled dom (addr, a)
forall a (dom :: Domain).
Bundle a =>
Signal dom a -> Unbundled dom a
unbundle (Maybe (addr, a) -> (addr, a)
forall a. HasCallStack => Maybe a -> a
fromJustX (Maybe (addr, a) -> (addr, a))
-> Signal dom (Maybe (addr, a)) -> Signal dom (addr, a)
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Signal dom (Maybe (addr, a))
wrM)
in (HasCallStack => Signal dom a) -> Signal dom a
forall a. HasCallStack => (HasCallStack => a) -> a
withFrozenCallStack
(Clock dom
-> Enable dom
-> Vec n a
-> Signal dom Int
-> Signal dom Bool
-> Signal dom Int
-> Signal dom a
-> Signal dom a
forall (dom :: Domain) a (n :: Nat).
(KnownDomain dom, HasCallStack, NFDataX a) =>
Clock dom
-> Enable dom
-> Vec n a
-> Signal dom Int
-> Signal dom Bool
-> Signal dom Int
-> Signal dom a
-> Signal dom a
blockRam# Clock dom
clk Enable dom
gen Vec n a
content (addr -> Int
forall a. Enum a => a -> Int
fromEnum (addr -> Int) -> Signal dom addr -> Signal dom Int
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Signal dom addr
rd) Signal dom Bool
en (addr -> Int
forall a. Enum a => a -> Int
fromEnum (addr -> Int) -> Signal dom addr -> Signal dom Int
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Signal dom addr
wr) Signal dom a
din)
{-# INLINE blockRam #-}
blockRamPow2
:: ( KnownDomain dom
, HasCallStack
, NFDataX a
, KnownNat n )
=> Clock dom
-> Enable dom
-> Vec (2^n) a
-> Signal dom (Unsigned n)
-> Signal dom (Maybe (Unsigned n, a))
-> Signal dom a
blockRamPow2 :: Clock dom
-> Enable dom
-> Vec (2 ^ n) a
-> Signal dom (Unsigned n)
-> Signal dom (Maybe (Unsigned n, a))
-> Signal dom a
blockRamPow2 = \Clock dom
clk Enable dom
en Vec (2 ^ n) a
cnt Signal dom (Unsigned n)
rd Signal dom (Maybe (Unsigned n, a))
wrM -> (HasCallStack => Signal dom a) -> Signal dom a
forall a. HasCallStack => (HasCallStack => a) -> a
withFrozenCallStack
(Clock dom
-> Enable dom
-> Vec (2 ^ n) a
-> Signal dom (Unsigned n)
-> Signal dom (Maybe (Unsigned n, a))
-> Signal dom a
forall (dom :: Domain) a addr (n :: Nat).
(KnownDomain dom, HasCallStack, NFDataX a, Enum addr) =>
Clock dom
-> Enable dom
-> Vec n a
-> Signal dom addr
-> Signal dom (Maybe (addr, a))
-> Signal dom a
blockRam Clock dom
clk Enable dom
en Vec (2 ^ n) a
cnt Signal dom (Unsigned n)
rd Signal dom (Maybe (Unsigned n, a))
wrM)
{-# INLINE blockRamPow2 #-}
data ResetStrategy (r :: Bool) where
ClearOnReset :: ResetStrategy 'True
NoClearOnReset :: ResetStrategy 'False
blockRamU
:: forall n dom a r addr
. ( KnownDomain dom
, HasCallStack
, NFDataX a
, Enum addr
, 1 <= n )
=> Clock dom
-> Reset dom
-> Enable dom
-> ResetStrategy r
-> SNat n
-> (Index n -> a)
-> Signal dom addr
-> Signal dom (Maybe (addr, a))
-> Signal dom a
blockRamU :: Clock dom
-> Reset dom
-> Enable dom
-> ResetStrategy r
-> SNat n
-> (Index n -> a)
-> Signal dom addr
-> Signal dom (Maybe (addr, a))
-> Signal dom a
blockRamU Clock dom
clk Reset dom
rst0 Enable dom
en ResetStrategy r
rstStrategy n :: SNat n
n@SNat n
SNat Index n -> a
initF Signal dom addr
rd0 Signal dom (Maybe (addr, a))
mw0 =
case ResetStrategy r
rstStrategy of
ResetStrategy r
ClearOnReset ->
Clock dom
-> Enable dom
-> SNat n
-> Signal dom Int
-> Signal dom Bool
-> Signal dom Int
-> Signal dom a
-> Signal dom a
forall (n :: Nat) (dom :: Domain) a.
(KnownDomain dom, HasCallStack, NFDataX a) =>
Clock dom
-> Enable dom
-> SNat n
-> Signal dom Int
-> Signal dom Bool
-> Signal dom Int
-> Signal dom a
-> Signal dom a
blockRamU# Clock dom
clk Enable dom
en SNat n
n Signal dom Int
rd1 Signal dom Bool
we1 Signal dom Int
wa1 Signal dom a
w1
ResetStrategy r
NoClearOnReset ->
Clock dom
-> Enable dom
-> SNat n
-> Signal dom Int
-> Signal dom Bool
-> Signal dom Int
-> Signal dom a
-> Signal dom a
forall (n :: Nat) (dom :: Domain) a.
(KnownDomain dom, HasCallStack, NFDataX a) =>
Clock dom
-> Enable dom
-> SNat n
-> Signal dom Int
-> Signal dom Bool
-> Signal dom Int
-> Signal dom a
-> Signal dom a
blockRamU# Clock dom
clk Enable dom
en SNat n
n
(addr -> Int
forall a. Enum a => a -> Int
fromEnum (addr -> Int) -> Signal dom addr -> Signal dom Int
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Signal dom addr
rd0)
Signal dom Bool
we0
(addr -> Int
forall a. Enum a => a -> Int
fromEnum (addr -> Int) -> Signal dom addr -> Signal dom Int
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Signal dom addr
wa0)
Signal dom a
w0
where
rstBool :: Signal dom Bool
rstBool = Clock dom
-> Reset dom
-> Enable dom
-> Bool
-> Signal dom Bool
-> Signal dom Bool
forall (dom :: Domain) a.
(KnownDomain dom, NFDataX a) =>
Clock dom
-> Reset dom -> Enable dom -> a -> Signal dom a -> Signal dom a
register Clock dom
clk Reset dom
rst0 Enable dom
en Bool
True (Bool -> Signal dom Bool
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure Bool
False)
rstInv :: Reset dom
rstInv = Reset dom -> Reset dom
forall (dom :: Domain). Reset dom -> Reset dom
invertReset Reset dom
rst0
waCounter :: Signal dom (Index n)
waCounter :: Signal dom (Index n)
waCounter = Clock dom
-> Reset dom
-> Enable dom
-> Index n
-> Signal dom (Index n)
-> Signal dom (Index n)
forall (dom :: Domain) a.
(KnownDomain dom, NFDataX a) =>
Clock dom
-> Reset dom -> Enable dom -> a -> Signal dom a -> Signal dom a
register Clock dom
clk Reset dom
rstInv Enable dom
en Index n
0 (SaturationMode -> Index n -> Index n
forall a. SaturatingNum a => SaturationMode -> a -> a
satSucc SaturationMode
SatBound (Index n -> Index n)
-> Signal dom (Index n) -> Signal dom (Index n)
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Signal dom (Index n)
waCounter)
wa0 :: Signal dom addr
wa0 = (addr, a) -> addr
forall a b. (a, b) -> a
fst ((addr, a) -> addr)
-> (Maybe (addr, a) -> (addr, a)) -> Maybe (addr, a) -> addr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe (addr, a) -> (addr, a)
forall a. HasCallStack => Maybe a -> a
fromJustX (Maybe (addr, a) -> addr)
-> Signal dom (Maybe (addr, a)) -> Signal dom addr
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Signal dom (Maybe (addr, a))
mw0
w0 :: Signal dom a
w0 = (addr, a) -> a
forall a b. (a, b) -> b
snd ((addr, a) -> a)
-> (Maybe (addr, a) -> (addr, a)) -> Maybe (addr, a) -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe (addr, a) -> (addr, a)
forall a. HasCallStack => Maybe a -> a
fromJustX (Maybe (addr, a) -> a)
-> Signal dom (Maybe (addr, a)) -> Signal dom a
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Signal dom (Maybe (addr, a))
mw0
we0 :: Signal dom Bool
we0 = Maybe (addr, a) -> Bool
forall a. Maybe a -> Bool
isJust (Maybe (addr, a) -> Bool)
-> Signal dom (Maybe (addr, a)) -> Signal dom Bool
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Signal dom (Maybe (addr, a))
mw0
rd1 :: Signal dom Int
rd1 = Signal dom Bool
-> Signal dom Int -> Signal dom Int -> Signal dom Int
forall (f :: Type -> Type) a.
Applicative f =>
f Bool -> f a -> f a -> f a
mux Signal dom Bool
rstBool Signal dom Int
0 (addr -> Int
forall a. Enum a => a -> Int
fromEnum (addr -> Int) -> Signal dom addr -> Signal dom Int
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Signal dom addr
rd0)
we1 :: Signal dom Bool
we1 = Signal dom Bool
-> Signal dom Bool -> Signal dom Bool -> Signal dom Bool
forall (f :: Type -> Type) a.
Applicative f =>
f Bool -> f a -> f a -> f a
mux Signal dom Bool
rstBool (Bool -> Signal dom Bool
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure Bool
True) Signal dom Bool
we0
wa1 :: Signal dom Int
wa1 = Signal dom Bool
-> Signal dom Int -> Signal dom Int -> Signal dom Int
forall (f :: Type -> Type) a.
Applicative f =>
f Bool -> f a -> f a -> f a
mux Signal dom Bool
rstBool (Integer -> Int
forall a. Num a => Integer -> a
fromInteger (Integer -> Int) -> (Index n -> Integer) -> Index n -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Index n -> Integer
forall a. Integral a => a -> Integer
toInteger (Index n -> Int) -> Signal dom (Index n) -> Signal dom Int
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Signal dom (Index n)
waCounter) (addr -> Int
forall a. Enum a => a -> Int
fromEnum (addr -> Int) -> Signal dom addr -> Signal dom Int
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Signal dom addr
wa0)
w1 :: Signal dom a
w1 = Signal dom Bool -> Signal dom a -> Signal dom a -> Signal dom a
forall (f :: Type -> Type) a.
Applicative f =>
f Bool -> f a -> f a -> f a
mux Signal dom Bool
rstBool (Index n -> a
initF (Index n -> a) -> Signal dom (Index n) -> Signal dom a
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Signal dom (Index n)
waCounter) Signal dom a
w0
blockRamU#
:: forall n dom a
. ( KnownDomain dom
, HasCallStack
, NFDataX a )
=> Clock dom
-> Enable dom
-> SNat n
-> Signal dom Int
-> Signal dom Bool
-> Signal dom Int
-> Signal dom a
-> Signal dom a
blockRamU# :: Clock dom
-> Enable dom
-> SNat n
-> Signal dom Int
-> Signal dom Bool
-> Signal dom Int
-> Signal dom a
-> Signal dom a
blockRamU# Clock dom
clk Enable dom
en SNat n
SNat =
Clock dom
-> Enable dom
-> Vec n a
-> Signal dom Int
-> Signal dom Bool
-> Signal dom Int
-> Signal dom a
-> Signal dom a
forall (dom :: Domain) a (n :: Nat).
(KnownDomain dom, HasCallStack, NFDataX a) =>
Clock dom
-> Enable dom
-> Vec n a
-> Signal dom Int
-> Signal dom Bool
-> Signal dom Int
-> Signal dom a
-> Signal dom a
blockRam#
Clock dom
clk
Enable dom
en
((Int -> a) -> Vec n Int -> Vec n a
forall a b (n :: Nat). (a -> b) -> Vec n a -> Vec n b
CV.map
(\Int
i -> String -> a
forall a. (NFDataX a, HasCallStack) => String -> a
deepErrorX (String -> a) -> String -> a
forall a b. (a -> b) -> a -> b
$ String
"Initial value at index " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Int -> String
forall a. Show a => a -> String
show Int
i String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
" undefined.")
((Int -> Int) -> Int -> Vec n Int
forall (n :: Nat) a. KnownNat n => (a -> a) -> a -> Vec n a
iterateI @n Int -> Int
forall a. Enum a => a -> a
succ (Int
0 :: Int)))
{-# NOINLINE blockRamU# #-}
{-# ANN blockRamU# hasBlackBox #-}
blockRam1
:: forall n dom a r addr
. ( KnownDomain dom
, HasCallStack
, NFDataX a
, Enum addr
, 1 <= n )
=> Clock dom
-> Reset dom
-> Enable dom
-> ResetStrategy r
-> SNat n
-> a
-> Signal dom addr
-> Signal dom (Maybe (addr, a))
-> Signal dom a
blockRam1 :: Clock dom
-> Reset dom
-> Enable dom
-> ResetStrategy r
-> SNat n
-> a
-> Signal dom addr
-> Signal dom (Maybe (addr, a))
-> Signal dom a
blockRam1 Clock dom
clk Reset dom
rst0 Enable dom
en ResetStrategy r
rstStrategy n :: SNat n
n@SNat n
SNat a
a Signal dom addr
rd0 Signal dom (Maybe (addr, a))
mw0 =
case ResetStrategy r
rstStrategy of
ResetStrategy r
ClearOnReset ->
Clock dom
-> Enable dom
-> SNat n
-> a
-> Signal dom Int
-> Signal dom Bool
-> Signal dom Int
-> Signal dom a
-> Signal dom a
forall (n :: Nat) (dom :: Domain) a.
(KnownDomain dom, HasCallStack, NFDataX a) =>
Clock dom
-> Enable dom
-> SNat n
-> a
-> Signal dom Int
-> Signal dom Bool
-> Signal dom Int
-> Signal dom a
-> Signal dom a
blockRam1# Clock dom
clk Enable dom
en SNat n
n a
a Signal dom Int
rd1 Signal dom Bool
we1 Signal dom Int
wa1 Signal dom a
w1
ResetStrategy r
NoClearOnReset ->
Clock dom
-> Enable dom
-> SNat n
-> a
-> Signal dom Int
-> Signal dom Bool
-> Signal dom Int
-> Signal dom a
-> Signal dom a
forall (n :: Nat) (dom :: Domain) a.
(KnownDomain dom, HasCallStack, NFDataX a) =>
Clock dom
-> Enable dom
-> SNat n
-> a
-> Signal dom Int
-> Signal dom Bool
-> Signal dom Int
-> Signal dom a
-> Signal dom a
blockRam1# Clock dom
clk Enable dom
en SNat n
n a
a
(addr -> Int
forall a. Enum a => a -> Int
fromEnum (addr -> Int) -> Signal dom addr -> Signal dom Int
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Signal dom addr
rd0)
Signal dom Bool
we0
(addr -> Int
forall a. Enum a => a -> Int
fromEnum (addr -> Int) -> Signal dom addr -> Signal dom Int
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Signal dom addr
wa0)
Signal dom a
w0
where
rstBool :: Signal dom Bool
rstBool = Clock dom
-> Reset dom
-> Enable dom
-> Bool
-> Signal dom Bool
-> Signal dom Bool
forall (dom :: Domain) a.
(KnownDomain dom, NFDataX a) =>
Clock dom
-> Reset dom -> Enable dom -> a -> Signal dom a -> Signal dom a
register Clock dom
clk Reset dom
rst0 Enable dom
en Bool
True (Bool -> Signal dom Bool
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure Bool
False)
rstInv :: Reset dom
rstInv = Reset dom -> Reset dom
forall (dom :: Domain). Reset dom -> Reset dom
invertReset Reset dom
rst0
waCounter :: Signal dom (Index n)
waCounter :: Signal dom (Index n)
waCounter = Clock dom
-> Reset dom
-> Enable dom
-> Index n
-> Signal dom (Index n)
-> Signal dom (Index n)
forall (dom :: Domain) a.
(KnownDomain dom, NFDataX a) =>
Clock dom
-> Reset dom -> Enable dom -> a -> Signal dom a -> Signal dom a
register Clock dom
clk Reset dom
rstInv Enable dom
en Index n
0 (SaturationMode -> Index n -> Index n
forall a. SaturatingNum a => SaturationMode -> a -> a
satSucc SaturationMode
SatBound (Index n -> Index n)
-> Signal dom (Index n) -> Signal dom (Index n)
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Signal dom (Index n)
waCounter)
wa0 :: Signal dom addr
wa0 = (addr, a) -> addr
forall a b. (a, b) -> a
fst ((addr, a) -> addr)
-> (Maybe (addr, a) -> (addr, a)) -> Maybe (addr, a) -> addr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe (addr, a) -> (addr, a)
forall a. HasCallStack => Maybe a -> a
fromJustX (Maybe (addr, a) -> addr)
-> Signal dom (Maybe (addr, a)) -> Signal dom addr
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Signal dom (Maybe (addr, a))
mw0
w0 :: Signal dom a
w0 = (addr, a) -> a
forall a b. (a, b) -> b
snd ((addr, a) -> a)
-> (Maybe (addr, a) -> (addr, a)) -> Maybe (addr, a) -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe (addr, a) -> (addr, a)
forall a. HasCallStack => Maybe a -> a
fromJustX (Maybe (addr, a) -> a)
-> Signal dom (Maybe (addr, a)) -> Signal dom a
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Signal dom (Maybe (addr, a))
mw0
we0 :: Signal dom Bool
we0 = Maybe (addr, a) -> Bool
forall a. Maybe a -> Bool
isJust (Maybe (addr, a) -> Bool)
-> Signal dom (Maybe (addr, a)) -> Signal dom Bool
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Signal dom (Maybe (addr, a))
mw0
rd1 :: Signal dom Int
rd1 = Signal dom Bool
-> Signal dom Int -> Signal dom Int -> Signal dom Int
forall (f :: Type -> Type) a.
Applicative f =>
f Bool -> f a -> f a -> f a
mux Signal dom Bool
rstBool Signal dom Int
0 (addr -> Int
forall a. Enum a => a -> Int
fromEnum (addr -> Int) -> Signal dom addr -> Signal dom Int
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Signal dom addr
rd0)
we1 :: Signal dom Bool
we1 = Signal dom Bool
-> Signal dom Bool -> Signal dom Bool -> Signal dom Bool
forall (f :: Type -> Type) a.
Applicative f =>
f Bool -> f a -> f a -> f a
mux Signal dom Bool
rstBool (Bool -> Signal dom Bool
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure Bool
True) Signal dom Bool
we0
wa1 :: Signal dom Int
wa1 = Signal dom Bool
-> Signal dom Int -> Signal dom Int -> Signal dom Int
forall (f :: Type -> Type) a.
Applicative f =>
f Bool -> f a -> f a -> f a
mux Signal dom Bool
rstBool (Integer -> Int
forall a. Num a => Integer -> a
fromInteger (Integer -> Int) -> (Index n -> Integer) -> Index n -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Index n -> Integer
forall a. Integral a => a -> Integer
toInteger (Index n -> Int) -> Signal dom (Index n) -> Signal dom Int
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Signal dom (Index n)
waCounter) (addr -> Int
forall a. Enum a => a -> Int
fromEnum (addr -> Int) -> Signal dom addr -> Signal dom Int
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Signal dom addr
wa0)
w1 :: Signal dom a
w1 = Signal dom Bool -> Signal dom a -> Signal dom a -> Signal dom a
forall (f :: Type -> Type) a.
Applicative f =>
f Bool -> f a -> f a -> f a
mux Signal dom Bool
rstBool (a -> Signal dom a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure a
a) Signal dom a
w0
blockRam1#
:: forall n dom a
. ( KnownDomain dom
, HasCallStack
, NFDataX a )
=> Clock dom
-> Enable dom
-> SNat n
-> a
-> Signal dom Int
-> Signal dom Bool
-> Signal dom Int
-> Signal dom a
-> Signal dom a
blockRam1# :: Clock dom
-> Enable dom
-> SNat n
-> a
-> Signal dom Int
-> Signal dom Bool
-> Signal dom Int
-> Signal dom a
-> Signal dom a
blockRam1# Clock dom
clk Enable dom
en SNat n
n a
a =
Clock dom
-> Enable dom
-> Vec n a
-> Signal dom Int
-> Signal dom Bool
-> Signal dom Int
-> Signal dom a
-> Signal dom a
forall (dom :: Domain) a (n :: Nat).
(KnownDomain dom, HasCallStack, NFDataX a) =>
Clock dom
-> Enable dom
-> Vec n a
-> Signal dom Int
-> Signal dom Bool
-> Signal dom Int
-> Signal dom a
-> Signal dom a
blockRam# Clock dom
clk Enable dom
en (SNat n -> a -> Vec n a
forall (n :: Nat) a. SNat n -> a -> Vec n a
replicate SNat n
n a
a)
{-# NOINLINE blockRam1# #-}
{-# ANN blockRam1# hasBlackBox #-}
blockRam#
:: forall dom a n
. ( KnownDomain dom
, HasCallStack
, NFDataX a )
=> Clock dom
-> Enable dom
-> Vec n a
-> Signal dom Int
-> Signal dom Bool
-> Signal dom Int
-> Signal dom a
-> Signal dom a
blockRam# :: Clock dom
-> Enable dom
-> Vec n a
-> Signal dom Int
-> Signal dom Bool
-> Signal dom Int
-> Signal dom a
-> Signal dom a
blockRam# (Clock SSymbol dom
_) Enable dom
gen Vec n a
content = \Signal dom Int
rd Signal dom Bool
wen Signal dom Int
waS Signal dom a
wd -> (forall s. ST s (Signal dom a)) -> Signal dom a
forall a. (forall s. ST s a) -> a
runST ((forall s. ST s (Signal dom a)) -> Signal dom a)
-> (forall s. ST s (Signal dom a)) -> Signal dom a
forall a b. (a -> b) -> a -> b
$ do
STArray s Int a
ramStart <- (Int, Int) -> [a] -> ST s (STArray s Int a)
forall (a :: Type -> Type -> Type) e (m :: Type -> Type) i.
(MArray a e m, Ix i) =>
(i, i) -> [e] -> m (a i e)
newListArray (Int
0,Int
szIInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) [a]
contentL
STArray s Int a
-> a
-> Signal dom Bool
-> Signal dom Int
-> Signal dom Bool
-> Signal dom Int
-> Signal dom a
-> ST s (Signal dom a)
forall s.
STArray s Int a
-> a
-> Signal dom Bool
-> Signal dom Int
-> Signal dom Bool
-> Signal dom Int
-> Signal dom a
-> ST s (Signal dom a)
go
STArray s Int a
ramStart
((HasCallStack => a) -> a
forall a. HasCallStack => (HasCallStack => a) -> a
withFrozenCallStack (String -> a
forall a. (NFDataX a, HasCallStack) => String -> a
deepErrorX String
"blockRam: intial value undefined"))
(Enable dom -> Signal dom Bool
forall (dom :: Domain). Enable dom -> Signal dom Bool
fromEnable Enable dom
gen)
Signal dom Int
rd
(Enable dom -> Signal dom Bool
forall (dom :: Domain). Enable dom -> Signal dom Bool
fromEnable Enable dom
gen Signal dom Bool -> Signal dom Bool -> Signal dom Bool
forall (f :: Type -> Type).
Applicative f =>
f Bool -> f Bool -> f Bool
.&&. Signal dom Bool
wen)
Signal dom Int
waS
Signal dom a
wd
where
contentL :: [a]
contentL = Vec n a -> [a]
forall a b. a -> b
unsafeCoerce Vec n a
content :: [a]
szI :: Int
szI = [a] -> Int
forall (t :: Type -> Type) a. Foldable t => t a -> Int
L.length [a]
contentL
go :: STArray s Int a -> a -> Signal dom Bool -> Signal dom Int
-> Signal dom Bool -> Signal dom Int -> Signal dom a
-> ST s (Signal dom a)
go :: STArray s Int a
-> a
-> Signal dom Bool
-> Signal dom Int
-> Signal dom Bool
-> Signal dom Int
-> Signal dom a
-> ST s (Signal dom a)
go !STArray s Int a
ram a
o ret :: Signal dom Bool
ret@(~(Bool
re :- Signal dom Bool
res)) rt :: Signal dom Int
rt@(~(Int
r :- Signal dom Int
rs)) et :: Signal dom Bool
et@(~(Bool
e :- Signal dom Bool
en)) wt :: Signal dom Int
wt@(~(Int
w :- Signal dom Int
wr)) dt :: Signal dom a
dt@(~(a
d :- Signal dom a
din)) = do
a
o a -> ST s (Signal dom a) -> ST s (Signal dom a)
forall a b. a -> b -> b
`seqX` (a
o a -> Signal dom a -> Signal dom a
forall (dom :: Domain) a. a -> Signal dom a -> Signal dom a
:-) (Signal dom a -> Signal dom a)
-> ST s (Signal dom a) -> ST s (Signal dom a)
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> (Signal dom Bool
ret Signal dom Bool -> ST s (Signal dom a) -> ST s (Signal dom a)
`seq` Signal dom Int
rt Signal dom Int -> ST s (Signal dom a) -> ST s (Signal dom a)
`seq` Signal dom Bool
et Signal dom Bool -> ST s (Signal dom a) -> ST s (Signal dom a)
`seq` Signal dom Int
wt Signal dom Int -> ST s (Signal dom a) -> ST s (Signal dom a)
`seq` Signal dom a
dt Signal dom a -> ST s (Signal dom a) -> ST s (Signal dom a)
`seq`
ST s (Signal dom a) -> ST s (Signal dom a)
forall s a. ST s a -> ST s a
unsafeInterleaveST
(do a
o' <- IO a -> ST s a
forall a s. IO a -> ST s a
unsafeIOToST
(IO a -> (XException -> IO a) -> IO a
forall e a. Exception e => IO a -> (e -> IO a) -> IO a
catch (if Bool
re then ST s a -> IO a
forall s a. ST s a -> IO a
unsafeSTToIO (STArray s Int a
ram STArray s Int a -> Int -> ST s a
forall s. HasCallStack => STArray s Int a -> Int -> ST s a
`safeAt` Int
r) else a -> IO a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure a
o)
(\err :: XException
err@XException {} -> a -> IO a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure (XException -> a
forall a e. Exception e => e -> a
throw XException
err)))
a
d a -> ST s () -> ST s ()
forall a b. NFDataX a => a -> b -> b
`defaultSeqX` STArray s Int a -> Bool -> Int -> a -> ST s ()
forall s. STArray s Int a -> Bool -> Int -> a -> ST s ()
upd STArray s Int a
ram Bool
e (Int -> Int
forall a. Enum a => a -> Int
fromEnum Int
w) a
d
STArray s Int a
-> a
-> Signal dom Bool
-> Signal dom Int
-> Signal dom Bool
-> Signal dom Int
-> Signal dom a
-> ST s (Signal dom a)
forall s.
STArray s Int a
-> a
-> Signal dom Bool
-> Signal dom Int
-> Signal dom Bool
-> Signal dom Int
-> Signal dom a
-> ST s (Signal dom a)
go STArray s Int a
ram a
o' Signal dom Bool
res Signal dom Int
rs Signal dom Bool
en Signal dom Int
wr Signal dom a
din))
upd :: STArray s Int a -> Bool -> Int -> a -> ST s ()
upd :: STArray s Int a -> Bool -> Int -> a -> ST s ()
upd STArray s Int a
ram Bool
we Int
waddr a
d = case Bool -> Maybe Bool
forall a. a -> Maybe a
maybeIsX Bool
we of
Maybe Bool
Nothing -> case Int -> Maybe Int
forall a. a -> Maybe a
maybeIsX Int
waddr of
Maybe Int
Nothing ->
[Int] -> (Int -> ST s ()) -> ST s ()
forall (t :: Type -> Type) (m :: Type -> Type) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [Int
0..(Int
szIInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1)] (\Int
i -> STArray s Int a -> Int -> a -> ST s ()
forall s i e. STArray s i e -> Int -> e -> ST s ()
unsafeWriteSTArray STArray s Int a
ram Int
i (Int -> a -> a
seq Int
waddr a
d))
Just Int
wa ->
Int -> a -> STArray s Int a -> ST s ()
forall s. HasCallStack => Int -> a -> STArray s Int a -> ST s ()
safeUpdate Int
wa (Bool -> a -> a
seq Bool
we a
d) STArray s Int a
ram
Just Bool
True -> case Int -> Maybe Int
forall a. a -> Maybe a
maybeIsX Int
waddr of
Maybe Int
Nothing ->
[Int] -> (Int -> ST s ()) -> ST s ()
forall (t :: Type -> Type) (m :: Type -> Type) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [Int
0..(Int
szIInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1)] (\Int
i -> STArray s Int a -> Int -> a -> ST s ()
forall s i e. STArray s i e -> Int -> e -> ST s ()
unsafeWriteSTArray STArray s Int a
ram Int
i (Int -> a -> a
seq Int
waddr a
d))
Just Int
wa -> Int -> a -> STArray s Int a -> ST s ()
forall s. HasCallStack => Int -> a -> STArray s Int a -> ST s ()
safeUpdate Int
wa a
d STArray s Int a
ram
Maybe Bool
_ -> () -> ST s ()
forall (m :: Type -> Type) a. Monad m => a -> m a
return ()
safeAt :: HasCallStack => STArray s Int a -> Int -> ST s a
safeAt :: STArray s Int a -> Int -> ST s a
safeAt STArray s Int a
s Int
i =
if (Int
0 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
i) Bool -> Bool -> Bool
&& (Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
szI) then
STArray s Int a -> Int -> ST s a
forall s i e. STArray s i e -> Int -> ST s e
unsafeReadSTArray STArray s Int a
s Int
i
else a -> ST s a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure (a -> ST s a) -> a -> ST s a
forall a b. (a -> b) -> a -> b
$
(HasCallStack => a) -> a
forall a. HasCallStack => (HasCallStack => a) -> a
withFrozenCallStack
(String -> a
forall a. (NFDataX a, HasCallStack) => String -> a
deepErrorX (String
"blockRam: read address " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Int -> String
forall a. Show a => a -> String
show Int
i String -> String -> String
forall a. Semigroup a => a -> a -> a
<>
String
" not in range [0.." String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Int -> String
forall a. Show a => a -> String
show Int
szI String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
")"))
{-# INLINE safeAt #-}
safeUpdate :: HasCallStack => Int -> a -> STArray s Int a -> ST s ()
safeUpdate :: Int -> a -> STArray s Int a -> ST s ()
safeUpdate Int
i a
a STArray s Int a
s =
if (Int
0 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
i) Bool -> Bool -> Bool
&& (Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
szI) then
STArray s Int a -> Int -> a -> ST s ()
forall s i e. STArray s i e -> Int -> e -> ST s ()
unsafeWriteSTArray STArray s Int a
s Int
i a
a
else
let d :: a
d = (HasCallStack => a) -> a
forall a. HasCallStack => (HasCallStack => a) -> a
withFrozenCallStack
(String -> a
forall a. (NFDataX a, HasCallStack) => String -> a
deepErrorX (String
"blockRam: write address " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Int -> String
forall a. Show a => a -> String
show Int
i String -> String -> String
forall a. Semigroup a => a -> a -> a
<>
String
" not in range [0.." String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Int -> String
forall a. Show a => a -> String
show Int
szI String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
")"))
in [Int] -> (Int -> ST s ()) -> ST s ()
forall (t :: Type -> Type) (m :: Type -> Type) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [Int
0..(Int
szIInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1)] (\Int
j -> STArray s Int a -> Int -> a -> ST s ()
forall s i e. STArray s i e -> Int -> e -> ST s ()
unsafeWriteSTArray STArray s Int a
s Int
j a
d)
{-# INLINE safeUpdate #-}
{-# ANN blockRam# hasBlackBox #-}
{-# NOINLINE blockRam# #-}
readNew
:: ( KnownDomain dom
, NFDataX a
, Eq addr )
=> Clock dom
-> Reset dom
-> Enable dom
-> (Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a)
-> Signal dom addr
-> Signal dom (Maybe (addr, a))
-> Signal dom a
readNew :: Clock dom
-> Reset dom
-> Enable dom
-> (Signal dom addr
-> Signal dom (Maybe (addr, a)) -> Signal dom a)
-> Signal dom addr
-> Signal dom (Maybe (addr, a))
-> Signal dom a
readNew Clock dom
clk Reset dom
rst Enable dom
en Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a
ram Signal dom addr
rdAddr Signal dom (Maybe (addr, a))
wrM = Signal dom Bool -> Signal dom a -> Signal dom a -> Signal dom a
forall (f :: Type -> Type) a.
Applicative f =>
f Bool -> f a -> f a -> f a
mux Signal dom Bool
wasSame Signal dom a
wasWritten (Signal dom a -> Signal dom a) -> Signal dom a -> Signal dom a
forall a b. (a -> b) -> a -> b
$ Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a
ram Signal dom addr
rdAddr Signal dom (Maybe (addr, a))
wrM
where readNewT :: a -> Maybe (a, b) -> (Bool, b)
readNewT a
rd (Just (a
wr, b
wrdata)) = (a
wr a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
rd, b
wrdata)
readNewT a
_ Maybe (a, b)
Nothing = (Bool
False , b
forall a. HasCallStack => a
undefined)
(Signal dom Bool
wasSame,Signal dom a
wasWritten) =
Signal dom (Bool, a) -> Unbundled dom (Bool, a)
forall a (dom :: Domain).
Bundle a =>
Signal dom a -> Unbundled dom a
unbundle (Clock dom
-> Reset dom
-> Enable dom
-> (Bool, a)
-> Signal dom (Bool, a)
-> Signal dom (Bool, a)
forall (dom :: Domain) a.
(KnownDomain dom, NFDataX a) =>
Clock dom
-> Reset dom -> Enable dom -> a -> Signal dom a -> Signal dom a
register Clock dom
clk Reset dom
rst Enable dom
en (Bool
False, a
forall a. HasCallStack => a
undefined)
(addr -> Maybe (addr, a) -> (Bool, a)
forall a b. Eq a => a -> Maybe (a, b) -> (Bool, b)
readNewT (addr -> Maybe (addr, a) -> (Bool, a))
-> Signal dom addr -> Signal dom (Maybe (addr, a) -> (Bool, a))
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Signal dom addr
rdAddr Signal dom (Maybe (addr, a) -> (Bool, a))
-> Signal dom (Maybe (addr, a)) -> Signal dom (Bool, a)
forall (f :: Type -> Type) a b.
Applicative f =>
f (a -> b) -> f a -> f b
<*> Signal dom (Maybe (addr, a))
wrM))
data RamOp n a
= RamRead (Index n)
| RamWrite (Index n) a
| RamNoOp
deriving ((forall x. RamOp n a -> Rep (RamOp n a) x)
-> (forall x. Rep (RamOp n a) x -> RamOp n a)
-> Generic (RamOp n a)
forall x. Rep (RamOp n a) x -> RamOp n a
forall x. RamOp n a -> Rep (RamOp n a) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall (n :: Nat) a x. Rep (RamOp n a) x -> RamOp n a
forall (n :: Nat) a x. RamOp n a -> Rep (RamOp n a) x
$cto :: forall (n :: Nat) a x. Rep (RamOp n a) x -> RamOp n a
$cfrom :: forall (n :: Nat) a x. RamOp n a -> Rep (RamOp n a) x
Generic, HasCallStack => String -> RamOp n a
RamOp n a -> Bool
RamOp n a -> ()
RamOp n a -> RamOp n a
(HasCallStack => String -> RamOp n a)
-> (RamOp n a -> Bool)
-> (RamOp n a -> RamOp n a)
-> (RamOp n a -> ())
-> NFDataX (RamOp n a)
forall a.
(HasCallStack => String -> a)
-> (a -> Bool) -> (a -> a) -> (a -> ()) -> NFDataX a
forall (n :: Nat) a.
(NFDataX a, HasCallStack) =>
String -> RamOp n a
forall (n :: Nat) a. NFDataX a => RamOp n a -> Bool
forall (n :: Nat) a. NFDataX a => RamOp n a -> ()
forall (n :: Nat) a. NFDataX a => RamOp n a -> RamOp n a
rnfX :: RamOp n a -> ()
$crnfX :: forall (n :: Nat) a. NFDataX a => RamOp n a -> ()
ensureSpine :: RamOp n a -> RamOp n a
$censureSpine :: forall (n :: Nat) a. NFDataX a => RamOp n a -> RamOp n a
hasUndefined :: RamOp n a -> Bool
$chasUndefined :: forall (n :: Nat) a. NFDataX a => RamOp n a -> Bool
deepErrorX :: String -> RamOp n a
$cdeepErrorX :: forall (n :: Nat) a.
(NFDataX a, HasCallStack) =>
String -> RamOp n a
NFDataX, Int -> RamOp n a -> String -> String
[RamOp n a] -> String -> String
RamOp n a -> String
(Int -> RamOp n a -> String -> String)
-> (RamOp n a -> String)
-> ([RamOp n a] -> String -> String)
-> Show (RamOp n a)
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
forall (n :: Nat) a. Show a => Int -> RamOp n a -> String -> String
forall (n :: Nat) a. Show a => [RamOp n a] -> String -> String
forall (n :: Nat) a. Show a => RamOp n a -> String
showList :: [RamOp n a] -> String -> String
$cshowList :: forall (n :: Nat) a. Show a => [RamOp n a] -> String -> String
show :: RamOp n a -> String
$cshow :: forall (n :: Nat) a. Show a => RamOp n a -> String
showsPrec :: Int -> RamOp n a -> String -> String
$cshowsPrec :: forall (n :: Nat) a. Show a => Int -> RamOp n a -> String -> String
Show)
ramOpAddr :: RamOp n a -> Index n
ramOpAddr :: RamOp n a -> Index n
ramOpAddr (RamRead Index n
addr) = Index n
addr
ramOpAddr (RamWrite Index n
addr a
_) = Index n
addr
ramOpAddr RamOp n a
RamNoOp = String -> Index n
forall a. HasCallStack => String -> a
errorX String
"Address for No operation undefined"
isRamWrite :: RamOp n a -> Bool
isRamWrite :: RamOp n a -> Bool
isRamWrite (RamWrite {}) = Bool
True
isRamWrite RamOp n a
_ = Bool
False
ramOpWriteVal :: RamOp n a -> Maybe a
ramOpWriteVal :: RamOp n a -> Maybe a
ramOpWriteVal (RamWrite Index n
_ a
val) = a -> Maybe a
forall a. a -> Maybe a
Just a
val
ramOpWriteVal RamOp n a
_ = Maybe a
forall a. Maybe a
Nothing
isOp :: RamOp n a -> Bool
isOp :: RamOp n a -> Bool
isOp RamOp n a
RamNoOp = Bool
False
isOp RamOp n a
_ = Bool
True
trueDualPortBlockRam ::
forall nAddrs domA domB a .
( HasCallStack
, KnownNat nAddrs
, KnownDomain domA
, KnownDomain domB
, NFDataX a
)
=> Clock domA
-> Clock domB
-> Signal domA (RamOp nAddrs a)
-> Signal domB (RamOp nAddrs a)
-> (Signal domA a, Signal domB a)
{-# INLINE trueDualPortBlockRam #-}
trueDualPortBlockRam :: Clock domA
-> Clock domB
-> Signal domA (RamOp nAddrs a)
-> Signal domB (RamOp nAddrs a)
-> (Signal domA a, Signal domB a)
trueDualPortBlockRam = \Clock domA
clkA Clock domB
clkB Signal domA (RamOp nAddrs a)
opA Signal domB (RamOp nAddrs a)
opB ->
Clock domA
-> Signal domA Bool
-> Signal domA Bool
-> Signal domA (Index nAddrs)
-> Signal domA a
-> Clock domB
-> Signal domB Bool
-> Signal domB Bool
-> Signal domB (Index nAddrs)
-> Signal domB a
-> (Signal domA a, Signal domB a)
forall (nAddrs :: Nat) (domA :: Domain) (domB :: Domain) a.
(HasCallStack, KnownNat nAddrs, KnownDomain domA, KnownDomain domB,
NFDataX a) =>
Clock domA
-> Signal domA Bool
-> Signal domA Bool
-> Signal domA (Index nAddrs)
-> Signal domA a
-> Clock domB
-> Signal domB Bool
-> Signal domB Bool
-> Signal domB (Index nAddrs)
-> Signal domB a
-> (Signal domA a, Signal domB a)
trueDualPortBlockRamWrapper
Clock domA
clkA (RamOp nAddrs a -> Bool
forall (n :: Nat) a. RamOp n a -> Bool
isOp (RamOp nAddrs a -> Bool)
-> Signal domA (RamOp nAddrs a) -> Signal domA Bool
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Signal domA (RamOp nAddrs a)
opA) (RamOp nAddrs a -> Bool
forall (n :: Nat) a. RamOp n a -> Bool
isRamWrite (RamOp nAddrs a -> Bool)
-> Signal domA (RamOp nAddrs a) -> Signal domA Bool
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Signal domA (RamOp nAddrs a)
opA) (RamOp nAddrs a -> Index nAddrs
forall (n :: Nat) a. RamOp n a -> Index n
ramOpAddr (RamOp nAddrs a -> Index nAddrs)
-> Signal domA (RamOp nAddrs a) -> Signal domA (Index nAddrs)
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Signal domA (RamOp nAddrs a)
opA) (Maybe a -> a
forall a. HasCallStack => Maybe a -> a
fromJustX (Maybe a -> a)
-> (RamOp nAddrs a -> Maybe a) -> RamOp nAddrs a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RamOp nAddrs a -> Maybe a
forall (n :: Nat) a. RamOp n a -> Maybe a
ramOpWriteVal (RamOp nAddrs a -> a)
-> Signal domA (RamOp nAddrs a) -> Signal domA a
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Signal domA (RamOp nAddrs a)
opA)
Clock domB
clkB (RamOp nAddrs a -> Bool
forall (n :: Nat) a. RamOp n a -> Bool
isOp (RamOp nAddrs a -> Bool)
-> Signal domB (RamOp nAddrs a) -> Signal domB Bool
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Signal domB (RamOp nAddrs a)
opB) (RamOp nAddrs a -> Bool
forall (n :: Nat) a. RamOp n a -> Bool
isRamWrite (RamOp nAddrs a -> Bool)
-> Signal domB (RamOp nAddrs a) -> Signal domB Bool
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Signal domB (RamOp nAddrs a)
opB) (RamOp nAddrs a -> Index nAddrs
forall (n :: Nat) a. RamOp n a -> Index n
ramOpAddr (RamOp nAddrs a -> Index nAddrs)
-> Signal domB (RamOp nAddrs a) -> Signal domB (Index nAddrs)
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Signal domB (RamOp nAddrs a)
opB) (Maybe a -> a
forall a. HasCallStack => Maybe a -> a
fromJustX (Maybe a -> a)
-> (RamOp nAddrs a -> Maybe a) -> RamOp nAddrs a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RamOp nAddrs a -> Maybe a
forall (n :: Nat) a. RamOp n a -> Maybe a
ramOpWriteVal (RamOp nAddrs a -> a)
-> Signal domB (RamOp nAddrs a) -> Signal domB a
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Signal domB (RamOp nAddrs a)
opB)
toMaybeX :: a -> MaybeX a
toMaybeX :: a -> MaybeX a
toMaybeX a
a =
case a -> Either String a
forall a. a -> Either String a
isX a
a of
Left String
_ -> MaybeX a
forall a. MaybeX a
IsX
Right a
_ -> a -> MaybeX a
forall a. a -> MaybeX a
IsDefined a
a
data MaybeX a = IsX | IsDefined !a
data Conflict = Conflict
{ Conflict -> MaybeX Bool
cfWrite :: !(MaybeX Bool)
, Conflict -> MaybeX Int
cfAddress :: !(MaybeX Int) }
instance Semigroup Conflict where
<> :: Conflict -> Conflict -> Conflict
(<>) = Conflict -> Conflict -> Conflict
mergeConflicts
mergeConflicts :: Conflict -> Conflict -> Conflict
mergeConflicts :: Conflict -> Conflict -> Conflict
mergeConflicts Conflict
conflict1 Conflict
conflict2 = Conflict :: MaybeX Bool -> MaybeX Int -> Conflict
Conflict
{ cfWrite :: MaybeX Bool
cfWrite = MaybeX Bool -> MaybeX Bool -> MaybeX Bool
mergeWrite (Conflict -> MaybeX Bool
cfWrite Conflict
conflict1) (Conflict -> MaybeX Bool
cfWrite Conflict
conflict2)
, cfAddress :: MaybeX Int
cfAddress = MaybeX Int -> MaybeX Int -> MaybeX Int
forall a b. MaybeX a -> MaybeX b -> MaybeX a
mergeAddress (Conflict -> MaybeX Int
cfAddress Conflict
conflict1) (Conflict -> MaybeX Int
cfAddress Conflict
conflict2) }
where
mergeX :: (t -> t -> a) -> MaybeX t -> MaybeX t -> MaybeX a
mergeX t -> t -> a
_ MaybeX t
IsX MaybeX t
_ = MaybeX a
forall a. MaybeX a
IsX
mergeX t -> t -> a
_ MaybeX t
_ MaybeX t
IsX = MaybeX a
forall a. MaybeX a
IsX
mergeX t -> t -> a
f (IsDefined t
a) (IsDefined t
b) = a -> MaybeX a
forall a. a -> MaybeX a
IsDefined (t -> t -> a
f t
a t
b)
mergeWrite :: MaybeX Bool -> MaybeX Bool -> MaybeX Bool
mergeWrite MaybeX Bool
a MaybeX Bool
b = (Bool -> Bool -> Bool) -> MaybeX Bool -> MaybeX Bool -> MaybeX Bool
forall t t a. (t -> t -> a) -> MaybeX t -> MaybeX t -> MaybeX a
mergeX Bool -> Bool -> Bool
(||) MaybeX Bool
a MaybeX Bool
b
mergeAddress :: MaybeX a -> MaybeX b -> MaybeX a
mergeAddress MaybeX a
a MaybeX b
b = (a -> b -> a) -> MaybeX a -> MaybeX b -> MaybeX a
forall t t a. (t -> t -> a) -> MaybeX t -> MaybeX t -> MaybeX a
mergeX a -> b -> a
forall a b. a -> b -> a
const MaybeX a
a MaybeX b
b
trueDualPortBlockRamWrapper :: Clock domA
-> Signal domA Bool
-> Signal domA Bool
-> Signal domA (Index nAddrs)
-> Signal domA a
-> Clock domB
-> Signal domB Bool
-> Signal domB Bool
-> Signal domB (Index nAddrs)
-> Signal domB a
-> (Signal domA a, Signal domB a)
trueDualPortBlockRamWrapper Clock domA
clkA Signal domA Bool
enA Signal domA Bool
weA Signal domA (Index nAddrs)
addrA Signal domA a
datA Clock domB
clkB Signal domB Bool
enB Signal domB Bool
weB Signal domB (Index nAddrs)
addrB Signal domB a
datB =
Clock domA
-> Signal domA Bool
-> Signal domA Bool
-> Signal domA (Index nAddrs)
-> Signal domA a
-> Clock domB
-> Signal domB Bool
-> Signal domB Bool
-> Signal domB (Index nAddrs)
-> Signal domB a
-> (Signal domA a, Signal domB a)
forall (nAddrs :: Nat) (domA :: Domain) (domB :: Domain) a.
(HasCallStack, KnownNat nAddrs, KnownDomain domA, KnownDomain domB,
NFDataX a) =>
Clock domA
-> Signal domA Bool
-> Signal domA Bool
-> Signal domA (Index nAddrs)
-> Signal domA a
-> Clock domB
-> Signal domB Bool
-> Signal domB Bool
-> Signal domB (Index nAddrs)
-> Signal domB a
-> (Signal domA a, Signal domB a)
trueDualPortBlockRam# Clock domA
clkA Signal domA Bool
enA Signal domA Bool
weA Signal domA (Index nAddrs)
addrA Signal domA a
datA Clock domB
clkB Signal domB Bool
enB Signal domB Bool
weB Signal domB (Index nAddrs)
addrB Signal domB a
datB
{-# NOINLINE trueDualPortBlockRamWrapper #-}
trueDualPortBlockRam#, trueDualPortBlockRamWrapper ::
forall nAddrs domA domB a .
( HasCallStack
, KnownNat nAddrs
, KnownDomain domA
, KnownDomain domB
, NFDataX a
)
=> Clock domA
-> Signal domA Bool
-> Signal domA Bool
-> Signal domA (Index nAddrs)
-> Signal domA a
-> Clock domB
-> Signal domB Bool
-> Signal domB Bool
-> Signal domB (Index nAddrs)
-> Signal domB a
-> (Signal domA a, Signal domB a)
trueDualPortBlockRam# :: Clock domA
-> Signal domA Bool
-> Signal domA Bool
-> Signal domA (Index nAddrs)
-> Signal domA a
-> Clock domB
-> Signal domB Bool
-> Signal domB Bool
-> Signal domB (Index nAddrs)
-> Signal domB a
-> (Signal domA a, Signal domB a)
trueDualPortBlockRam# Clock domA
clkA Signal domA Bool
enA Signal domA Bool
weA Signal domA (Index nAddrs)
addrA Signal domA a
datA Clock domB
clkB Signal domB Bool
enB Signal domB Bool
weB Signal domB (Index nAddrs)
addrB Signal domB a
datB
| SNat (DomainConfigurationPeriod (KnownConf domA)) -> Int
forall a (n :: Nat). Num a => SNat n -> a
snatToNum @Int (forall (period :: Nat).
(KnownDomain domA,
DomainConfigurationPeriod (KnownConf domA) ~ period) =>
SNat period
forall (dom :: Domain) (period :: Nat).
(KnownDomain dom, DomainPeriod dom ~ period) =>
SNat period
clockPeriod @domA) Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< SNat (DomainConfigurationPeriod (KnownConf domB)) -> Int
forall a (n :: Nat). Num a => SNat n -> a
snatToNum @Int (forall (period :: Nat).
(KnownDomain domB,
DomainConfigurationPeriod (KnownConf domB) ~ period) =>
SNat period
forall (dom :: Domain) (period :: Nat).
(KnownDomain dom, DomainPeriod dom ~ period) =>
SNat period
clockPeriod @domB)
= (Signal domB a, Signal domA a) -> (Signal domA a, Signal domB a)
forall a b. (a, b) -> (b, a)
swap (Clock domB
-> Signal domB Bool
-> Signal domB Bool
-> Signal domB (Index nAddrs)
-> Signal domB a
-> Clock domA
-> Signal domA Bool
-> Signal domA Bool
-> Signal domA (Index nAddrs)
-> Signal domA a
-> (Signal domB a, Signal domA a)
forall (nAddrs :: Nat) (domFast :: Domain) (domSlow :: Domain) a.
(HasCallStack, KnownNat nAddrs, KnownDomain domSlow,
KnownDomain domFast, NFDataX a) =>
Clock domSlow
-> Signal domSlow Bool
-> Signal domSlow Bool
-> Signal domSlow (Index nAddrs)
-> Signal domSlow a
-> Clock domFast
-> Signal domFast Bool
-> Signal domFast Bool
-> Signal domFast (Index nAddrs)
-> Signal domFast a
-> (Signal domSlow a, Signal domFast a)
trueDualPortBlockRamModel Clock domB
clkB Signal domB Bool
enB Signal domB Bool
weB Signal domB (Index nAddrs)
addrB Signal domB a
datB Clock domA
clkA Signal domA Bool
enA Signal domA Bool
weA Signal domA (Index nAddrs)
addrA Signal domA a
datA)
| Bool
otherwise
= Clock domA
-> Signal domA Bool
-> Signal domA Bool
-> Signal domA (Index nAddrs)
-> Signal domA a
-> Clock domB
-> Signal domB Bool
-> Signal domB Bool
-> Signal domB (Index nAddrs)
-> Signal domB a
-> (Signal domA a, Signal domB a)
forall (nAddrs :: Nat) (domFast :: Domain) (domSlow :: Domain) a.
(HasCallStack, KnownNat nAddrs, KnownDomain domSlow,
KnownDomain domFast, NFDataX a) =>
Clock domSlow
-> Signal domSlow Bool
-> Signal domSlow Bool
-> Signal domSlow (Index nAddrs)
-> Signal domSlow a
-> Clock domFast
-> Signal domFast Bool
-> Signal domFast Bool
-> Signal domFast (Index nAddrs)
-> Signal domFast a
-> (Signal domSlow a, Signal domFast a)
trueDualPortBlockRamModel Clock domA
clkA Signal domA Bool
enA Signal domA Bool
weA Signal domA (Index nAddrs)
addrA Signal domA a
datA Clock domB
clkB Signal domB Bool
enB Signal domB Bool
weB Signal domB (Index nAddrs)
addrB Signal domB a
datB
{-# NOINLINE trueDualPortBlockRam# #-}
{-# ANN trueDualPortBlockRam# hasBlackBox #-}
trueDualPortBlockRamModel ::
forall nAddrs domFast domSlow a .
( HasCallStack
, KnownNat nAddrs
, KnownDomain domSlow
, KnownDomain domFast
, NFDataX a
) =>
Clock domSlow ->
Signal domSlow Bool ->
Signal domSlow Bool ->
Signal domSlow (Index nAddrs) ->
Signal domSlow a ->
Clock domFast ->
Signal domFast Bool ->
Signal domFast Bool ->
Signal domFast (Index nAddrs) ->
Signal domFast a ->
(Signal domSlow a, Signal domFast a)
trueDualPortBlockRamModel :: Clock domSlow
-> Signal domSlow Bool
-> Signal domSlow Bool
-> Signal domSlow (Index nAddrs)
-> Signal domSlow a
-> Clock domFast
-> Signal domFast Bool
-> Signal domFast Bool
-> Signal domFast (Index nAddrs)
-> Signal domFast a
-> (Signal domSlow a, Signal domFast a)
trueDualPortBlockRamModel !Clock domSlow
_clkA Signal domSlow Bool
enA Signal domSlow Bool
weA Signal domSlow (Index nAddrs)
addrA Signal domSlow a
datA !Clock domFast
_clkB Signal domFast Bool
enB Signal domFast Bool
weB Signal domFast (Index nAddrs)
addrB Signal domFast a
datB =
( String -> a
forall a. (NFDataX a, HasCallStack) => String -> a
deepErrorX String
"trueDualPortBlockRam: Port A: First value undefined" a -> Signal domSlow a -> Signal domSlow a
forall (dom :: Domain) a. a -> Signal dom a -> Signal dom a
:- Signal domSlow a
outA
, String -> a
forall a. (NFDataX a, HasCallStack) => String -> a
deepErrorX String
"trueDualPortBlockRam: Port B: First value undefined" a -> Signal domFast a -> Signal domFast a
forall (dom :: Domain) a. a -> Signal dom a -> Signal dom a
:- Signal domFast a
outB )
where
(Signal domSlow a
outA, Signal domFast a
outB) =
Maybe Conflict
-> Seq a
-> Int
-> Signal domSlow (Bool, Bool, Int, a)
-> Signal domFast (Bool, Bool, Int, a)
-> (Signal domSlow a, Signal domFast a)
go
Maybe Conflict
forall a. Maybe a
Nothing
(Int -> (Int -> a) -> Seq a
forall a. Int -> (Int -> a) -> Seq a
Seq.fromFunction (forall a. (Num a, KnownNat nAddrs) => a
forall (n :: Nat) a. (Num a, KnownNat n) => a
natToNum @nAddrs) Int -> a
initElement)
Int
tA
(Unbundled domSlow (Bool, Bool, Int, a)
-> Signal domSlow (Bool, Bool, Int, a)
forall a (dom :: Domain).
Bundle a =>
Unbundled dom a -> Signal dom a
bundle (Signal domSlow Bool
enA, Signal domSlow Bool
weA, Index nAddrs -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Index nAddrs -> Integer)
-> Signal domSlow (Index nAddrs) -> Signal domSlow Integer
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Signal domSlow (Index nAddrs)
addrA, Signal domSlow a
datA))
(Unbundled domFast (Bool, Bool, Int, a)
-> Signal domFast (Bool, Bool, Int, a)
forall a (dom :: Domain).
Bundle a =>
Unbundled dom a -> Signal dom a
bundle (Signal domFast Bool
enB, Signal domFast Bool
weB, Index nAddrs -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Index nAddrs -> Integer)
-> Signal domFast (Index nAddrs) -> Signal domFast Integer
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Signal domFast (Index nAddrs)
addrB, Signal domFast a
datB))
tA :: Int
tA = SNat (DomainConfigurationPeriod (KnownConf domSlow)) -> Int
forall a (n :: Nat). Num a => SNat n -> a
snatToNum @Int (forall (period :: Nat).
(KnownDomain domSlow,
DomainConfigurationPeriod (KnownConf domSlow) ~ period) =>
SNat period
forall (dom :: Domain) (period :: Nat).
(KnownDomain dom, DomainPeriod dom ~ period) =>
SNat period
clockPeriod @domSlow)
tB :: Int
tB = SNat (DomainConfigurationPeriod (KnownConf domFast)) -> Int
forall a (n :: Nat). Num a => SNat n -> a
snatToNum @Int (forall (period :: Nat).
(KnownDomain domFast,
DomainConfigurationPeriod (KnownConf domFast) ~ period) =>
SNat period
forall (dom :: Domain) (period :: Nat).
(KnownDomain dom, DomainPeriod dom ~ period) =>
SNat period
clockPeriod @domFast)
initElement :: Int -> a
initElement :: Int -> a
initElement Int
n =
String -> a
forall a. (NFDataX a, HasCallStack) => String -> a
deepErrorX (String
"Unknown initial element; position " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Int -> String
forall a. Show a => a -> String
show Int
n)
unknownEnableAndAddr :: Int -> a
unknownEnableAndAddr :: Int -> a
unknownEnableAndAddr Int
n =
String -> a
forall a. (NFDataX a, HasCallStack) => String -> a
deepErrorX (String
"Write enable and data unknown; position " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Int -> String
forall a. Show a => a -> String
show Int
n)
unknownAddr :: Int -> a
unknownAddr :: Int -> a
unknownAddr Int
n =
String -> a
forall a. (NFDataX a, HasCallStack) => String -> a
deepErrorX (String
"Write enabled, but address unknown; position " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Int -> String
forall a. Show a => a -> String
show Int
n)
getConflict :: Bool -> Int -> Bool -> Int -> Maybe Conflict
getConflict :: Bool -> Int -> Bool -> Int -> Maybe Conflict
getConflict Bool
enableA Int
addrA_ Bool
enableB Int
addrB_ =
if Bool
sameAddr then Maybe Conflict
maybeConflict else Maybe Conflict
forall a. Maybe a
Nothing
where
conflict :: Conflict
conflict = Conflict :: MaybeX Bool -> MaybeX Int -> Conflict
Conflict
{ cfWrite :: MaybeX Bool
cfWrite = Bool -> MaybeX Bool
forall a. a -> MaybeX a
toMaybeX Bool
enableA
, cfAddress :: MaybeX Int
cfAddress = Int -> MaybeX Int
forall a. a -> MaybeX a
toMaybeX Int
addrA_ }
maybeConflict :: Maybe Conflict
maybeConflict =
case (Bool -> Either String Bool
forall a. a -> Either String a
isX Bool
enableA, Bool -> Either String Bool
forall a. a -> Either String a
isX Bool
enableB) of
(Left String
_, Either String Bool
_) -> Conflict -> Maybe Conflict
forall a. a -> Maybe a
Just Conflict
conflict
(Right Bool
True, Either String Bool
_) -> Conflict -> Maybe Conflict
forall a. a -> Maybe a
Just Conflict
conflict
(Either String Bool
_, Left String
_) -> Conflict -> Maybe Conflict
forall a. a -> Maybe a
Just Conflict
conflict
(Either String Bool
_, Right Bool
True) -> Conflict -> Maybe Conflict
forall a. a -> Maybe a
Just Conflict
conflict
(Either String Bool, Either String Bool)
_ -> Maybe Conflict
forall a. Maybe a
Nothing
sameAddr :: Bool
sameAddr =
case (Int -> Either String Int
forall a. a -> Either String a
isX Int
addrA_, Int -> Either String Int
forall a. a -> Either String a
isX Int
addrB_) of
(Left String
_, Either String Int
_) -> Bool
True
(Either String Int
_, Left String
_) -> Bool
True
(Either String Int, Either String Int)
_ -> Int
addrA_ Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
addrB_
writeRam :: Bool -> Int -> a -> Seq a -> (Maybe a, Seq a)
writeRam :: Bool -> Int -> a -> Seq a -> (Maybe a, Seq a)
writeRam Bool
enable Int
addr a
dat Seq a
mem
| Bool
enableUndefined Bool -> Bool -> Bool
&& Bool
addrUndefined
= ( a -> Maybe a
forall a. a -> Maybe a
Just (String -> a
forall a. (NFDataX a, HasCallStack) => String -> a
deepErrorX String
"Unknown enable and address")
, Int -> (Int -> a) -> Seq a
forall a. Int -> (Int -> a) -> Seq a
Seq.fromFunction (forall a. (Num a, KnownNat nAddrs) => a
forall (n :: Nat) a. (Num a, KnownNat n) => a
natToNum @nAddrs) Int -> a
unknownEnableAndAddr )
| Bool
addrUndefined
= ( a -> Maybe a
forall a. a -> Maybe a
Just (String -> a
forall a. (NFDataX a, HasCallStack) => String -> a
deepErrorX String
"Unknown address")
, Int -> (Int -> a) -> Seq a
forall a. Int -> (Int -> a) -> Seq a
Seq.fromFunction (forall a. (Num a, KnownNat nAddrs) => a
forall (n :: Nat) a. (Num a, KnownNat n) => a
natToNum @nAddrs) Int -> a
unknownAddr )
| Bool
enableUndefined
= Bool -> Int -> a -> Seq a -> (Maybe a, Seq a)
writeRam Bool
True Int
addr (String -> a
forall a. (NFDataX a, HasCallStack) => String -> a
deepErrorX (String
"Write unknown; position" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Int -> String
forall a. Show a => a -> String
show Int
addr)) Seq a
mem
| Bool
enable
= (a -> Maybe a
forall a. a -> Maybe a
Just a
dat, Int -> a -> Seq a -> Seq a
forall a. Int -> a -> Seq a -> Seq a
Seq.update Int
addr a
dat Seq a
mem)
| Bool
otherwise
= (Maybe a
forall a. Maybe a
Nothing, Seq a
mem)
where
enableUndefined :: Bool
enableUndefined = Either String Bool -> Bool
forall a b. Either a b -> Bool
isLeft (Bool -> Either String Bool
forall a. a -> Either String a
isX Bool
enable)
addrUndefined :: Bool
addrUndefined = Either String Int -> Bool
forall a b. Either a b -> Bool
isLeft (Int -> Either String Int
forall a. a -> Either String a
isX Int
addr)
go ::
Maybe Conflict ->
Seq a ->
Int ->
Signal domSlow (Bool, Bool, Int, a) ->
Signal domFast (Bool, Bool, Int, a) ->
(Signal domSlow a, Signal domFast a)
go :: Maybe Conflict
-> Seq a
-> Int
-> Signal domSlow (Bool, Bool, Int, a)
-> Signal domFast (Bool, Bool, Int, a)
-> (Signal domSlow a, Signal domFast a)
go Maybe Conflict
conflict0 Seq a
ram0 Int
relativeTime Signal domSlow (Bool, Bool, Int, a)
as0 Signal domFast (Bool, Bool, Int, a)
bs0 =
if Int
relativeTime Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0 then (Signal domSlow a, Signal domFast a)
goSlow else (Signal domSlow a, Signal domFast a)
goFast
where
(Bool
enA_, Bool
weA_, Int
addrA_, a
datA_) :- Signal domSlow (Bool, Bool, Int, a)
as1 = Signal domSlow (Bool, Bool, Int, a)
as0
(Bool
enB_, Bool
weB_, Int
addrB_, a
datB_) :- Signal domFast (Bool, Bool, Int, a)
bs1 = Signal domFast (Bool, Bool, Int, a)
bs0
goSlow :: (Signal domSlow a, Signal domFast a)
goSlow = a
out1 a
-> (Signal domSlow a, Signal domFast a)
-> (Signal domSlow a, Signal domFast a)
forall a b. a -> b -> b
`seqX` (a
out1 a -> Signal domSlow a -> Signal domSlow a
forall (dom :: Domain) a. a -> Signal dom a -> Signal dom a
:- Signal domSlow a
as2, Signal domFast a
bs2)
where
(Maybe a
wrote, !Seq a
ram1) = Bool -> Int -> a -> Seq a -> (Maybe a, Seq a)
writeRam Bool
weA_ Int
addrA_ a
datA_ Seq a
ram0
out0 :: a
out0 = a -> Maybe a -> a
forall a. a -> Maybe a -> a
fromMaybe (Seq a
ram1 Seq a -> Int -> a
forall a. Seq a -> Int -> a
`Seq.index` Int
addrA_) Maybe a
wrote
(Signal domSlow a
as2, Signal domFast a
bs2) = Maybe Conflict
-> Seq a
-> Int
-> Signal domSlow (Bool, Bool, Int, a)
-> Signal domFast (Bool, Bool, Int, a)
-> (Signal domSlow a, Signal domFast a)
go Maybe Conflict
forall a. Maybe a
Nothing Seq a
ram1 (Int
relativeTime Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
tA) Signal domSlow (Bool, Bool, Int, a)
as1 Signal domFast (Bool, Bool, Int, a)
bs0
out1 :: a
out1 =
case Maybe Conflict
conflict0 of
Just Conflict{cfWrite :: Conflict -> MaybeX Bool
cfWrite=IsDefined Bool
True} ->
String -> a
forall a. (NFDataX a, HasCallStack) => String -> a
deepErrorX String
"trueDualPortBlockRam: conflicting read/write queries"
Just Conflict{cfWrite :: Conflict -> MaybeX Bool
cfWrite=MaybeX Bool
IsX} ->
String -> a
forall a. (NFDataX a, HasCallStack) => String -> a
deepErrorX String
"trueDualPortBlockRam: conflicting read/write queries"
Maybe Conflict
_ -> a
out0
goFast :: (Signal domSlow a, Signal domFast a)
goFast = a
out1 a
-> (Signal domSlow a, Signal domFast a)
-> (Signal domSlow a, Signal domFast a)
forall a b. a -> b -> b
`seqX` (Signal domSlow a
as2, a
out1 a -> Signal domFast a -> Signal domFast a
forall (dom :: Domain) a. a -> Signal dom a -> Signal dom a
:- Signal domFast a
bs2)
where
conflict1 :: Maybe Conflict
conflict1 | Bool
enA_ Bool -> Bool -> Bool
&& Bool
enB_ = Bool -> Int -> Bool -> Int -> Maybe Conflict
getConflict Bool
weB_ Int
addrB_ Bool
weA_ Int
addrA_
| Bool
otherwise = Maybe Conflict
forall a. Maybe a
Nothing
(Maybe a
wrote, !Seq a
ram1) = Bool -> Int -> a -> Seq a -> (Maybe a, Seq a)
writeRam Bool
weB_ Int
addrB_ a
datB_ Seq a
ram0
out0 :: a
out0 = a -> Maybe a -> a
forall a. a -> Maybe a -> a
fromMaybe (Seq a
ram1 Seq a -> Int -> a
forall a. Seq a -> Int -> a
`Seq.index` Int
addrB_) Maybe a
wrote
conflict2 :: Maybe Conflict
conflict2 = Maybe Conflict
conflict0 Maybe Conflict -> Maybe Conflict -> Maybe Conflict
forall a. Semigroup a => a -> a -> a
<> Maybe Conflict
conflict1
(Signal domSlow a
as2, Signal domFast a
bs2) = Maybe Conflict
-> Seq a
-> Int
-> Signal domSlow (Bool, Bool, Int, a)
-> Signal domFast (Bool, Bool, Int, a)
-> (Signal domSlow a, Signal domFast a)
go Maybe Conflict
conflict2 Seq a
ram1 (Int
relativeTime Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
tB) Signal domSlow (Bool, Bool, Int, a)
as0 Signal domFast (Bool, Bool, Int, a)
bs1
out1 :: a
out1 =
case Maybe Conflict
conflict1 of
Just Conflict{cfWrite :: Conflict -> MaybeX Bool
cfWrite=IsDefined Bool
False} ->
String -> a
forall a. (NFDataX a, HasCallStack) => String -> a
deepErrorX String
"trueDualPortBlockRam: conflicting read/write queries"
Just Conflict{cfWrite :: Conflict -> MaybeX Bool
cfWrite=MaybeX Bool
IsX} ->
String -> a
forall a. (NFDataX a, HasCallStack) => String -> a
deepErrorX String
"trueDualPortBlockRam: conflicting read/write queries"
Maybe Conflict
_ ->
a
out0