Generate more unique variable names, generate truely unique entity names
[matthijs/master-project/cλash.git] / cλash / CLasH / VHDL / Generate.hs
1 module CLasH.VHDL.Generate where
2
3 -- Standard modules
4 import qualified Data.List as List
5 import qualified Data.Map as Map
6 import qualified Control.Monad as Monad
7 import qualified Maybe
8 import qualified Data.Either as Either
9 import Data.Accessor
10 import Data.Accessor.MonadState as MonadState
11 import Debug.Trace
12
13 -- ForSyDe
14 import qualified Language.VHDL.AST as AST
15
16 -- GHC API
17 import qualified CoreSyn
18 import qualified Type
19 import qualified Var
20 import qualified Id
21 import qualified IdInfo
22 import qualified Literal
23 import qualified Name
24 import qualified TyCon
25
26 -- Local imports
27 import CLasH.Translator.TranslatorTypes
28 import CLasH.VHDL.Constants
29 import CLasH.VHDL.VHDLTypes
30 import CLasH.VHDL.VHDLTools
31 import CLasH.Utils as Utils
32 import CLasH.Utils.Core.CoreTools
33 import CLasH.Utils.Pretty
34 import qualified CLasH.Normalize as Normalize
35
36 -----------------------------------------------------------------------------
37 -- Functions to generate VHDL for user-defined functions.
38 -----------------------------------------------------------------------------
39
40 -- | Create an entity for a given function
41 getEntity ::
42   CoreSyn.CoreBndr
43   -> TranslatorSession Entity -- ^ The resulting entity
44
45 getEntity fname = Utils.makeCached fname tsEntities $ do
46       expr <- Normalize.getNormalized fname
47       -- Strip off lambda's, these will be arguments
48       let (args, letexpr) = CoreSyn.collectBinders expr
49       -- Generate ports for all non-empty types
50       args' <- catMaybesM $ mapM mkMap args
51       -- There must be a let at top level 
52       let (CoreSyn.Let binds (CoreSyn.Var res)) = letexpr
53       -- TODO: Handle Nothing
54       res' <- mkMap res
55       count <- getA tsEntityCounter 
56       let vhdl_id = mkVHDLBasicId $ varToString fname ++ "Component_" ++ show count
57       putA tsEntityCounter (count + 1)
58       let ent_decl = createEntityAST vhdl_id args' res'
59       let signature = Entity vhdl_id args' res' ent_decl
60       return signature
61   where
62     mkMap ::
63       --[(SignalId, SignalInfo)] 
64       CoreSyn.CoreBndr 
65       -> TranslatorSession (Maybe Port)
66     mkMap = (\bndr ->
67       let
68         --info = Maybe.fromMaybe
69         --  (error $ "Signal not found in the name map? This should not happen!")
70         --  (lookup id sigmap)
71         --  Assume the bndr has a valid VHDL id already
72         id = varToVHDLId bndr
73         ty = Var.varType bndr
74         error_msg = "\nVHDL.createEntity.mkMap: Can not create entity: " ++ pprString fname ++ "\nbecause no type can be created for port: " ++ pprString bndr 
75       in do
76         type_mark_maybe <- MonadState.lift tsType $ vhdl_ty error_msg ty
77         case type_mark_maybe of 
78           Just type_mark -> return $ Just (id, type_mark)
79           Nothing -> return Nothing
80      )
81
82 -- | Create the VHDL AST for an entity
83 createEntityAST ::
84   AST.VHDLId                   -- ^ The name of the function
85   -> [Port]                    -- ^ The entity's arguments
86   -> Maybe Port                -- ^ The entity's result
87   -> AST.EntityDec             -- ^ The entity with the ent_decl filled in as well
88
89 createEntityAST vhdl_id args res =
90   AST.EntityDec vhdl_id ports
91   where
92     -- Create a basic Id, since VHDL doesn't grok filenames with extended Ids.
93     ports = map (mkIfaceSigDec AST.In) args
94               ++ (Maybe.maybeToList res_port)
95               ++ [clk_port]
96     -- Add a clk port if we have state
97     clk_port = AST.IfaceSigDec clockId AST.In std_logicTM
98     res_port = fmap (mkIfaceSigDec AST.Out) res
99
100 -- | Create a port declaration
101 mkIfaceSigDec ::
102   AST.Mode                         -- ^ The mode for the port (In / Out)
103   -> Port                          -- ^ The id and type for the port
104   -> AST.IfaceSigDec               -- ^ The resulting port declaration
105
106 mkIfaceSigDec mode (id, ty) = AST.IfaceSigDec id mode ty
107
108 -- | Create an architecture for a given function
109 getArchitecture ::
110   CoreSyn.CoreBndr -- ^ The function to get an architecture for
111   -> TranslatorSession (Architecture, [CoreSyn.CoreBndr])
112   -- ^ The architecture for this function
113
114 getArchitecture fname = Utils.makeCached fname tsArchitectures $ do
115   expr <- Normalize.getNormalized fname
116   signature <- getEntity fname
117   let entity_id = ent_id signature
118   -- Strip off lambda's, these will be arguments
119   let (args, letexpr) = CoreSyn.collectBinders expr
120   -- There must be a let at top level 
121   let (CoreSyn.Let (CoreSyn.Rec binds) (CoreSyn.Var res)) = letexpr
122
123   -- Create signal declarations for all binders in the let expression, except
124   -- for the output port (that will already have an output port declared in
125   -- the entity).
126   sig_dec_maybes <- mapM (mkSigDec . fst) (filter ((/=res).fst) binds)
127   let sig_decs = Maybe.catMaybes $ sig_dec_maybes
128   -- Process each bind, resulting in info about state variables and concurrent
129   -- statements.
130   (state_vars, sms) <- Monad.mapAndUnzipM dobind binds
131   let (in_state_maybes, out_state_maybes) = unzip state_vars
132   let (statementss, used_entitiess) = unzip sms
133   -- Create a state proc, if needed
134   let state_proc = case (Maybe.catMaybes in_state_maybes, Maybe.catMaybes out_state_maybes) of
135         ([in_state], [out_state]) -> [AST.CSPSm $ mkStateProcSm (in_state, out_state)]
136         ([], []) -> []
137         (ins, outs) -> error $ "Weird use of state in " ++ show fname ++ ". In: " ++ show ins ++ " Out: " ++ show outs
138   -- Join the create statements and the (optional) state_proc
139   let statements = concat statementss ++ state_proc
140   -- Create the architecture
141   let arch = AST.ArchBody (mkVHDLBasicId "structural") (AST.NSimple entity_id) (map AST.BDISD sig_decs) statements
142   let used_entities = concat used_entitiess
143   return (arch, used_entities)
144   where
145     dobind :: (CoreSyn.CoreBndr, CoreSyn.CoreExpr) -- ^ The bind to process
146               -> TranslatorSession ((Maybe CoreSyn.CoreBndr, Maybe CoreSyn.CoreBndr), ([AST.ConcSm], [CoreSyn.CoreBndr]))
147               -- ^ ((Input state variable, output state variable), (statements, used entities))
148     -- newtype unpacking is just a cast
149     dobind (bndr, (CoreSyn.Cast expr coercion)) 
150       | hasStateType expr
151       = return ((Just bndr, Nothing), ([], []))
152     -- With simplCore, newtype packing is just a cast
153     dobind (bndr, expr@(CoreSyn.Cast (CoreSyn.Var state) coercion)) 
154       | hasStateType expr
155       = return ((Nothing, Just state), ([], []))
156     -- Without simplCore, newtype packing uses a data constructor
157     dobind (bndr, (CoreSyn.App (CoreSyn.App (CoreSyn.Var con) (CoreSyn.Type _)) (CoreSyn.Var state))) 
158       | isStateCon con
159       = return ((Nothing, Just state), ([], []))
160     -- Anything else is handled by mkConcSm
161     dobind bind = do
162       sms <- mkConcSm bind
163       return ((Nothing, Nothing), sms)
164
165 mkStateProcSm :: 
166   (CoreSyn.CoreBndr, CoreSyn.CoreBndr) -- ^ The current and new state variables
167   -> AST.ProcSm -- ^ The resulting statement
168 mkStateProcSm (old, new) =
169   AST.ProcSm label [clk] [statement]
170   where
171     label       = mkVHDLBasicId $ "state"
172     clk         = mkVHDLBasicId "clock"
173     rising_edge = AST.NSimple $ mkVHDLBasicId "rising_edge"
174     wform       = AST.Wform [AST.WformElem (AST.PrimName $ varToVHDLName new) Nothing]
175     assign      = AST.SigAssign (varToVHDLName old) wform
176     rising_edge_clk = AST.PrimFCall $ AST.FCall rising_edge [Nothing AST.:=>: (AST.ADName $ AST.NSimple clk)]
177     statement   = AST.IfSm rising_edge_clk [assign] [] Nothing
178
179
180 -- | Transforms a core binding into a VHDL concurrent statement
181 mkConcSm ::
182   (CoreSyn.CoreBndr, CoreSyn.CoreExpr) -- ^ The binding to process
183   -> TranslatorSession ([AST.ConcSm], [CoreSyn.CoreBndr]) 
184   -- ^ The corresponding VHDL concurrent statements and entities
185   --   instantiated.
186
187
188 -- Ignore Cast expressions, they should not longer have any meaning as long as
189 -- the type works out.
190 mkConcSm (bndr, CoreSyn.Cast expr ty) = mkConcSm (bndr, expr)
191
192 -- Simple a = b assignments are just like applications, but without arguments.
193 -- We can't just generate an unconditional assignment here, since b might be a
194 -- top level binding (e.g., a function with no arguments).
195 mkConcSm (bndr, CoreSyn.Var v) = do
196   genApplication (Left bndr) v []
197
198 mkConcSm (bndr, app@(CoreSyn.App _ _))= do
199   let (CoreSyn.Var f, args) = CoreSyn.collectArgs app
200   let valargs = get_val_args (Var.varType f) args
201   genApplication (Left bndr) f (map Left valargs)
202
203 -- A single alt case must be a selector. This means thee scrutinee is a simple
204 -- variable, the alternative is a dataalt with a single non-wild binder that
205 -- is also returned.
206 mkConcSm (bndr, expr@(CoreSyn.Case (CoreSyn.Var scrut) b ty [alt])) 
207                 -- Don't generate VHDL for substate extraction
208                 | hasStateType bndr = return ([], [])
209                 | otherwise =
210   case alt of
211     (CoreSyn.DataAlt dc, bndrs, (CoreSyn.Var sel_bndr)) -> do
212       bndrs' <- Monad.filterM hasNonEmptyType bndrs
213       case List.elemIndex sel_bndr bndrs' of
214         Just i -> do
215           labels <- MonadState.lift tsType $ getFieldLabels (Id.idType scrut)
216           let label = labels!!i
217           let sel_name = mkSelectedName (varToVHDLName scrut) label
218           let sel_expr = AST.PrimName sel_name
219           return ([mkUncondAssign (Left bndr) sel_expr], [])
220         Nothing -> error $ "\nVHDL.mkConcSM: Not in normal form: Not a selector case:\n" ++ (pprString expr)
221       
222     _ -> error $ "\nVHDL.mkConcSM: Not in normal form: Not a selector case:\n" ++ (pprString expr)
223
224 -- Multiple case alt are be conditional assignments and have only wild
225 -- binders in the alts and only variables in the case values and a variable
226 -- for a scrutinee. We check the constructor of the second alt, since the
227 -- first is the default case, if there is any.
228 mkConcSm (bndr, (CoreSyn.Case (CoreSyn.Var scrut) b ty [(_, _, CoreSyn.Var false), (con, _, CoreSyn.Var true)])) = do
229   scrut' <- MonadState.lift tsType $ varToVHDLExpr scrut
230   let cond_expr = scrut' AST.:=: (altconToVHDLExpr con)
231   true_expr <- MonadState.lift tsType $ varToVHDLExpr true
232   false_expr <- MonadState.lift tsType $ varToVHDLExpr false
233   return ([mkCondAssign (Left bndr) cond_expr true_expr false_expr], [])
234
235 mkConcSm (_, (CoreSyn.Case (CoreSyn.Var _) _ _ alts)) = error "\nVHDL.mkConcSm: Not in normal form: Case statement with more than two alternatives"
236 mkConcSm (_, CoreSyn.Case _ _ _ _) = error "\nVHDL.mkConcSm: Not in normal form: Case statement has does not have a simple variable as scrutinee"
237 mkConcSm (bndr, expr) = error $ "\nVHDL.mkConcSM: Unsupported binding in let expression: " ++ pprString bndr ++ " = " ++ pprString expr
238
239 -----------------------------------------------------------------------------
240 -- Functions to generate VHDL for builtin functions
241 -----------------------------------------------------------------------------
242
243 -- | A function to wrap a builder-like function that expects its arguments to
244 -- be expressions.
245 genExprArgs wrap dst func args = do
246   args' <- argsToVHDLExprs args
247   wrap dst func args'
248
249 -- | Turn the all lefts into VHDL Expressions.
250 argsToVHDLExprs :: [Either CoreSyn.CoreExpr AST.Expr] -> TranslatorSession [AST.Expr]
251 argsToVHDLExprs = catMaybesM . (mapM argToVHDLExpr)
252
253 argToVHDLExpr :: Either CoreSyn.CoreExpr AST.Expr -> TranslatorSession (Maybe AST.Expr)
254 argToVHDLExpr (Left expr) = MonadState.lift tsType $ do
255   let errmsg = "Generate.argToVHDLExpr: Using non-representable type? Should not happen!"
256   ty_maybe <- vhdl_ty errmsg expr
257   case ty_maybe of
258     Just _ -> do
259       vhdl_expr <- varToVHDLExpr $ exprToVar expr
260       return $ Just vhdl_expr
261     Nothing -> return $ Nothing
262
263 argToVHDLExpr (Right expr) = return $ Just expr
264
265 -- A function to wrap a builder-like function that generates no component
266 -- instantiations
267 genNoInsts ::
268   (dst -> func -> args -> TranslatorSession [AST.ConcSm])
269   -> (dst -> func -> args -> TranslatorSession ([AST.ConcSm], [CoreSyn.CoreBndr]))
270 genNoInsts wrap dst func args = do
271   concsms <- wrap dst func args
272   return (concsms, [])
273
274 -- | A function to wrap a builder-like function that expects its arguments to
275 -- be variables.
276 genVarArgs ::
277   (dst -> func -> [Var.Var] -> res)
278   -> (dst -> func -> [Either CoreSyn.CoreExpr AST.Expr] -> res)
279 genVarArgs wrap dst func args = wrap dst func args'
280   where
281     args' = map exprToVar exprargs
282     -- Check (rather crudely) that all arguments are CoreExprs
283     (exprargs, []) = Either.partitionEithers args
284
285 -- | A function to wrap a builder-like function that expects its arguments to
286 -- be Literals
287 genLitArgs ::
288   (dst -> func -> [Literal.Literal] -> res)
289   -> (dst -> func -> [Either CoreSyn.CoreExpr AST.Expr] -> res)
290 genLitArgs wrap dst func args = wrap dst func args'
291   where
292     args' = map exprToLit litargs
293     -- FIXME: Check if we were passed an CoreSyn.App
294     litargs = concat (map getLiterals exprargs)
295     (exprargs, []) = Either.partitionEithers args
296
297 -- | A function to wrap a builder-like function that produces an expression
298 -- and expects it to be assigned to the destination.
299 genExprRes ::
300   ((Either CoreSyn.CoreBndr AST.VHDLName) -> func -> [arg] -> TranslatorSession AST.Expr)
301   -> ((Either CoreSyn.CoreBndr AST.VHDLName) -> func -> [arg] -> TranslatorSession [AST.ConcSm])
302 genExprRes wrap dst func args = do
303   expr <- wrap dst func args
304   return $ [mkUncondAssign dst expr]
305
306 -- | Generate a binary operator application. The first argument should be a
307 -- constructor from the AST.Expr type, e.g. AST.And.
308 genOperator2 :: (AST.Expr -> AST.Expr -> AST.Expr) -> BuiltinBuilder 
309 genOperator2 op = genNoInsts $ genExprArgs $ genExprRes (genOperator2' op)
310 genOperator2' :: (AST.Expr -> AST.Expr -> AST.Expr) -> dst -> CoreSyn.CoreBndr -> [AST.Expr] -> TranslatorSession AST.Expr
311 genOperator2' op _ f [arg1, arg2] = return $ op arg1 arg2
312
313 -- | Generate a unary operator application
314 genOperator1 :: (AST.Expr -> AST.Expr) -> BuiltinBuilder 
315 genOperator1 op = genNoInsts $ genExprArgs $ genExprRes (genOperator1' op)
316 genOperator1' :: (AST.Expr -> AST.Expr) -> dst -> CoreSyn.CoreBndr -> [AST.Expr] -> TranslatorSession AST.Expr
317 genOperator1' op _ f [arg] = return $ op arg
318
319 -- | Generate a unary operator application
320 genNegation :: BuiltinBuilder 
321 genNegation = genNoInsts $ genVarArgs $ genExprRes genNegation'
322 genNegation' :: dst -> CoreSyn.CoreBndr -> [Var.Var] -> TranslatorSession AST.Expr
323 genNegation' _ f [arg] = do
324   arg1 <- MonadState.lift tsType $ varToVHDLExpr arg
325   let ty = Var.varType arg
326   let (tycon, args) = Type.splitTyConApp ty
327   let name = Name.getOccString (TyCon.tyConName tycon)
328   case name of
329     "SizedInt" -> return $ AST.Neg arg1
330     otherwise -> error $ "\nGenerate.genNegation': Negation allowed for type: " ++ show name 
331
332 -- | Generate a function call from the destination binder, function name and a
333 -- list of expressions (its arguments)
334 genFCall :: Bool -> BuiltinBuilder 
335 genFCall switch = genNoInsts $ genExprArgs $ genExprRes (genFCall' switch)
336 genFCall' :: Bool -> Either CoreSyn.CoreBndr AST.VHDLName -> CoreSyn.CoreBndr -> [AST.Expr] -> TranslatorSession AST.Expr
337 genFCall' switch (Left res) f args = do
338   let fname = varToString f
339   let el_ty = if switch then (Var.varType res) else ((tfvec_elem . Var.varType) res)
340   id <- MonadState.lift tsType $ vectorFunId el_ty fname
341   return $ AST.PrimFCall $ AST.FCall (AST.NSimple id)  $
342              map (\exp -> Nothing AST.:=>: AST.ADExpr exp) args
343 genFCall' _ (Right name) _ _ = error $ "\nGenerate.genFCall': Cannot generate builtin function call assigned to a VHDLName: " ++ show name
344
345 genFromSizedWord :: BuiltinBuilder
346 genFromSizedWord = genNoInsts $ genExprArgs $ genExprRes genFromSizedWord'
347 genFromSizedWord' :: Either CoreSyn.CoreBndr AST.VHDLName -> CoreSyn.CoreBndr -> [AST.Expr] -> TranslatorSession AST.Expr
348 genFromSizedWord' (Left res) f args = do
349   let fname = varToString f
350   return $ AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLBasicId toIntegerId))  $
351              map (\exp -> Nothing AST.:=>: AST.ADExpr exp) args
352 genFromSizedWord' (Right name) _ _ = error $ "\nGenerate.genFromSizedWord': Cannot generate builtin function call assigned to a VHDLName: " ++ show name
353
354 genResize :: BuiltinBuilder
355 genResize = genNoInsts $ genExprArgs $ genExprRes genResize'
356 genResize' :: Either CoreSyn.CoreBndr AST.VHDLName -> CoreSyn.CoreBndr -> [AST.Expr] -> TranslatorSession AST.Expr
357 genResize' (Left res) f [arg] = do {
358   ; let { ty = Var.varType res
359         ; (tycon, args) = Type.splitTyConApp ty
360         ; name = Name.getOccString (TyCon.tyConName tycon)
361         } ;
362   ; len <- case name of
363       "SizedInt" -> MonadState.lift tsType $ tfp_to_int (sized_int_len_ty ty)
364       "SizedWord" -> MonadState.lift tsType $ tfp_to_int (sized_word_len_ty ty)
365   ; return $ AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLBasicId resizeId))
366              [Nothing AST.:=>: AST.ADExpr arg, Nothing AST.:=>: AST.ADExpr( AST.PrimLit (show len))]
367   }
368 genResize' (Right name) _ _ = error $ "\nGenerate.genFromSizedWord': Cannot generate builtin function call assigned to a VHDLName: " ++ show name
369
370 -- FIXME: I'm calling genLitArgs which is very specific function,
371 -- which needs to be fixed as well
372 genFromInteger :: BuiltinBuilder
373 genFromInteger = genNoInsts $ genLitArgs $ genExprRes genFromInteger'
374 genFromInteger' :: Either CoreSyn.CoreBndr AST.VHDLName -> CoreSyn.CoreBndr -> [Literal.Literal] -> TranslatorSession AST.Expr
375 genFromInteger' (Left res) f lits = do {
376   ; let { ty = Var.varType res
377         ; (tycon, args) = Type.splitTyConApp ty
378         ; name = Name.getOccString (TyCon.tyConName tycon)
379         } ;
380   ; case name of
381     "RangedWord" -> return $ AST.PrimLit (show (last lits))
382     otherwise -> do {
383       ; len <- case name of
384         "SizedInt" -> MonadState.lift tsType $ tfp_to_int (sized_int_len_ty ty)
385         "SizedWord" -> MonadState.lift tsType $ tfp_to_int (sized_word_len_ty ty)
386         "RangedWord" -> MonadState.lift tsType $ tfp_to_int (ranged_word_bound_ty ty)
387       ; let fname = case name of "SizedInt" -> toSignedId ; "SizedWord" -> toUnsignedId
388       ; return $ AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLBasicId fname))
389                 [Nothing AST.:=>: AST.ADExpr (AST.PrimLit (show (last lits))), Nothing AST.:=>: AST.ADExpr( AST.PrimLit (show len))]
390       }
391   }
392
393 genFromInteger' (Right name) _ _ = error $ "\nGenerate.genFromInteger': Cannot generate builtin function call assigned to a VHDLName: " ++ show name
394
395 genSizedInt :: BuiltinBuilder
396 genSizedInt = genFromInteger
397
398 {-
399 -- | Generate a Builder for the builtin datacon TFVec
400 genTFVec :: BuiltinBuilder
401 genTFVec (Left res) f [Left (CoreSyn.Let (CoreSyn.Rec letBinders) letRes)] = do {
402   -- Generate Assignments for all the binders
403   ; letAssigns <- mapM genBinderAssign letBinders
404   -- Generate assignments for the result (which might be another let binding)
405   ; (resBinders,resAssignments) <- genResAssign letRes
406   -- Get all the Assigned binders
407   ; let assignedBinders = Maybe.catMaybes (map fst letAssigns)
408   -- Make signal names for all the assigned binders
409   ; sigs <- mapM (\x -> MonadState.lift tsType $ varToVHDLExpr x) (assignedBinders ++ resBinders)
410   -- Assign all the signals to the resulting vector
411   ; let { vecsigns = mkAggregateSignal sigs
412         ; vecassign = mkUncondAssign (Left res) vecsigns
413         } ;
414   -- Generate all the signal declaration for the assigned binders
415   ; sig_dec_maybes <- mapM mkSigDec (assignedBinders ++ resBinders)
416   ; let { sig_decs = map (AST.BDISD) (Maybe.catMaybes $ sig_dec_maybes)
417   -- Setup the VHDL Block
418         ; block_label = mkVHDLExtId ("TFVec_" ++ show (varToString res))
419         ; block = AST.BlockSm block_label [] (AST.PMapAspect []) sig_decs ((concat (map snd letAssigns)) ++ resAssignments ++ [vecassign])
420         } ;
421   -- Return the block statement coressponding to the TFVec literal
422   ; return $ [AST.CSBSm block]
423   }
424   where
425     genBinderAssign :: (CoreSyn.CoreBndr, CoreSyn.CoreExpr) -> TranslatorSession (Maybe CoreSyn.CoreBndr, [AST.ConcSm])
426     -- For now we only translate applications
427     genBinderAssign (bndr, app@(CoreSyn.App _ _)) = do
428       let (CoreSyn.Var f, args) = CoreSyn.collectArgs app
429       let valargs = get_val_args (Var.varType f) args
430       apps <- genApplication (Left bndr) f (map Left valargs)
431       return (Just bndr, apps)
432     genBinderAssign _ = return (Nothing,[])
433     genResAssign :: CoreSyn.CoreExpr -> TranslatorSession ([CoreSyn.CoreBndr], [AST.ConcSm])
434     genResAssign app@(CoreSyn.App _ letexpr) = do
435       case letexpr of
436         (CoreSyn.Let (CoreSyn.Rec letbndrs) letres) -> do
437           letapps <- mapM genBinderAssign letbndrs
438           let bndrs = Maybe.catMaybes (map fst letapps)
439           let app = (map snd letapps)
440           (vars, apps) <- genResAssign letres
441           return ((bndrs ++ vars),((concat app) ++ apps))
442         otherwise -> return ([],[])
443     genResAssign _ = return ([],[])
444
445 genTFVec (Left res) f [Left app@(CoreSyn.App _ _)] = do {
446   ; let { elems = reduceCoreListToHsList app
447   -- Make signal names for all the binders
448         ; binders = map (\expr -> case expr of 
449                           (CoreSyn.Var b) -> b
450                           otherwise -> error $ "\nGenerate.genTFVec: Cannot generate TFVec: " 
451                             ++ show res ++ ", with elems:\n" ++ show elems ++ "\n" ++ pprString elems) elems
452         } ;
453   ; sigs <- mapM (\x -> MonadState.lift tsType $ varToVHDLExpr x) binders
454   -- Assign all the signals to the resulting vector
455   ; let { vecsigns = mkAggregateSignal sigs
456         ; vecassign = mkUncondAssign (Left res) vecsigns
457   -- Setup the VHDL Block
458         ; block_label = mkVHDLExtId ("TFVec_" ++ show (varToString res))
459         ; block = AST.BlockSm block_label [] (AST.PMapAspect []) [] [vecassign]
460         } ;
461   -- Return the block statement coressponding to the TFVec literal
462   ; return $ [AST.CSBSm block]
463   }
464   
465 genTFVec (Left name) _ [Left xs] = error $ "\nGenerate.genTFVec: Cannot generate TFVec: " ++ show name ++ ", with elems:\n" ++ show xs ++ "\n" ++ pprString xs
466
467 genTFVec (Right name) _ _ = error $ "\nGenerate.genTFVec: Cannot generate TFVec assigned to VHDLName: " ++ show name
468 -}
469 -- | Generate a generate statement for the builtin function "map"
470 genMap :: BuiltinBuilder
471 genMap (Left res) f [Left mapped_f, Left (CoreSyn.Var arg)] = do {
472   -- mapped_f must be a CoreExpr (since we can't represent functions as VHDL
473   -- expressions). arg must be a CoreExpr (and should be a CoreSyn.Var), since
474   -- we must index it (which we couldn't if it was a VHDL Expr, since only
475   -- VHDLNames can be indexed).
476   -- Setup the generate scheme
477   ; len <- MonadState.lift tsType $ tfp_to_int $ (tfvec_len_ty . Var.varType) res
478           -- TODO: Use something better than varToString
479   ; let { label       = mkVHDLExtId ("mapVector" ++ (varToString res))
480         ; n_id        = mkVHDLBasicId "n"
481         ; n_expr      = idToVHDLExpr n_id
482         ; range       = AST.ToRange (AST.PrimLit "0") (AST.PrimLit $ show (len-1))
483         ; genScheme   = AST.ForGn n_id range
484           -- Create the content of the generate statement: Applying the mapped_f to
485           -- each of the elements in arg, storing to each element in res
486         ; resname     = mkIndexedName (varToVHDLName res) n_expr
487         ; argexpr     = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName arg) n_expr
488         ; (CoreSyn.Var real_f, already_mapped_args) = CoreSyn.collectArgs mapped_f
489         ; valargs = get_val_args (Var.varType real_f) already_mapped_args
490         } ;
491   ; (app_concsms, used) <- genApplication (Right resname) real_f (map Left valargs ++ [Right argexpr])
492     -- Return the generate statement
493   ; return ([AST.CSGSm $ AST.GenerateSm label genScheme [] app_concsms], used)
494   }
495
496 genMap' (Right name) _ _ = error $ "\nGenerate.genMap': Cannot generate map function call assigned to a VHDLName: " ++ show name
497     
498 genZipWith :: BuiltinBuilder
499 genZipWith = genVarArgs genZipWith'
500 genZipWith' :: (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> TranslatorSession ([AST.ConcSm], [CoreSyn.CoreBndr])
501 genZipWith' (Left res) f args@[zipped_f, arg1, arg2] = do {
502   -- Setup the generate scheme
503   ; len <- MonadState.lift tsType $ tfp_to_int $ (tfvec_len_ty . Var.varType) res
504           -- TODO: Use something better than varToString
505   ; let { label       = mkVHDLExtId ("zipWithVector" ++ (varToString res))
506         ; n_id        = mkVHDLBasicId "n"
507         ; n_expr      = idToVHDLExpr n_id
508         ; range       = AST.ToRange (AST.PrimLit "0") (AST.PrimLit $ show (len-1))
509         ; genScheme   = AST.ForGn n_id range
510           -- Create the content of the generate statement: Applying the zipped_f to
511           -- each of the elements in arg1 and arg2, storing to each element in res
512         ; resname     = mkIndexedName (varToVHDLName res) n_expr
513         ; argexpr1    = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName arg1) n_expr
514         ; argexpr2    = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName arg2) n_expr
515         } ;
516   ; (app_concsms, used) <- genApplication (Right resname) zipped_f [Right argexpr1, Right argexpr2]
517     -- Return the generate functions
518   ; return ([AST.CSGSm $ AST.GenerateSm label genScheme [] app_concsms], used)
519   }
520
521 genFoldl :: BuiltinBuilder
522 genFoldl = genFold True
523
524 genFoldr :: BuiltinBuilder
525 genFoldr = genFold False
526
527 genFold :: Bool -> BuiltinBuilder
528 genFold left = genVarArgs (genFold' left)
529
530 genFold' :: Bool -> (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> TranslatorSession ([AST.ConcSm], [CoreSyn.CoreBndr])
531 genFold' left res f args@[folded_f , start ,vec]= do
532   len <- MonadState.lift tsType $ tfp_to_int $ (tfvec_len_ty (Var.varType vec))
533   genFold'' len left res f args
534
535 genFold'' :: Int -> Bool -> (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> TranslatorSession ([AST.ConcSm], [CoreSyn.CoreBndr])
536 -- Special case for an empty input vector, just assign start to res
537 genFold'' len left (Left res) _ [_, start, vec] | len == 0 = do
538   arg <- MonadState.lift tsType $ varToVHDLExpr start
539   return ([mkUncondAssign (Left res) arg], [])
540     
541 genFold'' len left (Left res) f [folded_f, start, vec] = do
542   -- The vector length
543   --len <- MonadState.lift tsType $ tfp_to_int $ (tfvec_len_ty . Var.varType) vec
544   -- An expression for len-1
545   let len_min_expr = (AST.PrimLit $ show (len-1))
546   -- evec is (TFVec n), so it still needs an element type
547   let (nvec, _) = Type.splitAppTy (Var.varType vec)
548   -- Put the type of the start value in nvec, this will be the type of our
549   -- temporary vector
550   let tmp_ty = Type.mkAppTy nvec (Var.varType start)
551   let error_msg = "\nGenerate.genFold': Can not construct temp vector for element type: " ++ pprString tmp_ty 
552   -- TODO: Handle Nothing
553   Just tmp_vhdl_ty <- MonadState.lift tsType $ vhdl_ty error_msg tmp_ty
554   -- Setup the generate scheme
555   let gen_label = mkVHDLExtId ("foldlVector" ++ (varToString vec))
556   let block_label = mkVHDLExtId ("foldlVector" ++ (varToString res))
557   let gen_range = if left then AST.ToRange (AST.PrimLit "0") len_min_expr
558                   else AST.DownRange len_min_expr (AST.PrimLit "0")
559   let gen_scheme   = AST.ForGn n_id gen_range
560   -- Make the intermediate vector
561   let  tmp_dec     = AST.BDISD $ AST.SigDec tmp_id tmp_vhdl_ty Nothing
562   -- Create the generate statement
563   cells' <- sequence [genFirstCell, genOtherCell]
564   let (cells, useds) = unzip cells'
565   let gen_sm = AST.GenerateSm gen_label gen_scheme [] (map AST.CSGSm cells)
566   -- Assign tmp[len-1] or tmp[0] to res
567   let out_assign = mkUncondAssign (Left res) $ vhdlNameToVHDLExpr (if left then
568                     (mkIndexedName tmp_name (AST.PrimLit $ show (len-1))) else
569                     (mkIndexedName tmp_name (AST.PrimLit "0")))      
570   let block = AST.BlockSm block_label [] (AST.PMapAspect []) [tmp_dec] [AST.CSGSm gen_sm, out_assign]
571   return ([AST.CSBSm block], concat useds)
572   where
573     -- An id for the counter
574     n_id = mkVHDLBasicId "n"
575     n_cur = idToVHDLExpr n_id
576     -- An expression for previous n
577     n_prev = if left then (n_cur AST.:-: (AST.PrimLit "1"))
578                      else (n_cur AST.:+: (AST.PrimLit "1"))
579     -- An id for the tmp result vector
580     tmp_id = mkVHDLBasicId "tmp"
581     tmp_name = AST.NSimple tmp_id
582     -- Generate parts of the fold
583     genFirstCell, genOtherCell :: TranslatorSession (AST.GenerateSm, [CoreSyn.CoreBndr])
584     genFirstCell = do
585       len <- MonadState.lift tsType $ tfp_to_int $ (tfvec_len_ty . Var.varType) vec
586       let cond_label = mkVHDLExtId "firstcell"
587       -- if n == 0 or n == len-1
588       let cond_scheme = AST.IfGn $ n_cur AST.:=: (if left then (AST.PrimLit "0")
589                                                   else (AST.PrimLit $ show (len-1)))
590       -- Output to tmp[current n]
591       let resname = mkIndexedName tmp_name n_cur
592       -- Input from start
593       argexpr1 <- MonadState.lift tsType $ varToVHDLExpr start
594       -- Input from vec[current n]
595       let argexpr2 = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName vec) n_cur
596       (app_concsms, used) <- genApplication (Right resname) folded_f  ( if left then
597                                                                   [Right argexpr1, Right argexpr2]
598                                                                 else
599                                                                   [Right argexpr2, Right argexpr1]
600                                                               )
601       -- Return the conditional generate part
602       return $ (AST.GenerateSm cond_label cond_scheme [] app_concsms, used)
603
604     genOtherCell = do
605       len <- MonadState.lift tsType $ tfp_to_int $ (tfvec_len_ty . Var.varType) vec
606       let cond_label = mkVHDLExtId "othercell"
607       -- if n > 0 or n < len-1
608       let cond_scheme = AST.IfGn $ n_cur AST.:/=: (if left then (AST.PrimLit "0")
609                                                    else (AST.PrimLit $ show (len-1)))
610       -- Output to tmp[current n]
611       let resname = mkIndexedName tmp_name n_cur
612       -- Input from tmp[previous n]
613       let argexpr1 = vhdlNameToVHDLExpr $ mkIndexedName tmp_name n_prev
614       -- Input from vec[current n]
615       let argexpr2 = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName vec) n_cur
616       (app_concsms, used) <- genApplication (Right resname) folded_f  ( if left then
617                                                                   [Right argexpr1, Right argexpr2]
618                                                                 else
619                                                                   [Right argexpr2, Right argexpr1]
620                                                               )
621       -- Return the conditional generate part
622       return $ (AST.GenerateSm cond_label cond_scheme [] app_concsms, used)
623
624 -- | Generate a generate statement for the builtin function "zip"
625 genZip :: BuiltinBuilder
626 genZip = genNoInsts $ genVarArgs genZip'
627 genZip' :: (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> TranslatorSession [AST.ConcSm]
628 genZip' (Left res) f args@[arg1, arg2] = do {
629     -- Setup the generate scheme
630   ; len <- MonadState.lift tsType $ tfp_to_int $ (tfvec_len_ty . Var.varType) res
631           -- TODO: Use something better than varToString
632   ; let { label           = mkVHDLExtId ("zipVector" ++ (varToString res))
633         ; n_id            = mkVHDLBasicId "n"
634         ; n_expr          = idToVHDLExpr n_id
635         ; range           = AST.ToRange (AST.PrimLit "0") (AST.PrimLit $ show (len-1))
636         ; genScheme       = AST.ForGn n_id range
637         ; resname'        = mkIndexedName (varToVHDLName res) n_expr
638         ; argexpr1        = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName arg1) n_expr
639         ; argexpr2        = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName arg2) n_expr
640         } ; 
641   ; labels <- MonadState.lift tsType $ getFieldLabels (tfvec_elem (Var.varType res))
642   ; let { resnameA    = mkSelectedName resname' (labels!!0)
643         ; resnameB    = mkSelectedName resname' (labels!!1)
644         ; resA_assign = mkUncondAssign (Right resnameA) argexpr1
645         ; resB_assign = mkUncondAssign (Right resnameB) argexpr2
646         } ;
647     -- Return the generate functions
648   ; return [AST.CSGSm $ AST.GenerateSm label genScheme [] [resA_assign,resB_assign]]
649   }
650   
651 -- | Generate a generate statement for the builtin function "fst"
652 genFst :: BuiltinBuilder
653 genFst = genNoInsts $ genVarArgs genFst'
654 genFst' :: (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> TranslatorSession [AST.ConcSm]
655 genFst' (Left res) f args@[arg] = do {
656   ; labels <- MonadState.lift tsType $ getFieldLabels (Var.varType arg)
657   ; let { argexpr'    = varToVHDLName arg
658         ; argexprA    = vhdlNameToVHDLExpr $ mkSelectedName argexpr' (labels!!0)
659         ; assign      = mkUncondAssign (Left res) argexprA
660         } ;
661     -- Return the generate functions
662   ; return [assign]
663   }
664   
665 -- | Generate a generate statement for the builtin function "snd"
666 genSnd :: BuiltinBuilder
667 genSnd = genNoInsts $ genVarArgs genSnd'
668 genSnd' :: (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> TranslatorSession [AST.ConcSm]
669 genSnd' (Left res) f args@[arg] = do {
670   ; labels <- MonadState.lift tsType $ getFieldLabels (Var.varType arg)
671   ; let { argexpr'    = varToVHDLName arg
672         ; argexprB    = vhdlNameToVHDLExpr $ mkSelectedName argexpr' (labels!!1)
673         ; assign      = mkUncondAssign (Left res) argexprB
674         } ;
675     -- Return the generate functions
676   ; return [assign]
677   }
678     
679 -- | Generate a generate statement for the builtin function "unzip"
680 genUnzip :: BuiltinBuilder
681 genUnzip = genNoInsts $ genVarArgs genUnzip'
682 genUnzip' :: (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> TranslatorSession [AST.ConcSm]
683 genUnzip' (Left res) f args@[arg] = do {
684     -- Setup the generate scheme
685   ; len <- MonadState.lift tsType $ tfp_to_int $ (tfvec_len_ty . Var.varType) arg
686     -- TODO: Use something better than varToString
687   ; let { label           = mkVHDLExtId ("unzipVector" ++ (varToString res))
688         ; n_id            = mkVHDLBasicId "n"
689         ; n_expr          = idToVHDLExpr n_id
690         ; range           = AST.ToRange (AST.PrimLit "0") (AST.PrimLit $ show (len-1))
691         ; genScheme       = AST.ForGn n_id range
692         ; resname'        = varToVHDLName res
693         ; argexpr'        = mkIndexedName (varToVHDLName arg) n_expr
694         } ;
695   ; reslabels <- MonadState.lift tsType $ getFieldLabels (Var.varType res)
696   ; arglabels <- MonadState.lift tsType $ getFieldLabels (tfvec_elem (Var.varType arg))
697   ; let { resnameA    = mkIndexedName (mkSelectedName resname' (reslabels!!0)) n_expr
698         ; resnameB    = mkIndexedName (mkSelectedName resname' (reslabels!!1)) n_expr
699         ; argexprA    = vhdlNameToVHDLExpr $ mkSelectedName argexpr' (arglabels!!0)
700         ; argexprB    = vhdlNameToVHDLExpr $ mkSelectedName argexpr' (arglabels!!1)
701         ; resA_assign = mkUncondAssign (Right resnameA) argexprA
702         ; resB_assign = mkUncondAssign (Right resnameB) argexprB
703         } ;
704     -- Return the generate functions
705   ; return [AST.CSGSm $ AST.GenerateSm label genScheme [] [resA_assign,resB_assign]]
706   }
707
708 genCopy :: BuiltinBuilder 
709 genCopy = genNoInsts $ genVarArgs genCopy'
710 genCopy' :: (Either CoreSyn.CoreBndr AST.VHDLName ) -> CoreSyn.CoreBndr -> [Var.Var] -> TranslatorSession [AST.ConcSm]
711 genCopy' (Left res) f args@[arg] =
712   let
713     resExpr = AST.Aggregate [AST.ElemAssoc (Just AST.Others) 
714                 (AST.PrimName $ (varToVHDLName arg))]
715     out_assign = mkUncondAssign (Left res) resExpr
716   in 
717     return [out_assign]
718     
719 genConcat :: BuiltinBuilder
720 genConcat = genNoInsts $ genVarArgs genConcat'
721 genConcat' :: (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> TranslatorSession [AST.ConcSm]
722 genConcat' (Left res) f args@[arg] = do {
723     -- Setup the generate scheme
724   ; len1 <- MonadState.lift tsType $ tfp_to_int $ (tfvec_len_ty . Var.varType) arg
725   ; let (_, nvec) = Type.splitAppTy (Var.varType arg)
726   ; len2 <- MonadState.lift tsType $ tfp_to_int $ tfvec_len_ty nvec
727           -- TODO: Use something better than varToString
728   ; let { label       = mkVHDLExtId ("concatVector" ++ (varToString res))
729         ; n_id        = mkVHDLBasicId "n"
730         ; n_expr      = idToVHDLExpr n_id
731         ; fromRange   = n_expr AST.:*: (AST.PrimLit $ show len2)
732         ; genScheme   = AST.ForGn n_id range
733           -- Create the content of the generate statement: Applying the mapped_f to
734           -- each of the elements in arg, storing to each element in res
735         ; toRange     = (n_expr AST.:*: (AST.PrimLit $ show len2)) AST.:+: (AST.PrimLit $ show (len2-1))
736         ; range       = AST.ToRange (AST.PrimLit "0") (AST.PrimLit $ show (len1-1))
737         ; resname     = vecSlice fromRange toRange
738         ; argexpr     = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName arg) n_expr
739         ; out_assign  = mkUncondAssign (Right resname) argexpr
740         } ;
741     -- Return the generate statement
742   ; return [AST.CSGSm $ AST.GenerateSm label genScheme [] [out_assign]]
743   }
744   where
745     vecSlice init last =  AST.NSlice (AST.SliceName (varToVHDLName res) 
746                             (AST.ToRange init last))
747
748 genIteraten :: BuiltinBuilder
749 genIteraten dst f args = genIterate dst f (tail args)
750
751 genIterate :: BuiltinBuilder
752 genIterate = genIterateOrGenerate True
753
754 genGeneraten :: BuiltinBuilder
755 genGeneraten dst f args = genGenerate dst f (tail args)
756
757 genGenerate :: BuiltinBuilder
758 genGenerate = genIterateOrGenerate False
759
760 genIterateOrGenerate :: Bool -> BuiltinBuilder
761 genIterateOrGenerate iter = genVarArgs (genIterateOrGenerate' iter)
762
763 genIterateOrGenerate' :: Bool -> (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> TranslatorSession ([AST.ConcSm], [CoreSyn.CoreBndr])
764 genIterateOrGenerate' iter (Left res) f args = do
765   len <- MonadState.lift tsType $ tfp_to_int ((tfvec_len_ty . Var.varType) res)
766   genIterateOrGenerate'' len iter (Left res) f args
767
768 genIterateOrGenerate'' :: Int -> Bool -> (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> TranslatorSession ([AST.ConcSm], [CoreSyn.CoreBndr])
769 -- Special case for an empty input vector, just assign start to res
770 genIterateOrGenerate'' len iter (Left res) _ [app_f, start] | len == 0 = return ([mkUncondAssign (Left res) (AST.PrimLit "\"\"")], [])
771
772 genIterateOrGenerate'' len iter (Left res) f [app_f, start] = do
773   -- The vector length
774   -- len <- MonadState.lift tsType $ tfp_to_int ((tfvec_len_ty . Var.varType) res)
775   -- An expression for len-1
776   let len_min_expr = (AST.PrimLit $ show (len-1))
777   -- -- evec is (TFVec n), so it still needs an element type
778   -- let (nvec, _) = splitAppTy (Var.varType vec)
779   -- -- Put the type of the start value in nvec, this will be the type of our
780   -- -- temporary vector
781   let tmp_ty = Var.varType res
782   let error_msg = "\nGenerate.genFold': Can not construct temp vector for element type: " ++ pprString tmp_ty 
783   -- TODO: Handle Nothing
784   Just tmp_vhdl_ty <- MonadState.lift tsType $ vhdl_ty error_msg tmp_ty
785   -- Setup the generate scheme
786   let gen_label = mkVHDLExtId ("iterateVector" ++ (varToString start))
787   let block_label = mkVHDLExtId ("iterateVector" ++ (varToString res))
788   let gen_range = AST.ToRange (AST.PrimLit "0") len_min_expr
789   let gen_scheme   = AST.ForGn n_id gen_range
790   -- Make the intermediate vector
791   let  tmp_dec     = AST.BDISD $ AST.SigDec tmp_id tmp_vhdl_ty Nothing
792   -- Create the generate statement
793   cells' <- sequence [genFirstCell, genOtherCell]
794   let (cells, useds) = unzip cells'
795   let gen_sm = AST.GenerateSm gen_label gen_scheme [] (map AST.CSGSm cells)
796   -- Assign tmp[len-1] or tmp[0] to res
797   let out_assign = mkUncondAssign (Left res) $ vhdlNameToVHDLExpr tmp_name    
798   let block = AST.BlockSm block_label [] (AST.PMapAspect []) [tmp_dec] [AST.CSGSm gen_sm, out_assign]
799   return ([AST.CSBSm block], concat useds)
800   where
801     -- An id for the counter
802     n_id = mkVHDLBasicId "n"
803     n_cur = idToVHDLExpr n_id
804     -- An expression for previous n
805     n_prev = n_cur AST.:-: (AST.PrimLit "1")
806     -- An id for the tmp result vector
807     tmp_id = mkVHDLBasicId "tmp"
808     tmp_name = AST.NSimple tmp_id
809     -- Generate parts of the fold
810     genFirstCell, genOtherCell :: TranslatorSession (AST.GenerateSm, [CoreSyn.CoreBndr])
811     genFirstCell = do
812       let cond_label = mkVHDLExtId "firstcell"
813       -- if n == 0 or n == len-1
814       let cond_scheme = AST.IfGn $ n_cur AST.:=: (AST.PrimLit "0")
815       -- Output to tmp[current n]
816       let resname = mkIndexedName tmp_name n_cur
817       -- Input from start
818       argexpr <- MonadState.lift tsType $ varToVHDLExpr start
819       let startassign = mkUncondAssign (Right resname) argexpr
820       (app_concsms, used) <- genApplication (Right resname) app_f  [Right argexpr]
821       -- Return the conditional generate part
822       let gensm = AST.GenerateSm cond_label cond_scheme [] (if iter then 
823                                                           [startassign]
824                                                          else 
825                                                           app_concsms
826                                                         )
827       return (gensm, used)
828
829     genOtherCell = do
830       let cond_label = mkVHDLExtId "othercell"
831       -- if n > 0 or n < len-1
832       let cond_scheme = AST.IfGn $ n_cur AST.:/=: (AST.PrimLit "0")
833       -- Output to tmp[current n]
834       let resname = mkIndexedName tmp_name n_cur
835       -- Input from tmp[previous n]
836       let argexpr = vhdlNameToVHDLExpr $ mkIndexedName tmp_name n_prev
837       (app_concsms, used) <- genApplication (Right resname) app_f [Right argexpr]
838       -- Return the conditional generate part
839       return $ (AST.GenerateSm cond_label cond_scheme [] app_concsms, used)
840
841
842 -----------------------------------------------------------------------------
843 -- Function to generate VHDL for applications
844 -----------------------------------------------------------------------------
845 genApplication ::
846   (Either CoreSyn.CoreBndr AST.VHDLName) -- ^ Where to store the result?
847   -> CoreSyn.CoreBndr -- ^ The function to apply
848   -> [Either CoreSyn.CoreExpr AST.Expr] -- ^ The arguments to apply
849   -> TranslatorSession ([AST.ConcSm], [CoreSyn.CoreBndr]) 
850   -- ^ The corresponding VHDL concurrent statements and entities
851   --   instantiated.
852 genApplication dst f args = do
853   case Var.isGlobalId f of
854     False -> do 
855       top <- isTopLevelBinder f
856       case top of
857         True -> do
858           -- Local binder that references a top level binding.  Generate a
859           -- component instantiation.
860           signature <- getEntity f
861           args' <- argsToVHDLExprs args
862           let entity_id = ent_id signature
863           -- TODO: Using show here isn't really pretty, but we'll need some
864           -- unique-ish value...
865           let label = "comp_ins_" ++ (either show prettyShow) dst
866           let portmaps = mkAssocElems args' ((either varToVHDLName id) dst) signature
867           return ([mkComponentInst label entity_id portmaps], [f])
868         False -> do
869           -- Not a top level binder, so this must be a local variable reference.
870           -- It should have a representable type (and thus, no arguments) and a
871           -- signal should be generated for it. Just generate an unconditional
872           -- assignment here.
873           f' <- MonadState.lift tsType $ varToVHDLExpr f
874           return $ ([mkUncondAssign dst f'], [])
875     True ->
876       case Var.idDetails f of
877         IdInfo.DataConWorkId dc -> case dst of
878           -- It's a datacon. Create a record from its arguments.
879           Left bndr -> do
880             -- We have the bndr, so we can get at the type
881             labels <- MonadState.lift tsType $ getFieldLabels (Var.varType bndr)
882             args' <- argsToVHDLExprs args
883             return $ (zipWith mkassign labels $ args', [])
884             where
885               mkassign :: AST.VHDLId -> AST.Expr -> AST.ConcSm
886               mkassign label arg =
887                 let sel_name = mkSelectedName ((either varToVHDLName id) dst) label in
888                 mkUncondAssign (Right sel_name) arg
889           Right _ -> error $ "\nGenerate.genApplication: Can't generate dataconstructor application without an original binder"
890         IdInfo.DataConWrapId dc -> case dst of
891           -- It's a datacon. Create a record from its arguments.
892           Left bndr -> do 
893             case (Map.lookup (varToString f) globalNameTable) of
894              Just (arg_count, builder) ->
895               if length args == arg_count then
896                 builder dst f args
897               else
898                 error $ "\nGenerate.genApplication(DataConWrapId): Incorrect number of arguments to builtin function: " ++ pprString f ++ " Args: " ++ show args
899              Nothing -> error $ "\nGenerate.genApplication: Can't generate dataconwrapper: " ++ (show dc)
900           Right _ -> error $ "\nGenerate.genApplication: Can't generate dataconwrapper application without an original binder"
901         IdInfo.VanillaId -> do
902           -- It's a global value imported from elsewhere. These can be builtin
903           -- functions. Look up the function name in the name table and execute
904           -- the associated builder if there is any and the argument count matches
905           -- (this should always be the case if it typechecks, but just to be
906           -- sure...).
907           case (Map.lookup (varToString f) globalNameTable) of
908             Just (arg_count, builder) ->
909               if length args == arg_count then
910                 builder dst f args
911               else
912                 error $ "\nGenerate.genApplication(VanillaId): Incorrect number of arguments to builtin function: " ++ pprString f ++ " Args: " ++ show args
913             Nothing -> do
914               top <- isTopLevelBinder f
915               case top of
916                 True -> do
917                   -- Local binder that references a top level binding.  Generate a
918                   -- component instantiation.
919                   signature <- getEntity f
920                   args' <- argsToVHDLExprs args
921                   let entity_id = ent_id signature
922                   -- TODO: Using show here isn't really pretty, but we'll need some
923                   -- unique-ish value...
924                   let label = "comp_ins_" ++ (either show prettyShow) dst
925                   let portmaps = mkAssocElems args' ((either varToVHDLName id) dst) signature
926                   return ([mkComponentInst label entity_id portmaps], [f])
927                 False -> do
928                   -- Not a top level binder, so this must be a local variable reference.
929                   -- It should have a representable type (and thus, no arguments) and a
930                   -- signal should be generated for it. Just generate an unconditional
931                   -- assignment here.
932                   -- FIXME : I DONT KNOW IF THE ABOVE COMMENT HOLDS HERE, SO FOR NOW JUST ERROR!
933                   -- f' <- MonadState.lift tsType $ varToVHDLExpr f
934                   --                   return $ ([mkUncondAssign dst f'], [])
935                   error $ ("\nGenerate.genApplication(VanillaId): Using function from another module that is not a known builtin: " ++ (pprString f))
936         IdInfo.ClassOpId cls -> do
937           -- FIXME: Not looking for what instance this class op is called for
938           -- Is quite stupid of course.
939           case (Map.lookup (varToString f) globalNameTable) of
940             Just (arg_count, builder) ->
941               if length args == arg_count then
942                 builder dst f args
943               else
944                 error $ "\nGenerate.genApplication(ClassOpId): Incorrect number of arguments to builtin function: " ++ pprString f ++ " Args: " ++ show args
945             Nothing -> error $ "\nGenerate.genApplication(ClassOpId): Using function from another module that is not a known builtin: " ++ pprString f
946         details -> error $ "\nGenerate.genApplication: Calling unsupported function " ++ pprString f ++ " with GlobalIdDetails " ++ pprString details
947
948 -----------------------------------------------------------------------------
949 -- Functions to generate functions dealing with vectors.
950 -----------------------------------------------------------------------------
951
952 -- Returns the VHDLId of the vector function with the given name for the given
953 -- element type. Generates -- this function if needed.
954 vectorFunId :: Type.Type -> String -> TypeSession AST.VHDLId
955 vectorFunId el_ty fname = do
956   let error_msg = "\nGenerate.vectorFunId: Can not construct vector function for element: " ++ pprString el_ty
957   -- TODO: Handle the Nothing case?
958   Just elemTM <- vhdl_ty error_msg el_ty
959   -- TODO: This should not be duplicated from mk_vector_ty. Probably but it in
960   -- the VHDLState or something.
961   let vectorTM = mkVHDLExtId $ "vector_" ++ (AST.fromVHDLId elemTM)
962   typefuns <- getA tsTypeFuns
963   case Map.lookup (OrdType el_ty, fname) typefuns of
964     -- Function already generated, just return it
965     Just (id, _) -> return id
966     -- Function not generated yet, generate it
967     Nothing -> do
968       let functions = genUnconsVectorFuns elemTM vectorTM
969       case lookup fname functions of
970         Just body -> do
971           modA tsTypeFuns $ Map.insert (OrdType el_ty, fname) (function_id, (fst body))
972           mapM_ (vectorFunId el_ty) (snd body)
973           return function_id
974         Nothing -> error $ "\nGenerate.vectorFunId: I don't know how to generate vector function " ++ fname
975   where
976     function_id = mkVHDLExtId fname
977
978 genUnconsVectorFuns :: AST.TypeMark -- ^ type of the vector elements
979                     -> AST.TypeMark -- ^ type of the vector
980                     -> [(String, (AST.SubProgBody, [String]))]
981 genUnconsVectorFuns elemTM vectorTM  = 
982   [ (exId, (AST.SubProgBody exSpec      []                  [exExpr],[]))
983   , (replaceId, (AST.SubProgBody replaceSpec [AST.SPVD replaceVar] [replaceExpr,replaceRet],[]))
984   , (lastId, (AST.SubProgBody lastSpec    []                  [lastExpr],[]))
985   , (initId, (AST.SubProgBody initSpec    [AST.SPVD initVar]  [initExpr, initRet],[]))
986   , (minimumId, (AST.SubProgBody minimumSpec [] [minimumExpr],[]))
987   , (takeId, (AST.SubProgBody takeSpec    [AST.SPVD takeVar]  [takeExpr, takeRet],[minimumId]))
988   , (dropId, (AST.SubProgBody dropSpec    [AST.SPVD dropVar]  [dropExpr, dropRet],[]))
989   , (plusgtId, (AST.SubProgBody plusgtSpec  [AST.SPVD plusgtVar] [plusgtExpr, plusgtRet],[]))
990   , (emptyId, (AST.SubProgBody emptySpec   [AST.SPVD emptyVar] [emptyExpr],[]))
991   , (singletonId, (AST.SubProgBody singletonSpec [AST.SPVD singletonVar] [singletonRet],[]))
992   , (copynId, (AST.SubProgBody copynSpec    [AST.SPVD copynVar]      [copynExpr],[]))
993   , (selId, (AST.SubProgBody selSpec  [AST.SPVD selVar] [selFor, selRet],[]))
994   , (ltplusId, (AST.SubProgBody ltplusSpec [AST.SPVD ltplusVar] [ltplusExpr, ltplusRet],[]))  
995   , (plusplusId, (AST.SubProgBody plusplusSpec [AST.SPVD plusplusVar] [plusplusExpr, plusplusRet],[]))
996   , (lengthTId, (AST.SubProgBody lengthTSpec [] [lengthTExpr],[]))
997   , (shiftlId, (AST.SubProgBody shiftlSpec [AST.SPVD shiftlVar] [shiftlExpr, shiftlRet], [initId]))
998   , (shiftrId, (AST.SubProgBody shiftrSpec [AST.SPVD shiftrVar] [shiftrExpr, shiftrRet], [tailId]))
999   , (nullId, (AST.SubProgBody nullSpec [] [nullExpr], []))
1000   , (rotlId, (AST.SubProgBody rotlSpec [AST.SPVD rotlVar] [rotlExpr, rotlRet], [nullId, lastId, initId]))
1001   , (rotrId, (AST.SubProgBody rotrSpec [AST.SPVD rotrVar] [rotrExpr, rotrRet], [nullId, tailId, headId]))
1002   , (reverseId, (AST.SubProgBody reverseSpec [AST.SPVD reverseVar] [reverseFor, reverseRet], []))
1003   ]
1004   where 
1005     ixPar   = AST.unsafeVHDLBasicId "ix"
1006     vecPar  = AST.unsafeVHDLBasicId "vec"
1007     vec1Par = AST.unsafeVHDLBasicId "vec1"
1008     vec2Par = AST.unsafeVHDLBasicId "vec2"
1009     nPar    = AST.unsafeVHDLBasicId "n"
1010     leftPar = AST.unsafeVHDLBasicId "nLeft"
1011     rightPar = AST.unsafeVHDLBasicId "nRight"
1012     iId     = AST.unsafeVHDLBasicId "i"
1013     iPar    = iId
1014     aPar    = AST.unsafeVHDLBasicId "a"
1015     fPar = AST.unsafeVHDLBasicId "f"
1016     sPar = AST.unsafeVHDLBasicId "s"
1017     resId   = AST.unsafeVHDLBasicId "res"    
1018     exSpec = AST.Function (mkVHDLExtId exId) [AST.IfaceVarDec vecPar vectorTM,
1019                                AST.IfaceVarDec ixPar  naturalTM] elemTM
1020     exExpr = AST.ReturnSm (Just $ AST.PrimName $ AST.NIndexed 
1021               (AST.IndexedName (AST.NSimple vecPar) [AST.PrimName $ 
1022                 AST.NSimple ixPar]))
1023     replaceSpec = AST.Function (mkVHDLExtId replaceId)  [ AST.IfaceVarDec vecPar vectorTM
1024                                           , AST.IfaceVarDec iPar   naturalTM
1025                                           , AST.IfaceVarDec aPar   elemTM
1026                                           ] vectorTM 
1027        -- variable res : fsvec_x (0 to vec'length-1);
1028     replaceVar =
1029          AST.VarDec resId 
1030                 (AST.SubtypeIn vectorTM
1031                   (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
1032                    [AST.ToRange (AST.PrimLit "0")
1033                             (AST.PrimName (AST.NAttribute $ 
1034                               AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:-:
1035                                 (AST.PrimLit "1"))   ]))
1036                 Nothing
1037        --  res AST.:= vec(0 to i-1) & a & vec(i+1 to length'vec-1)
1038     replaceExpr = AST.NSimple resId AST.:=
1039            (vecSlice (AST.PrimLit "0") (AST.PrimName (AST.NSimple iPar) AST.:-: AST.PrimLit "1") AST.:&:
1040             AST.PrimName (AST.NSimple aPar) AST.:&: 
1041              vecSlice (AST.PrimName (AST.NSimple iPar) AST.:+: AST.PrimLit "1")
1042                       ((AST.PrimName (AST.NAttribute $ 
1043                                 AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing)) 
1044                                                               AST.:-: AST.PrimLit "1"))
1045     replaceRet =  AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
1046     vecSlice init last =  AST.PrimName (AST.NSlice 
1047                                         (AST.SliceName 
1048                                               (AST.NSimple vecPar) 
1049                                               (AST.ToRange init last)))
1050     lastSpec = AST.Function (mkVHDLExtId lastId) [AST.IfaceVarDec vecPar vectorTM] elemTM
1051        -- return vec(vec'length-1);
1052     lastExpr = AST.ReturnSm (Just $ (AST.PrimName $ AST.NIndexed (AST.IndexedName 
1053                     (AST.NSimple vecPar) 
1054                     [AST.PrimName (AST.NAttribute $ 
1055                                 AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) 
1056                                                              AST.:-: AST.PrimLit "1"])))
1057     initSpec = AST.Function (mkVHDLExtId initId) [AST.IfaceVarDec vecPar vectorTM] vectorTM 
1058        -- variable res : fsvec_x (0 to vec'length-2);
1059     initVar = 
1060          AST.VarDec resId 
1061                 (AST.SubtypeIn vectorTM
1062                   (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
1063                    [AST.ToRange (AST.PrimLit "0")
1064                             (AST.PrimName (AST.NAttribute $ 
1065                               AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:-:
1066                                 (AST.PrimLit "2"))   ]))
1067                 Nothing
1068        -- resAST.:= vec(0 to vec'length-2)
1069     initExpr = AST.NSimple resId AST.:= (vecSlice 
1070                                (AST.PrimLit "0") 
1071                                (AST.PrimName (AST.NAttribute $ 
1072                                   AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) 
1073                                                              AST.:-: AST.PrimLit "2"))
1074     initRet =  AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
1075     minimumSpec = AST.Function (mkVHDLExtId minimumId) [AST.IfaceVarDec leftPar   naturalTM,
1076                                    AST.IfaceVarDec rightPar naturalTM ] naturalTM
1077     minimumExpr = AST.IfSm ((AST.PrimName $ AST.NSimple leftPar) AST.:<: (AST.PrimName $ AST.NSimple rightPar))
1078                         [AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple leftPar)]
1079                         []
1080                         (Just $ AST.Else [minimumExprRet])
1081       where minimumExprRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple rightPar)
1082     takeSpec = AST.Function (mkVHDLExtId takeId) [AST.IfaceVarDec nPar   naturalTM,
1083                                    AST.IfaceVarDec vecPar vectorTM ] vectorTM
1084        -- variable res : fsvec_x (0 to (minimum (n,vec'length))-1);
1085     minLength = AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLExtId minimumId))  
1086                               [Nothing AST.:=>: AST.ADExpr (AST.PrimName $ AST.NSimple nPar)
1087                               ,Nothing AST.:=>: AST.ADExpr (AST.PrimName (AST.NAttribute $ 
1088                                 AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing))]
1089     takeVar = 
1090          AST.VarDec resId 
1091                 (AST.SubtypeIn vectorTM
1092                   (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
1093                    [AST.ToRange (AST.PrimLit "0")
1094                                (minLength AST.:-:
1095                                 (AST.PrimLit "1"))   ]))
1096                 Nothing
1097        -- res AST.:= vec(0 to n-1)
1098     takeExpr = AST.NSimple resId AST.:= 
1099                     (vecSlice (AST.PrimLit "0") 
1100                               (minLength AST.:-: AST.PrimLit "1"))
1101     takeRet =  AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
1102     dropSpec = AST.Function (mkVHDLExtId dropId) [AST.IfaceVarDec nPar   naturalTM,
1103                                    AST.IfaceVarDec vecPar vectorTM ] vectorTM 
1104        -- variable res : fsvec_x (0 to vec'length-n-1);
1105     dropVar = 
1106          AST.VarDec resId 
1107                 (AST.SubtypeIn vectorTM
1108                   (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
1109                    [AST.ToRange (AST.PrimLit "0")
1110                             (AST.PrimName (AST.NAttribute $ 
1111                               AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:-:
1112                                (AST.PrimName $ AST.NSimple nPar)AST.:-: (AST.PrimLit "1")) ]))
1113                Nothing
1114        -- res AST.:= vec(n to vec'length-1)
1115     dropExpr = AST.NSimple resId AST.:= (vecSlice 
1116                                (AST.PrimName $ AST.NSimple nPar) 
1117                                (AST.PrimName (AST.NAttribute $ 
1118                                   AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) 
1119                                                              AST.:-: AST.PrimLit "1"))
1120     dropRet =  AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
1121     plusgtSpec = AST.Function (mkVHDLExtId plusgtId) [AST.IfaceVarDec aPar   elemTM,
1122                                        AST.IfaceVarDec vecPar vectorTM] vectorTM 
1123     -- variable res : fsvec_x (0 to vec'length);
1124     plusgtVar = 
1125       AST.VarDec resId 
1126              (AST.SubtypeIn vectorTM
1127                (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
1128                 [AST.ToRange (AST.PrimLit "0")
1129                         (AST.PrimName (AST.NAttribute $ 
1130                           AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing))]))
1131              Nothing
1132     plusgtExpr = AST.NSimple resId AST.:= 
1133                    ((AST.PrimName $ AST.NSimple aPar) AST.:&: 
1134                     (AST.PrimName $ AST.NSimple vecPar))
1135     plusgtRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
1136     emptySpec = AST.Function (mkVHDLExtId emptyId) [] vectorTM
1137     emptyVar = 
1138           AST.VarDec resId
1139             (AST.SubtypeIn vectorTM
1140               (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
1141                 [AST.ToRange (AST.PrimLit "0") (AST.PrimLit "-1")]))
1142              Nothing
1143     emptyExpr = AST.ReturnSm (Just $ AST.PrimName (AST.NSimple resId))
1144     singletonSpec = AST.Function (mkVHDLExtId singletonId) [AST.IfaceVarDec aPar elemTM ] 
1145                                          vectorTM
1146     -- variable res : fsvec_x (0 to 0) := (others => a);
1147     singletonVar = 
1148       AST.VarDec resId 
1149              (AST.SubtypeIn vectorTM
1150                (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
1151                 [AST.ToRange (AST.PrimLit "0") (AST.PrimLit "0")]))
1152              (Just $ AST.Aggregate [AST.ElemAssoc (Just AST.Others) 
1153                                           (AST.PrimName $ AST.NSimple aPar)])
1154     singletonRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
1155     copynSpec = AST.Function (mkVHDLExtId copynId) [AST.IfaceVarDec nPar   naturalTM,
1156                                    AST.IfaceVarDec aPar   elemTM   ] vectorTM 
1157     -- variable res : fsvec_x (0 to n-1) := (others => a);
1158     copynVar = 
1159       AST.VarDec resId 
1160              (AST.SubtypeIn vectorTM
1161                (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
1162                 [AST.ToRange (AST.PrimLit "0")
1163                             ((AST.PrimName (AST.NSimple nPar)) AST.:-:
1164                              (AST.PrimLit "1"))   ]))
1165              (Just $ AST.Aggregate [AST.ElemAssoc (Just AST.Others) 
1166                                           (AST.PrimName $ AST.NSimple aPar)])
1167     -- return res
1168     copynExpr = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
1169     selSpec = AST.Function (mkVHDLExtId selId) [AST.IfaceVarDec fPar   naturalTM,
1170                                AST.IfaceVarDec sPar   naturalTM,
1171                                AST.IfaceVarDec nPar   naturalTM,
1172                                AST.IfaceVarDec vecPar vectorTM ] vectorTM
1173     -- variable res : fsvec_x (0 to n-1);
1174     selVar = 
1175       AST.VarDec resId 
1176                 (AST.SubtypeIn vectorTM
1177                   (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
1178                     [AST.ToRange (AST.PrimLit "0")
1179                       ((AST.PrimName (AST.NSimple nPar)) AST.:-:
1180                       (AST.PrimLit "1"))   ])
1181                 )
1182                 Nothing
1183     -- for i res'range loop
1184     --   res(i) := vec(f+i*s);
1185     -- end loop;
1186     selFor = AST.ForSM iId (AST.AttribRange $ AST.AttribName (AST.NSimple resId) (AST.NSimple $ rangeId) Nothing) [selAssign]
1187     -- res(i) := vec(f+i*s);
1188     selAssign = let origExp = AST.PrimName (AST.NSimple fPar) AST.:+: 
1189                                 (AST.PrimName (AST.NSimple iId) AST.:*: 
1190                                   AST.PrimName (AST.NSimple sPar)) in
1191                                   AST.NIndexed (AST.IndexedName (AST.NSimple resId) [AST.PrimName (AST.NSimple iId)]) AST.:=
1192                                     (AST.PrimName $ AST.NIndexed (AST.IndexedName (AST.NSimple vecPar) [origExp]))
1193     -- return res;
1194     selRet =  AST.ReturnSm (Just $ AST.PrimName (AST.NSimple resId))
1195     ltplusSpec = AST.Function (mkVHDLExtId ltplusId) [AST.IfaceVarDec vecPar vectorTM,
1196                                         AST.IfaceVarDec aPar   elemTM] vectorTM 
1197      -- variable res : fsvec_x (0 to vec'length);
1198     ltplusVar = 
1199       AST.VarDec resId 
1200         (AST.SubtypeIn vectorTM
1201           (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
1202             [AST.ToRange (AST.PrimLit "0")
1203               (AST.PrimName (AST.NAttribute $ 
1204                 AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing))]))
1205         Nothing
1206     ltplusExpr = AST.NSimple resId AST.:= 
1207                      ((AST.PrimName $ AST.NSimple vecPar) AST.:&: 
1208                       (AST.PrimName $ AST.NSimple aPar))
1209     ltplusRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
1210     plusplusSpec = AST.Function (mkVHDLExtId plusplusId) [AST.IfaceVarDec vec1Par vectorTM,
1211                                              AST.IfaceVarDec vec2Par vectorTM] 
1212                                              vectorTM 
1213     -- variable res : fsvec_x (0 to vec1'length + vec2'length -1);
1214     plusplusVar = 
1215       AST.VarDec resId 
1216         (AST.SubtypeIn vectorTM
1217           (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
1218             [AST.ToRange (AST.PrimLit "0")
1219               (AST.PrimName (AST.NAttribute $ 
1220                 AST.AttribName (AST.NSimple vec1Par) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:+:
1221                   AST.PrimName (AST.NAttribute $ 
1222                 AST.AttribName (AST.NSimple vec2Par) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:-:
1223                   AST.PrimLit "1")]))
1224        Nothing
1225     plusplusExpr = AST.NSimple resId AST.:= 
1226                      ((AST.PrimName $ AST.NSimple vec1Par) AST.:&: 
1227                       (AST.PrimName $ AST.NSimple vec2Par))
1228     plusplusRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
1229     lengthTSpec = AST.Function (mkVHDLExtId lengthTId) [AST.IfaceVarDec vecPar vectorTM] naturalTM
1230     lengthTExpr = AST.ReturnSm (Just $ AST.PrimName (AST.NAttribute $ 
1231                                 AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing))
1232     shiftlSpec = AST.Function (mkVHDLExtId shiftlId) [AST.IfaceVarDec vecPar vectorTM,
1233                                    AST.IfaceVarDec aPar   elemTM  ] vectorTM 
1234     -- variable res : fsvec_x (0 to vec'length-1);
1235     shiftlVar = 
1236      AST.VarDec resId 
1237             (AST.SubtypeIn vectorTM
1238               (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
1239                [AST.ToRange (AST.PrimLit "0")
1240                         (AST.PrimName (AST.NAttribute $ 
1241                           AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:-:
1242                            (AST.PrimLit "1")) ]))
1243             Nothing
1244     -- res := a & init(vec)
1245     shiftlExpr = AST.NSimple resId AST.:=
1246                     (AST.PrimName (AST.NSimple aPar) AST.:&:
1247                      (AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLExtId initId))  
1248                        [Nothing AST.:=>: AST.ADExpr (AST.PrimName $ AST.NSimple vecPar)]))
1249     shiftlRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)       
1250     shiftrSpec = AST.Function (mkVHDLExtId shiftrId) [AST.IfaceVarDec vecPar vectorTM,
1251                                        AST.IfaceVarDec aPar   elemTM  ] vectorTM 
1252     -- variable res : fsvec_x (0 to vec'length-1);
1253     shiftrVar = 
1254      AST.VarDec resId 
1255             (AST.SubtypeIn vectorTM
1256               (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
1257                [AST.ToRange (AST.PrimLit "0")
1258                         (AST.PrimName (AST.NAttribute $ 
1259                           AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:-:
1260                            (AST.PrimLit "1")) ]))
1261             Nothing
1262     -- res := tail(vec) & a
1263     shiftrExpr = AST.NSimple resId AST.:=
1264                   ((AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLExtId tailId))  
1265                     [Nothing AST.:=>: AST.ADExpr (AST.PrimName $ AST.NSimple vecPar)]) AST.:&:
1266                   (AST.PrimName (AST.NSimple aPar)))
1267                 
1268     shiftrRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)      
1269     nullSpec = AST.Function (mkVHDLExtId nullId) [AST.IfaceVarDec vecPar vectorTM] booleanTM
1270     -- return vec'length = 0
1271     nullExpr = AST.ReturnSm (Just $ 
1272                 AST.PrimName (AST.NAttribute $ 
1273                   AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:=:
1274                     AST.PrimLit "0")
1275     rotlSpec = AST.Function (mkVHDLExtId rotlId) [AST.IfaceVarDec vecPar vectorTM] vectorTM 
1276     -- variable res : fsvec_x (0 to vec'length-1);
1277     rotlVar = 
1278      AST.VarDec resId 
1279             (AST.SubtypeIn vectorTM
1280               (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
1281                [AST.ToRange (AST.PrimLit "0")
1282                         (AST.PrimName (AST.NAttribute $ 
1283                           AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:-:
1284                            (AST.PrimLit "1")) ]))
1285             Nothing
1286     -- if null(vec) then res := vec else res := last(vec) & init(vec)
1287     rotlExpr = AST.IfSm (AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLExtId nullId))  
1288                           [Nothing AST.:=>: AST.ADExpr (AST.PrimName $ AST.NSimple vecPar)])
1289                         [AST.NSimple resId AST.:= (AST.PrimName $ AST.NSimple vecPar)]
1290                         []
1291                         (Just $ AST.Else [rotlExprRet])
1292       where rotlExprRet = 
1293                 AST.NSimple resId AST.:= 
1294                       ((AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLExtId lastId))  
1295                         [Nothing AST.:=>: AST.ADExpr (AST.PrimName $ AST.NSimple vecPar)]) AST.:&:
1296                       (AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLExtId initId))  
1297                         [Nothing AST.:=>: AST.ADExpr (AST.PrimName $ AST.NSimple vecPar)]))
1298     rotlRet =  AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)       
1299     rotrSpec = AST.Function (mkVHDLExtId rotrId) [AST.IfaceVarDec vecPar vectorTM] vectorTM 
1300     -- variable res : fsvec_x (0 to vec'length-1);
1301     rotrVar = 
1302      AST.VarDec resId 
1303             (AST.SubtypeIn vectorTM
1304               (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
1305                [AST.ToRange (AST.PrimLit "0")
1306                         (AST.PrimName (AST.NAttribute $ 
1307                           AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:-:
1308                            (AST.PrimLit "1")) ]))
1309             Nothing
1310     -- if null(vec) then res := vec else res := tail(vec) & head(vec)
1311     rotrExpr = AST.IfSm (AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLExtId nullId))  
1312                           [Nothing AST.:=>: AST.ADExpr (AST.PrimName $ AST.NSimple vecPar)])
1313                         [AST.NSimple resId AST.:= (AST.PrimName $ AST.NSimple vecPar)]
1314                         []
1315                         (Just $ AST.Else [rotrExprRet])
1316       where rotrExprRet = 
1317                 AST.NSimple resId AST.:= 
1318                       ((AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLExtId tailId))  
1319                         [Nothing AST.:=>: AST.ADExpr (AST.PrimName $ AST.NSimple vecPar)]) AST.:&:
1320                       (AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLExtId headId))  
1321                         [Nothing AST.:=>: AST.ADExpr (AST.PrimName $ AST.NSimple vecPar)]))
1322     rotrRet =  AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
1323     reverseSpec = AST.Function (mkVHDLExtId reverseId) [AST.IfaceVarDec vecPar vectorTM] vectorTM
1324     reverseVar = 
1325       AST.VarDec resId 
1326              (AST.SubtypeIn vectorTM
1327                (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
1328                 [AST.ToRange (AST.PrimLit "0")
1329                          (AST.PrimName (AST.NAttribute $ 
1330                            AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:-:
1331                             (AST.PrimLit "1")) ]))
1332              Nothing
1333     -- for i in 0 to res'range loop
1334     --   res(vec'length-i-1) := vec(i);
1335     -- end loop;
1336     reverseFor = 
1337        AST.ForSM iId (AST.AttribRange $ AST.AttribName (AST.NSimple resId) (AST.NSimple $ rangeId) Nothing) [reverseAssign]
1338     -- res(vec'length-i-1) := vec(i);
1339     reverseAssign = AST.NIndexed (AST.IndexedName (AST.NSimple resId) [destExp]) AST.:=
1340       (AST.PrimName $ AST.NIndexed (AST.IndexedName (AST.NSimple vecPar) 
1341                            [AST.PrimName $ AST.NSimple iId]))
1342         where destExp = AST.PrimName (AST.NAttribute $ AST.AttribName (AST.NSimple vecPar) 
1343                                    (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:-: 
1344                         AST.PrimName (AST.NSimple iId) AST.:-: 
1345                         (AST.PrimLit "1") 
1346     -- return res;
1347     reverseRet = AST.ReturnSm (Just $ AST.PrimName (AST.NSimple resId))
1348
1349     
1350 -----------------------------------------------------------------------------
1351 -- A table of builtin functions
1352 -----------------------------------------------------------------------------
1353
1354 -- A function that generates VHDL for a builtin function
1355 type BuiltinBuilder = 
1356   (Either CoreSyn.CoreBndr AST.VHDLName) -- ^ The destination signal and it's original type
1357   -> CoreSyn.CoreBndr -- ^ The function called
1358   -> [Either CoreSyn.CoreExpr AST.Expr] -- ^ The value arguments passed (excluding type and
1359                     --   dictionary arguments).
1360   -> TranslatorSession ([AST.ConcSm], [CoreSyn.CoreBndr]) 
1361   -- ^ The corresponding VHDL concurrent statements and entities
1362   --   instantiated.
1363
1364 -- A map of a builtin function to VHDL function builder 
1365 type NameTable = Map.Map String (Int, BuiltinBuilder )
1366
1367 -- | The builtin functions we support. Maps a name to an argument count and a
1368 -- builder function.
1369 globalNameTable :: NameTable
1370 globalNameTable = Map.fromList
1371   [ (exId             , (2, genFCall True          ) )
1372   , (replaceId        , (3, genFCall False          ) )
1373   , (headId           , (1, genFCall True           ) )
1374   , (lastId           , (1, genFCall True           ) )
1375   , (tailId           , (1, genFCall False          ) )
1376   , (initId           , (1, genFCall False          ) )
1377   , (takeId           , (2, genFCall False          ) )
1378   , (dropId           , (2, genFCall False          ) )
1379   , (selId            , (4, genFCall False          ) )
1380   , (plusgtId         , (2, genFCall False          ) )
1381   , (ltplusId         , (2, genFCall False          ) )
1382   , (plusplusId       , (2, genFCall False          ) )
1383   , (mapId            , (2, genMap                  ) )
1384   , (zipWithId        , (3, genZipWith              ) )
1385   , (foldlId          , (3, genFoldl                ) )
1386   , (foldrId          , (3, genFoldr                ) )
1387   , (zipId            , (2, genZip                  ) )
1388   , (unzipId          , (1, genUnzip                ) )
1389   , (shiftlId         , (2, genFCall False          ) )
1390   , (shiftrId         , (2, genFCall False          ) )
1391   , (rotlId           , (1, genFCall False          ) )
1392   , (rotrId           , (1, genFCall False          ) )
1393   , (concatId         , (1, genConcat               ) )
1394   , (reverseId        , (1, genFCall False          ) )
1395   , (iteratenId       , (3, genIteraten             ) )
1396   , (iterateId        , (2, genIterate              ) )
1397   , (generatenId      , (3, genGeneraten            ) )
1398   , (generateId       , (2, genGenerate             ) )
1399   , (emptyId          , (0, genFCall False          ) )
1400   , (singletonId      , (1, genFCall False          ) )
1401   , (copynId          , (2, genFCall False          ) )
1402   , (copyId           , (1, genCopy                 ) )
1403   , (lengthTId        , (1, genFCall False          ) )
1404   , (nullId           , (1, genFCall False          ) )
1405   , (hwxorId          , (2, genOperator2 AST.Xor    ) )
1406   , (hwandId          , (2, genOperator2 AST.And    ) )
1407   , (hworId           , (2, genOperator2 AST.Or     ) )
1408   , (hwnotId          , (1, genOperator1 AST.Not    ) )
1409   , (equalityId       , (2, genOperator2 (AST.:=:)  ) )
1410   , (inEqualityId     , (2, genOperator2 (AST.:/=:) ) )
1411   , (boolOrId         , (2, genOperator2 AST.Or     ) )
1412   , (boolAndId        , (2, genOperator2 AST.And    ) )
1413   , (plusId           , (2, genOperator2 (AST.:+:)  ) )
1414   , (timesId          , (2, genOperator2 (AST.:*:)  ) )
1415   , (negateId         , (1, genNegation             ) )
1416   , (minusId          , (2, genOperator2 (AST.:-:)  ) )
1417   , (fromSizedWordId  , (1, genFromSizedWord        ) )
1418   , (fromIntegerId    , (1, genFromInteger          ) )
1419   , (resizeId         , (1, genResize               ) )
1420   , (sizedIntId       , (1, genSizedInt             ) )
1421   , (smallIntegerId   , (1, genFromInteger          ) )
1422   , (fstId            , (1, genFst                  ) )
1423   , (sndId            , (1, genSnd                  ) )
1424   --, (tfvecId          , (1, genTFVec                ) )
1425   , (minimumId        , (2, error $ "\nFunction name: \"minimum\" is used internally, use another name"))
1426   ]