-----------------------------------------------------------------------------
-- |
-- Module  :  ForSyDe.Shallow.MoC.DomainInterface
-- Copyright   :  (c) ForSyDe Group, KTH 2007-2008
-- License     :  BSD-style (see the file LICENSE)
-- 
-- Maintainer  :  forsyde-dev@ict.kth.se
-- Stability   :  experimental
-- Portability :  portable
--
-- This module defines domain interface constructors for the multi-rate computational 
-- model.
-----------------------------------------------------------------------------
module ForSyDe.Shallow.MoC.DomainInterface(downDI, upDI, par2serxDI, ser2parxDI, 
        par2ser2DI, par2ser3DI, par2ser4DI, 
        ser2par2DI, ser2par3DI, ser2par4DI) where

import ForSyDe.Shallow.Core
import ForSyDe.Shallow.MoC.Synchronous


-- | The domain interface constructor 'downDI' takes a parameter 'k' and downsamples an input signal.
downDI     :: (Num a, Eq a) => a -> Signal b -> Signal b

-- | The domain interface constructors 'upDI' takes a parameter 'k' and upsamples an input signal.
upDI   :: (Num a, Eq a) => a -> Signal b -> Signal (AbstExt b)

-- | The domain interface constructor 'par2ser2DI' converts two parallel signals into one signal.
par2ser2DI :: Signal a -> Signal a -> Signal a

-- | The domain interface constructor 'par2ser3DI' converts three parallel signals into one signal
par2ser3DI :: Signal a -> Signal a -> Signal a -> Signal a

-- | The domain interface constructor 'par2ser4DI' converts four parallel signals into one signal
par2ser4DI :: Signal a -> Signal a -> Signal a -> Signal a 
       -> Signal a


-- | The domain interface constructor 'par2serxDI' converts n parallel signals into one signal.
par2serxDI :: Vector (Signal a) -> Signal a

-- | The domain interface constructor 'ser2par2DI' converts one signal into two parallel signals.
ser2par2DI :: Signal a -> (Signal (AbstExt a), Signal (AbstExt a))

-- | The domain interface constructor 'ser2par3DI' converts one signal into three parallel signals.
ser2par3DI :: Signal a -> (Signal (AbstExt a), Signal (AbstExt a), Signal (AbstExt a))

-- | The domain interface constructor 'ser2par4DI' converts one signal into four parallel signals.
ser2par4DI :: Signal a 
       -> (Signal (AbstExt a), Signal (AbstExt a), 
       Signal (AbstExt a), Signal (AbstExt a))

-- | The domain interface constructors 'ser2parxDI' converts one signal into n parallel signals.
ser2parxDI :: (Num a, Ord a) => a -> Signal (AbstExt b) 
              -> Vector (Signal (AbstExt b))

-- Implementation

downDI :: a -> Signal b -> Signal b
downDI a
n Signal b
xs     = a -> a -> Signal b -> Signal b
forall t a. (Eq t, Num t) => t -> t -> Signal a -> Signal a
down1 a
n a
1 Signal b
xs 
  where down1 :: t -> t -> Signal a -> Signal a
down1 t
_ t
_ Signal a
NullS   = Signal a
forall a. Signal a
NullS
        down1 t
1 t
1 (a
x:-Signal a
xs) = a
x a -> Signal a -> Signal a
forall a. a -> Signal a -> Signal a
:- t -> t -> Signal a -> Signal a
down1 t
1 t
1 Signal a
xs
        down1 t
n t
1 (a
x:-Signal a
xs) = a
x a -> Signal a -> Signal a
forall a. a -> Signal a -> Signal a
:- t -> t -> Signal a -> Signal a
down1 t
n t
2 Signal a
xs
        down1 t
n t
m (a
_:-Signal a
xs) = if t
m t -> t -> Bool
forall a. Eq a => a -> a -> Bool
== t
n then
                              t -> t -> Signal a -> Signal a
down1 t
n t
1 Signal a
xs
                            else
                              t -> t -> Signal a -> Signal a
down1 t
n (t
mt -> t -> t
forall a. Num a => a -> a -> a
+t
1) Signal a
xs 

