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