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