1 module CLasH.VHDL.Generate where
4 import qualified Data.Map as Map
6 import qualified Data.Either as Either
8 import Data.Accessor.MonadState as MonadState
12 import qualified Language.VHDL.AST as AST
15 import qualified CoreSyn
18 import qualified IdInfo
19 import qualified Literal
21 import qualified TyCon
24 import CLasH.VHDL.Constants
25 import CLasH.VHDL.VHDLTypes
26 import CLasH.VHDL.VHDLTools
27 import CLasH.Utils.Core.CoreTools
28 import CLasH.Utils.Pretty
30 -----------------------------------------------------------------------------
31 -- Functions to generate VHDL for builtin functions
32 -----------------------------------------------------------------------------
34 -- | A function to wrap a builder-like function that expects its arguments to
36 genExprArgs wrap dst func args = do
37 args' <- eitherCoreOrExprArgs args
40 eitherCoreOrExprArgs :: [Either CoreSyn.CoreExpr AST.Expr] -> VHDLSession [AST.Expr]
41 eitherCoreOrExprArgs args = mapM (Either.either ((MonadState.lift vsType) . varToVHDLExpr . exprToVar) return) args
43 -- | A function to wrap a builder-like function that expects its arguments to
46 (dst -> func -> [Var.Var] -> res)
47 -> (dst -> func -> [Either CoreSyn.CoreExpr AST.Expr] -> res)
48 genVarArgs wrap dst func args = wrap dst func args'
50 args' = map exprToVar exprargs
51 -- Check (rather crudely) that all arguments are CoreExprs
52 (exprargs, []) = Either.partitionEithers args
54 -- | A function to wrap a builder-like function that expects its arguments to
57 (dst -> func -> [Literal.Literal] -> res)
58 -> (dst -> func -> [Either CoreSyn.CoreExpr AST.Expr] -> res)
59 genLitArgs wrap dst func args = wrap dst func args'
61 args' = map exprToLit litargs
62 -- FIXME: Check if we were passed an CoreSyn.App
63 litargs = concat (map getLiterals exprargs)
64 (exprargs, []) = Either.partitionEithers args
66 -- | A function to wrap a builder-like function that produces an expression
67 -- and expects it to be assigned to the destination.
69 ((Either CoreSyn.CoreBndr AST.VHDLName) -> func -> [arg] -> VHDLSession AST.Expr)
70 -> ((Either CoreSyn.CoreBndr AST.VHDLName) -> func -> [arg] -> VHDLSession [AST.ConcSm])
71 genExprRes wrap dst func args = do
72 expr <- wrap dst func args
73 return $ [mkUncondAssign dst expr]
75 -- | Generate a binary operator application. The first argument should be a
76 -- constructor from the AST.Expr type, e.g. AST.And.
77 genOperator2 :: (AST.Expr -> AST.Expr -> AST.Expr) -> BuiltinBuilder
78 genOperator2 op = genExprArgs $ genExprRes (genOperator2' op)
79 genOperator2' :: (AST.Expr -> AST.Expr -> AST.Expr) -> dst -> CoreSyn.CoreBndr -> [AST.Expr] -> VHDLSession AST.Expr
80 genOperator2' op _ f [arg1, arg2] = return $ op arg1 arg2
82 -- | Generate a unary operator application
83 genOperator1 :: (AST.Expr -> AST.Expr) -> BuiltinBuilder
84 genOperator1 op = genExprArgs $ genExprRes (genOperator1' op)
85 genOperator1' :: (AST.Expr -> AST.Expr) -> dst -> CoreSyn.CoreBndr -> [AST.Expr] -> VHDLSession AST.Expr
86 genOperator1' op _ f [arg] = return $ op arg
88 -- | Generate a unary operator application
89 genNegation :: BuiltinBuilder
90 genNegation = genVarArgs $ genExprRes genNegation'
91 genNegation' :: dst -> CoreSyn.CoreBndr -> [Var.Var] -> VHDLSession AST.Expr
92 genNegation' _ f [arg] = do
93 arg1 <- MonadState.lift vsType $ varToVHDLExpr arg
94 let ty = Var.varType arg
95 let (tycon, args) = Type.splitTyConApp ty
96 let name = Name.getOccString (TyCon.tyConName tycon)
98 "SizedInt" -> return $ AST.Neg arg1
99 otherwise -> error $ "\nGenerate.genNegation': Negation allowed for type: " ++ show name
101 -- | Generate a function call from the destination binder, function name and a
102 -- list of expressions (its arguments)
103 genFCall :: Bool -> BuiltinBuilder
104 genFCall switch = genExprArgs $ genExprRes (genFCall' switch)
105 genFCall' :: Bool -> Either CoreSyn.CoreBndr AST.VHDLName -> CoreSyn.CoreBndr -> [AST.Expr] -> VHDLSession AST.Expr
106 genFCall' switch (Left res) f args = do
107 let fname = varToString f
108 let el_ty = if switch then (Var.varType res) else ((tfvec_elem . Var.varType) res)
109 id <- MonadState.lift vsType $ vectorFunId el_ty fname
110 return $ AST.PrimFCall $ AST.FCall (AST.NSimple id) $
111 map (\exp -> Nothing AST.:=>: AST.ADExpr exp) args
112 genFCall' _ (Right name) _ _ = error $ "\nGenerate.genFCall': Cannot generate builtin function call assigned to a VHDLName: " ++ show name
114 genFromSizedWord :: BuiltinBuilder
115 genFromSizedWord = genExprArgs $ genExprRes genFromSizedWord'
116 genFromSizedWord' :: Either CoreSyn.CoreBndr AST.VHDLName -> CoreSyn.CoreBndr -> [AST.Expr] -> VHDLSession AST.Expr
117 genFromSizedWord' (Left res) f args = do
118 let fname = varToString f
119 return $ AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLBasicId toIntegerId)) $
120 map (\exp -> Nothing AST.:=>: AST.ADExpr exp) args
121 genFromSizedWord' (Right name) _ _ = error $ "\nGenerate.genFromSizedWord': Cannot generate builtin function call assigned to a VHDLName: " ++ show name
123 genResize :: BuiltinBuilder
124 genResize = genExprArgs $ genExprRes genResize'
125 genResize' :: Either CoreSyn.CoreBndr AST.VHDLName -> CoreSyn.CoreBndr -> [AST.Expr] -> VHDLSession AST.Expr
126 genResize' (Left res) f [arg] = do {
127 ; let { ty = Var.varType res
128 ; (tycon, args) = Type.splitTyConApp ty
129 ; name = Name.getOccString (TyCon.tyConName tycon)
131 ; len <- case name of
132 "SizedInt" -> MonadState.lift vsType $ tfp_to_int (sized_int_len_ty ty)
133 "SizedWord" -> MonadState.lift vsType $ tfp_to_int (sized_word_len_ty ty)
134 ; return $ AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLBasicId resizeId))
135 [Nothing AST.:=>: AST.ADExpr arg, Nothing AST.:=>: AST.ADExpr( AST.PrimLit (show len))]
137 genResize' (Right name) _ _ = error $ "\nGenerate.genFromSizedWord': Cannot generate builtin function call assigned to a VHDLName: " ++ show name
139 -- FIXME: I'm calling genLitArgs which is very specific function,
140 -- which needs to be fixed as well
141 genFromInteger :: BuiltinBuilder
142 genFromInteger = genLitArgs $ genExprRes genFromInteger'
143 genFromInteger' :: Either CoreSyn.CoreBndr AST.VHDLName -> CoreSyn.CoreBndr -> [Literal.Literal] -> VHDLSession AST.Expr
144 genFromInteger' (Left res) f lits = do {
145 ; let { ty = Var.varType res
146 ; (tycon, args) = Type.splitTyConApp ty
147 ; name = Name.getOccString (TyCon.tyConName tycon)
149 ; len <- case name of
150 "SizedInt" -> MonadState.lift vsType $ tfp_to_int (sized_int_len_ty ty)
151 "SizedWord" -> MonadState.lift vsType $ tfp_to_int (sized_word_len_ty ty)
152 ; let fname = case name of "SizedInt" -> toSignedId ; "SizedWord" -> toUnsignedId
153 ; return $ AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLBasicId fname))
154 [Nothing AST.:=>: AST.ADExpr (AST.PrimLit (show (last lits))), Nothing AST.:=>: AST.ADExpr( AST.PrimLit (show len))]
157 genFromInteger' (Right name) _ _ = error $ "\nGenerate.genFromInteger': Cannot generate builtin function call assigned to a VHDLName: " ++ show name
159 genSizedInt :: BuiltinBuilder
160 genSizedInt = genFromInteger
162 genTFVec :: BuiltinBuilder
163 genTFVec (Left res) f [Left veclist] = do {
164 ; let (CoreSyn.Let (CoreSyn.Rec letbndrs) rez) = veclist
165 ; letapps <- mapM genLetApp letbndrs
166 ; let bndrs = Maybe.catMaybes (map fst letapps)
167 ; (aap,kooi) <- reduceFSVECListToHsList rez
168 ; sigs <- mapM (\x -> MonadState.lift vsType $ varToVHDLExpr x) (bndrs ++ aap)
169 ; let vecsigns = concatsigs sigs
170 ; let vecassign = mkUncondAssign (Left res) vecsigns
171 ; sig_dec_maybes <- mapM mkSigDec (bndrs ++ aap)
172 ; let sig_decs = map (AST.BDISD) (Maybe.catMaybes $ sig_dec_maybes)
173 ; let block_label = mkVHDLExtId ("FSVec_" ++ (show (map varToString (bndrs ++ aap))))
174 ; let block = AST.BlockSm block_label [] (AST.PMapAspect []) sig_decs ((concat (map snd letapps)) ++ kooi ++ [vecassign])
175 ; return $ [AST.CSBSm block]
178 concatsigs x = AST.Aggregate (map (\z -> AST.ElemAssoc Nothing z) x)
180 genLetApp :: (CoreSyn.CoreBndr, CoreSyn.CoreExpr) -> VHDLSession (Maybe CoreSyn.CoreBndr, [AST.ConcSm])
181 genLetApp (bndr, app@(CoreSyn.App _ _)) = do
182 let (CoreSyn.Var f, args) = CoreSyn.collectArgs app
183 let valargs = get_val_args (Var.varType f) args
184 apps <- genApplication (Left bndr) f (map Left valargs)
185 return (Just bndr, apps)
187 genLetApp _ = return (Nothing,[])
189 reduceFSVECListToHsList :: CoreSyn.CoreExpr -> VHDLSession ([CoreSyn.CoreBndr], [AST.ConcSm])
190 reduceFSVECListToHsList app@(CoreSyn.App _ letexpr) = do
192 (CoreSyn.Let (CoreSyn.Rec letbndrs) rez) -> do
193 letapps <- mapM genLetApp letbndrs
194 let bndrs = Maybe.catMaybes (map fst letapps)
195 let app = (map snd letapps)
196 (vars, apps) <- reduceFSVECListToHsList rez
197 return ((bndrs ++ vars),((concat app) ++ apps))
198 otherwise -> return ([],[])
201 -- | Generate a generate statement for the builtin function "map"
202 genMap :: BuiltinBuilder
203 genMap (Left res) f [Left mapped_f, Left (CoreSyn.Var arg)] = do {
204 -- mapped_f must be a CoreExpr (since we can't represent functions as VHDL
205 -- expressions). arg must be a CoreExpr (and should be a CoreSyn.Var), since
206 -- we must index it (which we couldn't if it was a VHDL Expr, since only
207 -- VHDLNames can be indexed).
208 -- Setup the generate scheme
209 ; len <- MonadState.lift vsType $ tfp_to_int $ (tfvec_len_ty . Var.varType) res
210 -- TODO: Use something better than varToString
211 ; let { label = mkVHDLExtId ("mapVector" ++ (varToString res))
212 ; n_id = mkVHDLBasicId "n"
213 ; n_expr = idToVHDLExpr n_id
214 ; range = AST.ToRange (AST.PrimLit "0") (AST.PrimLit $ show (len-1))
215 ; genScheme = AST.ForGn n_id range
216 -- Create the content of the generate statement: Applying the mapped_f to
217 -- each of the elements in arg, storing to each element in res
218 ; resname = mkIndexedName (varToVHDLName res) n_expr
219 ; argexpr = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName arg) n_expr
220 ; (CoreSyn.Var real_f, already_mapped_args) = CoreSyn.collectArgs mapped_f
221 ; valargs = get_val_args (Var.varType real_f) already_mapped_args
223 ; app_concsms <- genApplication (Right resname) real_f (map Left valargs ++ [Right argexpr])
224 -- Return the generate statement
225 ; return [AST.CSGSm $ AST.GenerateSm label genScheme [] app_concsms]
228 genMap' (Right name) _ _ = error $ "\nGenerate.genMap': Cannot generate map function call assigned to a VHDLName: " ++ show name
230 genZipWith :: BuiltinBuilder
231 genZipWith = genVarArgs genZipWith'
232 genZipWith' :: (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> VHDLSession [AST.ConcSm]
233 genZipWith' (Left res) f args@[zipped_f, arg1, arg2] = do {
234 -- Setup the generate scheme
235 ; len <- MonadState.lift vsType $ tfp_to_int $ (tfvec_len_ty . Var.varType) res
236 -- TODO: Use something better than varToString
237 ; let { label = mkVHDLExtId ("zipWithVector" ++ (varToString res))
238 ; n_id = mkVHDLBasicId "n"
239 ; n_expr = idToVHDLExpr n_id
240 ; range = AST.ToRange (AST.PrimLit "0") (AST.PrimLit $ show (len-1))
241 ; genScheme = AST.ForGn n_id range
242 -- Create the content of the generate statement: Applying the zipped_f to
243 -- each of the elements in arg1 and arg2, storing to each element in res
244 ; resname = mkIndexedName (varToVHDLName res) n_expr
245 ; argexpr1 = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName arg1) n_expr
246 ; argexpr2 = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName arg2) n_expr
248 ; app_concsms <- genApplication (Right resname) zipped_f [Right argexpr1, Right argexpr2]
249 -- Return the generate functions
250 ; return [AST.CSGSm $ AST.GenerateSm label genScheme [] app_concsms]
253 genFoldl :: BuiltinBuilder
254 genFoldl = genFold True
256 genFoldr :: BuiltinBuilder
257 genFoldr = genFold False
259 genFold :: Bool -> BuiltinBuilder
260 genFold left = genVarArgs (genFold' left)
262 genFold' :: Bool -> (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> VHDLSession [AST.ConcSm]
263 genFold' left res f args@[folded_f , start ,vec]= do
264 len <- MonadState.lift vsType $ tfp_to_int $ (tfvec_len_ty (Var.varType vec))
265 genFold'' len left res f args
267 genFold'' :: Int -> Bool -> (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> VHDLSession [AST.ConcSm]
268 -- Special case for an empty input vector, just assign start to res
269 genFold'' len left (Left res) _ [_, start, vec] | len == 0 = do
270 arg <- MonadState.lift vsType $ varToVHDLExpr start
271 return [mkUncondAssign (Left res) arg]
273 genFold'' len left (Left res) f [folded_f, start, vec] = do
275 --len <- MonadState.lift vsType $ tfp_to_int $ (tfvec_len_ty . Var.varType) vec
276 -- An expression for len-1
277 let len_min_expr = (AST.PrimLit $ show (len-1))
278 -- evec is (TFVec n), so it still needs an element type
279 let (nvec, _) = Type.splitAppTy (Var.varType vec)
280 -- Put the type of the start value in nvec, this will be the type of our
282 let tmp_ty = Type.mkAppTy nvec (Var.varType start)
283 let error_msg = "\nGenerate.genFold': Can not construct temp vector for element type: " ++ pprString tmp_ty
284 tmp_vhdl_ty <- MonadState.lift vsType $ vhdl_ty error_msg tmp_ty
285 -- Setup the generate scheme
286 let gen_label = mkVHDLExtId ("foldlVector" ++ (varToString vec))
287 let block_label = mkVHDLExtId ("foldlVector" ++ (varToString res))
288 let gen_range = if left then AST.ToRange (AST.PrimLit "0") len_min_expr
289 else AST.DownRange len_min_expr (AST.PrimLit "0")
290 let gen_scheme = AST.ForGn n_id gen_range
291 -- Make the intermediate vector
292 let tmp_dec = AST.BDISD $ AST.SigDec tmp_id tmp_vhdl_ty Nothing
293 -- Create the generate statement
294 cells <- sequence [genFirstCell, genOtherCell]
295 let gen_sm = AST.GenerateSm gen_label gen_scheme [] (map AST.CSGSm cells)
296 -- Assign tmp[len-1] or tmp[0] to res
297 let out_assign = mkUncondAssign (Left res) $ vhdlNameToVHDLExpr (if left then
298 (mkIndexedName tmp_name (AST.PrimLit $ show (len-1))) else
299 (mkIndexedName tmp_name (AST.PrimLit "0")))
300 let block = AST.BlockSm block_label [] (AST.PMapAspect []) [tmp_dec] [AST.CSGSm gen_sm, out_assign]
301 return [AST.CSBSm block]
303 -- An id for the counter
304 n_id = mkVHDLBasicId "n"
305 n_cur = idToVHDLExpr n_id
306 -- An expression for previous n
307 n_prev = if left then (n_cur AST.:-: (AST.PrimLit "1"))
308 else (n_cur AST.:+: (AST.PrimLit "1"))
309 -- An id for the tmp result vector
310 tmp_id = mkVHDLBasicId "tmp"
311 tmp_name = AST.NSimple tmp_id
312 -- Generate parts of the fold
313 genFirstCell, genOtherCell :: VHDLSession AST.GenerateSm
315 len <- MonadState.lift vsType $ tfp_to_int $ (tfvec_len_ty . Var.varType) vec
316 let cond_label = mkVHDLExtId "firstcell"
317 -- if n == 0 or n == len-1
318 let cond_scheme = AST.IfGn $ n_cur AST.:=: (if left then (AST.PrimLit "0")
319 else (AST.PrimLit $ show (len-1)))
320 -- Output to tmp[current n]
321 let resname = mkIndexedName tmp_name n_cur
323 argexpr1 <- MonadState.lift vsType $ varToVHDLExpr start
324 -- Input from vec[current n]
325 let argexpr2 = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName vec) n_cur
326 app_concsms <- genApplication (Right resname) folded_f ( if left then
327 [Right argexpr1, Right argexpr2]
329 [Right argexpr2, Right argexpr1]
331 -- Return the conditional generate part
332 return $ AST.GenerateSm cond_label cond_scheme [] app_concsms
335 len <- MonadState.lift vsType $ tfp_to_int $ (tfvec_len_ty . Var.varType) vec
336 let cond_label = mkVHDLExtId "othercell"
337 -- if n > 0 or n < len-1
338 let cond_scheme = AST.IfGn $ n_cur AST.:/=: (if left then (AST.PrimLit "0")
339 else (AST.PrimLit $ show (len-1)))
340 -- Output to tmp[current n]
341 let resname = mkIndexedName tmp_name n_cur
342 -- Input from tmp[previous n]
343 let argexpr1 = vhdlNameToVHDLExpr $ mkIndexedName tmp_name n_prev
344 -- Input from vec[current n]
345 let argexpr2 = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName vec) n_cur
346 app_concsms <- genApplication (Right resname) folded_f ( if left then
347 [Right argexpr1, Right argexpr2]
349 [Right argexpr2, Right argexpr1]
351 -- Return the conditional generate part
352 return $ AST.GenerateSm cond_label cond_scheme [] app_concsms
354 -- | Generate a generate statement for the builtin function "zip"
355 genZip :: BuiltinBuilder
356 genZip = genVarArgs genZip'
357 genZip' :: (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> VHDLSession [AST.ConcSm]
358 genZip' (Left res) f args@[arg1, arg2] = do {
359 -- Setup the generate scheme
360 ; len <- MonadState.lift vsType $ tfp_to_int $ (tfvec_len_ty . Var.varType) res
361 -- TODO: Use something better than varToString
362 ; let { label = mkVHDLExtId ("zipVector" ++ (varToString res))
363 ; n_id = mkVHDLBasicId "n"
364 ; n_expr = idToVHDLExpr n_id
365 ; range = AST.ToRange (AST.PrimLit "0") (AST.PrimLit $ show (len-1))
366 ; genScheme = AST.ForGn n_id range
367 ; resname' = mkIndexedName (varToVHDLName res) n_expr
368 ; argexpr1 = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName arg1) n_expr
369 ; argexpr2 = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName arg2) n_expr
371 ; labels <- MonadState.lift vsType $ getFieldLabels (tfvec_elem (Var.varType res))
372 ; let { resnameA = mkSelectedName resname' (labels!!0)
373 ; resnameB = mkSelectedName resname' (labels!!1)
374 ; resA_assign = mkUncondAssign (Right resnameA) argexpr1
375 ; resB_assign = mkUncondAssign (Right resnameB) argexpr2
377 -- Return the generate functions
378 ; return [AST.CSGSm $ AST.GenerateSm label genScheme [] [resA_assign,resB_assign]]
381 -- | Generate a generate statement for the builtin function "unzip"
382 genUnzip :: BuiltinBuilder
383 genUnzip = genVarArgs genUnzip'
384 genUnzip' :: (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> VHDLSession [AST.ConcSm]
385 genUnzip' (Left res) f args@[arg] = do {
386 -- Setup the generate scheme
387 ; len <- MonadState.lift vsType $ tfp_to_int $ (tfvec_len_ty . Var.varType) arg
388 -- TODO: Use something better than varToString
389 ; let { label = mkVHDLExtId ("unzipVector" ++ (varToString res))
390 ; n_id = mkVHDLBasicId "n"
391 ; n_expr = idToVHDLExpr n_id
392 ; range = AST.ToRange (AST.PrimLit "0") (AST.PrimLit $ show (len-1))
393 ; genScheme = AST.ForGn n_id range
394 ; resname' = varToVHDLName res
395 ; argexpr' = mkIndexedName (varToVHDLName arg) n_expr
397 ; reslabels <- MonadState.lift vsType $ getFieldLabels (Var.varType res)
398 ; arglabels <- MonadState.lift vsType $ getFieldLabels (tfvec_elem (Var.varType arg))
399 ; let { resnameA = mkIndexedName (mkSelectedName resname' (reslabels!!0)) n_expr
400 ; resnameB = mkIndexedName (mkSelectedName resname' (reslabels!!1)) n_expr
401 ; argexprA = vhdlNameToVHDLExpr $ mkSelectedName argexpr' (arglabels!!0)
402 ; argexprB = vhdlNameToVHDLExpr $ mkSelectedName argexpr' (arglabels!!1)
403 ; resA_assign = mkUncondAssign (Right resnameA) argexprA
404 ; resB_assign = mkUncondAssign (Right resnameB) argexprB
406 -- Return the generate functions
407 ; return [AST.CSGSm $ AST.GenerateSm label genScheme [] [resA_assign,resB_assign]]
410 genCopy :: BuiltinBuilder
411 genCopy = genVarArgs genCopy'
412 genCopy' :: (Either CoreSyn.CoreBndr AST.VHDLName ) -> CoreSyn.CoreBndr -> [Var.Var] -> VHDLSession [AST.ConcSm]
413 genCopy' (Left res) f args@[arg] =
415 resExpr = AST.Aggregate [AST.ElemAssoc (Just AST.Others)
416 (AST.PrimName $ (varToVHDLName arg))]
417 out_assign = mkUncondAssign (Left res) resExpr
421 genConcat :: BuiltinBuilder
422 genConcat = genVarArgs genConcat'
423 genConcat' :: (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> VHDLSession [AST.ConcSm]
424 genConcat' (Left res) f args@[arg] = do {
425 -- Setup the generate scheme
426 ; len1 <- MonadState.lift vsType $ tfp_to_int $ (tfvec_len_ty . Var.varType) arg
427 ; let (_, nvec) = Type.splitAppTy (Var.varType arg)
428 ; len2 <- MonadState.lift vsType $ tfp_to_int $ tfvec_len_ty nvec
429 -- TODO: Use something better than varToString
430 ; let { label = mkVHDLExtId ("concatVector" ++ (varToString res))
431 ; n_id = mkVHDLBasicId "n"
432 ; n_expr = idToVHDLExpr n_id
433 ; fromRange = n_expr AST.:*: (AST.PrimLit $ show len2)
434 ; genScheme = AST.ForGn n_id range
435 -- Create the content of the generate statement: Applying the mapped_f to
436 -- each of the elements in arg, storing to each element in res
437 ; toRange = (n_expr AST.:*: (AST.PrimLit $ show len2)) AST.:+: (AST.PrimLit $ show (len2-1))
438 ; range = AST.ToRange (AST.PrimLit "0") (AST.PrimLit $ show (len1-1))
439 ; resname = vecSlice fromRange toRange
440 ; argexpr = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName arg) n_expr
441 ; out_assign = mkUncondAssign (Right resname) argexpr
443 -- Return the generate statement
444 ; return [AST.CSGSm $ AST.GenerateSm label genScheme [] [out_assign]]
447 vecSlice init last = AST.NSlice (AST.SliceName (varToVHDLName res)
448 (AST.ToRange init last))
450 genIteraten :: BuiltinBuilder
451 genIteraten dst f args = genIterate dst f (tail args)
453 genIterate :: BuiltinBuilder
454 genIterate = genIterateOrGenerate True
456 genGeneraten :: BuiltinBuilder
457 genGeneraten dst f args = genGenerate dst f (tail args)
459 genGenerate :: BuiltinBuilder
460 genGenerate = genIterateOrGenerate False
462 genIterateOrGenerate :: Bool -> BuiltinBuilder
463 genIterateOrGenerate iter = genVarArgs (genIterateOrGenerate' iter)
465 genIterateOrGenerate' :: Bool -> (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> VHDLSession [AST.ConcSm]
466 genIterateOrGenerate' iter (Left res) f args = do
467 len <- MonadState.lift vsType $ tfp_to_int ((tfvec_len_ty . Var.varType) res)
468 genIterateOrGenerate'' len iter (Left res) f args
470 genIterateOrGenerate'' :: Int -> Bool -> (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> VHDLSession [AST.ConcSm]
471 -- Special case for an empty input vector, just assign start to res
472 genIterateOrGenerate'' len iter (Left res) _ [app_f, start] | len == 0 = return [mkUncondAssign (Left res) (AST.PrimLit "\"\"")]
474 genIterateOrGenerate'' len iter (Left res) f [app_f, start] = do
476 -- len <- MonadState.lift vsType $ tfp_to_int ((tfvec_len_ty . Var.varType) res)
477 -- An expression for len-1
478 let len_min_expr = (AST.PrimLit $ show (len-1))
479 -- -- evec is (TFVec n), so it still needs an element type
480 -- let (nvec, _) = splitAppTy (Var.varType vec)
481 -- -- Put the type of the start value in nvec, this will be the type of our
482 -- -- temporary vector
483 let tmp_ty = Var.varType res
484 let error_msg = "\nGenerate.genFold': Can not construct temp vector for element type: " ++ pprString tmp_ty
485 tmp_vhdl_ty <- MonadState.lift vsType $ vhdl_ty error_msg tmp_ty
486 -- Setup the generate scheme
487 let gen_label = mkVHDLExtId ("iterateVector" ++ (varToString start))
488 let block_label = mkVHDLExtId ("iterateVector" ++ (varToString res))
489 let gen_range = AST.ToRange (AST.PrimLit "0") len_min_expr
490 let gen_scheme = AST.ForGn n_id gen_range
491 -- Make the intermediate vector
492 let tmp_dec = AST.BDISD $ AST.SigDec tmp_id tmp_vhdl_ty Nothing
493 -- Create the generate statement
494 cells <- sequence [genFirstCell, genOtherCell]
495 let gen_sm = AST.GenerateSm gen_label gen_scheme [] (map AST.CSGSm cells)
496 -- Assign tmp[len-1] or tmp[0] to res
497 let out_assign = mkUncondAssign (Left res) $ vhdlNameToVHDLExpr tmp_name
498 let block = AST.BlockSm block_label [] (AST.PMapAspect []) [tmp_dec] [AST.CSGSm gen_sm, out_assign]
499 return [AST.CSBSm block]
501 -- An id for the counter
502 n_id = mkVHDLBasicId "n"
503 n_cur = idToVHDLExpr n_id
504 -- An expression for previous n
505 n_prev = n_cur AST.:-: (AST.PrimLit "1")
506 -- An id for the tmp result vector
507 tmp_id = mkVHDLBasicId "tmp"
508 tmp_name = AST.NSimple tmp_id
509 -- Generate parts of the fold
510 genFirstCell, genOtherCell :: VHDLSession AST.GenerateSm
512 let cond_label = mkVHDLExtId "firstcell"
513 -- if n == 0 or n == len-1
514 let cond_scheme = AST.IfGn $ n_cur AST.:=: (AST.PrimLit "0")
515 -- Output to tmp[current n]
516 let resname = mkIndexedName tmp_name n_cur
518 argexpr <- MonadState.lift vsType $ varToVHDLExpr start
519 let startassign = mkUncondAssign (Right resname) argexpr
520 app_concsms <- genApplication (Right resname) app_f [Right argexpr]
521 -- Return the conditional generate part
522 return $ AST.GenerateSm cond_label cond_scheme [] (if iter then
529 let cond_label = mkVHDLExtId "othercell"
530 -- if n > 0 or n < len-1
531 let cond_scheme = AST.IfGn $ n_cur AST.:/=: (AST.PrimLit "0")
532 -- Output to tmp[current n]
533 let resname = mkIndexedName tmp_name n_cur
534 -- Input from tmp[previous n]
535 let argexpr = vhdlNameToVHDLExpr $ mkIndexedName tmp_name n_prev
536 app_concsms <- genApplication (Right resname) app_f [Right argexpr]
537 -- Return the conditional generate part
538 return $ AST.GenerateSm cond_label cond_scheme [] app_concsms
541 -----------------------------------------------------------------------------
542 -- Function to generate VHDL for applications
543 -----------------------------------------------------------------------------
545 (Either CoreSyn.CoreBndr AST.VHDLName) -- ^ Where to store the result?
546 -> CoreSyn.CoreBndr -- ^ The function to apply
547 -> [Either CoreSyn.CoreExpr AST.Expr] -- ^ The arguments to apply
548 -> VHDLSession [AST.ConcSm] -- ^ The resulting concurrent statements
549 genApplication dst f args = do
550 case Var.isGlobalId f of
552 signatures <- getA vsSignatures
553 -- This is a local id, so it should be a function whose definition we
554 -- have and which can be turned into a component instantiation.
555 case (Map.lookup f signatures) of
557 args' <- eitherCoreOrExprArgs args
558 -- We have a signature, this is a top level binding. Generate a
559 -- component instantiation.
560 let entity_id = ent_id signature
561 -- TODO: Using show here isn't really pretty, but we'll need some
562 -- unique-ish value...
563 let label = "comp_ins_" ++ (either show prettyShow) dst
564 let portmaps = mkAssocElems args' ((either varToVHDLName id) dst) signature
565 return [mkComponentInst label entity_id portmaps]
567 -- No signature, so this must be a local variable reference. It
568 -- should have a representable type (and thus, no arguments) and a
569 -- signal should be generated for it. Just generate an
570 -- unconditional assignment here.
571 f' <- MonadState.lift vsType $ varToVHDLExpr f
572 return $ [mkUncondAssign dst f']
574 case Var.idDetails f of
575 IdInfo.DataConWorkId dc -> case dst of
576 -- It's a datacon. Create a record from its arguments.
578 -- We have the bndr, so we can get at the type
579 labels <- MonadState.lift vsType $ getFieldLabels (Var.varType bndr)
580 args' <- eitherCoreOrExprArgs args
581 return $ zipWith mkassign labels $ args'
583 mkassign :: AST.VHDLId -> AST.Expr -> AST.ConcSm
585 let sel_name = mkSelectedName ((either varToVHDLName id) dst) label in
586 mkUncondAssign (Right sel_name) arg
587 Right _ -> error $ "\nGenerate.genApplication: Can't generate dataconstructor application without an original binder"
588 IdInfo.DataConWrapId dc -> case dst of
589 -- It's a datacon. Create a record from its arguments.
591 case (Map.lookup (varToString f) globalNameTable) of
592 Just (arg_count, builder) ->
593 if length args == arg_count then
596 error $ "\nGenerate.genApplication(DataConWrapId): Incorrect number of arguments to builtin function: " ++ pprString f ++ " Args: " ++ show args
597 Nothing -> error $ "\nGenerate.genApplication: Can't generate dataconwrapper: " ++ (show dc)
598 Right _ -> error $ "\nGenerate.genApplication: Can't generate dataconwrapper application without an original binder"
599 IdInfo.VanillaId -> do
600 -- It's a global value imported from elsewhere. These can be builtin
601 -- functions. Look up the function name in the name table and execute
602 -- the associated builder if there is any and the argument count matches
603 -- (this should always be the case if it typechecks, but just to be
605 case (Map.lookup (varToString f) globalNameTable) of
606 Just (arg_count, builder) ->
607 if length args == arg_count then
610 error $ "\nGenerate.genApplication(VanillaGlobal): Incorrect number of arguments to builtin function: " ++ pprString f ++ " Args: " ++ show args
611 Nothing -> error $ ("\nGenerate.genApplication(VanillaGlobal): Using function from another module that is not a known builtin: " ++ (pprString f))
612 IdInfo.ClassOpId cls -> do
613 -- FIXME: Not looking for what instance this class op is called for
614 -- Is quite stupid of course.
615 case (Map.lookup (varToString f) globalNameTable) of
616 Just (arg_count, builder) ->
617 if length args == arg_count then
620 error $ "\nGenerate.genApplication(ClassOpId): Incorrect number of arguments to builtin function: " ++ pprString f ++ " Args: " ++ show args
621 Nothing -> error $ "\nGenerate.genApplication(ClassOpId): Using function from another module that is not a known builtin: " ++ pprString f
622 details -> error $ "\nGenerate.genApplication: Calling unsupported function " ++ pprString f ++ " with GlobalIdDetails " ++ pprString details
624 -----------------------------------------------------------------------------
625 -- Functions to generate functions dealing with vectors.
626 -----------------------------------------------------------------------------
628 -- Returns the VHDLId of the vector function with the given name for the given
629 -- element type. Generates -- this function if needed.
630 vectorFunId :: Type.Type -> String -> TypeSession AST.VHDLId
631 vectorFunId el_ty fname = do
632 let error_msg = "\nGenerate.vectorFunId: Can not construct vector function for element: " ++ pprString el_ty
633 elemTM <- vhdl_ty error_msg el_ty
634 -- TODO: This should not be duplicated from mk_vector_ty. Probably but it in
635 -- the VHDLState or something.
636 let vectorTM = mkVHDLExtId $ "vector_" ++ (AST.fromVHDLId elemTM)
637 typefuns <- getA vsTypeFuns
638 case Map.lookup (OrdType el_ty, fname) typefuns of
639 -- Function already generated, just return it
640 Just (id, _) -> return id
641 -- Function not generated yet, generate it
643 let functions = genUnconsVectorFuns elemTM vectorTM
644 case lookup fname functions of
646 modA vsTypeFuns $ Map.insert (OrdType el_ty, fname) (function_id, (fst body))
647 mapM_ (vectorFunId el_ty) (snd body)
649 Nothing -> error $ "\nGenerate.vectorFunId: I don't know how to generate vector function " ++ fname
651 function_id = mkVHDLExtId fname
653 genUnconsVectorFuns :: AST.TypeMark -- ^ type of the vector elements
654 -> AST.TypeMark -- ^ type of the vector
655 -> [(String, (AST.SubProgBody, [String]))]
656 genUnconsVectorFuns elemTM vectorTM =
657 [ (exId, (AST.SubProgBody exSpec [] [exExpr],[]))
658 , (replaceId, (AST.SubProgBody replaceSpec [AST.SPVD replaceVar] [replaceExpr,replaceRet],[]))
659 , (lastId, (AST.SubProgBody lastSpec [] [lastExpr],[]))
660 , (initId, (AST.SubProgBody initSpec [AST.SPVD initVar] [initExpr, initRet],[]))
661 , (takeId, (AST.SubProgBody takeSpec [AST.SPVD takeVar] [takeExpr, takeRet],[]))
662 , (dropId, (AST.SubProgBody dropSpec [AST.SPVD dropVar] [dropExpr, dropRet],[]))
663 , (plusgtId, (AST.SubProgBody plusgtSpec [AST.SPVD plusgtVar] [plusgtExpr, plusgtRet],[]))
664 , (emptyId, (AST.SubProgBody emptySpec [AST.SPCD emptyVar] [emptyExpr],[]))
665 , (singletonId, (AST.SubProgBody singletonSpec [AST.SPVD singletonVar] [singletonRet],[]))
666 , (copynId, (AST.SubProgBody copynSpec [AST.SPVD copynVar] [copynExpr],[]))
667 , (selId, (AST.SubProgBody selSpec [AST.SPVD selVar] [selFor, selRet],[]))
668 , (ltplusId, (AST.SubProgBody ltplusSpec [AST.SPVD ltplusVar] [ltplusExpr, ltplusRet],[]))
669 , (plusplusId, (AST.SubProgBody plusplusSpec [AST.SPVD plusplusVar] [plusplusExpr, plusplusRet],[]))
670 , (lengthTId, (AST.SubProgBody lengthTSpec [] [lengthTExpr],[]))
671 , (shiftlId, (AST.SubProgBody shiftlSpec [AST.SPVD shiftlVar] [shiftlExpr, shiftlRet], [initId]))
672 , (shiftrId, (AST.SubProgBody shiftrSpec [AST.SPVD shiftrVar] [shiftrExpr, shiftrRet], [tailId]))
673 , (nullId, (AST.SubProgBody nullSpec [] [nullExpr], []))
674 , (rotlId, (AST.SubProgBody rotlSpec [AST.SPVD rotlVar] [rotlExpr, rotlRet], [nullId, lastId, initId]))
675 , (rotrId, (AST.SubProgBody rotrSpec [AST.SPVD rotrVar] [rotrExpr, rotrRet], [nullId, tailId, headId]))
676 , (reverseId, (AST.SubProgBody reverseSpec [AST.SPVD reverseVar] [reverseFor, reverseRet], []))
679 ixPar = AST.unsafeVHDLBasicId "ix"
680 vecPar = AST.unsafeVHDLBasicId "vec"
681 vec1Par = AST.unsafeVHDLBasicId "vec1"
682 vec2Par = AST.unsafeVHDLBasicId "vec2"
683 nPar = AST.unsafeVHDLBasicId "n"
684 iId = AST.unsafeVHDLBasicId "i"
686 aPar = AST.unsafeVHDLBasicId "a"
687 fPar = AST.unsafeVHDLBasicId "f"
688 sPar = AST.unsafeVHDLBasicId "s"
689 resId = AST.unsafeVHDLBasicId "res"
690 exSpec = AST.Function (mkVHDLExtId exId) [AST.IfaceVarDec vecPar vectorTM,
691 AST.IfaceVarDec ixPar naturalTM] elemTM
692 exExpr = AST.ReturnSm (Just $ AST.PrimName $ AST.NIndexed
693 (AST.IndexedName (AST.NSimple vecPar) [AST.PrimName $
695 replaceSpec = AST.Function (mkVHDLExtId replaceId) [ AST.IfaceVarDec vecPar vectorTM
696 , AST.IfaceVarDec iPar naturalTM
697 , AST.IfaceVarDec aPar elemTM
699 -- variable res : fsvec_x (0 to vec'length-1);
702 (AST.SubtypeIn vectorTM
703 (Just $ AST.ConstraintIndex $ AST.IndexConstraint
704 [AST.ToRange (AST.PrimLit "0")
705 (AST.PrimName (AST.NAttribute $
706 AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:-:
707 (AST.PrimLit "1")) ]))
709 -- res AST.:= vec(0 to i-1) & a & vec(i+1 to length'vec-1)
710 replaceExpr = AST.NSimple resId AST.:=
711 (vecSlice (AST.PrimLit "0") (AST.PrimName (AST.NSimple iPar) AST.:-: AST.PrimLit "1") AST.:&:
712 AST.PrimName (AST.NSimple aPar) AST.:&:
713 vecSlice (AST.PrimName (AST.NSimple iPar) AST.:+: AST.PrimLit "1")
714 ((AST.PrimName (AST.NAttribute $
715 AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing))
716 AST.:-: AST.PrimLit "1"))
717 replaceRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
718 vecSlice init last = AST.PrimName (AST.NSlice
721 (AST.ToRange init last)))
722 lastSpec = AST.Function (mkVHDLExtId lastId) [AST.IfaceVarDec vecPar vectorTM] elemTM
723 -- return vec(vec'length-1);
724 lastExpr = AST.ReturnSm (Just $ (AST.PrimName $ AST.NIndexed (AST.IndexedName
726 [AST.PrimName (AST.NAttribute $
727 AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing)
728 AST.:-: AST.PrimLit "1"])))
729 initSpec = AST.Function (mkVHDLExtId initId) [AST.IfaceVarDec vecPar vectorTM] vectorTM
730 -- variable res : fsvec_x (0 to vec'length-2);
733 (AST.SubtypeIn vectorTM
734 (Just $ AST.ConstraintIndex $ AST.IndexConstraint
735 [AST.ToRange (AST.PrimLit "0")
736 (AST.PrimName (AST.NAttribute $
737 AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:-:
738 (AST.PrimLit "2")) ]))
740 -- resAST.:= vec(0 to vec'length-2)
741 initExpr = AST.NSimple resId AST.:= (vecSlice
743 (AST.PrimName (AST.NAttribute $
744 AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing)
745 AST.:-: AST.PrimLit "2"))
746 initRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
747 takeSpec = AST.Function (mkVHDLExtId takeId) [AST.IfaceVarDec nPar naturalTM,
748 AST.IfaceVarDec vecPar vectorTM ] vectorTM
749 -- variable res : fsvec_x (0 to n-1);
752 (AST.SubtypeIn vectorTM
753 (Just $ AST.ConstraintIndex $ AST.IndexConstraint
754 [AST.ToRange (AST.PrimLit "0")
755 ((AST.PrimName (AST.NSimple nPar)) AST.:-:
756 (AST.PrimLit "1")) ]))
758 -- res AST.:= vec(0 to n-1)
759 takeExpr = AST.NSimple resId AST.:=
760 (vecSlice (AST.PrimLit "1")
761 (AST.PrimName (AST.NSimple $ nPar) AST.:-: AST.PrimLit "1"))
762 takeRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
763 dropSpec = AST.Function (mkVHDLExtId dropId) [AST.IfaceVarDec nPar naturalTM,
764 AST.IfaceVarDec vecPar vectorTM ] vectorTM
765 -- variable res : fsvec_x (0 to vec'length-n-1);
768 (AST.SubtypeIn vectorTM
769 (Just $ AST.ConstraintIndex $ AST.IndexConstraint
770 [AST.ToRange (AST.PrimLit "0")
771 (AST.PrimName (AST.NAttribute $
772 AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:-:
773 (AST.PrimName $ AST.NSimple nPar)AST.:-: (AST.PrimLit "1")) ]))
775 -- res AST.:= vec(n to vec'length-1)
776 dropExpr = AST.NSimple resId AST.:= (vecSlice
777 (AST.PrimName $ AST.NSimple nPar)
778 (AST.PrimName (AST.NAttribute $
779 AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing)
780 AST.:-: AST.PrimLit "1"))
781 dropRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
782 plusgtSpec = AST.Function (mkVHDLExtId plusgtId) [AST.IfaceVarDec aPar elemTM,
783 AST.IfaceVarDec vecPar vectorTM] vectorTM
784 -- variable res : fsvec_x (0 to vec'length);
787 (AST.SubtypeIn vectorTM
788 (Just $ AST.ConstraintIndex $ AST.IndexConstraint
789 [AST.ToRange (AST.PrimLit "0")
790 (AST.PrimName (AST.NAttribute $
791 AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing))]))
793 plusgtExpr = AST.NSimple resId AST.:=
794 ((AST.PrimName $ AST.NSimple aPar) AST.:&:
795 (AST.PrimName $ AST.NSimple vecPar))
796 plusgtRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
797 emptySpec = AST.Function (mkVHDLExtId emptyId) [] vectorTM
800 (AST.SubtypeIn vectorTM Nothing)
801 (Just $ AST.PrimLit "\"\"")
802 emptyExpr = AST.ReturnSm (Just $ AST.PrimName (AST.NSimple resId))
803 singletonSpec = AST.Function (mkVHDLExtId singletonId) [AST.IfaceVarDec aPar elemTM ]
805 -- variable res : fsvec_x (0 to 0) := (others => a);
808 (AST.SubtypeIn vectorTM
809 (Just $ AST.ConstraintIndex $ AST.IndexConstraint
810 [AST.ToRange (AST.PrimLit "0") (AST.PrimLit "0")]))
811 (Just $ AST.Aggregate [AST.ElemAssoc (Just AST.Others)
812 (AST.PrimName $ AST.NSimple aPar)])
813 singletonRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
814 copynSpec = AST.Function (mkVHDLExtId copynId) [AST.IfaceVarDec nPar naturalTM,
815 AST.IfaceVarDec aPar elemTM ] vectorTM
816 -- variable res : fsvec_x (0 to n-1) := (others => a);
819 (AST.SubtypeIn vectorTM
820 (Just $ AST.ConstraintIndex $ AST.IndexConstraint
821 [AST.ToRange (AST.PrimLit "0")
822 ((AST.PrimName (AST.NSimple nPar)) AST.:-:
823 (AST.PrimLit "1")) ]))
824 (Just $ AST.Aggregate [AST.ElemAssoc (Just AST.Others)
825 (AST.PrimName $ AST.NSimple aPar)])
827 copynExpr = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
828 selSpec = AST.Function (mkVHDLExtId selId) [AST.IfaceVarDec fPar naturalTM,
829 AST.IfaceVarDec sPar naturalTM,
830 AST.IfaceVarDec nPar naturalTM,
831 AST.IfaceVarDec vecPar vectorTM ] vectorTM
832 -- variable res : fsvec_x (0 to n-1);
835 (AST.SubtypeIn vectorTM
836 (Just $ AST.ConstraintIndex $ AST.IndexConstraint
837 [AST.ToRange (AST.PrimLit "0")
838 ((AST.PrimName (AST.NSimple nPar)) AST.:-:
839 (AST.PrimLit "1")) ])
842 -- for i res'range loop
843 -- res(i) := vec(f+i*s);
845 selFor = AST.ForSM iId (AST.AttribRange $ AST.AttribName (AST.NSimple resId) (AST.NSimple $ rangeId) Nothing) [selAssign]
846 -- res(i) := vec(f+i*s);
847 selAssign = let origExp = AST.PrimName (AST.NSimple fPar) AST.:+:
848 (AST.PrimName (AST.NSimple iId) AST.:*:
849 AST.PrimName (AST.NSimple sPar)) in
850 AST.NIndexed (AST.IndexedName (AST.NSimple resId) [AST.PrimName (AST.NSimple iId)]) AST.:=
851 (AST.PrimName $ AST.NIndexed (AST.IndexedName (AST.NSimple vecPar) [origExp]))
853 selRet = AST.ReturnSm (Just $ AST.PrimName (AST.NSimple resId))
854 ltplusSpec = AST.Function (mkVHDLExtId ltplusId) [AST.IfaceVarDec vecPar vectorTM,
855 AST.IfaceVarDec aPar elemTM] vectorTM
856 -- variable res : fsvec_x (0 to vec'length);
859 (AST.SubtypeIn vectorTM
860 (Just $ AST.ConstraintIndex $ AST.IndexConstraint
861 [AST.ToRange (AST.PrimLit "0")
862 (AST.PrimName (AST.NAttribute $
863 AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing))]))
865 ltplusExpr = AST.NSimple resId AST.:=
866 ((AST.PrimName $ AST.NSimple vecPar) AST.:&:
867 (AST.PrimName $ AST.NSimple aPar))
868 ltplusRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
869 plusplusSpec = AST.Function (mkVHDLExtId plusplusId) [AST.IfaceVarDec vec1Par vectorTM,
870 AST.IfaceVarDec vec2Par vectorTM]
872 -- variable res : fsvec_x (0 to vec1'length + vec2'length -1);
875 (AST.SubtypeIn vectorTM
876 (Just $ AST.ConstraintIndex $ AST.IndexConstraint
877 [AST.ToRange (AST.PrimLit "0")
878 (AST.PrimName (AST.NAttribute $
879 AST.AttribName (AST.NSimple vec1Par) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:+:
880 AST.PrimName (AST.NAttribute $
881 AST.AttribName (AST.NSimple vec2Par) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:-:
884 plusplusExpr = AST.NSimple resId AST.:=
885 ((AST.PrimName $ AST.NSimple vec1Par) AST.:&:
886 (AST.PrimName $ AST.NSimple vec2Par))
887 plusplusRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
888 lengthTSpec = AST.Function (mkVHDLExtId lengthTId) [AST.IfaceVarDec vecPar vectorTM] naturalTM
889 lengthTExpr = AST.ReturnSm (Just $ AST.PrimName (AST.NAttribute $
890 AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing))
891 shiftlSpec = AST.Function (mkVHDLExtId shiftlId) [AST.IfaceVarDec vecPar vectorTM,
892 AST.IfaceVarDec aPar elemTM ] vectorTM
893 -- variable res : fsvec_x (0 to vec'length-1);
896 (AST.SubtypeIn vectorTM
897 (Just $ AST.ConstraintIndex $ AST.IndexConstraint
898 [AST.ToRange (AST.PrimLit "0")
899 (AST.PrimName (AST.NAttribute $
900 AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:-:
901 (AST.PrimLit "1")) ]))
903 -- res := a & init(vec)
904 shiftlExpr = AST.NSimple resId AST.:=
905 (AST.PrimName (AST.NSimple aPar) AST.:&:
906 (AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLExtId initId))
907 [Nothing AST.:=>: AST.ADExpr (AST.PrimName $ AST.NSimple vecPar)]))
908 shiftlRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
909 shiftrSpec = AST.Function (mkVHDLExtId shiftrId) [AST.IfaceVarDec vecPar vectorTM,
910 AST.IfaceVarDec aPar elemTM ] vectorTM
911 -- variable res : fsvec_x (0 to vec'length-1);
914 (AST.SubtypeIn vectorTM
915 (Just $ AST.ConstraintIndex $ AST.IndexConstraint
916 [AST.ToRange (AST.PrimLit "0")
917 (AST.PrimName (AST.NAttribute $
918 AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:-:
919 (AST.PrimLit "1")) ]))
921 -- res := tail(vec) & a
922 shiftrExpr = AST.NSimple resId AST.:=
923 ((AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLExtId tailId))
924 [Nothing AST.:=>: AST.ADExpr (AST.PrimName $ AST.NSimple vecPar)]) AST.:&:
925 (AST.PrimName (AST.NSimple aPar)))
927 shiftrRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
928 nullSpec = AST.Function (mkVHDLExtId nullId) [AST.IfaceVarDec vecPar vectorTM] booleanTM
929 -- return vec'length = 0
930 nullExpr = AST.ReturnSm (Just $
931 AST.PrimName (AST.NAttribute $
932 AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:=:
934 rotlSpec = AST.Function (mkVHDLExtId rotlId) [AST.IfaceVarDec vecPar vectorTM] vectorTM
935 -- variable res : fsvec_x (0 to vec'length-1);
938 (AST.SubtypeIn vectorTM
939 (Just $ AST.ConstraintIndex $ AST.IndexConstraint
940 [AST.ToRange (AST.PrimLit "0")
941 (AST.PrimName (AST.NAttribute $
942 AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:-:
943 (AST.PrimLit "1")) ]))
945 -- if null(vec) then res := vec else res := last(vec) & init(vec)
946 rotlExpr = AST.IfSm (AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLExtId nullId))
947 [Nothing AST.:=>: AST.ADExpr (AST.PrimName $ AST.NSimple vecPar)])
948 [AST.NSimple resId AST.:= (AST.PrimName $ AST.NSimple vecPar)]
950 (Just $ AST.Else [rotlExprRet])
952 AST.NSimple resId AST.:=
953 ((AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLExtId lastId))
954 [Nothing AST.:=>: AST.ADExpr (AST.PrimName $ AST.NSimple vecPar)]) AST.:&:
955 (AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLExtId initId))
956 [Nothing AST.:=>: AST.ADExpr (AST.PrimName $ AST.NSimple vecPar)]))
957 rotlRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
958 rotrSpec = AST.Function (mkVHDLExtId rotrId) [AST.IfaceVarDec vecPar vectorTM] vectorTM
959 -- variable res : fsvec_x (0 to vec'length-1);
962 (AST.SubtypeIn vectorTM
963 (Just $ AST.ConstraintIndex $ AST.IndexConstraint
964 [AST.ToRange (AST.PrimLit "0")
965 (AST.PrimName (AST.NAttribute $
966 AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:-:
967 (AST.PrimLit "1")) ]))
969 -- if null(vec) then res := vec else res := tail(vec) & head(vec)
970 rotrExpr = AST.IfSm (AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLExtId nullId))
971 [Nothing AST.:=>: AST.ADExpr (AST.PrimName $ AST.NSimple vecPar)])
972 [AST.NSimple resId AST.:= (AST.PrimName $ AST.NSimple vecPar)]
974 (Just $ AST.Else [rotrExprRet])
976 AST.NSimple resId AST.:=
977 ((AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLExtId tailId))
978 [Nothing AST.:=>: AST.ADExpr (AST.PrimName $ AST.NSimple vecPar)]) AST.:&:
979 (AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLExtId headId))
980 [Nothing AST.:=>: AST.ADExpr (AST.PrimName $ AST.NSimple vecPar)]))
981 rotrRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
982 reverseSpec = AST.Function (mkVHDLExtId reverseId) [AST.IfaceVarDec vecPar vectorTM] vectorTM
985 (AST.SubtypeIn vectorTM
986 (Just $ AST.ConstraintIndex $ AST.IndexConstraint
987 [AST.ToRange (AST.PrimLit "0")
988 (AST.PrimName (AST.NAttribute $
989 AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:-:
990 (AST.PrimLit "1")) ]))
992 -- for i in 0 to res'range loop
993 -- res(vec'length-i-1) := vec(i);
996 AST.ForSM iId (AST.AttribRange $ AST.AttribName (AST.NSimple resId) (AST.NSimple $ rangeId) Nothing) [reverseAssign]
997 -- res(vec'length-i-1) := vec(i);
998 reverseAssign = AST.NIndexed (AST.IndexedName (AST.NSimple resId) [destExp]) AST.:=
999 (AST.PrimName $ AST.NIndexed (AST.IndexedName (AST.NSimple vecPar)
1000 [AST.PrimName $ AST.NSimple iId]))
1001 where destExp = AST.PrimName (AST.NAttribute $ AST.AttribName (AST.NSimple vecPar)
1002 (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:-:
1003 AST.PrimName (AST.NSimple iId) AST.:-:
1006 reverseRet = AST.ReturnSm (Just $ AST.PrimName (AST.NSimple resId))
1009 -----------------------------------------------------------------------------
1010 -- A table of builtin functions
1011 -----------------------------------------------------------------------------
1013 -- | The builtin functions we support. Maps a name to an argument count and a
1014 -- builder function.
1015 globalNameTable :: NameTable
1016 globalNameTable = Map.fromList
1017 [ (exId , (2, genFCall False ) )
1018 , (replaceId , (3, genFCall False ) )
1019 , (headId , (1, genFCall True ) )
1020 , (lastId , (1, genFCall True ) )
1021 , (tailId , (1, genFCall False ) )
1022 , (initId , (1, genFCall False ) )
1023 , (takeId , (2, genFCall False ) )
1024 , (dropId , (2, genFCall False ) )
1025 , (selId , (4, genFCall False ) )
1026 , (plusgtId , (2, genFCall False ) )
1027 , (ltplusId , (2, genFCall False ) )
1028 , (plusplusId , (2, genFCall False ) )
1029 , (mapId , (2, genMap ) )
1030 , (zipWithId , (3, genZipWith ) )
1031 , (foldlId , (3, genFoldl ) )
1032 , (foldrId , (3, genFoldr ) )
1033 , (zipId , (2, genZip ) )
1034 , (unzipId , (1, genUnzip ) )
1035 , (shiftlId , (2, genFCall False ) )
1036 , (shiftrId , (2, genFCall False ) )
1037 , (rotlId , (1, genFCall False ) )
1038 , (rotrId , (1, genFCall False ) )
1039 , (concatId , (1, genConcat ) )
1040 , (reverseId , (1, genFCall False ) )
1041 , (iteratenId , (3, genIteraten ) )
1042 , (iterateId , (2, genIterate ) )
1043 , (generatenId , (3, genGeneraten ) )
1044 , (generateId , (2, genGenerate ) )
1045 , (emptyId , (0, genFCall False ) )
1046 , (singletonId , (1, genFCall False ) )
1047 , (copynId , (2, genFCall False ) )
1048 , (copyId , (1, genCopy ) )
1049 , (lengthTId , (1, genFCall False ) )
1050 , (nullId , (1, genFCall False ) )
1051 , (hwxorId , (2, genOperator2 AST.Xor ) )
1052 , (hwandId , (2, genOperator2 AST.And ) )
1053 , (hworId , (2, genOperator2 AST.Or ) )
1054 , (hwnotId , (1, genOperator1 AST.Not ) )
1055 , (plusId , (2, genOperator2 (AST.:+:) ) )
1056 , (timesId , (2, genOperator2 (AST.:*:) ) )
1057 , (negateId , (1, genNegation ) )
1058 , (minusId , (2, genOperator2 (AST.:-:) ) )
1059 , (fromSizedWordId , (1, genFromSizedWord ) )
1060 , (fromIntegerId , (1, genFromInteger ) )
1061 , (resizeId , (1, genResize ) )
1062 , (sizedIntId , (1, genSizedInt ) )
1063 , (tfvecId , (1, genTFVec ) )