upDI :: a -> Signal b -> Signal (AbstExt b)
upDI a
_ Signal b
NullS   = Signal (AbstExt b)
forall a. Signal a
NullS
upDI a
n (b
x:-Signal b
xs) = (b -> AbstExt b
forall a. a -> AbstExt a
Prst b
x) AbstExt b -> Signal (AbstExt b) -> Signal (AbstExt b)
forall a. a -> Signal a -> Signal a
:- ((a -> AbstExt b -> Signal (AbstExt b)
forall a b. (Num a, Eq a) => a -> b -> Signal b
copyS (a
na -> a -> a
forall a. Num a => a -> a -> a
-a
1) AbstExt b
forall a. AbstExt a
Abst) Signal (AbstExt b) -> Signal (AbstExt b) -> Signal (AbstExt b)
forall a. Signal a -> Signal a -> Signal a
+-+ a -> Signal b -> Signal (AbstExt b)
forall a b. (Num a, Eq a) => a -> Signal b -> Signal (AbstExt b)
upDI a
n Signal b
xs)

par2ser2DI :: Signal a -> Signal a -> Signal a
par2ser2DI Signal a
xs Signal a
ys  = Signal (a, a) -> Signal a
forall a. Signal (a, a) -> Signal a
par2ser2DI' (Signal a -> Signal a -> Signal (a, a)
forall a b. Signal a -> Signal b -> Signal (a, b)
zipSY Signal a
xs Signal a
ys)
  where par2ser2DI' :: Signal (a, a) -> Signal a
par2ser2DI' Signal (a, a)
NullS = Signal a
forall a. Signal a
NullS
        par2ser2DI' ((a
x,a
y):-Signal (a, a)
xys) = a
xa -> Signal a -> Signal a
forall a. a -> Signal a -> Signal a
:-a
ya -> Signal a -> Signal a
forall a. a -> Signal a -> Signal a
:-Signal (a, a) -> Signal a
par2ser2DI' Signal (a, a)
xys

par2ser3DI :: Signal a -> Signal a -> Signal a -> Signal a
par2ser3DI Signal a
xs Signal a
ys Signal a
zs = Signal (a, a, a) -> Signal a
forall a. Signal (a, a, a) -> Signal a
par2ser3DI' (Signal a -> Signal a -> Signal a -> Signal (a, a, a)
forall a b c. Signal a -> Signal b -> Signal c -> Signal (a, b, c)
zip3SY Signal a
xs Signal a
ys Signal a
zs)
  where par2ser3DI' :: Signal (a, a, a) -> Signal a
par2ser3DI' Signal (a, a, a)
NullS = Signal a
forall a. Signal a
NullS
        par2ser3DI' ((a
x,a
y,a
z):-Signal (a, a, a)
xyzs) = a
xa -> Signal a -> Signal a
forall a. a -> Signal a -> Signal a
:- a
y a -> Signal a -> Signal a
forall a. a -> Signal a -> Signal a
:-a
z a -> Signal a -> Signal a
forall a. a -> Signal a -> Signal a
:- Signal (a, a, a) -> Signal a
par2ser3DI' Signal (a, a, a)
xyzs

par2ser4DI :: Signal a -> Signal a -> Signal a -> Signal a -> Signal a
par2ser4DI Signal a
ws Signal a
xs Signal a
ys Signal a
zs = Signal (a, a, a, a) -> Signal a
forall a. Signal (a, a, a, a) -> Signal a
par2ser4DI' (Signal a -> Signal a -> Signal a -> Signal a -> Signal (a, a, a, a)
forall a b c d.
Signal a -> Signal b -> Signal c -> Signal d -> Signal (a, b, c, d)
zip4SY Signal a
ws Signal a
xs Signal a
ys Signal a
zs)
  where par2ser4DI' :: Signal (a, a, a, a) -> Signal a
par2ser4DI' Signal (a, a, a, a)
NullS = Signal a
forall a. Signal a
NullS
        par2ser4DI' ((a
w,a
x,a
y,a
z):-Signal (a, a, a, a)
wxyzs) 
          = a
wa -> Signal a -> Signal a
forall a. a -> Signal a -> Signal a
:-a
xa -> Signal a -> Signal a
forall a. a -> Signal a -> Signal a
:-a
ya -> Signal a -> Signal a
forall a. a -> Signal a -> Signal a
:-a
za -> Signal a -> Signal a
forall a. a -> Signal a -> Signal a
:- Signal (a, a, a, a) -> Signal a
par2ser4DI' Signal (a, a, a, a)
wxyzs

ser2par2DI :: Signal a -> (Signal (AbstExt a), Signal (AbstExt a))
ser2par2DI = Signal (AbstExt a, AbstExt a)
-> (Signal (AbstExt a), Signal (AbstExt a))
forall a b. Signal (a, b) -> (Signal a, Signal b)
unzipSY (Signal (AbstExt a, AbstExt a)
 -> (Signal (AbstExt a), Signal (AbstExt a)))
