ForSyDe-3.0: examples/ALU_Shallow.hs
{-# LANGUAGE TemplateHaskell #-}
-- *** Shallow-Embedded ForSyDe Model ***
--
-- The following example is designed as tutorial example for the paper.
--
-- It implements a simple ALU, which has the following modes
-- HH: out <- a AND b
-- HL: out <- a OR b
-- LH: (cout, out) <- ADD a b
-- LL: out <- shiftl a 0
--
module ALU_Shallow where
import ForSyDe.Shallow
import ForSyDe.Bit
import Data.Bits
import Data.Param.FSVec
import Data.TypeLevel.Num.Reps
import Data.TypeLevel.Num.Aliases
----- AND - 4 Bit
and4Bit :: Signal (FSVec D4 Bit)
-> Signal (FSVec D4 Bit)
-> Signal (FSVec D4 Bit)
and4Bit = zipWithSY (Data.Param.FSVec.zipWith (.&.))
----- OR - 4 Bit
or4Bit :: Signal (FSVec D4 Bit)
-> Signal (FSVec D4 Bit)
-> Signal (FSVec D4 Bit)
or4Bit = zipWithSY (Data.Param.FSVec.zipWith (.|.))
----- Logical Shift Left
lsl :: Signal (FSVec D4 Bit) -> Signal (FSVec D4 Bit)
lsl = mapSY shiftl_L where
shiftl_L v = shiftl v L
----- Mux 4/1 (no use of FSVec as input, only for selection)
mux41Fun :: FSVec D2 Bit
-> FSVec D4 Bit
-> FSVec D4 Bit
-> FSVec D4 Bit
-> FSVec D4 Bit
-> FSVec D4 Bit
mux41Fun sel x3 x2 x1 x0 = if sel == H +> H +> empty then
x3
else
if sel == H +> L +> empty then
x2
else
if sel == L +> H +> empty then
x1
else
x0
mux41 :: Signal (FSVec D2 Bit) -> Signal (FSVec D4 Bit)
-> Signal (FSVec D4 Bit) -> Signal (FSVec D4 Bit)
-> Signal (FSVec D4 Bit) -> Signal (FSVec D4 Bit)
mux41 = zipWith5SY mux41Fun
----- Convert FSVector to Tuple (Size 4)
convFromFSVec4 :: FSVec D4 a -> (a, a, a, a)
convFromFSVec4 v = (v!d3, v!d2, v!d1, v!d0)
----- Convert To FSVector (Size 4)
convToFSVec4 :: a -> a -> a -> a -> FSVec D4 a
convToFSVec4 x3 x2 x1 x0 = x3 +> x2 +> x1 +> x0 +> empty
----- 4-Bit Adder
------ 4-bit Adder Chain
fourBitAdder :: Signal Bit -- C_IN
-> Signal Bit -- A3
-> Signal Bit -- A2
-> Signal Bit -- A1
-> Signal Bit -- A0
-> Signal Bit -- B3
-> Signal Bit -- B2
-> Signal Bit -- B1
-> Signal Bit -- B0
-> (Signal Bit, -- C_OUT
Signal Bit, -- SUM3
Signal Bit, -- SUM2
Signal Bit, -- SUM1
Signal Bit) -- SUM0
fourBitAdder c_in a3 a2 a1 a0 b3 b2 b1 b0
= (c_out, sum3, sum2, sum1, sum0)
where (c_out, sum3) = unzipSY $ zipWith3SY fullAdd a3 b3 c2
(c2, sum2) = unzipSY $ zipWith3SY fullAdd a2 b2 c1
(c1, sum1) = unzipSY $ zipWith3SY fullAdd a1 b1 c0
(c0, sum0) = unzipSY $ zipWith3SY fullAdd a0 b0 c_in
fullAdd a b cin = (cout, sum)
where
cout = (a .&. b) .|. (a .&. cin) .|. (b .&. cin)
sum = (a `xor` b) `xor` cin
----- FSVec Adder
add4FSVec :: Signal (FSVec D4 Bit)
-> Signal (FSVec D4 Bit)
-> (Signal Bit, Signal (FSVec D4 Bit))
add4FSVec a b = (cout, sum)
where
(a3,a2,a1,a0) = unzip4SY $ mapSY convFromFSVec4 a
(b3,b2,b1,b0) = unzip4SY $ mapSY convFromFSVec4 b
(cout, s3, s2, s1, s0) = fourBitAdder zero a3 a2 a1 a0 b3 b2 b1 b0
sum = zipWith4SY convToFSVec4 s3 s2 s1 s0
zero = sourceSY id L
----- ALU
alu :: Signal(FSVec D2 Bit)
-> Signal (FSVec D4 Bit)
-> Signal (FSVec D4 Bit)
-> (Signal Bit, Signal (FSVec D4 Bit))
alu sel a b = (cout, out)
where
andOut = and4Bit a b
orOut = or4Bit a b
(cout, sum) = add4FSVec a b
lslOut = lsl a
out = mux41 sel andOut orOut sum lslOut
----- Test-Inputs
sel = signal [reallyUnsafeVector [H,H], -- AND
reallyUnsafeVector [H,L], -- OR
reallyUnsafeVector [L,H], -- ADD
reallyUnsafeVector [L,L]] -- LSL
a = signal [reallyUnsafeVector [L,H,H,H],
reallyUnsafeVector [L,H,L,H],
reallyUnsafeVector [L,H,H,H],
reallyUnsafeVector [L,H,H,H]]
b = signal [reallyUnsafeVector [H,H,H,H],
reallyUnsafeVector [H,H,L,H],
reallyUnsafeVector [H,H,H,H],
reallyUnsafeVector [H,H,H,H]]
c = signal [reallyUnsafeVector [L,L,L,L], -- LSB D1 D2 MSB
reallyUnsafeVector [H,L,L,L],
reallyUnsafeVector [L,L,L,H],
reallyUnsafeVector [L,L,L,H]]
d = signal [reallyUnsafeVector [L,L,L,L],
reallyUnsafeVector [L,L,L,L],
reallyUnsafeVector [L,L,L,H],
reallyUnsafeVector [H,H,H,H]]
x0 = signal [L,L,L,L]
x1 = signal [H,H,H,H]
-- Helper functions
zipWith5SY :: (a -> b -> c -> d -> e -> f)
-> Signal a
-> Signal b
-> Signal c
-> Signal d
-> Signal e
-> Signal f
zipWith5SY _ NullS _ _ _ _ = NullS
zipWith5SY _ _ NullS _ _ _ = NullS
zipWith5SY _ _ _ NullS _ _ = NullS
zipWith5SY _ _ _ _ NullS _ = NullS
zipWith5SY _ _ _ _ _ NullS = NullS
zipWith5SY f (a :- as) (b :- bs) (c :- cs) (d :- ds) (e:-es) =
f a b c d e :- zipWith5SY f as bs cs ds es