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