Great speed-up in type generation
[matthijs/master-project/cλash.git] / Adders.hs
1 {-# LANGUAGE TemplateHaskell #-}
2
3 module Adders where
4 import Bits
5 import qualified Sim
6
7 import qualified Prelude as P
8 import Prelude hiding (
9   null, length, head, tail, last, init, take, drop, (++), map, foldl, foldr,
10   zipWith, zip, unzip, concat, reverse, iterate )
11
12 import Language.Haskell.Syntax
13 import Types
14 import Data.Param.TFVec
15 import Data.RangedWord
16 import Data.SizedInt
17 import Data.SizedWord
18
19 mainIO f = Sim.simulateIO (Sim.stateless f) ()
20
21 -- This function is from Sim.hs, but we redefine it here so it can get inlined
22 -- by default.
23 stateless :: (i -> o) -> (i -> () -> ((), o))
24 stateless f = \i s -> (s, f i)
25
26 show_add f = do print ("Sum:   " P.++ (displaysigs s)); print ("Carry: " P.++ (displaysig c))
27   where
28     a = [High, High, High, High]
29     b = [Low, Low, Low, High]
30     (s, c) = f (a, b)
31
32 mux2 :: Bit -> (Bit, Bit) -> Bit
33 mux2 Low (a, b) = a
34 mux2 High (a, b) = b
35
36 -- Not really an adder, but this is nice minimal hardware description
37 wire :: Bit -> Bit
38 wire a = a
39
40 -- bus :: (TypeLevel.Pos len) => BitVec len -> BitVec len
41 bus v = v
42
43 -- bus_4 :: BitVec TypeLevel.D4 -> BitVec TypeLevel.D4
44 bus_4 v = v
45
46 {-
47 inv_n :: (Pos len) => BitVec len -> BitVec len
48 inv_n v =
49   --FSVec.map hwnot v
50   inv_n_rec v
51
52 class Inv vec where
53   inv_n_rec :: vec -> vec
54
55 instance (Pos len) => Inv (BitVec len) where
56   inv_n_rec v = 
57     h FSVec.+> t
58     where
59       h = FSVec.head v
60       t = FSVec.tail v
61
62 instance Inv (BitVec D0) where
63   inv_n_rec v = v
64 -}
65 -- Not really an adder either, but a slightly more complex example
66 inv :: Bit -> Bit
67 inv a = let r = hwnot a in r
68
69 -- Not really an adder either, but a slightly more complex example
70 invinv :: Bit -> Bit
71 invinv a = hwnot (hwnot a)
72
73 -- Not really an adder either, but a slightly more complex example
74 dup :: Bit -> (Bit, Bit)
75 dup a = (a, a)
76
77 -- Not really an adder either, but a simple stateful example (D-flipflop)
78 dff :: Bit -> Bit -> (Bit, Bit)
79 dff d s = (s', q)
80   where
81     q = s
82     s' = d
83
84 type ShifterState = (Bit, Bit, Bit, Bit)
85 shifter :: Bit -> ShifterState -> (ShifterState, Bit)
86 shifter i (a, b, c, d) =
87   (s', d)
88   where
89     s' = (i, a, b, c)
90
91 {-# NOINLINE shifter_en #-}
92 shifter_en :: Bit -> Bit-> ShifterState -> (ShifterState, Bit)
93 shifter_en High i (a, b, c, d) =
94   (s', d)
95   where
96     s' = (i, a, b, c)
97
98 shifter_en Low i s@(a, b, c, d) =
99   (s, d)
100
101 -- Two multiplexed shifters
102 type ShiftersState = (ShifterState, ShifterState)
103 shifters :: Bit -> Bit -> ShiftersState -> (ShiftersState, Bit)
104 shifters sel i (sa, sb) =
105   (s', out)
106   where
107     (sa', outa) = shifter_en sel i sa
108     (sb', outb) = shifter_en (hwnot sel) i sb
109     s' = (sa', sb')
110     out = if sel == High then outa else outb
111
112 -- Combinatoric stateless no-carry adder
113 -- A -> B -> S
114 no_carry_adder :: (Bit, Bit) -> Bit
115 no_carry_adder (a, b) = a `hwxor` b
116
117 -- Combinatoric stateless half adder
118 -- A -> B -> (S, C)
119 half_adder :: (Bit, Bit) -> (Bit, Bit)
120 {-# NOINLINE half_adder #-}
121 half_adder (a, b) = 
122   ( a `hwxor` b, a `hwand` b )
123
124 -- Combinatoric stateless full adder
125 -- (A, B, C) -> (S, C)
126 full_adder :: (Bit, Bit, Bit) -> (Bit, Bit)
127 full_adder (a, b, cin) = (s, c)
128   where
129     (s1, c1) = half_adder(a, b)
130     (s, c2)  = half_adder(s1, cin)
131     c        = c1 `hwor` c2
132
133 sfull_adder = stateless full_adder
134
135 -- Four bit adder
136 -- Explicit version
137 -- [a] -> [b] -> ([s], cout)
138 exp_adder :: ([Bit], [Bit]) -> ([Bit], Bit)
139
140 exp_adder ([a3,a2,a1,a0], [b3,b2,b1,b0]) =
141   ([s3, s2, s1, s0], c3)
142   where
143     (s0, c0) = full_adder (a0, b0, Low)
144     (s1, c1) = full_adder (a1, b1, c0)
145     (s2, c2) = full_adder (a2, b2, c1)
146     (s3, c3) = full_adder (a3, b3, c2)
147
148 -- Any number of bits adder
149 -- Recursive version
150 -- [a] -> [b] -> ([s], cout)
151 rec_adder :: ([Bit], [Bit]) -> ([Bit], Bit)
152
153 rec_adder ([], []) = ([], Low)
154 rec_adder ((a:as), (b:bs)) = 
155   (s : rest, cout)
156   where
157     (rest, cin) = rec_adder (as, bs)
158     (s, cout) = full_adder (a, b, cin)
159
160 foo = id
161 add, sub :: Int -> Int -> Int
162 add a b = a + b
163 sub a b = a - b
164
165 highordtest = \x ->
166   let s = foo x
167   in
168      case s of
169        (a, b) ->
170          case a of
171            High -> add
172            Low -> let
173              op' = case b of
174                 High -> sub
175                 Low -> \c d -> c
176              in
177                 \c d -> op' d c
178
179 xand a b = hwand a b
180
181 functiontest :: TFVec D3 (TFVec D4 Bit) -> TFVec D12 Bit
182 functiontest = \v -> let r = concat v in r
183
184 xhwnot x = hwnot x
185
186 maptest :: TFVec D4 Bit -> TFVec D4 Bit
187 maptest = \v -> let r = map xhwnot v in r
188
189 highordtest2 = \a b ->
190          case a of
191            High -> \c d -> d
192            Low -> let
193              op' :: Bit -> Bit -> Bit
194              op' = case b of
195                 High -> \c d -> d
196                 Low -> \c d -> c
197              in
198                 \c d -> op' d c
199 -- Four bit adder, using the continous adder below
200 -- [a] -> [b] -> ([s], cout)
201 con_adder_4 as bs = 
202  ([s3, s2, s1, s0], c)
203  where
204    ((s0, _):(s1, _):(s2, _):(s3, c):_) = con_adder (P.zip ((P.reverse as) P.++ lows) ((P.reverse bs) P.++ lows))
205
206 -- Continuous sequential version
207 -- Stream a -> Stream b -> Stream (sum, cout)
208 con_adder :: Stream (Bit, Bit) -> Stream (Bit, Bit)
209
210 -- Forward to con_adder_int, but supply an initial state
211 con_adder pin =
212  con_adder_int pin Low
213
214 -- Stream a -> Stream b -> state -> Stream (s, c)
215 con_adder_int :: Stream (Bit, Bit) -> Bit -> Stream (Bit, Bit)
216 con_adder_int ((a,b):rest) cin =
217  (s, cout) : con_adder_int rest cout
218  where
219    (s, cout) = full_adder (a, b, cin)
220
221 -- vim: set ts=8 sw=2 sts=2 expandtab: