a72cc62d409205bdd6a36d2c11b64af46cef5330
[matthijs/master-project/cλash.git] / Generate.hs
1 module Generate where
2
3 -- Standard modules
4 import qualified Control.Monad as Monad
5 import qualified Data.Map as Map
6 import qualified Maybe
7 import qualified Data.Either as Either
8 import Data.Accessor
9 import Data.Accessor.MonadState as MonadState
10 import Debug.Trace
11
12 -- ForSyDe
13 import qualified ForSyDe.Backend.VHDL.AST as AST
14
15 -- GHC API
16 import CoreSyn
17 import Type
18 import qualified Var
19 import qualified IdInfo
20 import qualified Literal
21 import qualified Name
22 import qualified TyCon
23
24 -- Local imports
25 import Constants
26 import VHDLTypes
27 import VHDLTools
28 import CoreTools
29 import Pretty
30
31 -----------------------------------------------------------------------------
32 -- Functions to generate VHDL for builtin functions
33 -----------------------------------------------------------------------------
34
35 -- | A function to wrap a builder-like function that expects its arguments to
36 -- be expressions.
37 genExprArgs ::
38   (dst -> func -> [AST.Expr] -> res)
39   -> (dst -> func -> [Either CoreSyn.CoreExpr AST.Expr] -> res)
40 genExprArgs wrap dst func args = wrap dst func args'
41   where args' = map (either (varToVHDLExpr.exprToVar) id) args
42   
43 -- | A function to wrap a builder-like function that expects its arguments to
44 -- be variables.
45 genVarArgs ::
46   (dst -> func -> [Var.Var] -> res)
47   -> (dst -> func -> [Either CoreSyn.CoreExpr AST.Expr] -> res)
48 genVarArgs wrap dst func args = wrap dst func args'
49   where
50     args' = map exprToVar exprargs
51     -- Check (rather crudely) that all arguments are CoreExprs
52     (exprargs, []) = Either.partitionEithers args
53
54 -- | A function to wrap a builder-like function that expects its arguments to
55 -- be Literals
56 genLitArgs ::
57   (dst -> func -> [Literal.Literal] -> res)
58   -> (dst -> func -> [Either CoreSyn.CoreExpr AST.Expr] -> res)
59 genLitArgs wrap dst func args = wrap dst func args'
60   where
61     args' = map exprToLit litargs
62     -- FIXME: Check if we were passed an CoreSyn.App
63     litargs = concat (map getLiterals exprargs)
64     (exprargs, []) = Either.partitionEithers args
65
66 -- | A function to wrap a builder-like function that produces an expression
67 -- and expects it to be assigned to the destination.
68 genExprRes ::
69   ((Either CoreSyn.CoreBndr AST.VHDLName) -> func -> [arg] -> VHDLSession AST.Expr)
70   -> ((Either CoreSyn.CoreBndr AST.VHDLName) -> func -> [arg] -> VHDLSession [AST.ConcSm])
71 genExprRes wrap dst func args = do
72   expr <- wrap dst func args
73   return $ [mkUncondAssign dst expr]
74
75 -- | Generate a binary operator application. The first argument should be a
76 -- constructor from the AST.Expr type, e.g. AST.And.
77 genOperator2 :: (AST.Expr -> AST.Expr -> AST.Expr) -> BuiltinBuilder 
78 genOperator2 op = genExprArgs $ genExprRes (genOperator2' op)
79 genOperator2' :: (AST.Expr -> AST.Expr -> AST.Expr) -> dst -> CoreSyn.CoreBndr -> [AST.Expr] -> VHDLSession AST.Expr
80 genOperator2' op _ f [arg1, arg2] = return $ op arg1 arg2
81
82 -- | Generate a unary operator application
83 genOperator1 :: (AST.Expr -> AST.Expr) -> BuiltinBuilder 
84 genOperator1 op = genExprArgs $ genExprRes (genOperator1' op)
85 genOperator1' :: (AST.Expr -> AST.Expr) -> dst -> CoreSyn.CoreBndr -> [AST.Expr] -> VHDLSession AST.Expr
86 genOperator1' op _ f [arg] = return $ op arg
87
88 -- | Generate a unary operator application
89 genNegation :: BuiltinBuilder 
90 genNegation = genVarArgs $ genExprRes genNegation'
91 genNegation' :: dst -> CoreSyn.CoreBndr -> [Var.Var] -> VHDLSession AST.Expr
92 genNegation' _ f [arg] = return $ op (varToVHDLExpr arg)
93   where
94     ty = Var.varType arg
95     (tycon, args) = Type.splitTyConApp ty
96     name = Name.getOccString (TyCon.tyConName tycon)
97     op = case name of
98       "SizedInt" -> AST.Neg
99       otherwise -> error $ "\nGenerate.genNegation': Negation allowed for type: " ++ show name 
100
101 -- | Generate a function call from the destination binder, function name and a
102 -- list of expressions (its arguments)
103 genFCall :: Bool -> BuiltinBuilder 
104 genFCall switch = genExprArgs $ genExprRes (genFCall' switch)
105 genFCall' :: Bool -> Either CoreSyn.CoreBndr AST.VHDLName -> CoreSyn.CoreBndr -> [AST.Expr] -> VHDLSession AST.Expr
106 genFCall' switch (Left res) f args = do
107   let fname = varToString f
108   let el_ty = if switch then (Var.varType res) else ((tfvec_elem . Var.varType) res)
109   id <- MonadState.lift vsType $ vectorFunId el_ty fname
110   return $ AST.PrimFCall $ AST.FCall (AST.NSimple id)  $
111              map (\exp -> Nothing AST.:=>: AST.ADExpr exp) args
112 genFCall' _ (Right name) _ _ = error $ "\nGenerate.genFCall': Cannot generate builtin function call assigned to a VHDLName: " ++ show name
113
114 genFromSizedWord :: BuiltinBuilder
115 genFromSizedWord = genExprArgs $ genExprRes genFromSizedWord'
116 genFromSizedWord' :: Either CoreSyn.CoreBndr AST.VHDLName -> CoreSyn.CoreBndr -> [AST.Expr] -> VHDLSession AST.Expr
117 genFromSizedWord' (Left res) f args = do
118   let fname = varToString f
119   return $ AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLBasicId toIntegerId))  $
120              map (\exp -> Nothing AST.:=>: AST.ADExpr exp) args
121 genFromSizedWord' (Right name) _ _ = error $ "\nGenerate.genFromSizedWord': Cannot generate builtin function call assigned to a VHDLName: " ++ show name
122
123 -- FIXME: I'm calling genLitArgs which is very specific function,
124 -- which needs to be fixed as well
125 genFromInteger :: BuiltinBuilder
126 genFromInteger = genLitArgs $ genExprRes genFromInteger'
127 genFromInteger' :: Either CoreSyn.CoreBndr AST.VHDLName -> CoreSyn.CoreBndr -> [Literal.Literal] -> VHDLSession AST.Expr
128 genFromInteger' (Left res) f lits = 
129   return $ AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLBasicId fname)) 
130             [Nothing AST.:=>: AST.ADExpr (AST.PrimLit (show (last lits))), Nothing AST.:=>: AST.ADExpr( AST.PrimLit (show len))]
131   where
132   ty = Var.varType res
133   (tycon, args) = Type.splitTyConApp ty
134   name = Name.getOccString (TyCon.tyConName tycon)
135   len = case name of
136     "SizedInt" -> sized_int_len ty
137     "SizedWord" -> sized_word_len ty
138   fname = case name of
139     "SizedInt" -> toSignedId
140     "SizedWord" -> toUnsignedId
141
142 genFromInteger' (Right name) _ _ = error $ "\nGenerate.genFromInteger': Cannot generate builtin function call assigned to a VHDLName: " ++ show name
143
144
145 -- | Generate a generate statement for the builtin function "map"
146 genMap :: BuiltinBuilder
147 genMap (Left res) f [Left mapped_f, Left (Var arg)] =
148   -- mapped_f must be a CoreExpr (since we can't represent functions as VHDL
149   -- expressions). arg must be a CoreExpr (and should be a CoreSyn.Var), since
150   -- we must index it (which we couldn't if it was a VHDL Expr, since only
151   -- VHDLNames can be indexed).
152   let
153     -- Setup the generate scheme
154     len         = (tfvec_len . Var.varType) res
155     -- TODO: Use something better than varToString
156     label       = mkVHDLExtId ("mapVector" ++ (varToString res))
157     n_id        = mkVHDLBasicId "n"
158     n_expr      = idToVHDLExpr n_id
159     range       = AST.ToRange (AST.PrimLit "0") (AST.PrimLit $ show (len-1))
160     genScheme   = AST.ForGn n_id range
161
162     -- Create the content of the generate statement: Applying the mapped_f to
163     -- each of the elements in arg, storing to each element in res
164     resname     = mkIndexedName (varToVHDLName res) n_expr
165     argexpr     = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName arg) n_expr
166   in do
167     let (CoreSyn.Var real_f, already_mapped_args) = CoreSyn.collectArgs mapped_f
168     let valargs = get_val_args (Var.varType real_f) already_mapped_args
169     app_concsms <- genApplication (Right resname) real_f (map Left valargs ++ [Right argexpr])
170     -- Return the generate statement
171     return [AST.CSGSm $ AST.GenerateSm label genScheme [] app_concsms]
172
173 genMap' (Right name) _ _ = error $ "\nGenerate.genMap': Cannot generate map function call assigned to a VHDLName: " ++ show name
174     
175 genZipWith :: BuiltinBuilder
176 genZipWith = genVarArgs genZipWith'
177 genZipWith' :: (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> VHDLSession [AST.ConcSm]
178 genZipWith' (Left res) f args@[zipped_f, arg1, arg2] =
179   let
180     -- Setup the generate scheme
181     len         = (tfvec_len . Var.varType) res
182     -- TODO: Use something better than varToString
183     label       = mkVHDLExtId ("zipWithVector" ++ (varToString res))
184     n_id        = mkVHDLBasicId "n"
185     n_expr      = idToVHDLExpr n_id
186     range       = AST.ToRange (AST.PrimLit "0") (AST.PrimLit $ show (len-1))
187     genScheme   = AST.ForGn n_id range
188
189     -- Create the content of the generate statement: Applying the zipped_f to
190     -- each of the elements in arg1 and arg2, storing to each element in res
191     resname     = mkIndexedName (varToVHDLName res) n_expr
192     argexpr1    = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName arg1) n_expr
193     argexpr2    = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName arg2) n_expr
194   in do
195     app_concsms <- genApplication (Right resname) zipped_f [Right argexpr1, Right argexpr2]
196     -- Return the generate functions
197     return [AST.CSGSm $ AST.GenerateSm label genScheme [] app_concsms]
198
199 genFoldl :: BuiltinBuilder
200 genFoldl = genFold True
201
202 genFoldr :: BuiltinBuilder
203 genFoldr = genFold False
204
205 genFold :: Bool -> BuiltinBuilder
206 genFold left = genVarArgs (genFold' left)
207 genFold' :: Bool -> (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> VHDLSession [AST.ConcSm]
208 -- Special case for an empty input vector, just assign start to res
209 genFold' left (Left res) _ [_, start, vec] | len == 0 = return [mkUncondAssign (Left res) (varToVHDLExpr start)]
210     where len = (tfvec_len . Var.varType) vec
211 genFold' left (Left res) f [folded_f, start, vec] = do
212   -- evec is (TFVec n), so it still needs an element type
213   let (nvec, _) = splitAppTy (Var.varType vec)
214   -- Put the type of the start value in nvec, this will be the type of our
215   -- temporary vector
216   let tmp_ty = Type.mkAppTy nvec (Var.varType start)
217   let error_msg = "\nGenerate.genFold': Can not construct temp vector for element type: " ++ pprString tmp_ty 
218   tmp_vhdl_ty <- MonadState.lift vsType $ vhdl_ty error_msg tmp_ty
219   -- Setup the generate scheme
220   let gen_label = mkVHDLExtId ("foldlVector" ++ (varToString vec))
221   let block_label = mkVHDLExtId ("foldlVector" ++ (varToString start))
222   let gen_range = if left then AST.ToRange (AST.PrimLit "0") len_min_expr
223                   else AST.DownRange len_min_expr (AST.PrimLit "0")
224   let gen_scheme   = AST.ForGn n_id gen_range
225   -- Make the intermediate vector
226   let  tmp_dec     = AST.BDISD $ AST.SigDec tmp_id tmp_vhdl_ty Nothing
227   -- Create the generate statement
228   cells <- sequence [genFirstCell, genOtherCell]
229   let gen_sm = AST.GenerateSm gen_label gen_scheme [] (map AST.CSGSm cells)
230   -- Assign tmp[len-1] or tmp[0] to res
231   let out_assign = mkUncondAssign (Left res) $ vhdlNameToVHDLExpr (if left then
232                     (mkIndexedName tmp_name (AST.PrimLit $ show (len-1))) else
233                     (mkIndexedName tmp_name (AST.PrimLit "0")))      
234   let block = AST.BlockSm block_label [] (AST.PMapAspect []) [tmp_dec] [AST.CSGSm gen_sm, out_assign]
235   return [AST.CSBSm block]
236   where
237     -- The vector length
238     len         = (tfvec_len . Var.varType) vec
239     -- An id for the counter
240     n_id = mkVHDLBasicId "n"
241     n_cur = idToVHDLExpr n_id
242     -- An expression for previous n
243     n_prev = if left then (n_cur AST.:-: (AST.PrimLit "1"))
244                      else (n_cur AST.:+: (AST.PrimLit "1"))
245     -- An expression for len-1
246     len_min_expr = (AST.PrimLit $ show (len-1))
247     -- An id for the tmp result vector
248     tmp_id = mkVHDLBasicId "tmp"
249     tmp_name = AST.NSimple tmp_id
250     -- Generate parts of the fold
251     genFirstCell, genOtherCell :: VHDLSession AST.GenerateSm
252     genFirstCell = do
253       let cond_label = mkVHDLExtId "firstcell"
254       -- if n == 0 or n == len-1
255       let cond_scheme = AST.IfGn $ n_cur AST.:=: (if left then (AST.PrimLit "0")
256                                                   else (AST.PrimLit $ show (len-1)))
257       -- Output to tmp[current n]
258       let resname = mkIndexedName tmp_name n_cur
259       -- Input from start
260       let argexpr1 = varToVHDLExpr start
261       -- Input from vec[current n]
262       let argexpr2 = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName vec) n_cur
263       app_concsms <- genApplication (Right resname) folded_f  ( if left then
264                                                                   [Right argexpr1, Right argexpr2]
265                                                                 else
266                                                                   [Right argexpr2, Right argexpr1]
267                                                               )
268       -- Return the conditional generate part
269       return $ AST.GenerateSm cond_label cond_scheme [] app_concsms
270
271     genOtherCell = do
272       let cond_label = mkVHDLExtId "othercell"
273       -- if n > 0 or n < len-1
274       let cond_scheme = AST.IfGn $ n_cur AST.:/=: (if left then (AST.PrimLit "0")
275                                                    else (AST.PrimLit $ show (len-1)))
276       -- Output to tmp[current n]
277       let resname = mkIndexedName tmp_name n_cur
278       -- Input from tmp[previous n]
279       let argexpr1 = vhdlNameToVHDLExpr $ mkIndexedName tmp_name n_prev
280       -- Input from vec[current n]
281       let argexpr2 = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName vec) n_cur
282       app_concsms <- genApplication (Right resname) folded_f  ( if left then
283                                                                   [Right argexpr1, Right argexpr2]
284                                                                 else
285                                                                   [Right argexpr2, Right argexpr1]
286                                                               )
287       -- Return the conditional generate part
288       return $ AST.GenerateSm cond_label cond_scheme [] app_concsms
289
290 -- | Generate a generate statement for the builtin function "zip"
291 genZip :: BuiltinBuilder
292 genZip = genVarArgs genZip'
293 genZip' :: (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> VHDLSession [AST.ConcSm]
294 genZip' (Left res) f args@[arg1, arg2] =
295   let
296     -- Setup the generate scheme
297     len             = (tfvec_len . Var.varType) res
298     -- TODO: Use something better than varToString
299     label           = mkVHDLExtId ("zipVector" ++ (varToString res))
300     n_id            = mkVHDLBasicId "n"
301     n_expr          = idToVHDLExpr n_id
302     range           = AST.ToRange (AST.PrimLit "0") (AST.PrimLit $ show (len-1))
303     genScheme       = AST.ForGn n_id range
304     resname'        = mkIndexedName (varToVHDLName res) n_expr
305     argexpr1        = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName arg1) n_expr
306     argexpr2        = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName arg2) n_expr
307   in do
308     labels <- MonadState.lift vsType $ getFieldLabels (tfvec_elem (Var.varType res))
309     let resnameA    = mkSelectedName resname' (labels!!0)
310     let resnameB    = mkSelectedName resname' (labels!!1)
311     let resA_assign = mkUncondAssign (Right resnameA) argexpr1
312     let resB_assign = mkUncondAssign (Right resnameB) argexpr2
313     -- Return the generate functions
314     return [AST.CSGSm $ AST.GenerateSm label genScheme [] [resA_assign,resB_assign]]
315     
316 -- | Generate a generate statement for the builtin function "unzip"
317 genUnzip :: BuiltinBuilder
318 genUnzip = genVarArgs genUnzip'
319 genUnzip' :: (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> VHDLSession [AST.ConcSm]
320 genUnzip' (Left res) f args@[arg] =
321   let
322     -- Setup the generate scheme
323     len             = (tfvec_len . Var.varType) arg
324     -- TODO: Use something better than varToString
325     label           = mkVHDLExtId ("unzipVector" ++ (varToString res))
326     n_id            = mkVHDLBasicId "n"
327     n_expr          = idToVHDLExpr n_id
328     range           = AST.ToRange (AST.PrimLit "0") (AST.PrimLit $ show (len-1))
329     genScheme       = AST.ForGn n_id range
330     resname'        = varToVHDLName res
331     argexpr'        = mkIndexedName (varToVHDLName arg) n_expr
332   in do
333     reslabels <- MonadState.lift vsType $ getFieldLabels (Var.varType res)
334     arglabels <- MonadState.lift vsType $ getFieldLabels (tfvec_elem (Var.varType arg))
335     let resnameA    = mkIndexedName (mkSelectedName resname' (reslabels!!0)) n_expr
336     let resnameB    = mkIndexedName (mkSelectedName resname' (reslabels!!1)) n_expr
337     let argexprA    = vhdlNameToVHDLExpr $ mkSelectedName argexpr' (arglabels!!0)
338     let argexprB    = vhdlNameToVHDLExpr $ mkSelectedName argexpr' (arglabels!!1)
339     let resA_assign = mkUncondAssign (Right resnameA) argexprA
340     let resB_assign = mkUncondAssign (Right resnameB) argexprB
341     -- Return the generate functions
342     return [AST.CSGSm $ AST.GenerateSm label genScheme [] [resA_assign,resB_assign]]
343
344 genCopy :: BuiltinBuilder 
345 genCopy = genVarArgs genCopy'
346 genCopy' :: (Either CoreSyn.CoreBndr AST.VHDLName ) -> CoreSyn.CoreBndr -> [Var.Var] -> VHDLSession [AST.ConcSm]
347 genCopy' (Left res) f args@[arg] =
348   let
349     resExpr = AST.Aggregate [AST.ElemAssoc (Just AST.Others) 
350                 (AST.PrimName $ (varToVHDLName arg))]
351     out_assign = mkUncondAssign (Left res) resExpr
352   in 
353     return [out_assign]
354     
355 genConcat :: BuiltinBuilder
356 genConcat = genVarArgs genConcat'
357 genConcat' :: (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> VHDLSession [AST.ConcSm]
358 genConcat' (Left res) f args@[arg] =
359   let
360     -- Setup the generate scheme
361     len1        = (tfvec_len . Var.varType) arg
362     (_, nvec)   = splitAppTy (Var.varType arg)
363     len2        = tfvec_len nvec
364     -- TODO: Use something better than varToString
365     label       = mkVHDLExtId ("concatVector" ++ (varToString res))
366     n_id        = mkVHDLBasicId "n"
367     n_expr      = idToVHDLExpr n_id
368     fromRange   = n_expr AST.:*: (AST.PrimLit $ show len2)
369     genScheme   = AST.ForGn n_id range
370     -- Create the content of the generate statement: Applying the mapped_f to
371     -- each of the elements in arg, storing to each element in res
372     toRange     = (n_expr AST.:*: (AST.PrimLit $ show len2)) AST.:+: (AST.PrimLit $ show (len2-1))
373     range       = AST.ToRange (AST.PrimLit "0") (AST.PrimLit $ show (len1-1))
374     resname     = vecSlice fromRange toRange
375     argexpr     = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName arg) n_expr
376     out_assign  = mkUncondAssign (Right resname) argexpr
377   in
378     -- Return the generate statement
379     return [AST.CSGSm $ AST.GenerateSm label genScheme [] [out_assign]]
380   where
381     vecSlice init last =  AST.NSlice (AST.SliceName (varToVHDLName res) 
382                             (AST.ToRange init last))
383
384 genIteraten :: BuiltinBuilder
385 genIteraten dst f args = genIterate dst f (tail args)
386
387 genIterate :: BuiltinBuilder
388 genIterate = genIterateOrGenerate True
389
390 genGeneraten :: BuiltinBuilder
391 genGeneraten dst f args = genGenerate dst f (tail args)
392
393 genGenerate :: BuiltinBuilder
394 genGenerate = genIterateOrGenerate False
395
396 genIterateOrGenerate :: Bool -> BuiltinBuilder
397 genIterateOrGenerate iter = genVarArgs (genIterateOrGenerate' iter)
398 genIterateOrGenerate' :: Bool -> (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> VHDLSession [AST.ConcSm]
399 -- Special case for an empty input vector, just assign start to res
400 genIterateOrGenerate' iter (Left res) _ [app_f, start] | len == 0 = return [mkUncondAssign (Left res) (AST.PrimLit "\"\"")]
401     where len = (tfvec_len . Var.varType) res
402 genIterateOrGenerate' iter (Left res) f [app_f, start] = do
403   -- -- evec is (TFVec n), so it still needs an element type
404   -- let (nvec, _) = splitAppTy (Var.varType vec)
405   -- -- Put the type of the start value in nvec, this will be the type of our
406   -- -- temporary vector
407   let tmp_ty = Var.varType res
408   let error_msg = "\nGenerate.genFold': Can not construct temp vector for element type: " ++ pprString tmp_ty 
409   tmp_vhdl_ty <- MonadState.lift vsType $ vhdl_ty error_msg tmp_ty
410   -- Setup the generate scheme
411   let gen_label = mkVHDLExtId ("iterateVector" ++ (varToString start))
412   let block_label = mkVHDLExtId ("iterateVector" ++ (varToString res))
413   let gen_range = AST.ToRange (AST.PrimLit "0") len_min_expr
414   let gen_scheme   = AST.ForGn n_id gen_range
415   -- Make the intermediate vector
416   let  tmp_dec     = AST.BDISD $ AST.SigDec tmp_id tmp_vhdl_ty Nothing
417   -- Create the generate statement
418   cells <- sequence [genFirstCell, genOtherCell]
419   let gen_sm = AST.GenerateSm gen_label gen_scheme [] (map AST.CSGSm cells)
420   -- Assign tmp[len-1] or tmp[0] to res
421   let out_assign = mkUncondAssign (Left res) $ vhdlNameToVHDLExpr tmp_name    
422   let block = AST.BlockSm block_label [] (AST.PMapAspect []) [tmp_dec] [AST.CSGSm gen_sm, out_assign]
423   return [AST.CSBSm block]
424   where
425     -- The vector length
426     len = (tfvec_len . Var.varType) res
427     -- An id for the counter
428     n_id = mkVHDLBasicId "n"
429     n_cur = idToVHDLExpr n_id
430     -- An expression for previous n
431     n_prev = n_cur AST.:-: (AST.PrimLit "1")
432     -- An expression for len-1
433     len_min_expr = (AST.PrimLit $ show (len-1))
434     -- An id for the tmp result vector
435     tmp_id = mkVHDLBasicId "tmp"
436     tmp_name = AST.NSimple tmp_id
437     -- Generate parts of the fold
438     genFirstCell, genOtherCell :: VHDLSession AST.GenerateSm
439     genFirstCell = do
440       let cond_label = mkVHDLExtId "firstcell"
441       -- if n == 0 or n == len-1
442       let cond_scheme = AST.IfGn $ n_cur AST.:=: (AST.PrimLit "0")
443       -- Output to tmp[current n]
444       let resname = mkIndexedName tmp_name n_cur
445       -- Input from start
446       let argexpr = varToVHDLExpr start
447       let startassign = mkUncondAssign (Right resname) argexpr
448       app_concsms <- genApplication (Right resname) app_f  [Right argexpr]
449       -- Return the conditional generate part
450       return $ AST.GenerateSm cond_label cond_scheme [] (if iter then 
451                                                           [startassign]
452                                                          else 
453                                                           app_concsms
454                                                         )
455
456     genOtherCell = do
457       let cond_label = mkVHDLExtId "othercell"
458       -- if n > 0 or n < len-1
459       let cond_scheme = AST.IfGn $ n_cur AST.:/=: (AST.PrimLit "0")
460       -- Output to tmp[current n]
461       let resname = mkIndexedName tmp_name n_cur
462       -- Input from tmp[previous n]
463       let argexpr = vhdlNameToVHDLExpr $ mkIndexedName tmp_name n_prev
464       app_concsms <- genApplication (Right resname) app_f [Right argexpr]
465       -- Return the conditional generate part
466       return $ AST.GenerateSm cond_label cond_scheme [] app_concsms
467
468
469 -----------------------------------------------------------------------------
470 -- Function to generate VHDL for applications
471 -----------------------------------------------------------------------------
472 genApplication ::
473   (Either CoreSyn.CoreBndr AST.VHDLName) -- ^ Where to store the result?
474   -> CoreSyn.CoreBndr -- ^ The function to apply
475   -> [Either CoreSyn.CoreExpr AST.Expr] -- ^ The arguments to apply
476   -> VHDLSession [AST.ConcSm] -- ^ The resulting concurrent statements
477 genApplication dst f args =
478   case Var.globalIdVarDetails f of
479     IdInfo.DataConWorkId dc -> case dst of
480       -- It's a datacon. Create a record from its arguments.
481       Left bndr -> do
482         -- We have the bndr, so we can get at the type
483         labels <- MonadState.lift vsType $ getFieldLabels (Var.varType bndr)
484         return $ zipWith mkassign labels $ map (either exprToVHDLExpr id) args
485         where
486           mkassign :: AST.VHDLId -> AST.Expr -> AST.ConcSm
487           mkassign label arg =
488             let sel_name = mkSelectedName ((either varToVHDLName id) dst) label in
489             mkUncondAssign (Right sel_name) arg
490       Right _ -> error $ "\nGenerate.genApplication: Can't generate dataconstructor application without an original binder"
491     IdInfo.VanillaGlobal -> do
492       -- It's a global value imported from elsewhere. These can be builtin
493       -- functions. Look up the function name in the name table and execute
494       -- the associated builder if there is any and the argument count matches
495       -- (this should always be the case if it typechecks, but just to be
496       -- sure...).
497       case (Map.lookup (varToString f) globalNameTable) of
498         Just (arg_count, builder) ->
499           if length args == arg_count then
500             builder dst f args
501           else
502             error $ "\nGenerate.genApplication(VanillaGlobal): Incorrect number of arguments to builtin function: " ++ pprString f ++ " Args: " ++ show args
503         Nothing -> error $ "\nGenerate.genApplication(VanillaGlobal): Using function from another module that is not a known builtin: " ++ pprString f
504     IdInfo.NotGlobalId -> do
505       signatures <- getA vsSignatures
506       -- This is a local id, so it should be a function whose definition we
507       -- have and which can be turned into a component instantiation.
508       let  
509         signature = Maybe.fromMaybe 
510           (error $ "\nGenerate.genApplication: Using function '" ++ (varToString f) ++ "' without signature? This should not happen!") 
511           (Map.lookup f signatures)
512         entity_id = ent_id signature
513         -- TODO: Using show here isn't really pretty, but we'll need some
514         -- unique-ish value...
515         label = "comp_ins_" ++ (either show prettyShow) dst
516         portmaps = mkAssocElems (map (either exprToVHDLExpr id) args) ((either varToVHDLName id) dst) signature
517         in
518           return [mkComponentInst label entity_id portmaps]
519     IdInfo.ClassOpId cls -> do
520       -- FIXME: Not looking for what instance this class op is called for
521       -- Is quite stupid of course.
522       case (Map.lookup (varToString f) globalNameTable) of
523         Just (arg_count, builder) ->
524           if length args == arg_count then
525             builder dst f args
526           else
527             error $ "\nGenerate.genApplication(ClassOpId): Incorrect number of arguments to builtin function: " ++ pprString f ++ " Args: " ++ show args
528         Nothing -> error $ "\nGenerate.genApplication(ClassOpId): Using function from another module that is not a known builtin: " ++ pprString f
529     details -> error $ "\nGenerate.genApplication: Calling unsupported function " ++ pprString f ++ " with GlobalIdDetails " ++ pprString details
530
531 -----------------------------------------------------------------------------
532 -- Functions to generate functions dealing with vectors.
533 -----------------------------------------------------------------------------
534
535 -- Returns the VHDLId of the vector function with the given name for the given
536 -- element type. Generates -- this function if needed.
537 vectorFunId :: Type.Type -> String -> TypeSession AST.VHDLId
538 vectorFunId el_ty fname = do
539   let error_msg = "\nGenerate.vectorFunId: Can not construct vector function for element: " ++ pprString el_ty
540   elemTM <- vhdl_ty error_msg el_ty
541   -- TODO: This should not be duplicated from mk_vector_ty. Probably but it in
542   -- the VHDLState or something.
543   let vectorTM = mkVHDLExtId $ "vector_" ++ (AST.fromVHDLId elemTM)
544   typefuns <- getA vsTypeFuns
545   case Map.lookup (OrdType el_ty, fname) typefuns of
546     -- Function already generated, just return it
547     Just (id, _) -> return id
548     -- Function not generated yet, generate it
549     Nothing -> do
550       let functions = genUnconsVectorFuns elemTM vectorTM
551       case lookup fname functions of
552         Just body -> do
553           modA vsTypeFuns $ Map.insert (OrdType el_ty, fname) (function_id, (fst body))
554           mapM_ (vectorFunId el_ty) (snd body)
555           return function_id
556         Nothing -> error $ "\nGenerate.vectorFunId: I don't know how to generate vector function " ++ fname
557   where
558     function_id = mkVHDLExtId fname
559
560 genUnconsVectorFuns :: AST.TypeMark -- ^ type of the vector elements
561                     -> AST.TypeMark -- ^ type of the vector
562                     -> [(String, (AST.SubProgBody, [String]))]
563 genUnconsVectorFuns elemTM vectorTM  = 
564   [ (exId, (AST.SubProgBody exSpec      []                  [exExpr],[]))
565   , (replaceId, (AST.SubProgBody replaceSpec [AST.SPVD replaceVar] [replaceExpr,replaceRet],[]))
566   , (headId, (AST.SubProgBody headSpec    []                  [headExpr],[]))
567   , (lastId, (AST.SubProgBody lastSpec    []                  [lastExpr],[]))
568   , (initId, (AST.SubProgBody initSpec    [AST.SPVD initVar]  [initExpr, initRet],[]))
569   , (tailId, (AST.SubProgBody tailSpec    [AST.SPVD tailVar]  [tailExpr, tailRet],[]))
570   , (takeId, (AST.SubProgBody takeSpec    [AST.SPVD takeVar]  [takeExpr, takeRet],[]))
571   , (dropId, (AST.SubProgBody dropSpec    [AST.SPVD dropVar]  [dropExpr, dropRet],[]))
572   , (plusgtId, (AST.SubProgBody plusgtSpec  [AST.SPVD plusgtVar] [plusgtExpr, plusgtRet],[]))
573   , (emptyId, (AST.SubProgBody emptySpec   [AST.SPCD emptyVar] [emptyExpr],[]))
574   , (singletonId, (AST.SubProgBody singletonSpec [AST.SPVD singletonVar] [singletonRet],[]))
575   , (copynId, (AST.SubProgBody copynSpec    [AST.SPVD copynVar]      [copynExpr],[]))
576   , (selId, (AST.SubProgBody selSpec  [AST.SPVD selVar] [selFor, selRet],[]))
577   , (ltplusId, (AST.SubProgBody ltplusSpec [AST.SPVD ltplusVar] [ltplusExpr, ltplusRet],[]))  
578   , (plusplusId, (AST.SubProgBody plusplusSpec [AST.SPVD plusplusVar] [plusplusExpr, plusplusRet],[]))
579   , (lengthTId, (AST.SubProgBody lengthTSpec [] [lengthTExpr],[]))
580   , (shiftlId, (AST.SubProgBody shiftlSpec [AST.SPVD shiftlVar] [shiftlExpr, shiftlRet], [initId]))
581   , (shiftrId, (AST.SubProgBody shiftrSpec [AST.SPVD shiftrVar] [shiftrExpr, shiftrRet], [tailId]))
582   , (nullId, (AST.SubProgBody nullSpec [] [nullExpr], []))
583   , (rotlId, (AST.SubProgBody rotlSpec [AST.SPVD rotlVar] [rotlExpr, rotlRet], [nullId, lastId, initId]))
584   , (rotrId, (AST.SubProgBody rotrSpec [AST.SPVD rotrVar] [rotrExpr, rotrRet], [nullId, tailId, headId]))
585   , (reverseId, (AST.SubProgBody reverseSpec [AST.SPVD reverseVar] [reverseFor, reverseRet], []))
586   ]
587   where 
588     ixPar   = AST.unsafeVHDLBasicId "ix"
589     vecPar  = AST.unsafeVHDLBasicId "vec"
590     vec1Par = AST.unsafeVHDLBasicId "vec1"
591     vec2Par = AST.unsafeVHDLBasicId "vec2"
592     nPar    = AST.unsafeVHDLBasicId "n"
593     iId     = AST.unsafeVHDLBasicId "i"
594     iPar    = iId
595     aPar    = AST.unsafeVHDLBasicId "a"
596     fPar = AST.unsafeVHDLBasicId "f"
597     sPar = AST.unsafeVHDLBasicId "s"
598     resId   = AST.unsafeVHDLBasicId "res"
599     exSpec = AST.Function (mkVHDLExtId exId) [AST.IfaceVarDec vecPar vectorTM,
600                                AST.IfaceVarDec ixPar  naturalTM] elemTM
601     exExpr = AST.ReturnSm (Just $ AST.PrimName $ AST.NIndexed 
602               (AST.IndexedName (AST.NSimple vecPar) [AST.PrimName $ 
603                 AST.NSimple ixPar]))
604     replaceSpec = AST.Function (mkVHDLExtId replaceId)  [ AST.IfaceVarDec vecPar vectorTM
605                                           , AST.IfaceVarDec iPar   naturalTM
606                                           , AST.IfaceVarDec aPar   elemTM
607                                           ] vectorTM 
608        -- variable res : fsvec_x (0 to vec'length-1);
609     replaceVar =
610          AST.VarDec resId 
611                 (AST.SubtypeIn vectorTM
612                   (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
613                    [AST.ToRange (AST.PrimLit "0")
614                             (AST.PrimName (AST.NAttribute $ 
615                               AST.AttribName (AST.NSimple vecPar) (mkVHDLBasicId lengthId) Nothing) AST.:-:
616                                 (AST.PrimLit "1"))   ]))
617                 Nothing
618        --  res AST.:= vec(0 to i-1) & a & vec(i+1 to length'vec-1)
619     replaceExpr = AST.NSimple resId AST.:=
620            (vecSlice (AST.PrimLit "0") (AST.PrimName (AST.NSimple iPar) AST.:-: AST.PrimLit "1") AST.:&:
621             AST.PrimName (AST.NSimple aPar) AST.:&: 
622              vecSlice (AST.PrimName (AST.NSimple iPar) AST.:+: AST.PrimLit "1")
623                       ((AST.PrimName (AST.NAttribute $ 
624                                 AST.AttribName (AST.NSimple vecPar) (mkVHDLBasicId lengthId) Nothing)) 
625                                                               AST.:-: AST.PrimLit "1"))
626     replaceRet =  AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
627     vecSlice init last =  AST.PrimName (AST.NSlice 
628                                         (AST.SliceName 
629                                               (AST.NSimple vecPar) 
630                                               (AST.ToRange init last)))
631     headSpec = AST.Function (mkVHDLExtId headId) [AST.IfaceVarDec vecPar vectorTM] elemTM
632        -- return vec(0);
633     headExpr = AST.ReturnSm (Just $ (AST.PrimName $ AST.NIndexed (AST.IndexedName 
634                     (AST.NSimple vecPar) [AST.PrimLit "0"])))
635     lastSpec = AST.Function (mkVHDLExtId lastId) [AST.IfaceVarDec vecPar vectorTM] elemTM
636        -- return vec(vec'length-1);
637     lastExpr = AST.ReturnSm (Just $ (AST.PrimName $ AST.NIndexed (AST.IndexedName 
638                     (AST.NSimple vecPar) 
639                     [AST.PrimName (AST.NAttribute $ 
640                                 AST.AttribName (AST.NSimple vecPar) (mkVHDLBasicId lengthId) Nothing) 
641                                                              AST.:-: AST.PrimLit "1"])))
642     initSpec = AST.Function (mkVHDLExtId initId) [AST.IfaceVarDec vecPar vectorTM] vectorTM 
643        -- variable res : fsvec_x (0 to vec'length-2);
644     initVar = 
645          AST.VarDec resId 
646                 (AST.SubtypeIn vectorTM
647                   (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
648                    [AST.ToRange (AST.PrimLit "0")
649                             (AST.PrimName (AST.NAttribute $ 
650                               AST.AttribName (AST.NSimple vecPar) (mkVHDLBasicId lengthId) Nothing) AST.:-:
651                                 (AST.PrimLit "2"))   ]))
652                 Nothing
653        -- resAST.:= vec(0 to vec'length-2)
654     initExpr = AST.NSimple resId AST.:= (vecSlice 
655                                (AST.PrimLit "0") 
656                                (AST.PrimName (AST.NAttribute $ 
657                                   AST.AttribName (AST.NSimple vecPar) (mkVHDLBasicId lengthId) Nothing) 
658                                                              AST.:-: AST.PrimLit "2"))
659     initRet =  AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
660     tailSpec = AST.Function (mkVHDLExtId tailId) [AST.IfaceVarDec vecPar vectorTM] vectorTM
661        -- variable res : fsvec_x (0 to vec'length-2); 
662     tailVar = 
663          AST.VarDec resId 
664                 (AST.SubtypeIn vectorTM
665                   (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
666                    [AST.ToRange (AST.PrimLit "0")
667                             (AST.PrimName (AST.NAttribute $ 
668                               AST.AttribName (AST.NSimple vecPar) (mkVHDLBasicId lengthId) Nothing) AST.:-:
669                                 (AST.PrimLit "2"))   ]))
670                 Nothing       
671        -- res AST.:= vec(1 to vec'length-1)
672     tailExpr = AST.NSimple resId AST.:= (vecSlice 
673                                (AST.PrimLit "1") 
674                                (AST.PrimName (AST.NAttribute $ 
675                                   AST.AttribName (AST.NSimple vecPar) (mkVHDLBasicId lengthId) Nothing) 
676                                                              AST.:-: AST.PrimLit "1"))
677     tailRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
678     takeSpec = AST.Function (mkVHDLExtId takeId) [AST.IfaceVarDec nPar   naturalTM,
679                                    AST.IfaceVarDec vecPar vectorTM ] vectorTM
680        -- variable res : fsvec_x (0 to n-1);
681     takeVar = 
682          AST.VarDec resId 
683                 (AST.SubtypeIn vectorTM
684                   (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
685                    [AST.ToRange (AST.PrimLit "0")
686                                ((AST.PrimName (AST.NSimple nPar)) AST.:-:
687                                 (AST.PrimLit "1"))   ]))
688                 Nothing
689        -- res AST.:= vec(0 to n-1)
690     takeExpr = AST.NSimple resId AST.:= 
691                     (vecSlice (AST.PrimLit "1") 
692                               (AST.PrimName (AST.NSimple $ nPar) AST.:-: AST.PrimLit "1"))
693     takeRet =  AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
694     dropSpec = AST.Function (mkVHDLExtId dropId) [AST.IfaceVarDec nPar   naturalTM,
695                                    AST.IfaceVarDec vecPar vectorTM ] vectorTM 
696        -- variable res : fsvec_x (0 to vec'length-n-1);
697     dropVar = 
698          AST.VarDec resId 
699                 (AST.SubtypeIn vectorTM
700                   (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
701                    [AST.ToRange (AST.PrimLit "0")
702                             (AST.PrimName (AST.NAttribute $ 
703                               AST.AttribName (AST.NSimple vecPar) (mkVHDLBasicId lengthId) Nothing) AST.:-:
704                                (AST.PrimName $ AST.NSimple nPar)AST.:-: (AST.PrimLit "1")) ]))
705                Nothing
706        -- res AST.:= vec(n to vec'length-1)
707     dropExpr = AST.NSimple resId AST.:= (vecSlice 
708                                (AST.PrimName $ AST.NSimple nPar) 
709                                (AST.PrimName (AST.NAttribute $ 
710                                   AST.AttribName (AST.NSimple vecPar) (mkVHDLBasicId lengthId) Nothing) 
711                                                              AST.:-: AST.PrimLit "1"))
712     dropRet =  AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
713     plusgtSpec = AST.Function (mkVHDLExtId plusgtId) [AST.IfaceVarDec aPar   elemTM,
714                                        AST.IfaceVarDec vecPar vectorTM] vectorTM 
715     -- variable res : fsvec_x (0 to vec'length);
716     plusgtVar = 
717       AST.VarDec resId 
718              (AST.SubtypeIn vectorTM
719                (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
720                 [AST.ToRange (AST.PrimLit "0")
721                         (AST.PrimName (AST.NAttribute $ 
722                           AST.AttribName (AST.NSimple vecPar) (mkVHDLBasicId lengthId) Nothing))]))
723              Nothing
724     plusgtExpr = AST.NSimple resId AST.:= 
725                    ((AST.PrimName $ AST.NSimple aPar) AST.:&: 
726                     (AST.PrimName $ AST.NSimple vecPar))
727     plusgtRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
728     emptySpec = AST.Function (mkVHDLExtId emptyId) [] vectorTM
729     emptyVar = 
730           AST.ConstDec resId 
731               (AST.SubtypeIn vectorTM Nothing)
732               (Just $ AST.PrimLit "\"\"")
733     emptyExpr = AST.ReturnSm (Just $ AST.PrimName (AST.NSimple resId))
734     singletonSpec = AST.Function (mkVHDLExtId singletonId) [AST.IfaceVarDec aPar elemTM ] 
735                                          vectorTM
736     -- variable res : fsvec_x (0 to 0) := (others => a);
737     singletonVar = 
738       AST.VarDec resId 
739              (AST.SubtypeIn vectorTM
740                (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
741                 [AST.ToRange (AST.PrimLit "0") (AST.PrimLit "0")]))
742              (Just $ AST.Aggregate [AST.ElemAssoc (Just AST.Others) 
743                                           (AST.PrimName $ AST.NSimple aPar)])
744     singletonRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
745     copynSpec = AST.Function (mkVHDLExtId copynId) [AST.IfaceVarDec nPar   naturalTM,
746                                    AST.IfaceVarDec aPar   elemTM   ] vectorTM 
747     -- variable res : fsvec_x (0 to n-1) := (others => a);
748     copynVar = 
749       AST.VarDec resId 
750              (AST.SubtypeIn vectorTM
751                (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
752                 [AST.ToRange (AST.PrimLit "0")
753                             ((AST.PrimName (AST.NSimple nPar)) AST.:-:
754                              (AST.PrimLit "1"))   ]))
755              (Just $ AST.Aggregate [AST.ElemAssoc (Just AST.Others) 
756                                           (AST.PrimName $ AST.NSimple aPar)])
757     -- return res
758     copynExpr = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
759     selSpec = AST.Function (mkVHDLExtId selId) [AST.IfaceVarDec fPar   naturalTM,
760                                AST.IfaceVarDec sPar   naturalTM,
761                                AST.IfaceVarDec nPar   naturalTM,
762                                AST.IfaceVarDec vecPar vectorTM ] vectorTM
763     -- variable res : fsvec_x (0 to n-1);
764     selVar = 
765       AST.VarDec resId 
766                 (AST.SubtypeIn vectorTM
767                   (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
768                     [AST.ToRange (AST.PrimLit "0")
769                       ((AST.PrimName (AST.NSimple nPar)) AST.:-:
770                       (AST.PrimLit "1"))   ])
771                 )
772                 Nothing
773     -- for i res'range loop
774     --   res(i) := vec(f+i*s);
775     -- end loop;
776     selFor = AST.ForSM iId (AST.AttribRange $ AST.AttribName (AST.NSimple resId) rangeId Nothing) [selAssign]
777     -- res(i) := vec(f+i*s);
778     selAssign = let origExp = AST.PrimName (AST.NSimple fPar) AST.:+: 
779                                 (AST.PrimName (AST.NSimple iId) AST.:*: 
780                                   AST.PrimName (AST.NSimple sPar)) in
781                                   AST.NIndexed (AST.IndexedName (AST.NSimple resId) [AST.PrimName (AST.NSimple iId)]) AST.:=
782                                     (AST.PrimName $ AST.NIndexed (AST.IndexedName (AST.NSimple vecPar) [origExp]))
783     -- return res;
784     selRet =  AST.ReturnSm (Just $ AST.PrimName (AST.NSimple resId))
785     ltplusSpec = AST.Function (mkVHDLExtId ltplusId) [AST.IfaceVarDec vecPar vectorTM,
786                                         AST.IfaceVarDec aPar   elemTM] vectorTM 
787      -- variable res : fsvec_x (0 to vec'length);
788     ltplusVar = 
789       AST.VarDec resId 
790         (AST.SubtypeIn vectorTM
791           (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
792             [AST.ToRange (AST.PrimLit "0")
793               (AST.PrimName (AST.NAttribute $ 
794                 AST.AttribName (AST.NSimple vecPar) (mkVHDLBasicId lengthId) Nothing))]))
795         Nothing
796     ltplusExpr = AST.NSimple resId AST.:= 
797                      ((AST.PrimName $ AST.NSimple vecPar) AST.:&: 
798                       (AST.PrimName $ AST.NSimple aPar))
799     ltplusRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
800     plusplusSpec = AST.Function (mkVHDLExtId plusplusId) [AST.IfaceVarDec vec1Par vectorTM,
801                                              AST.IfaceVarDec vec2Par vectorTM] 
802                                              vectorTM 
803     -- variable res : fsvec_x (0 to vec1'length + vec2'length -1);
804     plusplusVar = 
805       AST.VarDec resId 
806         (AST.SubtypeIn vectorTM
807           (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
808             [AST.ToRange (AST.PrimLit "0")
809               (AST.PrimName (AST.NAttribute $ 
810                 AST.AttribName (AST.NSimple vec1Par) (mkVHDLBasicId lengthId) Nothing) AST.:+:
811                   AST.PrimName (AST.NAttribute $ 
812                 AST.AttribName (AST.NSimple vec2Par) (mkVHDLBasicId lengthId) Nothing) AST.:-:
813                   AST.PrimLit "1")]))
814        Nothing
815     plusplusExpr = AST.NSimple resId AST.:= 
816                      ((AST.PrimName $ AST.NSimple vec1Par) AST.:&: 
817                       (AST.PrimName $ AST.NSimple vec2Par))
818     plusplusRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
819     lengthTSpec = AST.Function (mkVHDLExtId lengthTId) [AST.IfaceVarDec vecPar vectorTM] naturalTM
820     lengthTExpr = AST.ReturnSm (Just $ AST.PrimName (AST.NAttribute $ 
821                                 AST.AttribName (AST.NSimple vecPar) (mkVHDLBasicId lengthId) Nothing))
822     shiftlSpec = AST.Function (mkVHDLExtId shiftlId) [AST.IfaceVarDec vecPar vectorTM,
823                                    AST.IfaceVarDec aPar   elemTM  ] vectorTM 
824     -- variable res : fsvec_x (0 to vec'length-1);
825     shiftlVar = 
826      AST.VarDec resId 
827             (AST.SubtypeIn vectorTM
828               (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
829                [AST.ToRange (AST.PrimLit "0")
830                         (AST.PrimName (AST.NAttribute $ 
831                           AST.AttribName (AST.NSimple vecPar) (mkVHDLBasicId lengthId) Nothing) AST.:-:
832                            (AST.PrimLit "1")) ]))
833             Nothing
834     -- res := a & init(vec)
835     shiftlExpr = AST.NSimple resId AST.:=
836                     (AST.PrimName (AST.NSimple aPar) AST.:&:
837                      (AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLExtId initId))  
838                        [Nothing AST.:=>: AST.ADExpr (AST.PrimName $ AST.NSimple vecPar)]))
839     shiftlRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)       
840     shiftrSpec = AST.Function (mkVHDLExtId shiftrId) [AST.IfaceVarDec vecPar vectorTM,
841                                        AST.IfaceVarDec aPar   elemTM  ] vectorTM 
842     -- variable res : fsvec_x (0 to vec'length-1);
843     shiftrVar = 
844      AST.VarDec resId 
845             (AST.SubtypeIn vectorTM
846               (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
847                [AST.ToRange (AST.PrimLit "0")
848                         (AST.PrimName (AST.NAttribute $ 
849                           AST.AttribName (AST.NSimple vecPar) (mkVHDLBasicId lengthId) Nothing) AST.:-:
850                            (AST.PrimLit "1")) ]))
851             Nothing
852     -- res := tail(vec) & a
853     shiftrExpr = AST.NSimple resId AST.:=
854                   ((AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLExtId tailId))  
855                     [Nothing AST.:=>: AST.ADExpr (AST.PrimName $ AST.NSimple vecPar)]) AST.:&:
856                   (AST.PrimName (AST.NSimple aPar)))
857                 
858     shiftrRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)      
859     nullSpec = AST.Function (mkVHDLExtId nullId) [AST.IfaceVarDec vecPar vectorTM] booleanTM
860     -- return vec'length = 0
861     nullExpr = AST.ReturnSm (Just $ 
862                 AST.PrimName (AST.NAttribute $ 
863                   AST.AttribName (AST.NSimple vecPar) (mkVHDLBasicId lengthId) Nothing) AST.:=:
864                     AST.PrimLit "0")
865     rotlSpec = AST.Function (mkVHDLExtId rotlId) [AST.IfaceVarDec vecPar vectorTM] vectorTM 
866     -- variable res : fsvec_x (0 to vec'length-1);
867     rotlVar = 
868      AST.VarDec resId 
869             (AST.SubtypeIn vectorTM
870               (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
871                [AST.ToRange (AST.PrimLit "0")
872                         (AST.PrimName (AST.NAttribute $ 
873                           AST.AttribName (AST.NSimple vecPar) (mkVHDLBasicId lengthId) Nothing) AST.:-:
874                            (AST.PrimLit "1")) ]))
875             Nothing
876     -- if null(vec) then res := vec else res := last(vec) & init(vec)
877     rotlExpr = AST.IfSm (AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLExtId nullId))  
878                           [Nothing AST.:=>: AST.ADExpr (AST.PrimName $ AST.NSimple vecPar)])
879                         [AST.NSimple resId AST.:= (AST.PrimName $ AST.NSimple vecPar)]
880                         []
881                         (Just $ AST.Else [rotlExprRet])
882       where rotlExprRet = 
883                 AST.NSimple resId AST.:= 
884                       ((AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLExtId lastId))  
885                         [Nothing AST.:=>: AST.ADExpr (AST.PrimName $ AST.NSimple vecPar)]) AST.:&:
886                       (AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLExtId initId))  
887                         [Nothing AST.:=>: AST.ADExpr (AST.PrimName $ AST.NSimple vecPar)]))
888     rotlRet =  AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)       
889     rotrSpec = AST.Function (mkVHDLExtId rotrId) [AST.IfaceVarDec vecPar vectorTM] vectorTM 
890     -- variable res : fsvec_x (0 to vec'length-1);
891     rotrVar = 
892      AST.VarDec resId 
893             (AST.SubtypeIn vectorTM
894               (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
895                [AST.ToRange (AST.PrimLit "0")
896                         (AST.PrimName (AST.NAttribute $ 
897                           AST.AttribName (AST.NSimple vecPar) (mkVHDLBasicId lengthId) Nothing) AST.:-:
898                            (AST.PrimLit "1")) ]))
899             Nothing
900     -- if null(vec) then res := vec else res := tail(vec) & head(vec)
901     rotrExpr = AST.IfSm (AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLExtId nullId))  
902                           [Nothing AST.:=>: AST.ADExpr (AST.PrimName $ AST.NSimple vecPar)])
903                         [AST.NSimple resId AST.:= (AST.PrimName $ AST.NSimple vecPar)]
904                         []
905                         (Just $ AST.Else [rotrExprRet])
906       where rotrExprRet = 
907                 AST.NSimple resId AST.:= 
908                       ((AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLExtId tailId))  
909                         [Nothing AST.:=>: AST.ADExpr (AST.PrimName $ AST.NSimple vecPar)]) AST.:&:
910                       (AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLExtId headId))  
911                         [Nothing AST.:=>: AST.ADExpr (AST.PrimName $ AST.NSimple vecPar)]))
912     rotrRet =  AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
913     reverseSpec = AST.Function (mkVHDLExtId reverseId) [AST.IfaceVarDec vecPar vectorTM] vectorTM
914     reverseVar = 
915       AST.VarDec resId 
916              (AST.SubtypeIn vectorTM
917                (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
918                 [AST.ToRange (AST.PrimLit "0")
919                          (AST.PrimName (AST.NAttribute $ 
920                            AST.AttribName (AST.NSimple vecPar) (mkVHDLBasicId lengthId) Nothing) AST.:-:
921                             (AST.PrimLit "1")) ]))
922              Nothing
923     -- for i in 0 to res'range loop
924     --   res(vec'length-i-1) := vec(i);
925     -- end loop;
926     reverseFor = 
927        AST.ForSM iId (AST.AttribRange $ AST.AttribName (AST.NSimple resId) rangeId Nothing) [reverseAssign]
928     -- res(vec'length-i-1) := vec(i);
929     reverseAssign = AST.NIndexed (AST.IndexedName (AST.NSimple resId) [destExp]) AST.:=
930       (AST.PrimName $ AST.NIndexed (AST.IndexedName (AST.NSimple vecPar) 
931                            [AST.PrimName $ AST.NSimple iId]))
932         where destExp = AST.PrimName (AST.NAttribute $ AST.AttribName (AST.NSimple vecPar) 
933                                    (mkVHDLBasicId lengthId) Nothing) AST.:-: 
934                         AST.PrimName (AST.NSimple iId) AST.:-: 
935                         (AST.PrimLit "1") 
936     -- return res;
937     reverseRet = AST.ReturnSm (Just $ AST.PrimName (AST.NSimple resId))
938     
939 -----------------------------------------------------------------------------
940 -- A table of builtin functions
941 -----------------------------------------------------------------------------
942
943 -- | The builtin functions we support. Maps a name to an argument count and a
944 -- builder function.
945 globalNameTable :: NameTable
946 globalNameTable = Map.fromList
947   [ (exId             , (2, genFCall False          ) )
948   , (replaceId        , (3, genFCall False          ) )
949   , (headId           , (1, genFCall True           ) )
950   , (lastId           , (1, genFCall True           ) )
951   , (tailId           , (1, genFCall False          ) )
952   , (initId           , (1, genFCall False          ) )
953   , (takeId           , (2, genFCall False          ) )
954   , (dropId           , (2, genFCall False          ) )
955   , (selId            , (4, genFCall False          ) )
956   , (plusgtId         , (2, genFCall False          ) )
957   , (ltplusId         , (2, genFCall False          ) )
958   , (plusplusId       , (2, genFCall False          ) )
959   , (mapId            , (2, genMap                  ) )
960   , (zipWithId        , (3, genZipWith              ) )
961   , (foldlId          , (3, genFoldl                ) )
962   , (foldrId          , (3, genFoldr                ) )
963   , (zipId            , (2, genZip                  ) )
964   , (unzipId          , (1, genUnzip                ) )
965   , (shiftlId         , (2, genFCall False          ) )
966   , (shiftrId         , (2, genFCall False          ) )
967   , (rotlId           , (1, genFCall False          ) )
968   , (rotrId           , (1, genFCall False          ) )
969   , (concatId         , (1, genConcat               ) )
970   , (reverseId        , (1, genFCall False          ) )
971   , (iteratenId       , (3, genIteraten             ) )
972   , (iterateId        , (2, genIterate              ) )
973   , (generatenId      , (3, genGeneraten            ) )
974   , (generateId       , (2, genGenerate             ) )
975   , (emptyId          , (0, genFCall False          ) )
976   , (singletonId      , (1, genFCall False          ) )
977   , (copynId          , (2, genFCall False          ) )
978   , (copyId           , (1, genCopy                 ) )
979   , (lengthTId        , (1, genFCall False          ) )
980   , (nullId           , (1, genFCall False          ) )
981   , (hwxorId          , (2, genOperator2 AST.Xor    ) )
982   , (hwandId          , (2, genOperator2 AST.And    ) )
983   , (hworId           , (2, genOperator2 AST.Or     ) )
984   , (hwnotId          , (1, genOperator1 AST.Not    ) )
985   , (plusId           , (2, genOperator2 (AST.:+:)  ) )
986   , (timesId          , (2, genOperator2 (AST.:*:)  ) )
987   , (negateId         , (1, genNegation             ) )
988   , (minusId          , (2, genOperator2 (AST.:-:)  ) )
989   , (fromSizedWordId  , (1, genFromSizedWord        ) )
990   , (fromIntegerId    , (1, genFromInteger          ) )
991   ]