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