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