-> (Signal a -> Signal (AbstExt a, AbstExt a))
-> Signal a
-> (Signal (AbstExt a), Signal (AbstExt a))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Signal (AbstExt a) -> Signal (AbstExt a, AbstExt a)
forall t. Signal t -> Signal (t, t)
group2SY (Signal (AbstExt a) -> Signal (AbstExt a, AbstExt a))
-> (Signal a -> Signal (AbstExt a))
-> Signal a
-> Signal (AbstExt a, AbstExt a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AbstExt a -> Int -> Signal (AbstExt a) -> Signal (AbstExt a)
forall a. a -> Int -> Signal a -> Signal a
delaynSY AbstExt a
forall a. AbstExt a
Abst Int
2 (Signal (AbstExt a) -> Signal (AbstExt a))
-> (Signal a -> Signal (AbstExt a))
-> Signal a
-> Signal (AbstExt a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> AbstExt a) -> Signal a -> Signal (AbstExt a)
forall a b. (a -> b) -> Signal a -> Signal b
mapSY a -> AbstExt a
forall a. a -> AbstExt a
abstExt

ser2par3DI :: Signal a
-> (Signal (AbstExt a), Signal (AbstExt a), Signal (AbstExt a))
ser2par3DI = Signal (AbstExt a, AbstExt a, AbstExt a)
-> (Signal (AbstExt a), Signal (AbstExt a), Signal (AbstExt a))
forall a b c. Signal (a, b, c) -> (Signal a, Signal b, Signal c)
unzip3SY (Signal (AbstExt a, AbstExt a, AbstExt a)
 -> (Signal (AbstExt a), Signal (AbstExt a), Signal (AbstExt a)))
-> (Signal a -> Signal (AbstExt a, AbstExt a, AbstExt a))
-> Signal a
-> (Signal (AbstExt a), Signal (AbstExt a), Signal (AbstExt a))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Signal (AbstExt a) -> Signal (AbstExt a, AbstExt a, AbstExt a)
forall t. Signal t -> Signal (t, t, t)
group3SY (Signal (AbstExt a) -> Signal (AbstExt a, AbstExt a, AbstExt a))
-> (Signal a -> Signal (AbstExt a))
-> Signal a
-> Signal (AbstExt a, AbstExt a, AbstExt a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AbstExt a -> Int -> Signal (AbstExt a) -> Signal (AbstExt a)
forall a. a -> Int -> Signal a -> Signal a
delaynSY AbstExt a
forall a. AbstExt a
Abst Int
3 (Signal (AbstExt a) -> Signal (AbstExt a))
-> (Signal a -> Signal (AbstExt a))
-> Signal a
-> Signal (AbstExt a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> AbstExt a) -> Signal a -> Signal (AbstExt a)
forall a b. (a -> b) -> Signal a -> Signal b
mapSY a -> AbstExt a
forall a. a -> AbstExt a
abstExt

ser2par4DI :: Signal a
-> (Signal (AbstExt a), Signal (AbstExt a), Signal (AbstExt a),
    Signal (AbstExt a))
ser2par4DI = Signal (AbstExt a, AbstExt a, AbstExt a, AbstExt a)
-> (Signal (AbstExt a), Signal (AbstExt a), Signal (AbstExt a),
    Signal (AbstExt a))
forall a b c d.
Signal (a, b, c, d) -> (Signal a, Signal b, Signal c, Signal d)
unzip4SY (Signal (AbstExt a, AbstExt a, AbstExt a, AbstExt a)
 -> (Signal (AbstExt a), Signal (AbstExt a), Signal (AbstExt a),
     Signal (AbstExt a)))
-> (Signal a
    -> Signal (AbstExt a, AbstExt a, AbstExt a, AbstExt a))
-> Signal a
-> (Signal (AbstExt a), Signal (AbstExt a), Signal (AbstExt a),
    Signal (AbstExt a))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Signal (AbstExt a)
-> Signal (AbstExt a, AbstExt a, AbstExt a, AbstExt a)
forall t. Signal t -> Signal (t, t, t, t)
group4SY (Signal (AbstExt a)
 -> Signal (AbstExt a, AbstExt a, AbstExt a, AbstExt a))
-> (Signal a -> Signal (AbstExt a))
-> Signal a
-> Signal (AbstExt a, AbstExt a, AbstExt a, AbstExt a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AbstExt a -> Int -> Signal (AbstExt a) -> Signal (AbstExt a)
forall a. a -> Int -> Signal a -> Signal a
delaynSY AbstExt a
forall a. AbstExt a
Abst Int
4 (Signal (AbstExt a) -> Signal (AbstExt a))
-> (Signal a -> Signal (AbstExt a))
-> Signal a
-> Signal (AbstExt a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> AbstExt a) -> Signal a -> Signal (AbstExt a)
forall a b. (a -> b) -> Signal a -> Signal b
mapSY a -> AbstExt a
forall a. a -> AbstExt a
abstExt


par2serxDI :: Vector (Signal a) -> Signal a
par2serxDI = Signal (Vector a) -> Signal a
forall a. Signal (Vector a) -> Signal a
par2serxDI' (Signal (Vector a) -> Signal a)
-> (Vector (Signal a) -> Signal (Vector a))
-> Vector (Signal a)
-> Signal a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector (Signal a) -> Signal (Vector a)
forall a. Vector (Signal a) -> Signal (Vector a)
zipxSY 
  where par2serxDI' :: Signal (Vector a) -> Signal a
par2serxDI' Signal (Vector a)
NullS    = Signal a
forall a. Signal a
NullS
        par2serxDI' (Vector a
xv:-Signal (Vector a)
xs) = ([a] -> Signal a
forall a. [a] -> Signal a
signal ([a] -> Signal a) -> (Vector a -> [a]) -> Vector a -> Signal a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector a -> [a]
forall a. Vector a -> [a]
fromVector) Vector a
xv 
                               Signal a -> Signal a -> Signal a
forall a. Signal a -> Signal a -> Signal a
+-+ Signal (Vector a) -> Signal a
par2serxDI' Signal (Vector a)
xs 

ser2parxDI :: a -> Signal (AbstExt b) -> Vector (Signal (AbstExt b))
ser2parxDI a
n = Signal (Vector (AbstExt b)) -> Vector (Signal (AbstExt b))
forall a. Signal (Vector a) -> Vector (Signal a)
unzipxSY (Signal (Vector (AbstExt b)) -> Vector (Signal (AbstExt b)))
-> (Signal (AbstExt b) -> Signal (Vector (AbstExt b)))
-> Signal (AbstExt b)
-> Vector (Signal (AbstExt b))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector (AbstExt b)
-> Signal (Vector (AbstExt b)) -> Signal (Vector (AbstExt b))
forall a. a -> Signal a -> Signal a
delaySY (a -> AbstExt b -> Vector (AbstExt b)
forall a b. (Num a, Eq a) => a -> b -> Vector b
copyV a
n AbstExt b
forall a. AbstExt a
Abst) 
               (Signal (Vector (AbstExt b)) -> Signal (Vector (AbstExt b)))
-> (Signal (AbstExt b) -> Signal (Vector (AbstExt b)))
-> Signal (AbstExt b)
-> Signal (Vector (AbstExt b))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Signal (AbstExt (Vector (AbstExt b)))
-> Signal (Vector (AbstExt b))
forall a. Signal (AbstExt a) -> Signal a
filterAbstDI (Signal (AbstExt (Vector (AbstExt b)))
 -> Signal (Vector (AbstExt b)))
-> (Signal (AbstExt b) -> Signal (AbstExt (Vector (AbstExt b))))
-> Signal (AbstExt b)
-> Signal (Vector (AbstExt b))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Signal (AbstExt b) -> Signal (AbstExt (Vector (AbstExt b)))
forall a a1.
(Ord a, Num a) =>
a -> Signal a1 -> Signal (AbstExt (Vector a1))
group a
n

group2SY :: Signal t -> Signal (t, t)
group2SY :: Signal t -> Signal (t, t)
group2SY Signal t
NullS = Signal (t, t)
forall a. Signal a
NullS
group2SY (t
_:-Signal t
NullS) = Signal (t, t)
forall a. Signal a
NullS
group2SY (t
x:-t
y:-Signal t
xys) = (t
x, t
y) (t, t) -> Signal (t, t) -> Signal (t, t)
forall a. a -> Signal a -> Signal a
:- Signal t -> Signal (t, t)
forall t. Signal t -> Signal (t, t)
group2SY Signal t
xys

group3SY :: Signal t -> Signal (t, t, t)
group3SY :: Signal t -> Signal (t, t, t)
group3SY Signal t
NullS = Signal (t, t, t)
forall a. Signal a
NullS
group3SY (t
_:-Signal t
NullS) = Signal (t, t, t)
forall a. Signal a
NullS
group3SY (t
_:-t
_:-Signal t
NullS) = Signal (t, t, t)
forall a. Signal a
NullS
group3SY (t
x:-t
y:-t
z:-Signal t
xyzs) = (t
x, t
y, t
z) (t, t, t) -> Signal (t, t, t) -> Signal (t, t, t)
forall a. a -> Signal a -> Signal a
:- Signal t -> Signal (t, t, t)
forall t. Signal t -> Signal (t, t, t)
group3SY Signal t
xyzs

group4SY :: Signal t -> Signal (t, t, t, t)
group4SY :: Signal t -> Signal (t, t, t, t)
group4SY Signal t
NullS = Signal (t, t, t, t)
forall a. Signal a
NullS
group4SY (t
_:-Signal t
NullS) = Signal (t, t, t, t)
forall a. Signal a
NullS
group4SY (t
_:-t
_:-Signal t
NullS) = Signal (t, t, t, t)
forall a. Signal a
NullS
group4SY (t
_:-t
_:-t
_:-Signal t
NullS) = Signal (t, t, t, t)
forall a. Signal a
NullS
group4SY (t
w:-t
x:-t
y:-t
z:-Signal t
wxyzs) = (t
w, t
x, t
y, t
z) (t, t, t, t) -> Signal (t, t, t, t) -> Signal (t, t, t, t)
forall a. a -> Signal a -> Signal a
:- Signal t -> Signal (t, t, t, t)
forall t. Signal t -> Signal (t, t, t, t)
group4SY Signal t
wxyzs 


filterAbstDI :: Signal (AbstExt a) -> Signal a
filterAbstDI :: Signal (AbstExt a) -> Signal a
filterAbstDI Signal (AbstExt a)
NullS      = Signal a
forall a. Signal a
NullS
filterAbstDI (AbstExt a
Abst:-Signal (AbstExt a)
xs)     = Signal (AbstExt a) -> Signal a
forall a. Signal (AbstExt a) -> Signal a
filterAbstDI Signal (AbstExt a)
xs
filterAbstDI ((Prst a
x):-Signal (AbstExt a)
xs) = a
x a -> Signal a -> Signal a
forall a. a -> Signal a -> Signal a
:- Signal (AbstExt a) -> Signal a
forall a. Signal (AbstExt a) -> Signal a
filterAbstDI Signal (AbstExt a)
xs

group :: (Ord a, Num a) => a -> Signal a1 -> Signal (AbstExt (Vector a1))
group :: a -> Signal a1 -> Signal (AbstExt (Vector a1))
group a
n Signal a1
xs = ((Vector a1, a) -> AbstExt (Vector a1))
-> Signal (Vector a1, a) -> Signal (AbstExt (Vector a1))
forall a b. (a -> b) -> Signal a -> Signal b
mapSY (a -> (Vector a1, a) -> AbstExt (Vector a1)
forall a a. Eq a => a -> (a, a) -> AbstExt a
output a
n) (((Vector a1, a) -> a1 -> (Vector a1, a))
-> (Vector a1, a) -> Signal a1 -> Signal (Vector a1, a)
forall a b. (a -> b -> a) -> a -> Signal b -> Signal a
scanlSY (a -> (Vector a1, a) -> a1 -> (Vector a1, a)
forall a a.
(Ord a, Num a) =>
a -> (Vector a, a) -> a -> (Vector a, a)
addElement a
n)  (Vector a1
forall a. Vector a
NullV, a
0) Signal a1
xs)
  where addElement :: a -> (Vector a, a) -> a -> (Vector a, a)
addElement a
m (Vector a
vs, a
n) a
x | a
n a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
m  = (Vector a
vs Vector a -> a -> Vector a
forall a. Vector a -> a -> Vector a
<: a
x, a
na -> a -> a
forall a. Num a => a -> a -> a
+a
1)
                               | a
n a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
m = (a -> Vector a
forall a. a -> Vector a
unitV a
x, a
1)
                               | Bool
otherwise = [Char] -> (Vector a, a)
forall a. HasCallStack => [Char] -> a
error [Char]
"Vector of wrong size"
        output :: a -> (a, a) -> AbstExt a
output a
m (a
vs, a
n) | a
m a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
n = a -> AbstExt a
forall a. a -> AbstExt a
Prst a
vs
                         | Bool
otherwise = AbstExt a
forall a. AbstExt a
Abst