-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | ForSyDe's Haskell-embedded Domain Specific Language. -- -- The ForSyDe (Formal System Design) methodology has been developed with -- the objective to move system design to a higher level of abstraction -- and to bridge the abstraction gap by transformational design -- refinement. This library provides ForSyDe's implementation as a -- Haskell-embedded Domain Specific Language (DSL). For more information, -- please see ForSyDe's website: http://www.ict.kth.se/forsyde/. -- This will be most probably the last update on this package. It will be -- splitted to ForSyDe-shallow and ForSyDe-deep in the next release. @package ForSyDe @version 3.1.1 -- | This module defines the data type Vector and the corresponding -- functions. It is a development of the module defined by Reekie. Though -- the vector is modeled as a list, it should be viewed as an array, i.e. -- a vector has a fixed size. Unfortunately, it is not possible to have -- the size of the vector as a parameter of the vector data type, due to -- restrictions in Haskells type system. Still most operations are -- defined for vectors with the same size. module ForSyDe.Shallow.Vector -- | The data type Vector is modeled similar to a list. It has two -- data type constructors. NullV constructs the empty vector, -- while :> constructsa vector by adding an value to an -- existing vector. Using the inheritance mechanism of Haskell we have -- declared Vector as an instance of the classes Read and -- Show. -- -- | This means that the vector 1:>2:>3:>NullV is shown as -- 1,2,3. data Vector a NullV :: Vector a (:>) :: a -> (Vector a) -> Vector a -- | The function vector converts a list into a vector. vector :: [a] -> Vector a -- | The function fromVector converts a vector into a list. fromVector :: Vector a -> [a] -- | The function unitV creates a vector with one element. unitV :: a -> Vector a -- | The function nullV returns True if a vector is empty. nullV :: Vector a -> Bool -- | The function lengthV returns the number of elements in a value. lengthV :: Vector a -> Int -- | The function atV returns the n-th element in a vector, starting -- from zero. atV :: (Num a) => Vector b -> a -> b -- | The function replaceV replaces an element in a vector. replaceV :: Vector a -> Int -> a -> Vector a -- | The functions headV returns the first element of a vector. headV :: Vector a -> a -- | The functions tailV returns all, but the first element of a -- vector. tailV :: Vector a -> Vector a -- | The function lastV returns the last element of a vector. lastV :: Vector a -> a -- | The function initV returns all but the last elements of a -- vector. initV :: Vector a -> Vector a -- | The function takeV returns the first n elements of a vector. takeV :: (Num a, Ord a) => a -> Vector b -> Vector b -- | The function dropV drops the first n elements of a vector. dropV :: (Num a, Ord a) => a -> Vector b -> Vector b -- | The function selectV selects elements in the vector. The first -- argument gives the initial element, starting from zero, the second -- argument gives the stepsize between elements and the last argument -- gives the number of elements. selectV :: Int -> Int -> Int -> Vector a -> Vector a -- | The function groupV groups a vector into a vector of vectors of -- size n. groupV :: Int -> Vector a -> Vector (Vector a) -- | The operator '(+)' concatinates two vectors. (<+>) :: Vector a -> Vector a -> Vector a -- | The operator '(<:)' adds an element at the end of a vector. (<:) :: Vector a -> a -> Vector a -- | The higher-order function mapV applies a function on all -- elements of a vector. mapV :: (a -> b) -> Vector a -> Vector b -- | The higher-order functions foldlV folds a function from the -- right to the left over a vector using an initial value. foldlV :: (a -> b -> a) -> a -> Vector b -> a -- | The higher-order functions foldrV folds a function from the -- left to the right over a vector using an initial value. foldrV :: (b -> a -> a) -> a -> Vector b -> a -- | The higher-order function zipWithV applies a function pairwise -- on to vectors. zipWithV :: (a -> b -> c) -> Vector a -> Vector b -> Vector c -- | The higher-function filterV takes a predicate function and a -- vector and creates a new vector with the elements for which the -- predicate is true. filterV :: (a -> Bool) -> Vector a -> Vector a -- | The function zipV zips two vectors into a vector of tuples. zipV :: Vector a -> Vector b -> Vector (a, b) -- | The function unzipV unzips a vector of tuples into two vectors. unzipV :: Vector (a, b) -> (Vector a, Vector b) -- | The function concatV transforms a vector of vectors to a single -- vector. concatV :: Vector (Vector a) -> Vector a -- | The function reverseV reverses the order of elements in a -- vector. reverseV :: Vector a -> Vector a -- | The function shiftlV shifts a value from the left into a -- vector. shiftlV :: Vector a -> a -> Vector a -- | The function shiftrV shifts a value from the right into a -- vector. shiftrV :: Vector a -> a -> Vector a -- | The function rotrV rotates a vector to the right. Note that -- this fuction does not change the size of a vector. rotrV :: Vector a -> Vector a -- | The function rotlV rotates a vector to the left. Note that this -- fuctions does not change the size of a vector. rotlV :: Vector a -> Vector a -- | The function generateV behaves in the same way, but starts with -- the application of the supplied function to the supplied value. -- --
--   Vector> generateV 5 (+1) 1
--   
-- --
--   <2,3,4,5,6> :: Vector Integer
--   
generateV :: (Num a) => a -> (b -> b) -> b -> Vector b -- | The function iterateV generates a vector with a given number of -- elements starting from an initial element using a supplied function -- for the generation of elements. -- --
--   Vector> iterateV 5 (+1) 1
--   
-- --
--   <1,2,3,4,5> :: Vector Integer
--   
iterateV :: (Num a) => a -> (b -> b) -> b -> Vector b -- | The function copyV generates a vector with a given number of -- copies of the same element. -- --
--   Vector> copyV 7 5 
--   
-- --
--   <5,5,5,5,5,5,5> :: Vector Integer
--   
copyV :: (Num a) => a -> b -> Vector b instance (Eq a) => Eq (Vector a) instance (Read a) => Read (Vector a) instance (Show a) => Show (Vector a) -- | This module includes the standard Discrete Fourier Transform (DFT) -- function, and a fast Fourier transform (FFT) algorithm, for computing -- the DFT, when the input vectors' length is a power of 2. module ForSyDe.Shallow.DFT -- | The function dft performs a standard Discrete Fourier -- Transformation dft :: Int -> Vector (Complex Double) -> Vector (Complex Double) -- | The function fft implements a fast Fourier transform (FFT) -- algorithm, for computing the DFT, when the size N is a power of 2. fft :: Int -> Vector (Complex Double) -> Vector (Complex Double) -- | It defines the bit vector operations from/to integer. module ForSyDe.Shallow.BitVector type BitVector = Vector Integer data Parity Even :: Parity Odd :: Parity -- | To transform the input integer to a bit-vector with specified number -- of bits. intToBitVector :: Int -> Integer -> BitVector -- | To transform the input bit-vecotr to an integer. bitVectorToInt :: BitVector -> Integer -- | To add even parity bit on the bit-vector in the tail. addEvenParityBit :: (Num a) => Vector a -> Vector a -- | To add odd parity bit on the bit-vector in the tail. addOddParityBit :: (Num a) => Vector a -> Vector a addParityBit :: (Num a) => Parity -> Vector a -> Vector a -- | To remove the parity bit in the tail. removeParityBit :: (Num t) => Vector t -> Vector t -- | To check the even parity of the bit-vector. isEvenParity :: (Num t) => Vector t -> Bool -- | To check the odd parity of the bit-vector. isOddParity :: (Num t) => Vector t -> Bool -- | To judge whether the input bit-vector is in a proper form. isBitVector :: (Num t) => Vector t -> Bool instance Show Parity instance Eq Parity -- | This is the polynomial arithematic library. The arithematic operations -- include addition, multiplication, division and power. However, the -- computation time is not optimized for multiplication and is O(n2), -- which could be considered to be optimized by FFT algorithms later on. module ForSyDe.Shallow.PolyArith -- | Polynomial data type. data (Num a) => Poly a Poly :: [a] -> Poly a PolyPair :: (Poly a, Poly a) -> Poly a -- | Addition operations of polynomials. addPoly :: (Num a) => Poly a -> Poly a -> Poly a -- | Multiplication operation of polynomials. mulPoly :: (Num a) => Poly a -> Poly a -> Poly a -- | Division operation of polynomials. divPoly :: (Num a) => Poly a -> Poly a -> Poly a -- | Power operation of polynomials. powerPoly :: (Num a) => Poly a -> Int -> Poly a -- | Some helper functions below. -- -- To get the coefficients of the polynomial. getCoef :: (Num a) => Poly a -> ([a], [a]) scalePoly :: (Num a) => a -> Poly a -> Poly a addPolyCoef :: (Num a) => [a] -> [a] -> [a] subPolyCoef :: (RealFloat a) => [a] -> [a] -> [a] scalePolyCoef :: (Num a) => a -> [a] -> [a] instance (Num a) => Eq (Poly a) -- | This module defines the shallow-embedded Signal datatype and -- functions operating on it. module ForSyDe.Shallow.Signal -- | A signal is defined as a list of events. An event has a tag and a -- value. The tag of an event is defined by the position in the list. A -- signal is defined as an instance of the classes Read and -- Show. The signal 1 :- 2 :- NullS is represented as {1,2}. data Signal a NullS :: Signal a (:-) :: a -> Signal a -> Signal a -- | The operator -: adds at an element to a signal at the tail. (-:) :: Signal a -> a -> Signal a -- | The operator +-+ concatinates two signals into one signal. (+-+) :: Signal a -> Signal a -> Signal a (!-) :: Signal a -> Int -> a -- | The function signal converts a list into a signal. signal :: [a] -> Signal a -- | The function fromSignal converts a signal into a list. fromSignal :: Signal a -> [a] -- | The function unitS creates a signal with one value. unitS :: a -> Signal a -- | The function nullS checks if a signal is empty. nullS :: Signal a -> Bool -- | The function headS gives the first value - the head - of a -- signal. headS :: Signal a -> a -- | The function tailS gives the rest of the signal - the tail. tailS :: Signal a -> Signal a -- | The function atS returns the n-th event in a signal. The -- numbering of events in a signal starts with 0. There is also an -- operator version of this function, '(!-)'. atS :: Int -> Signal a -> a -- | The function takeS returns the first n values of a signal. takeS :: Int -> Signal a -> Signal a -- | The function dropS drops the first $n$ values from a signal. dropS :: Int -> Signal a -> Signal a -- | The function lengthS returns the length of a finite -- signal. lengthS :: Signal b -> Int -- | The function infiniteS creates an infinite signal. The first -- argument f is a function that is applied on the current -- value. The second argument x gives the first value of the -- signal. -- --
--   Signal> takeS 5 (infiniteS (*3) 1)
--   {1,3,9,27,81} :: Signal Integer
--   
infiniteS :: (a -> a) -> a -> Signal a -- | The function copyS creates a signal with n values x. copyS :: (Num a) => a -> b -> Signal b -- | The function selectS takes three parameters, an offset, a -- stepsize and a signal and returns some elements of the signal such as -- in the following example: -- --
--   Signal> selectS 2 3 (signal[1,2,3,4,5,6,7,8,9,10])
--   {3,6,9} :: Signal Integer
--   
selectS :: Int -> Int -> Signal a -> Signal a -- | The function writeS transforms a signal into a string of the -- following format: -- --
--   
--   Signal> writeS (signal[1,2,3,4,5])
--   1n2n3n4n5n :: [Char]
--   
writeS :: (Show a) => Signal a -> [Char] -- | The function readS transforms a formatted string into a signal. -- --
--   Signal> readS 1n2n3n4n5n :: Signal Int
--   {1,2,3,4,5} :: Signal Int
--   
readS :: (Read a) => [Char] -> Signal a -- | The combinator fanS takes two processes p1 and -- p2 and and generates a process network, where a signal is -- split and processed by the processes p1 and p2. fanS :: (Signal a -> Signal b) -> (Signal a -> Signal c) -> Signal a -> (Signal b, Signal c) instance (Eq a) => Eq (Signal a) instance (Read a) => Read (Signal a) instance (Show a) => Show (Signal a) -- | The AbstExt is used to extend existing data types with the -- value 'absent', which models the absence of a value. module ForSyDe.Shallow.AbsentExt -- | The data type AbstExt has two constructors. The constructor -- Abst is used to model the absence of a value, while the -- constructor Prst is used to model present values. data AbstExt a Abst :: AbstExt a Prst :: a -> AbstExt a -- | The function fromAbstExt converts a value from a extended -- value. fromAbstExt :: a -> AbstExt a -> a -- | The function abstExt converts a usual value to a present value. abstExt :: a -> AbstExt a -- | The function psi is identical to abstExtFunc and should -- be used in future. psi :: (a -> b) -> AbstExt a -> AbstExt b -- | The functions isAbsent checks for the absence of a value. isAbsent :: AbstExt a -> Bool -- | The functions isPresent checks for the presence of a value. isPresent :: AbstExt a -> Bool -- | The function abstExtFunc extends a function in order to process -- absent extended values. If the input is ("bottom"), the output will -- also be ("bottom"). abstExtFunc :: (a -> b) -> AbstExt a -> AbstExt b instance (Eq a) => Eq (AbstExt a) instance (Read a) => Read (AbstExt a) instance (Show a) => Show (AbstExt a) -- | This provides two data types, that can be used to model queue -- structures, such as FIFOs. There is a data type for an queue of -- infinite size Queue and one for finite size FiniteQueue. module ForSyDe.Shallow.Queue -- | A queue is modeled as a list. The data type Queue modelles an -- queue of infinite size. data Queue a Q :: [a] -> Queue a -- | The data type FiniteQueue has an additional parameter, that -- determines the size of the queue. data FiniteQueue a FQ :: Int -> [a] -> FiniteQueue a -- | pushQ pushes one element into an infinite queue. pushQ :: Queue a -> a -> Queue a -- | pushListQ pushes a list of elements into an infinite queue. pushListQ :: Queue a -> [a] -> Queue a -- | popQ pops one element from an infinite queue. popQ :: Queue a -> (Queue a, AbstExt a) -- | queue transforms a list into an infinite queue. queue :: [a] -> Queue a -- | pushFQ pushes one element into a finite queue. pushFQ :: FiniteQueue a -> a -> FiniteQueue a -- | pushListFQ pushes a list of elements into a finite queue. pushListFQ :: FiniteQueue a -> [a] -> FiniteQueue a -- | popFQ pops one element from a finite queue. popFQ :: FiniteQueue a -> (FiniteQueue a, AbstExt a) -- | finiteQueue transforms a list into an infinite queue. finiteQueue :: Int -> [a] -> FiniteQueue a instance (Eq a) => Eq (FiniteQueue a) instance (Show a) => Show (FiniteQueue a) instance (Eq a) => Eq (Queue a) instance (Show a) => Show (Queue a) -- | This module contains the data structure and access functions for the -- memory model. module ForSyDe.Shallow.Memory -- | The data type Memory is modeled as a vector. data Memory a Mem :: Adr -> (Vector (AbstExt a)) -> Memory a -- | The data type Access defines two access patterns. data Access a -- | 'Read adr' reads an address from the memory. Read :: Adr -> Access a -- | 'Write Adr a' writes a value into an address. Write :: Adr -> a -> Access a type MemSize = Int type Adr = Int -- | The function newMem creates a new memory, where the number of -- entries is given by a parameter. newMem :: MemSize -> Memory a -- | The function memState gives the new state of the memory, after -- an access to a memory. A Read operation leaves the memory -- unchanged. memState :: Memory a -> Access a -> Memory a -- | The function memOutput gives the output of the memory after an -- access to the memory. A Write operation gives an absent value -- as output. memOutput :: Memory a -> Access a -> AbstExt a instance (Eq a) => Eq (Access a) instance (Show a) => Show (Access a) instance (Eq a) => Eq (Memory a) instance (Show a) => Show (Memory a) -- | The ForSyDeUtilityLib is a container including all libraries that are -- related to the ForSyDe shallow-embedded implementation and either -- extend the ForSyDe MoC libraries or add additional functionality to -- ForSyDe. -- -- module ForSyDe.Shallow.UtilityLib -- | The CoreLib is the base for all MoC libraries and is a container that -- includes the following libraries: -- -- module ForSyDe.Shallow.CoreLib -- | The synchronuous library defines process constructors and processes -- for the synchronous computational model. A process constructor is a -- higher order function which together with combinational function(s) -- and values as arguments constructs a process. module ForSyDe.Shallow.SynchronousLib -- | The process constructor mapSY takes a combinational function as -- argument and returns a process with one input signal and one output -- signal. mapSY :: (a -> b) -> Signal a -> Signal b -- | The process constructor zipWithSY takes a combinational -- function as argument and returns a process with two input signals and -- one output signal. zipWithSY :: (a -> b -> c) -> Signal a -> Signal b -> Signal c -- | The process constructor zipWith3SY takes a combinational -- function as argument and returns a process with three input signals -- and one output signal. zipWith3SY :: (a -> b -> c -> d) -> Signal a -> Signal b -> Signal c -> Signal d -- | The process constructor zipWith4SY takes a combinational -- function as argument and returns a process with four input signals and -- one output signal. zipWith4SY :: (a -> b -> c -> d -> e) -> Signal a -> Signal b -> Signal c -> Signal d -> Signal e -- | The process constructor zipWithxSY works as zipWithSY, -- but takes a vector of signals as input. zipWithxSY :: (Vector a -> b) -> Vector (Signal a) -> Signal b -- | The process constructor delaySY delays the signal one event -- cycle by introducing an initial value at the beginning of the output -- signal. Note, that this implies that there is one event (the first) at -- the output signal that has no corresponding event at the input signal. -- One could argue that input and output signals are not fully -- synchronized, even though all input events are synchronous with a -- corresponding output event. However, this is necessary to initialize -- feed-back loops. delaySY :: a -> Signal a -> Signal a -- | The process constructor delaynSY delays the signal n events by -- introducing n identical default values. delaynSY :: a -> Int -> Signal a -> Signal a -- | The process constructor scanlSY is used to construct a finite -- state machine process without output decoder. It takes an initial -- value and a function for the next state decoder. The process -- constructor behaves similar to the Haskell prelude function -- scanlSY and has the value of the new state as its output value -- as illustrated by the following example. -- --
--   SynchronousLib> scanldSY (+) 0 (signal [1,2,3,4])
--   
-- --
--   {1,3,6,10} :: Signal Integer
--   
-- -- This is in contrast to the function scanldSY, which has its -- current state as its output value. scanlSY :: (a -> b -> a) -> a -> Signal b -> Signal a -- | The process constructor scanl2SY behaves like scanlSY, -- but has two input signals. scanl2SY :: (a -> b -> c -> a) -> a -> Signal b -> Signal c -> Signal a -- | The process constructor scanl3SY behaves like scanlSY, -- but has three input signals. scanl3SY :: (a -> b -> c -> d -> a) -> a -> Signal b -> Signal c -> Signal d -> Signal a -- | The process constructor scanldSY is used to construct a finite -- state machine process without output decoder. It takes an initial -- value and a function for the next state decoder. The process -- constructor behaves similar to the Haskell prelude function -- scanlSY. In contrast to the process constructor scanlSY -- here the output value is the current state and not the one of the next -- state. -- --
--   SynchronousLib> scanlSY (+) 0 (signal [1,2,3,4])
--   
-- --
--   {0,1,3,6} :: Signal Integer
--   
scanldSY :: (a -> b -> a) -> a -> Signal b -> Signal a -- | The process constructor scanld2SY behaves like scanldSY, -- but has two input signals. scanld2SY :: (a -> b -> c -> a) -> a -> Signal b -> Signal c -> Signal a -- | The process constructor scanld3SY behaves like scanldSY, -- but has three input signals. scanld3SY :: (a -> b -> c -> d -> a) -> a -> Signal b -> Signal c -> Signal d -> Signal a -- | The process constructor mooreSY is used to model state machines -- of "Moore" type, where the output only depends on the current state. -- The process constructor is based on the process constructor -- scanldSY, since it is natural for state machines in hardware, -- that the output operates on the current state and not on the next -- state. The process constructors takes a function to calculate the next -- state, another function to calculate the output and a value for the -- initial state. -- -- In contrast the output of a process created by the process constructor -- mealySY depends not only on the state, but also on the input -- values. mooreSY :: (a -> b -> a) -> (a -> c) -> a -> Signal b -> Signal c -- | The process constructor moore2SY behaves like mooreSY, -- but has two input signals. moore2SY :: (a -> b -> c -> a) -> (a -> d) -> a -> Signal b -> Signal c -> Signal d -- | The process constructor moore3SY behaves like mooreSY, -- but has three input signals. moore3SY :: (a -> b -> c -> d -> a) -> (a -> e) -> a -> Signal b -> Signal c -> Signal d -> Signal e -- | The process constructor melaySY is used to model state -- machines of "Mealy" type, where the output only depends on the current -- state and the input values. The process constructor is based on the -- process constructor scanldSY, since it is natural for state -- machines in hardware, that the output operates on the current state -- and not on the next state. The process constructors takes a function -- to calculate the next state, another function to calculate the output -- and a value for the initial state. -- -- In contrast the output of a process created by the process constructor -- mooreSY depends only on the state, but not on the input values. mealySY :: (a -> b -> a) -> (a -> b -> c) -> a -> Signal b -> Signal c -- | The process constructor mealy2SY behaves like mealySY, -- but has two input signals. mealy2SY :: (a -> b -> c -> a) -> (a -> b -> c -> d) -> a -> Signal b -> Signal c -> Signal d -- | The process constructor mealy3SY behaves like mealySY, -- but has three input signals. mealy3SY :: (a -> b -> c -> d -> a) -> (a -> b -> c -> d -> e) -> a -> Signal b -> Signal c -> Signal d -> Signal e -- | The process sourceSY takes a function and an initial state and -- generates an infinite signal starting with the initial state as first -- output followed by the recursive application of the function on the -- current state. The state also serves as output value. -- -- The process that has the infinite signal of natural numbers as output -- is constructed by -- --
--   SynchronousLib> takeS 5 (sourceSY (+1) 0)
--   
-- --
--   {0,1,2,3,4} :: Signal Integer
--   
sourceSY :: (a -> a) -> a -> Signal a -- | The process constructor filterSY discards the values who do not -- fulfill a predicate given by a predicate function and replaces them -- with absent events. filterSY :: (a -> Bool) -> Signal a -> Signal (AbstExt a) -- | The process constructor fillSY creates a process that -- fills a signal with present values by replacing absent values -- with a given value. The output signal is not any more of the type -- AbstExt. fillSY :: a -> Signal (AbstExt a) -> Signal a -- | The process constructor holdSY creates a process that -- fills a signal with values by replacing absent values by the -- preceding present value. Only in cases, where no preceding value -- exists, the absent value is replaced by a default value. The output -- signal is not any more of the type AbstExt. holdSY :: a -> Signal (AbstExt a) -> Signal a -- | The process constructor whenSY creates a process that -- synchronizes a signal of absent extended values with another signal of -- absent extended values. The output signal has the value of the first -- signal whenever an event has a present value and Abst when the -- event has an absent value. whenSY :: Signal (AbstExt a) -> Signal (AbstExt b) -> Signal (AbstExt a) -- | The process zipSY "zips" two incoming signals into one signal -- of tuples. zipSY :: Signal a -> Signal b -> Signal (a, b) -- | The process zip3SY works as zipSY, but takes three input -- signals. zip3SY :: Signal a -> Signal b -> Signal c -> Signal (a, b, c) -- | The process zip4SY works as zipSY, but takes four input -- signals. zip4SY :: Signal a -> Signal b -> Signal c -> Signal d -> Signal (a, b, c, d) -- | The process zip5SY works as zipSY, but takes four input -- signals. zip5SY :: Signal a -> Signal b -> Signal c -> Signal d -> Signal e -> Signal (a, b, c, d, e) -- | The process zip6SY works as zipSY, but takes four input -- signals. zip6SY :: Signal a -> Signal b -> Signal c -> Signal d -> Signal e -> Signal f -> Signal (a, b, c, d, e, f) -- | The process unzipSY "unzips" a signal of tuples into two -- signals. unzipSY :: Signal (a, b) -> (Signal a, Signal b) -- | The process unzip3SY works as unzipSY, but has three -- output signals. unzip3SY :: Signal (a, b, c) -> (Signal a, Signal b, Signal c) -- | The process unzip4SY works as unzipSY, but has four -- output signals. unzip4SY :: Signal (a, b, c, d) -> (Signal a, Signal b, Signal c, Signal d) -- | The process unzip5SY works as unzipSY, but has four -- output signals. unzip5SY :: Signal (a, b, c, d, e) -> (Signal a, Signal b, Signal c, Signal d, Signal e) -- | The process unzip6SY works as unzipSY, but has four -- output signals. unzip6SY :: Signal (a, b, c, d, e, f) -> (Signal a, Signal b, Signal c, Signal d, Signal e, Signal f) -- | The process zipxSY "zips" a signal of vectors into a vector of -- signals. zipxSY :: Vector (Signal a) -> Signal (Vector a) -- | The process unzipxSY "unzips" a vector of signals into a signal -- of vectors. unzipxSY :: Signal (Vector a) -> Vector (Signal a) -- | The process constructor mapxSY creates a process network that -- maps a function onto all signals in a vector of signals. mapxSY :: (a -> b) -> Vector (Signal a) -> Vector (Signal b) -- | The process fstSY selects always the first value from a signal -- of pairs. fstSY :: Signal (a, b) -> Signal a -- | The process sndSY selects always the second value from a signal -- of pairs. sndSY :: Signal (a, b) -> Signal b -- | The stochastic library provides a few stochastic skeletons, which are -- relatives to the skeletons of the synchronous library. These skeletons -- are based on two elementary functions, sigmaUn and -- sigmaGe which provide stochastic signals. The background and -- motivation for this approach is described in the paper -- -- Axel Jantsch, Ingo Sander, and Wenbiao Wu, "The usage of stochastic -- processes in embedded system specifications", In Proceedings of the -- Ninth International Symposium on Hardware and Software Codesign, -- April 2001 -- (http://web.it.kth.se/~axel/papers/2001/codes-2001.pdf). -- -- Unfortunately, not all of the suggested skeletons are implemented. In -- particular, consolidation-based process constructors and all -- constructors for the untimed and the discrete timed MoCs are missing. module ForSyDe.Shallow.StochasticLib -- | The skeleton selMapSY is a stochastic variant of mapSY. -- It has an internal stochastic process and selects one out of two -- combinatorial functions depending on the output of the stochastic -- process. selMapSY :: Int -> (a -> b) -> (a -> b) -> Signal a -> Signal b -- | The skeleton selScanlSY is a stochastic variant of -- scanlSY. selScanlSY :: Int -> (a -> b -> a) -> (a -> b -> a) -> a -> Signal b -> Signal a -- | selMealySY is the stochastic variant of mealySY. Both the -- next-state and the output function is randomly selected based on a -- uniform distribution. selMealySY :: Int -> Int -> (a -> b -> a) -> (a -> b -> a) -> (a -> b -> c) -> (a -> b -> c) -> a -> Signal b -> Signal c -- | selMooreSY is the stochastic variant of mooreSY. Both the -- next-state and the output function is randomly selected based on a -- uniform distribution. selMooreSY :: Int -> Int -> (a -> b -> a) -> (a -> b -> a) -> (a -> c) -> (a -> c) -> a -> Signal b -> Signal c -- | sigmaUn generates a signal list of uniformly distributed Int -- within the given range and with a given seed. sigmaUn :: Int -> (Int, Int) -> Signal Int -- | sigmaGe is a more general stochastic process. The first -- argument is a function f which describes the distribution. For each -- value v in the given range (r1,r2), f(v) is the probability that v is -- generated. -- -- Note, that the user has to make sure that sum(f(v))=1 for v in -- (r1,r2). -- -- For illustration consider the following example. -- --
--   pdist :: Float -> Float
--   pdist d = 1\/\(2**d\)
--   pdistsum 1 = pdist 1
--   pdistsum d = \(pdist d\) + \(pdistsum \(d-1\)\)
--   
-- --
--   pdistnorm :: Float -> Float -> Float
--   pdistnorm dmax d = 1\/((pdistsum dmax) * (2**d))
--   
-- -- pdistnorm dmax d gives the probability of a value <= d; -- -- pdistnorm dmax dmax is always 1.0 -- -- Hence, using pdistnorm as a function in sigmaGe gives an -- exponantial distribution for values in the range [0, dmax]. sigmaGe :: (Float -> Float) -> Int -> (Int, Int) -> Signal Int -- | The synchronous process library defines processes for the synchronous -- computational model. It is based on the synchronous library -- ForSyDe.Shallow.SynchronousLib. module ForSyDe.Shallow.SynchronousProcessLib -- | The process fifoDelaySY implements a synchronous model of a -- FIFO with infinite size. The FIFOs take a list of values at each event -- cycle and output one value. There is a delay of one cycle. fifoDelaySY :: Signal [a] -> Signal (AbstExt a) -- | The process finiteFifoDelaySY implements a FIFO with finite -- size. The FIFOs take a list of values at each event cycle and output -- one value. There is a delay of one cycle. finiteFifoDelaySY :: Int -> Signal [a] -> Signal (AbstExt a) -- | The process memorySY implements a synchronous memory. It uses -- access functions of the type 'Read adr' and 'Write adr value'. memorySY :: Int -> Signal (Access a) -> Signal (AbstExt a) -- | The process mergeSY merges two input signals into a single -- signal. The process has an internal buffer in order to prevent loss of -- data. The process is deterministic and outputs events according to -- their time tag. If there are two valid values at on both signals. The -- value of the first signal is output first. mergeSY :: Signal (AbstExt a) -> Signal (AbstExt a) -> Signal (AbstExt a) -- | The function groupSY groups values into a vector of size n, -- which takes n cycles. While the grouping takes place the output from -- this process consists of absent values. groupSY :: Int -> Signal a -> Signal (AbstExt (Vector a)) -- | The process counterSY implements a counter, that counts from -- min to max. The process counterSY has no input and its output -- is an infinite signal. counterSY :: (Enum a, Ord a) => a -> a -> Signal a -- | This is the ForSyDe library for continuous time MoC (CT-MoC). -- Revision: $Revision: 1.7 $ Id: $Id: CTLib.hs,v 1.7 20070711 -- 08:38:34 axel Exp $ It is still experimental. Right now there are only -- constructors combCT, combCT2, delayCT, -- shiftCT, mealyCT, mooreCT, scaleCT, -- addCT, multCT and absCT. -- -- The main idea is to represent continuous time signals as functions -- Real --> a with a being a numerical type. This -- allows us to represent a continuous time signal without loss of -- information because no sampling or ADC is required. The sampling -- occurs only when a signal is evaluated, for instance when it is -- plotted. -- -- Thus, a signal is represented as a sequence of functions and -- intervals. For instance a signal -- --
--   s = <(sin,[0,100])>
--   
-- -- represents a sinus signal in the interval between 0 and 100. The -- signal -- --
--   s2 = <(f1(x)=2x, [0,2]), (f2(x)=3+x,[2,4])>
--   
-- -- defines a signal that is defined by function f1 in the -- interval [0,2] and by function f2 in the interval -- [2,4]. -- -- A process transforms the incoming functions into outgoing -- functions. The approach is described in more detail in the ANDRES -- deliverable D1.1a. Here we only briefly comment the main functions and -- constructors. module ForSyDe.Shallow.CTLib -- | The type of a sub-signal of a continuous signal. It consisits of the -- function and the interval on which the function is defined. The -- continuous time signal is then defined as a sequence of SubsigCT -- elements: Signal SubsigCT data (Num a) => SubsigCT a SubsigCT :: (Rational -> a, (Rational, Rational)) -> SubsigCT a -- | This constant gives the default time step for sampling and plotting. -- Its value is 10ns. timeStep :: Rational -- | combCT is a process constructor with one input and one output -- signal. It instantiates a combinatorial, stateless process. combCT :: (Num a) => Rational -> ((Rational -> a) -> (Rational -> a)) -> Signal (SubsigCT a) -> Signal (SubsigCT a) -- | combCT2 is a process constructor just like combCT but -- operates on two input signals. combCT2 :: (Num a) => Rational -> ((Rational -> a) -> (Rational -> a) -> (Rational -> a)) -> Signal (SubsigCT a) -> Signal (SubsigCT a) -> Signal (SubsigCT a) -- | The state-full constructor mooreCT resembles a Moore machine. mooreCT :: (Num b, Num c) => (a -> Rational) -> (a -> (Rational -> b) -> a) -> (a -> (Rational -> c)) -> a -> Signal (SubsigCT b) -> Signal (SubsigCT c) -- | The state-full constructor mealyCT resembles a Mealy machine. mealyCT :: (Num b, Num c) => (a -> Rational) -> (a -> (Rational -> b) -> a) -> (a -> (Rational -> b) -> (Rational -> c)) -> a -> Signal (SubsigCT b) -> Signal (SubsigCT c) -- | delayCT is a delay process which simply delays the output but -- does not buffer it. The value at each time t is the same as for the -- input signal, after the initial delay. delayCT :: (Num a) => Rational -> Signal (SubsigCT a) -> Signal (SubsigCT a) -- | shiftCT shifts the shape of the input signal by delay to the -- right. shiftCT :: (Num a) => Rational -> Signal (SubsigCT a) -> Signal (SubsigCT a) -- | initCT takes an initial signal, outputs it and then copies its second -- input signal, which is delayed by the duration of the initial signal. -- The delay is realized by delayCT initCT :: (Num a) => Signal (SubsigCT a) -> Signal (SubsigCT a) -> Signal (SubsigCT a) -- | scaleCT amplifies an input by a constant factor: scaleCT :: (Num a) => a -> Signal (SubsigCT a) -> Signal (SubsigCT a) -- | addCT adds two input signals together. addCT :: (Num a) => Signal (SubsigCT a) -> Signal (SubsigCT a) -> Signal (SubsigCT a) -- | multCT multiplies two input signals together. multCT :: (Num a) => Signal (SubsigCT a) -> Signal (SubsigCT a) -> Signal (SubsigCT a) -- | absCT takes the absolute value of a signal. absCT :: (Num a, Ord a) => Signal (SubsigCT a) -> Signal (SubsigCT a) takeCT :: (Num a) => Rational -> Signal (SubsigCT a) -> Signal (SubsigCT a) dropCT :: (Num a) => Rational -> Signal (SubsigCT a) -> Signal (SubsigCT a) duration :: (Num a) => Signal (SubsigCT a) -> Rational startTime :: (Num a) => Signal (SubsigCT a) -> Rational -- | sineWave generates a sinus signal with the given frequency -- defined over a given period. The function is defined as -- f(x)=sin(2*pi*freq*x). sineWave :: (Floating a) => Rational -> (Rational, Rational) -> Signal (SubsigCT a) -- | constCT generates a constant signal for a given time duration. constCT :: (Num a) => Rational -> a -> Signal (SubsigCT a) -- | zeroCT generates a constant 0 signal for the given time duration. zeroCT :: (Num a) => Rational -> Signal (SubsigCT a) -- | For the digital-analog conversion we have two different possibilities -- which is determined by this data type DACMode. data DACMode -- | linear interpolation DAlinear :: DACMode -- | the last digital value is frozen DAhold :: DACMode -- | The process a2dConverter converts a continuous time signal to -- an untimed or synchronous signal. The first parameter gives the -- sampling period of the converter. -- -- Note, that the process a2dConverter is an ideal component, i.e. -- there are no losses due to a limited resolution due to a fixed number -- of bits. a2dConverter :: (Num a) => Rational -> Signal (SubsigCT a) -> Signal a -- | d2aConverter converts an untimes or synchronous signal into a -- continuous time signal. The process d2aConverter converts a -- signal of the digital domain into a continuous time signal. There are -- two modes, DAlinear, which makes a smooth transition between -- adjacent digital values and DAhold, where the analog value -- directly follows the digital value. This means that in -- DAhold-mode a staircase function remains a staircase function, -- while in DAlinear the staircase function would resemble at -- least partially a saw tooth-curve. -- -- The resolution of the converter is given by the parameter -- timeStep. -- -- Note, that the process d2aConverter is an ideal component, i.e. -- there are no losses due to a limited resolution due to a fixed number -- of bits. d2aConverter :: (Fractional a) => DACMode -> Rational -> Signal a -> Signal (SubsigCT a) -- | applyF1 applies a function on a sub-signal, which means the function -- of the subsignal is transformed to another function: applyF1 :: (Num a, Num b) => ((Rational -> a) -> (Rational -> b)) -> Signal (SubsigCT a) -> Signal (SubsigCT b) -- | applyF2 works just like applyF1 but operates on two incoming signals. applyF2 :: (Num a, Num b, Num c) => ((Rational -> a) -> (Rational -> b) -> (Rational -> c)) -> Signal (SubsigCT a) -> Signal (SubsigCT b) -> Signal (SubsigCT c) -- | applyG1 is used to apply a next-state function. A very interesting -- question is, what should be an argument to the next-state function: -- the incoming function, defining the value of the input signal? or the -- incoming function and the incoming interval? or the value of the -- incoming signal at a particular point, e.g. at the left most point of -- the interval? To give the next-state function the interval itself as -- argument, would mean that the process becomes time variant process, -- i.e. its behaviour is dependent on the absolute time values. This is -- not a good thing to have! Another possibility may be to give a -- sub-signal that is relative to the current evaluation, i.e. the left -- most point is always 0. Would that make sense? applyG1 :: (Num b) => (a -> (Rational -> b) -> a) -> a -> Signal (SubsigCT b) -> a -- | cutEq partitions the two signals such that the partitioning are -- identical in both result signals, but only up to the duration of the -- shorter of the two signals: cutEq :: (Num a, Num b) => Signal (SubsigCT a) -> Signal (SubsigCT b) -> (Signal (SubsigCT a), Signal (SubsigCT b)) -- | plot plots one signal in a graph with the default sampling -- period of 1/200 of the duration of the signal. plot :: (Num a) => Signal (SubsigCT a) -> IO String -- | plotCT plots a list of signals in the same graph. The sampling -- period has to be given as argument. In the graph default label names -- are used to identify the signals. plotCT :: (Num a) => Rational -> [Signal (SubsigCT a)] -> IO String -- | plotCT' is the work horse for plotting and the functions -- plot and plotCT use it with specialising arguments. -- -- plotCT' plots all the signals in the list in one graph. If a -- label is given for a signal, this label appears in the graph. If the -- label string is "", a default label like "sig-1" is used. -- -- In addition to displaying the graph on the screen, the following files -- are created in directory ./fig: -- -- plotCT' :: (Num a) => Rational -> [(Signal (SubsigCT a), String)] -> IO String -- | showParts allows to see how a signal is partitioned into -- sub-signals. It returns the sequence of intervals. showParts :: (Num a) => Signal (SubsigCT a) -> [(Double, Double)] -- | vcdGen dumps the values of a list of signal in VCD (Value Change Dump) -- format (IEEE Std 1364-2001), which is part of the Verilog standard -- (http://en.wikipedia.org/wiki/Value_change_dump). There are -- public domain tools to view VCD files. For instance, GTKWave -- (http://home.nc.rr.com/gtkwave/) is a popular viewer available -- for Windows and Linux. -- -- The values are written to the file .figct-moc.vcd. If the file -- exists, it is overwritten. If the directory does not exist, it is -- created. vcdGen :: (Num a) => Rational -> [(Signal (SubsigCT a), String)] -> IO String instance Show DACMode instance Eq DACMode instance (Num a) => Show (SubsigCT a) -- | The untimed library defines process constructors and processes for the -- untimed computational model. A process constructor is a higher order -- function which together with combinational function(s) and values as -- arguments constructs a process. module ForSyDe.Shallow.UntimedLib combU :: Int -> ([a] -> [b]) -> Signal a -> Signal b comb2U :: Int -> Int -> ([a] -> [b] -> [c]) -> Signal a -> Signal b -> Signal c comb2UC :: Int -> (a -> [b] -> [c]) -> Signal a -> Signal b -> Signal c -- | The first parameter of mapU is a constant integer defining the -- number of tokens consumed in every evaluation cycle. The second -- argument is a function on lists of the input type and returning a list -- of the output type. For instance, -- --
--   r2 = mapU 1 f
--     where f :: [Int] -> [Int]
--           f [x] = [2*x]
--   
-- -- defines a process r2 which consumes one token in each evaluation cycle -- and multiplies it by two. mapU :: Int -> ([a] -> [b]) -> Signal a -> Signal b -- | scanU has an internal state which is visible at the output. The -- first argument is a function 'gamma' which, given the state returns -- the number of tokens consumed next. The second argument is the next -- state function and the third is the initial state. scanU :: (b -> Int) -> (b -> [a] -> b) -> b -> Signal a -> Signal b -- | The process constructor mealyU creates a state machine of Moore -- type. In addition to the next state function they also have an output -- encoding function. The output depends directly on the internal state. mealyU :: (b -> Int) -> (b -> [a] -> b) -> (b -> [a] -> [c]) -> b -> Signal a -> Signal c -- | The process constructor mooreU creates a state machine of Moore -- type. In addition to the next state function they also have an output -- encoding function. The output depends directly on the internal state. mooreU :: (b -> Int) -> (b -> [a] -> b) -> (b -> [c]) -> b -> Signal a -> Signal c sourceU :: (a -> a) -> a -> Signal a sinkU :: (a -> Int) -> (a -> a) -> a -> Signal b -> Signal b -- | initU is used to initialise a signal. Its first argument is -- prepended to its second argument, a signal. initU :: [a] -> Signal a -> Signal a zipU :: Signal (Int, Int) -> Signal a -> Signal b -> Signal ([a], [b]) zipUs :: Int -> Int -> Signal a -> Signal b -> Signal ([a], [b]) zipWithU :: Int -> Int -> ([a] -> [b] -> [c]) -> Signal a -> Signal b -> Signal c zipWith3U :: Int -> Int -> Int -> ([a] -> [b] -> [c] -> [d]) -> Signal a -> Signal b -> Signal c -> Signal d zipWith4U :: Int -> Int -> Int -> Int -> ([a] -> [b] -> [c] -> [d] -> [e]) -> Signal a -> Signal b -> Signal c -> Signal d -> Signal e unzipU :: Signal ([a], [b]) -> (Signal a, Signal b) -- | Adaptivity Library, yet to be completed. module ForSyDe.Shallow.AdaptivityLib applyfSY :: Signal (a -> b) -> Signal a -> Signal b applyf2SY :: Signal (a -> c -> d) -> Signal a -> Signal c -> Signal d applyf3SY :: Signal (a -> c -> d -> e) -> Signal a -> Signal c -> Signal d -> Signal e applyfU :: Int -> Signal ([a] -> [b]) -> Signal a -> Signal b -- | We follow the Box-Muller method to generate white gaussian noise, -- described at: http://www.dspguru.com/howto/tech/wgn.htm module ForSyDe.Shallow.Gaussian -- | To generate an infinite Signal of Gaussian values pGaussianNoise :: Double -> Double -> Int -> Signal Double -- | The dataflow library defines data types, process constructors and -- functions to model dataflow process networks, as described by Lee and -- Parks in Dataflow process networks, IEEE Proceedings, 1995 -- ([LeeParks95]). -- -- Each process is defined by a set of firing rules and corresponding -- actions. A process fires, if the incoming signals match a firing rule. -- Then the process consumes the matched tokens and executes the action -- corresponding to the firing rule. module ForSyDe.Shallow.DataflowLib data FiringToken a Wild :: FiringToken a Value :: a -> FiringToken a -- | The process constructor mapDF takes a list of firing rules, a -- list of corresponding output functions and generates a data flow -- process with one input and one output signal. mapDF :: (Eq a) => [[FiringToken a]] -> (Signal a -> [[b]]) -> Signal a -> Signal b -- | The process constructors zipWithDF takes a list of firing -- rules, a list of corresponding output functions to generate a data -- flow process with two input signals and one output signal. zipWithDF :: (Eq a, Eq b) => [([FiringToken b], [FiringToken a])] -> (Signal b -> Signal a -> [[c]]) -> Signal b -> Signal a -> Signal c -- | The process constructors zipWith3DF takes a list of firing -- rules, a list of corresponding output functions to generate a data -- flow process with three input signals and one output signal. zipWith3DF :: (Eq a, Eq b, Eq c) => [([FiringToken a], [FiringToken b], [FiringToken c])] -> (Signal a -> Signal b -> Signal c -> [[d]]) -> Signal a -> Signal b -> Signal c -> Signal d -- | The process constructor scanlDF implements a finite state -- machine without output decoder in the ForSyDe methodology. It takes a -- set of firing rules and a set of corresponding next state functions as -- arguments. A firing rule is a tuple. The first value is a pattern for -- the state, the second value corresponds to an input pattern. When a -- pattern matches, the process fires, the corresponding next state is -- executed, and the tokens matching the pattern are consumed. scanlDF :: (Eq a, Eq b) => [(FiringToken b, [FiringToken a])] -> (b -> Signal a -> [b]) -> b -> Signal a -> Signal b -- | The process constructor mooreDF implements a Moore finite -- state machine in the ForSyDe methodology. It takes a set of firing -- rules, a set of corresponding next state functions and a set of output -- functions as argument. A firing rule is a tuple. The first value is a -- pattern for the state, the second value corresponds to an input -- pattern. When a pattern matches, the process fires, the corresponding -- next state and output functions are executed, and the tokens matching -- the pattern are consumed. mooreDF :: (Eq a, Eq b) => [(FiringToken b, [FiringToken a])] -> (b -> Signal a -> [b]) -> (b -> [c]) -> b -> Signal a -> Signal c -- | The process constructor mealyDF implements the most general -- state machine in the ForSyDe methodology. It takes a set of firing -- rules, a set of corresponding next state functions and a set of output -- functions as argument. A firing rule is a tuple. The first value is a -- pattern for the state, the second value corresponds to an input -- pattern. When a pattern matches, the process fires, the corresponding -- next state and output functions are executed, and the tokens matching -- the pattern are consumed. mealyDF :: (Eq a, Eq b) => [(FiringToken b, [FiringToken a])] -> (b -> Signal a -> [b]) -> (b -> Signal a -> [[c]]) -> b -> Signal a -> Signal c instance (Eq a) => Eq (FiringToken a) instance (Show a) => Show (FiringToken a) -- | This module defines domain interface constructors for the multi-rate -- computational model. module ForSyDe.Shallow.DomainInterfaces -- | The domain interface constructor downDI takes a parameter -- k and downsamples an input signal. downDI :: (Num a) => a -> Signal b -> Signal b -- | The domain interface constructors upDI takes a parameter -- k and upsamples an input signal. upDI :: (Num a) => a -> Signal b -> Signal (AbstExt b) -- | The domain interface constructor par2serxDI converts n parallel -- signals into one signal. par2serxDI :: Vector (Signal a) -> Signal 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)) -- | 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 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 ForSyDeMoCLib is a container including all MoC libraries and their -- domain interfaces. It consists of the following libraries: -- -- module ForSyDe.Shallow.MoCLib -- | This module implements a FIR filters for the synchronous computational -- model. module ForSyDe.Shallow.FIR -- | The function firSY implements a FIR-filter for the synchronous -- computational model. All kinds of FIR-filters can now be modeled by -- means of firSY. The only argument needed is the list of -- coefficients, which is given as a vector of any size. To illustrate -- this, an 8-th order band pass filter is modeled as follows. -- --
--   bp = firSY (vector [0.06318761339784, 0.08131651217682, 0.09562326700432, 
--                       0.10478344432968, 0.10793629404886, 0.10478344432968, 
--                       0.09562326700432, 0.08131651217682, 0.06318761339784 ])
--   
firSY :: (Fractional a) => Vector a -> Signal a -> Signal a -- | This is the filter library for ForSyDe heterogeneous MoCs - CT-MoC, -- SR-MoC, and Untimed-MoC. -- -- The filters at CT-MoC are based on the filters implemented at SR-MoC -- and Untimed-MoC, which means a signal in CT-MoC is always digitalized -- by a A/D converter, processed by digital filters at SR or Untimed -- domain, and converted back into a CT domain signal by a D/A converter. -- A CT-filter is composed of one A/D converter, one digital filter, and -- one D/A converter. -- -- The implementation of the filters at untimed and synchronous domains -- follows the way in a paper /An introduction to Haskell with -- applications to digital signal processing, David M. Goblirsch, in -- Proceedings of the 1994 ACM symposium on Applied computing./, where -- the details of the FIR/IIR, AR, and ARMA filters are introduced. The -- ARMA filter is the kernel part of our general linear filter -- zLinearFilter in Z-domain at SR/Untimed MoC, and is also the -- kernel digital filter for the linear filter sLinearFilter in -- S-domain at CT-MoC. module ForSyDe.Shallow.FilterLib -- | The FIR filter. Let '[x_n]' denote the input signal, '[y_n]' denote -- the ouput signal, and '[h_n]' the impulse response of the filter. -- Suppose the length of the impulse responses is M samples. The formula -- for '[y_n]' is $sum_{k=0}^{M-1} h_k*x_{n-k}$. firFilter :: (Num a) => [a] -> Signal a -> Signal a -- | The autoregressive filter is the simplest IIR filter. It is -- characterized by a list of numbers '[a_1,a_2,...,a_M]' called the -- autoregression coefficients and a single number b called the -- gain. M is the order of the filter. Let '[x_n]' denote the -- input signal, '[y_n]' denote the ouput signal. The formula for '[y_n]' -- is $sum_{k=1}^M {a_k*y_{n-k}+b*x_n}$. Although it is an IIR filter, -- here we only get the same length of ouput signal as the input signal. arFilterTrim :: (Num a, Fractional a) => [a] -> a -> Signal a -> Signal a -- | The ARMA filter combines the FIR and AR filters. Let '[x_n]' denote -- the input signal, '[y_n]' denote the ouput signal. The formula for -- '[y_n]' is $sum_{k=1}^M {a_k*y_{n-k}+b*x_n} + sum_{i=0}^{N-1} -- b_i*x_{n-i}$. The ARMA filter can be defined as the composition of an -- FIR filter having the impulse reponse '[b_0,b_1,...,b_N-1]' and an AR -- filter having the regression coefficients '[a_1,a_2,...,a_M]' and a -- gain of '1'. Although it is an IIR filter, here we only get the same -- length of ouput signal as the input signal. armaFilterTrim :: (Num a, Fractional a) => [a] -> [a] -> Signal a -> Signal a -- | The solver mode. data SolverMode -- | Tustin tranfer from s-domain to z-domain S2Z :: SolverMode -- | Runge Kutta 4 with fixed simulation steps RK4 :: SolverMode -- | The general linear filter in S-domain at CT-MoC. As the kernel -- implementation is in Z-domain, the smapling rate should be specified. -- It is used on the S-transformation with the following forms, with -- coefficients for the descending powers of s and m < n. -- --
--           b_0*s^m + b_1*s^m-1 + ... + b_m-1*s^1 + b_m*s^0
--   H(s) = ------------------------------------------------         (Eq 1)
--           a_0*s^n + a_1*s^n-1 + ... + a_n-1*s^1 + a_n*s^0
--   
-- -- If we multiply both the numerator and the denominator with s^-n, we -- get another equivelent canonical form -- --
--           b_0*s^m-n + b_1*s^m-n-1 + ... + b_m-1*s^1-n + b_m*s^-n
--   H(s) = -----------------------------------------------------    (Eq 2)
--           a_0*s^0 + a_1*s^-1 + ... + a_n-1*s^1-n + a_n*s^-n
--   
-- -- To instantiate a filter, with sampling interval 'T ', we use -- --
--   filter1 = sLinearFilter T [1] [2,1]
--   
-- -- to get a filter with the transfer function -- --
--             1
--   H(s) = --------
--          2*s + 1
--   
-- -- and -- --
--   filter2 = sLinearFilter T [2,1] [1,2,2]
--   
-- -- to get another filter with the transfer function -- --
--              2*s +1
--   H(s) = ----------------
--           s^2 + 2*s + 2
--   
-- -- There are two solver modes, S2Z and RK4. Caused by the -- precision problem, the time interval in CT uses Rational data type and -- the digital data types in all the domains are Double. sLinearFilter :: (Num a, Fractional a) => SolverMode -> Rational -> [a] -> [a] -> Signal (SubsigCT a) -> Signal (SubsigCT a) -- | The general linear filter in Z-domain. zLinearFilter :: (Fractional a) => [a] -> [a] -> Signal a -> Signal a -- | s2z domain coefficient tranformation with a specified sampling rate. -- The Tustin transformation is used for the transfer, with -- --
--        2(z - 1)  
--   s = ----------                                                 (Eq 3)
--        T(z + 1)
--   
-- -- in which, T is the sampling interval. s2zCoef :: (Num a, Fractional a) => Rational -> [a] -> [a] -> ([a], [a]) -- | The Z-domain to ARMA coefficient tranformation. It is used on the -- Z-transfer function -- --
--           b_0*z^m-n + b_1*z^m-n-1 + ... + b_m-1*z^1-n + b_m*z^-n
--   H(z) = -----------------------------------------------------    (Eq 4)
--           a_0*z^0 + a_1*z^-1 + ... + a_n-1*z^1-n + a_n*z^-n
--   
-- -- which is normalized as -- --
--           b_0/a_0*z^m-n + b_1/a_0*z^m-n-1 + ... + b_m/a_0*z^-n
--   H(z) = -------------------------------------------------------  (Eq 5)
--           1 + a_1/a_0*z^-1 + ... + a_n-1/a_0*z^1-n + a_n/a_0*z^-n
--   
-- -- The implementation coudl be -- --
--   y(k) = b_0/a_0*x_k+m-n + b_1/a_0*x_k+m-n-1 + ... + b_m/a_0*x_k-n
--                                                                   (Eq 6)
--                          - a_1/a_0*y_k-1 - ... - a_n/a_0*y_k-n
--   
-- -- Then, we could get the coefficients of the ARMA filter. h2ARMACoef :: (Num a, Fractional a) => ([a], [a]) -> ([a], [a]) instance Show SolverMode instance Eq SolverMode -- | Shallow-embedded implementation of ForSyDe (see -- ForSyDe.Shallow.Signal). -- -- Unlike systems built using the deep-embedded Signal type of ForSyDe -- (see ForSyDe.Signal), systems built with -- ForSyDe.Shallow.Signal can make use of new and experimental -- features such as multiple, heterogeneous MoCs (Models of Computation) -- other than the Synchronous MoC (the only Model of Computation -- currently supported by deep-embdded ForSyDe). However, as an important -- tradeoff, ForSyDe.Shallow.Signal is unaware of the resulting -- system structure, only allowing simulation (i.e. a VHDL or GraphML -- backend is impossible to implement). -- -- The shallow implementation of ForSyDe consists of three main -- libraries: -- -- module ForSyDe.Shallow -- | This module includes the standard Discrete Fourier Transform (DFT) -- function, and a fast Fourier transform (FFT) algorithm, for computing -- the DFT, when the input vectors' length is a power of 2. module ForSyDe.DFT -- | The function dft performs a standard Discrete Fourier -- Transformation dft :: (Nat s) => FSVec s (Complex Double) -> FSVec s (Complex Double) -- | The function fft implements a fast Fourier transform (FFT) -- algorithm, for computing the DFT, when the size N is a power of 2. fft :: (Nat s, IsPowOf D2 s) => FSVec s (Complex Double) -> FSVec s (Complex Double) -- | ForSyDe identifier types module ForSyDe.Ids -- | A process identifier type ProcId = String -- | A Port identifier type PortId = String -- | A System identifier type SysId = String -- | Automatically derive Template Haskell's Lift class for -- datatypes using Template Haskell splices. -- -- Based on Lynagh's th-lift package: -- http://hackage.haskell.org/cgi-bin/hackage-scripts/package/th-lift module Language.Haskell.TH.Lift -- | Automatically generate an instance of Lift for one data type. -- For example: -- --
--   {-# LANGUAGE TemplateHaskell #-}
--   module Colour where
--   import Language.Haskell.TH.Lift
--   
--   data RGB = Red | Green | Blue
--   
--   -- Generate the Lift instance of RGB
--   $(deriveLift1 ''RGB)
--   
deriveLift1 :: Name -> Q [Dec] -- | Version of deriveLif1 used to automatically generate -- instances of Lift for multiple data types. For instance: -- --
--   {-# LANGUAGE TemplateHaskell #-}
--   module Colour where
--   import Language.Haskell.TH.Lift
--   
--   data RGB = Red | Green | Blue
--   
--   data Num a => Pixel a = Pixel a a a
--   
--   -- Generate Lift instances for RGB and Pixel
--   $(mapM deriveLift [''RGB, ''Pixel])
--   
deriveLift :: Name -> Q Dec instance Lift NameSpace instance Lift NameFlavour instance Lift PkgName instance Lift ModName instance Lift OccName instance Lift Name -- | This module provides Lift instances for all the AST-types -- defined in Language.Haskell.Syntax: Guard Strict, -- Callconv, Safety,Body, Con, FunDep, -- Foreign, Lit, Pat, Match, Stmt, -- Range, Clause, Type, Dec, Exp -- -- Furthermore it provides a Lift instance of Ratio, -- Int8, Int16, Int32, (essential for some of the -- other instantiations) and a function (metaLift) which lifts an -- expression twice, obtaing its meta AST (the AST of the AST) module Language.Haskell.TH.LiftInstances -- | lift twice, getting the meta AST (the AST of the AST) metaLift :: (Lift a) => a -> Q Exp instance Lift Int8 instance Lift Int16 instance Lift Int32 instance Lift Int64 instance Lift InlineSpec instance Lift Pragma instance Lift FamFlavour instance Lift Kind instance Lift TyVarBndr instance Lift Pred instance Lift Exp instance Lift Dec instance Lift Type instance Lift Clause instance Lift Range instance Lift Stmt instance Lift Match instance Lift Pat instance Lift Lit instance Lift Foreign instance Lift FunDep instance Lift Con instance Lift Body instance Lift Safety instance Lift Callconv instance Lift Strict instance Lift Guard instance (Lift a[acgp], Integral a[acgp]) => Lift (Ratio a[acgp]) -- | This module provides the fundamental data structure for deep-embedded -- ForSyDe models: Signal. module ForSyDe.Signal -- | A signal can be seen as wire which carries values of certain type and -- which can be connected and processed by the two computational entities -- of a ForSyDe system: processes and block instances. data Signal a -- | This module provides publicly usable functions to build a system -- definition and instantiate it. module ForSyDe.System -- | We add a phantom parameter to indicate the type of the system data SysDef a -- | SysDef constructor -- -- Builds a system definition out of a system function describing the -- system and its port identifers. newSysDef :: (SysFun f) => f -> SysId -> [PortId] -> [PortId] -> SysDef f -- | CURRENTLY BROKEN, do not use! -- -- SysDef constructor, Template Haskell version -- -- Builds a system definition out of a system function, a system -- identifiers and its port identifers. -- -- For example $(newSysDefTH mySysFun "mysys" ["in1"] ["out1"]) -- creates a system definition from system funcion mySysFun -- which should have one input and output signals. -- -- The advantage of newSysDefTH over newSysDef is that it -- reports errors (e.g duplicated port and process identifiers) earlier, -- at host-language (Haskell) compile-time. -- -- In addition, due to the use of Template Haskell, newSysDefTH is -- aware of the source location at which it was called, making further -- error reports friendlier to the user. newSysDefTH :: (SysFun f) => f -> SysId -> [PortId] -> [PortId] -> ExpQ -- | SysDef constructor, Template Haskell Name version -- -- Builds a SysDef out of the name of a system function and its -- port identifers. -- -- The system will later be identified by the basename (i.e. unqualified -- name) of the function. -- -- For example $(newSysDefTHName 'mySysFun ["in1"] ["out1"]) -- creates a system definition from system funcion mySysFun -- which has one input and output signals. -- -- The advantage of newSysDefTHName over newSysDefTH is -- that it doesn't suffer from the Template Haskell bug -- http://hackage.haskell.org/trac/ghc/ticket/1800, or in other -- words, it allows to declare the system defintion and system function -- in the same module. -- -- However, since it doesn't have acces to the system function itself, it -- can only give early error reports related to incorrect port -- identifiers (process identifier duplicate errors will be reported at -- runtime). newSysDefTHName :: Name -> [PortId] -> [PortId] -> ExpQ -- | Class used to describe a System function. It uses the same trick as -- Text.Printf to implement the variable number of arguments. class SysFun f -- | Multiparameter class to transform a System Function into a Simulation -- Function, able to simulate a System using a list-based representation -- of its signals. class (SysFun sysFun) => SysFunToSimFun sysFun simFun | sysFun -> simFun, simFun -> sysFun -- | Multiparameter class to transform a System Function into an IO -- Simulation Function, able to externally simulate a System using a -- list-based representation of its signals. class (SysFun sysFun) => SysFunToIOSimFun sysFun simFun | sysFun -> simFun, simFun -> sysFun -- | Generates an instance of a SysDef in the form of function out -- of the name of a SysDef with the same type as its system -- function. The resulting function can then be used to plug the instance -- to the rest of the system. instantiate :: (SysFun f) => ProcId -> SysDef f -> f -- | This module provides the simulation backend of ForSyDe's embedded -- compiler -- -- This module is based on Lava2000: -- http://www.cs.chalmers.se/~koen/Lava/ module ForSyDe.Backend.Simulate -- | simulate takes a system definition and generates a function -- able simulate a System using a list-based representation of its -- signals. simulate :: (SysFunToSimFun sysFun simFun) => SysDef sysFun -> simFun -- | This module provides the GraphML backend of ForSyDe's embedded -- compiler module ForSyDe.Backend.GraphML -- | Given a System Definition whose name is A generate A.graphml -- in current working directory using the default compilation options. writeGraphML :: SysDef a -> IO () -- | writeGraphML-alternative which allows setting GraphML -- compilation options. writeGraphMLOps :: GraphMLOps -> SysDef a -> IO () -- | GraphML Compilation options data GraphMLOps GraphMLOps :: GraphMLDebugLevel -> GraphMLRecursivity -> Bool -> GraphMLOps debugGraphML :: GraphMLOps -> GraphMLDebugLevel recursivityGraphML :: GraphMLOps -> GraphMLRecursivity -- | Generate yFiles markup? yFilesMarkup :: GraphMLOps -> Bool -- | Debug level data GraphMLDebugLevel GraphMLNormal :: GraphMLDebugLevel GraphMLVerbose :: GraphMLDebugLevel -- | Recursivity, should the parent systems of system instances be compiled -- as well? data GraphMLRecursivity GraphMLRecursive :: GraphMLRecursivity GraphMLNonRecursive :: GraphMLRecursivity -- | Default traversing options defaultGraphMLOps :: GraphMLOps -- | Bit Datatype. Note that the Num instance is phony and -- shouldn't be used module ForSyDe.Bit data Bit -- | High value H :: Bit -- | Low value L :: Bit -- | Not operation over bits not :: Bit -> Bit -- | Convert a bit to a boolean bitToBool :: Bit -> Bool -- | Convert a boolean to a bit boolToBit :: Bool -> Bit toBitVector8 :: Int8 -> FSVec D8 Bit fromBitVector8 :: FSVec D8 Bit -> Int8 toBitVector16 :: Int16 -> FSVec D16 Bit fromBitVector16 :: FSVec D16 Bit -> Int16 toBitVector32 :: Int32 -> FSVec D32 Bit fromBitVector32 :: FSVec D32 Bit -> Int32 toBitVector64 :: Int64 -> FSVec D64 Bit fromBitVector64 :: FSVec D64 Bit -> Int64 instance Num Bit instance Bits Bit instance Lift Bit instance Typeable Bit instance Eq Bit instance Show Bit instance Data Bit -- | The AbstExt is used to extend existing data types with the -- value 'absent', which models the absence of a value. module ForSyDe.AbsentExt -- | The data type AbstExt has two constructors. The constructor -- Abst is used to model the absence of a value, while the -- constructor Prst is used to model present values. data AbstExt a Abst :: AbstExt a Prst :: a -> AbstExt a -- | The function fromAbstExt extracts the inner value contained in -- AbstExt fromAbstExt :: a -> AbstExt a -> a -- | Similar to fromAbstExt, but without default value unsafeFromAbstExt :: AbstExt a -> a -- | The function abstExt converts a usual value to a present value. abstExt :: a -> AbstExt a -- | The function psi is identical to abstExtFunc and should -- be used in future. psi :: (a -> b) -> AbstExt a -> AbstExt b -- | The functions isAbsent checks for the absence of a value. isAbsent :: AbstExt a -> Bool -- | The functions isPresent checks for the presence of a value. isPresent :: AbstExt a -> Bool -- | The function abstExtFunc extends a function in order to process -- absent extended values. If the input is ("bottom"), the output will -- also be ("bottom"). abstExtFunc :: (a -> b) -> AbstExt a -> AbstExt b instance (Read a) => Read (AbstExt a) instance (Show a) => Show (AbstExt a) instance (Lift a[a8cpC]) => Lift (AbstExt a[a8cpC]) instance Typeable1 AbstExt instance (Eq a) => Eq (AbstExt a) instance (Data a) => Data (AbstExt a) -- | This module provides the synchronous process constructors of ForSyDe -- and some useful synchronous processes. module ForSyDe.Process.SynchProc -- | Creates a constant process. A process which outputs the same signal -- value in every clock cycle. constSY :: (ProcType a) => ProcId -> a -> Signal a -- | The process constructor mapSY takes an identifier and a -- combinational function as arguments and returns a process with one -- input signal and one output signal. mapSY :: (ProcType a, ProcType b) => ProcId -> ProcFun (a -> b) -> Signal a -> Signal b -- | The process constructor zipWithSY takes an identifier and a -- combinational function as arguments and returns a process with two -- input signals and one output signal. zipWithSY :: (ProcType a, ProcType b, ProcType c) => ProcId -> ProcFun (a -> b -> c) -> Signal a -> Signal b -> Signal c -- | The process constructor zipWith3SY takes an identifier and a -- combinational function as arguments and returns a process with three -- input signals and one output signal. zipWith3SY :: (ProcType a, ProcType b, ProcType c, ProcType d) => ProcId -> ProcFun (a -> b -> c -> d) -> Signal a -> Signal b -> Signal c -> Signal d -- | The process constructor zipWith4SY takes an identifier and a -- combinational function as arguments and returns a process with four -- input signals and one output signal. zipWith4SY :: (ProcType a, ProcType b, ProcType c, ProcType d, ProcType e) => ProcId -> ProcFun (a -> b -> c -> d -> e) -> Signal a -> Signal b -> Signal c -> Signal d -> Signal e -- | The process constructor zipWith5SY takes an identifier and a -- combinational function as arguments and returns a process with five -- input signals and one output signal. zipWith5SY :: (ProcType a, ProcType b, ProcType c, ProcType d, ProcType e, ProcType f) => ProcId -> ProcFun (a -> b -> c -> d -> e -> f) -> Signal a -> Signal b -> Signal c -> Signal d -> Signal e -> Signal f -- | The process constructor zipWith6SY takes an identifier and a -- combinational function as arguments and returns a process with five -- input signals and one output signal. zipWith6SY :: (ProcType a, ProcType b, ProcType c, ProcType d, ProcType e, ProcType f, ProcType g) => ProcId -> ProcFun (a -> b -> c -> d -> e -> f -> g) -> Signal a -> Signal b -> Signal c -> Signal d -> Signal e -> Signal f -> Signal g -- | The process constructor zipWithxSY works as zipWithSY, -- but takes a vector of signals as input. zipWithxSY :: (Nat s, Typeable s, ProcType a, ProcType b) => ProcId -> ProcFun (FSVec s a -> b) -> FSVec s (Signal a) -> Signal b -- | The process constructor delaySY delays the signal one event -- cycle by introducing an initial value at the beginning of the output -- signal. Note, that this implies that there is one event (the first) at -- the output signal that has no corresponding event at the input signal. -- One could argue that input and output signals are not fully -- synchronized, even though all input events are synchronous with a -- corresponding output event. However, this is necessary to initialize -- feed-back loops. delaySY :: (ProcType a) => ProcId -> a -> Signal a -> Signal a -- | The process constructor delaynSY delays the signal n events by -- introducing n identical default values. It creates a chain of -- delaySY processes. delaynSY :: (ProcType a) => ProcId -> a -> Int -> Signal a -> Signal a -- | The process constructor scanlSY is used to construct a finite -- state machine process without output decoder. It takes an initial -- value and a function for the next state decoder. The process -- constructor behaves similar to the Haskell prelude function -- scanlSY and has the value of the new state as its output value -- as illustrated by the following example. -- -- This is in contrast to the function scanldSY, which has its -- current state as its output value. scanlSY :: (ProcType a, ProcType b) => ProcId -> ProcFun (a -> b -> a) -> a -> Signal b -> Signal a -- | The process constructor scanl2SY behaves like scanlSY, -- but has two input signals. scanl2SY :: (ProcType a, ProcType b, ProcType c) => ProcId -> ProcFun (a -> b -> c -> a) -> a -> Signal b -> Signal c -> Signal a -- | The process constructor scanl2SY behaves like scanlSY, -- but has two input signals. scanl3SY :: (ProcType a, ProcType b, ProcType c, ProcType d) => ProcId -> ProcFun (a -> b -> c -> d -> a) -> a -> Signal b -> Signal c -> Signal d -> Signal a -- | The process constructor scanldSY is used to construct a finite -- state machine process without output decoder. It takes an initial -- value and a function for the next state decoder. The process -- constructor behaves similarly to the Haskell prelude function -- scanlSY. In contrast to the process constructor scanlSY -- here the output value is the current state and not the one of the next -- state. scanldSY :: (ProcType a, ProcType b) => ProcId -> ProcFun (a -> b -> a) -> a -> Signal b -> Signal a -- | The process constructor scanld2SY behaves like scanldSY, -- but has two input signals. scanld2SY :: (ProcType a, ProcType b, ProcType c) => ProcId -> ProcFun (a -> b -> c -> a) -> a -> Signal b -> Signal c -> Signal a -- | The process constructor scanld2SY behaves like scanldSY, -- but has two input signals. scanld3SY :: (ProcType a, ProcType b, ProcType c, ProcType d) => ProcId -> ProcFun (a -> b -> c -> d -> a) -> a -> Signal b -> Signal c -> Signal d -> Signal a -- | The process constructor mooreSY is used to model state machines -- of "Moore" type, where the output only depends on the current state. -- The process constructor is based on the process constructor -- scanldSY, since it is natural for state machines in hardware, -- that the output operates on the current state and not on the next -- state. The process constructors takes a function to calculate the next -- state, another function to calculate the output and a value for the -- initial state. -- -- In contrast the output of a process created by the process constructor -- mealySY depends not only on the state, but also on the input -- values. mooreSY :: (ProcType a, ProcType b, ProcType c) => ProcId -> ProcFun (a -> b -> a) -> ProcFun (a -> c) -> a -> Signal b -> Signal c -- | The process constructor moore2SY behaves like mooreSY, -- but has two input signals. moore2SY :: (ProcType a, ProcType b, ProcType c, ProcType d) => ProcId -> ProcFun (a -> b -> c -> a) -> ProcFun (a -> d) -> a -> Signal b -> Signal c -> Signal d -- | The process constructor moore2SY behaves like mooreSY, -- but has two input signals. moore3SY :: (ProcType a, ProcType b, ProcType c, ProcType d, ProcType e) => ProcId -> ProcFun (a -> b -> c -> d -> a) -> ProcFun (a -> e) -> a -> Signal b -> Signal c -> Signal d -> Signal e -- | The process constructor melaySY is used to model state -- machines of "Mealy" type, where the output only depends on the current -- state and the input values. The process constructor is based on the -- process constructor scanldSY, since it is natural for state -- machines in hardware, that the output operates on the current state -- and not on the next state. The process constructors takes a function -- to calculate the next state, another function to calculate the output -- and a value for the initial state. -- -- In contrast the output of a process created by the process constructor -- mooreSY depends only on the state, but not on the input values. mealySY :: (ProcType a, ProcType b, ProcType c) => ProcId -> ProcFun (a -> b -> a) -> ProcFun (a -> b -> c) -> a -> Signal b -> Signal c -- | The process constructor mealy2SY behaves like mealySY, -- but has two input signals. mealy2SY :: (ProcType a, ProcType b, ProcType c, ProcType d) => ProcId -> ProcFun (a -> b -> c -> a) -> ProcFun (a -> b -> c -> d) -> a -> Signal b -> Signal c -> Signal d -- | The process constructor mealy2SY behaves like mealySY, -- but has two input signals. mealy3SY :: (ProcType a, ProcType b, ProcType c, ProcType d, ProcType e) => ProcId -> ProcFun (a -> b -> c -> d -> a) -> ProcFun (a -> b -> c -> d -> e) -> a -> Signal b -> Signal c -> Signal d -> Signal e -- | The process sourceSY takes a function and an initial state and -- generates an infinite signal starting with the initial state as first -- output followed by the recursive application of the function on the -- current state. The state also serves as output value. -- -- The process that has the infinite signal of natural numbers as output -- is con structed by -- -- sourceSY "naturals" (+1) 0 sourceSY :: (ProcType a) => ProcId -> ProcFun (a -> a) -> a -> Signal a -- | The process constructor filterSY discards the values who do not -- fulfill a predicate given by a predicate function and replaces them -- with absent events. filterSY :: (ProcType a) => ProcId -> ProcFun (a -> Bool) -> Signal a -> Signal (AbstExt a) -- | The process constructor fillSY creates a process that -- fills a signal with present values by replacing absent values -- with a given value. The output signal is not any more of the type -- AbstExt. fillSY :: (ProcType a) => ProcId -> a -> Signal (AbstExt a) -> Signal a -- | The process constructor holdSY creates a process that -- fills a signal with values by replacing absent values by the -- preceding present value. Only in cases, where no preceding value -- exists, the absent value is replaced by a default value. The output -- signal is not any more of the type AbstExt. holdSY :: (ProcType a) => ProcId -> a -> Signal (AbstExt a) -> Signal a -- | The process constructor whenSY creates a process that -- synchronizes a signal of absent extended values with another signal of -- absent extended values. The output signal has the value of the first -- signal whenever an event has a present value and Abst when the -- event has an absent value. whenSY :: (ProcType a, ProcType b) => ProcId -> Signal (AbstExt a) -> Signal (AbstExt b) -> Signal (AbstExt a) -- | The process zipSY "zips" two incoming signals into one signal -- of tuples. zipSY :: (ProcType a, ProcType b) => ProcId -> Signal a -> Signal b -> Signal (a, b) -- | The process zip3SY works as zipSY, but takes three input -- signals. zip3SY :: (ProcType a, ProcType b, ProcType c) => ProcId -> Signal a -> Signal b -> Signal c -> Signal (a, b, c) -- | The process zip4SY works as zipSY, but takes four input -- signals. zip4SY :: (ProcType a, ProcType b, ProcType c, ProcType d) => ProcId -> Signal a -> Signal b -> Signal c -> Signal d -> Signal (a, b, c, d) -- | The process zip5SY works as zipSY, but takes five input -- signals. zip5SY :: (ProcType a, ProcType b, ProcType c, ProcType d, ProcType e) => ProcId -> Signal a -> Signal b -> Signal c -> Signal d -> Signal e -> Signal (a, b, c, d, e) -- | The process zip6SY works as zipSY, but takes six input -- signals. zip6SY :: (ProcType a, ProcType b, ProcType c, ProcType d, ProcType e, ProcType f) => ProcId -> Signal a -> Signal b -> Signal c -> Signal d -> Signal e -> Signal f -> Signal (a, b, c, d, e, f) -- | The process unzipSY "unzips" a signal of tuples into two -- signals. unzipSY :: (ProcType a, ProcType b) => ProcId -> Signal (a, b) -> (Signal a, Signal b) -- | The process unzip3SY "unzips" a signal of tuples into three -- signals. unzip3SY :: (ProcType a, ProcType b, ProcType c) => ProcId -> Signal (a, b, c) -> (Signal a, Signal b, Signal c) -- | The process unzip4SY "unzips" a signal of tuples into four -- signals. unzip4SY :: (ProcType a, ProcType b, ProcType c, ProcType d) => ProcId -> Signal (a, b, c, d) -> (Signal a, Signal b, Signal c, Signal d) -- | The process unzip5SY "unzips" a signal of tuples into five -- signals. unzip5SY :: (ProcType a, ProcType b, ProcType c, ProcType d, ProcType e) => ProcId -> Signal (a, b, c, d, e) -> (Signal a, Signal b, Signal c, Signal d, Signal e) -- | The process unzip6SY "unzips" a signal of tuples into six -- signals. unzip6SY :: (ProcType a, ProcType b, ProcType c, ProcType d, ProcType e, ProcType f) => ProcId -> Signal (a, b, c, d, e, f) -> (Signal a, Signal b, Signal c, Signal d, Signal e, Signal f) -- | The process zipxSY "zips" a signal of vectors into a vector of -- signals. zipxSY :: (Nat s, Typeable s, ProcType a) => ProcId -> FSVec s (Signal a) -> Signal (FSVec s a) -- | The process unzipxSY "unzips" a vector of n signals into a -- signal of vectors. unzipxSY :: (Typeable s, Nat s, ProcType a) => ProcId -> Signal (FSVec s a) -> FSVec s (Signal a) -- | The process constructor mapxSY creates a process network that -- maps a function onto all signals in a vector of signals. The -- identifier is used as the identifier prefix of the processes created -- (a number starting with 1 will be appended to each identifier) mapxSY :: (Nat s, ProcType a, ProcType b) => ProcId -> ProcFun (a -> b) -> FSVec s (Signal a) -> FSVec s (Signal b) -- | The process fstSY selects always the first value from a signal -- of pairs fstSY :: (ProcType a, ProcType b) => ProcId -> Signal (a, b) -> Signal a -- | The process sndSY selects always the second value from a signal -- of pairs sndSY :: (ProcType a, ProcType b) => ProcId -> Signal (a, b) -> Signal b -- | The function groupSY groups values into a vector of size n, -- which takes n cycles. While the grouping takes place the output from -- this process consists of absent values. groupSY :: (Nat k, Typeable k, ProcType a) => ProcId -> k -> Signal a -> Signal (AbstExt (FSVec k a)) -- | Publicly usable functions to create primitive processes. (Reexports -- ForSyDe.Process.SynchProc) module ForSyDe.Process -- | A Process Function data ProcFun a -- | Template Haskell constructor for ProcFun, here is an example on -- how to use it -- --
--   plus1Fun :: ProcFun (Int -> Int)
--   plus1Fun = $(newProcFun [d| plus1 :: Int -> Int
--                               plus1 n = n + 1     |])
--   
newProcFun :: Q [Dec] -> ExpQ -- | Sets a default value for an argument of the process function defArgVal :: (Lift a, ProcType a) => ProcFun (a -> b) -> a -> ProcFun b -- | Sets a default value for an argument of the process function when the -- argument is a process function itself defArgPF :: ProcFun (a -> b) -> ProcFun a -> ProcFun b -- | Class used to constrain the arguments (values and ProcFuns) -- taken by process constructors class (Data a, Lift a) => ProcType a -- | This module implements FIR filters for the synchronous computational -- model. module ForSyDe.FIR -- | All kinds of FIR-filters can now be modeled by means of fir. -- The only argument needed is the list of coefficients, which is given -- as a vector of any size. To illustrate this, an 8-th order band pass -- filter is modeled as follows. -- --
--   bp = fir "fir Id" $(vectorTH [0.06318761339784, 0.08131651217682, 0.09562326700432, 
--                                 0.10478344432968, 0.10793629404886, 0.10478344432968, 
--                                 0.09562326700432, 0.08131651217682, 0.06318761339784 ])
--   
fir :: (Fractional b, ProcType b, Pos s, Typeable s) => ProcId -> FSVec s b -> Signal b -> Signal b -- | This module provides the VHDL backend of ForSyDe's embedded compiler module ForSyDe.Backend.VHDL -- | Given a System Definition whose name is a valid VHDL _basic_ -- identifier (call it "A") generate A.vhd in current working -- directory using default compilation options. Imp: the input and output -- signal names of A must be valid VHDL identifiers (basic or extended) -- and different to clk and reset which are reserved -- for the main clock and reset signals writeVHDL :: SysDef a -> IO () -- | writeVHDL-alternative which allows setting VHDL compilation -- options. writeVHDLOps :: VHDLOps -> SysDef a -> IO () -- | Generate a function which, given a system definition and some -- simulation stimuli: -- --
    --
  1. Writes a VHDL model of the system
  2. --
  3. Simulates the VHDL model with Modelsim getting the results back to -- Haskell
  4. --
writeAndModelsimVHDL :: (SysFunToIOSimFun sysF simF) => Maybe Int -> SysDef sysF -> simF -- | VHDLOps-alternative of writeAndModelsimVHDL, note that -- compileModelSim will implicitly be set to True writeAndModelsimVHDLOps :: (SysFunToIOSimFun sysF simF) => VHDLOps -> Maybe Int -> SysDef sysF -> simF -- | VHDL Compilation options data VHDLOps VHDLOps :: VHDLDebugLevel -> VHDLRecursivity -> Maybe QuartusOps -> Bool -> VHDLOps -- | Debug mode debugVHDL :: VHDLOps -> VHDLDebugLevel recursivityVHDL :: VHDLOps -> VHDLRecursivity -- | Analyze the generated code with Quartus execQuartus :: VHDLOps -> Maybe QuartusOps -- | Compile the generated code with Modelsim compileModelsim :: VHDLOps -> Bool -- | Options passed to Quartus II by the VHDL Backend. Most of them are -- optional and Quartus will use a default value. -- -- It contains: -- -- data QuartusOps QuartusOps :: QuartusAction -> Maybe Int -> Maybe (String, Maybe String) -> [(String, String)] -> QuartusOps action :: QuartusOps -> QuartusAction fMax :: QuartusOps -> Maybe Int fpgaFamiliyDevice :: QuartusOps -> Maybe (String, Maybe String) pinAssigs :: QuartusOps -> [(String, String)] -- | Action to perform by Quartus data QuartusAction -- | Analysis and eleboration flow AnalysisAndElaboration :: QuartusAction -- | Call map executable AnalysisAndSynthesis :: QuartusAction -- | Compile flow FullCompilation :: QuartusAction -- | Options to check if the model is synthesizable, all options except the -- action to take are set to default. checkSynthesisQuartus :: QuartusOps -- | Debug level data VHDLDebugLevel VHDLNormal :: VHDLDebugLevel VHDLVerbose :: VHDLDebugLevel -- | Recursivity, should the parent systems of system instances be compiled -- as well? data VHDLRecursivity VHDLRecursive :: VHDLRecursivity VHDLNonRecursive :: VHDLRecursivity -- | Default traversing options defaultVHDLOps :: VHDLOps -- | Wrapper module exporting all the backends module ForSyDe.Backend -- | This module is a wrapper for all the publicly usable types and -- functions of ForSyDe's deep-embedded Domain Specific Language (DSL). -- For the shallow-embedded DSL, please see ForSyDe.Shallow. module ForSyDe