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