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