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