4 import qualified Control.Monad as Monad
5 import qualified Data.Map as Map
10 import qualified ForSyDe.Backend.VHDL.AST as AST
23 -- | Generate a binary operator application. The first argument should be a
24 -- constructor from the AST.Expr type, e.g. AST.And.
25 genExprOp2 :: (AST.Expr -> AST.Expr -> AST.Expr) -> CoreSyn.CoreBndr -> [AST.Expr] -> VHDLSession AST.Expr
26 genExprOp2 op res [arg1, arg2] = return $ op arg1 arg2
28 -- | Generate a unary operator application
29 genExprOp1 :: (AST.Expr -> AST.Expr) -> CoreSyn.CoreBndr -> [AST.Expr] -> VHDLSession AST.Expr
30 genExprOp1 op res [arg] = return $ op arg
32 -- | Generate a function call from the destination binder, function name and a
33 -- list of expressions (its arguments)
34 genExprFCall :: String -> CoreSyn.CoreBndr -> [AST.Expr] -> VHDLSession AST.Expr
35 genExprFCall fname res args = do
36 let el_ty = (tfvec_elem . Var.varType) res
37 id <- vectorFunId el_ty fname
38 return $ AST.PrimFCall $ AST.FCall (AST.NSimple id) $
39 map (\exp -> Nothing AST.:=>: AST.ADExpr exp) args
41 -- | Generate a generate statement for the builtin function "map"
43 Entity -- | The entity to map
44 -> [CoreSyn.CoreBndr] -- | The vectors
45 -> VHDLSession AST.ConcSm -- | The resulting generate statement
46 genMapCall entity [arg, res] = return $ genSm
48 -- Setup the generate scheme
49 len = (tfvec_len . Var.varType) res
50 label = mkVHDLExtId ("mapVector" ++ (varToString res))
51 nPar = AST.unsafeVHDLBasicId "n"
52 range = AST.ToRange (AST.PrimLit "0") (AST.PrimLit $ show (len-1))
53 genScheme = AST.ForGn nPar range
54 -- Get the entity name and port names
55 entity_id = ent_id entity
56 argports = map (Monad.liftM fst) (ent_args entity)
57 resport = (Monad.liftM fst) (ent_res entity)
59 inport = mkAssocElemIndexed (argports!!0) (varToVHDLId arg) nPar
60 outport = mkAssocElemIndexed resport (varToVHDLId res) nPar
61 portassigns = Maybe.catMaybes [inport,outport]
62 -- Generate the portmap
63 mapLabel = "map" ++ (AST.fromVHDLId entity_id)
64 compins = mkComponentInst mapLabel entity_id portassigns
65 -- Return the generate functions
66 genSm = AST.CSGSm $ AST.GenerateSm label genScheme [] [compins]
71 -> VHDLSession AST.ConcSm
72 genZipWithCall entity [arg1, arg2, res] = return $ genSm
74 -- Setup the generate scheme
75 len = (tfvec_len . Var.varType) res
76 label = mkVHDLExtId ("zipWithVector" ++ (varToString res))
77 nPar = AST.unsafeVHDLBasicId "n"
78 range = AST.ToRange (AST.PrimLit "0") (AST.PrimLit $ show (len-1))
79 genScheme = AST.ForGn nPar range
80 -- Get the entity name and port names
81 entity_id = ent_id entity
82 argports = map (Monad.liftM fst) (ent_args entity)
83 resport = (Monad.liftM fst) (ent_res entity)
85 inport1 = mkAssocElemIndexed (argports!!0) (varToVHDLId arg1) nPar
86 inport2 = mkAssocElemIndexed (argports!!1) (varToVHDLId arg2) nPar
87 outport = mkAssocElemIndexed resport (varToVHDLId res) nPar
88 portassigns = Maybe.catMaybes [inport1,inport2,outport]
89 -- Generate the portmap
90 mapLabel = "zipWith" ++ (AST.fromVHDLId entity_id)
91 compins = mkComponentInst mapLabel entity_id portassigns
92 -- Return the generate functions
93 genSm = AST.CSGSm $ AST.GenerateSm label genScheme [] [compins]
98 -> VHDLSession AST.ConcSm
99 genFoldlCall entity [startVal, inVec, resVal] = do
100 let (vec, _) = splitAppTy (Var.varType inVec)
101 let vecty = Type.mkAppTy vec (Var.varType startVal)
102 vecType <- vhdl_ty vecty
103 -- Setup the generate scheme
104 let len = (tfvec_len . Var.varType) inVec
105 let genlabel = mkVHDLExtId ("foldlVector" ++ (varToString inVec))
106 let blockLabel = mkVHDLExtId ("foldlVector" ++ (varToString startVal))
107 let range = AST.ToRange (AST.PrimLit "0") (AST.PrimLit $ show (len-1))
108 let genScheme = AST.ForGn (AST.unsafeVHDLBasicId "n") range
109 -- Make the intermediate vector
110 let tmpVec = AST.BDISD $ AST.SigDec (mkVHDLExtId "tmp") vecType Nothing
111 -- Get the entity name and port names
112 let entity_id = ent_id entity
113 let argports = map (Monad.liftM fst) (ent_args entity)
114 let resport = (Monad.liftM fst) (ent_res entity)
115 -- Return the generate functions
116 let genSm = AST.GenerateSm genlabel genScheme []
117 [ AST.CSGSm (genFirstCell (entity_id, argports, resport)
118 [startVal, inVec, resVal])
119 , AST.CSGSm (genOtherCell (entity_id, argports, resport)
120 [startVal, inVec, resVal])
121 , AST.CSGSm (genLastCell (entity_id, argports, resport)
122 [startVal, inVec, resVal])
124 return $ AST.CSBSm $ AST.BlockSm blockLabel [] (AST.PMapAspect []) [tmpVec] [AST.CSGSm genSm]
126 genFirstCell (entity_id, argports, resport) [startVal, inVec, resVal] = cellGn
128 cellLabel = mkVHDLExtId "firstcell"
129 cellGenScheme = AST.IfGn ((AST.PrimName $ AST.NSimple nPar) AST.:=: (AST.PrimLit "0"))
130 tmpId = mkVHDLExtId "tmp"
131 nPar = AST.unsafeVHDLBasicId "n"
133 inport1 = mkAssocElem (argports!!0) (varToString startVal)
134 inport2 = mkAssocElemIndexed (argports!!1) (varToVHDLId inVec) nPar
135 outport = mkAssocElemIndexed resport tmpId nPar
136 portassigns = Maybe.catMaybes [inport1,inport2,outport]
137 -- Generate the portmap
138 mapLabel = "cell" ++ (AST.fromVHDLId entity_id)
139 compins = mkComponentInst mapLabel entity_id portassigns
140 -- Return the generate functions
141 cellGn = AST.GenerateSm cellLabel cellGenScheme [] [compins]
142 genOtherCell (entity_id, argports, resport) [startVal, inVec, resVal] = cellGn
144 len = (tfvec_len . Var.varType) inVec
145 cellLabel = mkVHDLExtId "othercell"
146 cellGenScheme = AST.IfGn $ AST.And ((AST.PrimName $ AST.NSimple nPar) AST.:>: (AST.PrimLit "0"))
147 ((AST.PrimName $ AST.NSimple nPar) AST.:<: (AST.PrimLit $ show (len-1)))
148 tmpId = mkVHDLExtId "tmp"
149 nPar = AST.unsafeVHDLBasicId "n"
151 inport1 = mkAssocElemIndexed (argports!!0) tmpId (AST.unsafeVHDLBasicId "n-1")
152 inport2 = mkAssocElemIndexed (argports!!1) (varToVHDLId inVec) nPar
153 outport = mkAssocElemIndexed resport tmpId nPar
154 portassigns = Maybe.catMaybes [inport1,inport2,outport]
155 -- Generate the portmap
156 mapLabel = "cell" ++ (AST.fromVHDLId entity_id)
157 compins = mkComponentInst mapLabel entity_id portassigns
158 -- Return the generate functions
159 cellGn = AST.GenerateSm cellLabel cellGenScheme [] [compins]
160 genLastCell (entity_id, argports, resport) [startVal, inVec, resVal] = cellGn
162 len = (tfvec_len . Var.varType) inVec
163 cellLabel = mkVHDLExtId "lastCell"
164 cellGenScheme = AST.IfGn ((AST.PrimName $ AST.NSimple nPar) AST.:=: (AST.PrimLit $ show (len-1)))
165 tmpId = mkVHDLExtId "tmp"
166 nPar = AST.unsafeVHDLBasicId "n"
168 inport1 = mkAssocElemIndexed (argports!!0) tmpId (AST.unsafeVHDLBasicId "n-1")
169 inport2 = mkAssocElemIndexed (argports!!1) (varToVHDLId inVec) nPar
170 outport = mkAssocElemIndexed resport tmpId nPar
171 portassigns = Maybe.catMaybes [inport1,inport2,outport]
172 -- Generate the portmap
173 mapLabel = "cell" ++ (AST.fromVHDLId entity_id)
174 compins = mkComponentInst mapLabel entity_id portassigns
175 -- Generate the output assignment
176 assign = mkUncondAssign (Left resVal) (AST.PrimName (AST.NIndexed (AST.IndexedName
177 (AST.NSimple tmpId) [AST.PrimLit $ show (len-1)])))
178 -- Return the generate functions
179 cellGn = AST.GenerateSm cellLabel cellGenScheme [] [compins,assign]
182 -- Returns the VHDLId of the vector function with the given name for the given
183 -- element type. Generates -- this function if needed.
184 vectorFunId :: Type.Type -> String -> VHDLSession AST.VHDLId
185 vectorFunId el_ty fname = do
186 elemTM <- vhdl_ty el_ty
187 -- TODO: This should not be duplicated from mk_vector_ty. Probably but it in
188 -- the VHDLState or something.
189 let vectorTM = mkVHDLExtId $ "vector_" ++ (AST.fromVHDLId elemTM)
190 typefuns <- getA vsTypeFuns
191 case Map.lookup (OrdType el_ty, fname) typefuns of
192 -- Function already generated, just return it
193 Just (id, _) -> return id
194 -- Function not generated yet, generate it
196 let functions = genUnconsVectorFuns elemTM vectorTM
197 case lookup fname functions of
199 modA vsTypeFuns $ Map.insert (OrdType el_ty, fname) (function_id, body)
201 Nothing -> error $ "I don't know how to generate vector function " ++ fname
203 function_id = mkVHDLExtId fname
205 genUnconsVectorFuns :: AST.TypeMark -- ^ type of the vector elements
206 -> AST.TypeMark -- ^ type of the vector
207 -> [(String, AST.SubProgBody)]
208 genUnconsVectorFuns elemTM vectorTM =
209 [ (exId, AST.SubProgBody exSpec [] [exExpr])
210 , (replaceId, AST.SubProgBody replaceSpec [AST.SPVD replaceVar] [replaceExpr,replaceRet])
211 , (headId, AST.SubProgBody headSpec [] [headExpr])
212 , (lastId, AST.SubProgBody lastSpec [] [lastExpr])
213 , (initId, AST.SubProgBody initSpec [AST.SPVD initVar] [initExpr, initRet])
214 , (tailId, AST.SubProgBody tailSpec [AST.SPVD tailVar] [tailExpr, tailRet])
215 , (takeId, AST.SubProgBody takeSpec [AST.SPVD takeVar] [takeExpr, takeRet])
216 , (dropId, AST.SubProgBody dropSpec [AST.SPVD dropVar] [dropExpr, dropRet])
217 , (plusgtId, AST.SubProgBody plusgtSpec [AST.SPVD plusgtVar] [plusgtExpr, plusgtRet])
218 , (emptyId, AST.SubProgBody emptySpec [AST.SPCD emptyVar] [emptyExpr])
219 , (singletonId, AST.SubProgBody singletonSpec [AST.SPVD singletonVar] [singletonRet])
220 , (copyId, AST.SubProgBody copySpec [AST.SPVD copyVar] [copyExpr])
223 ixPar = AST.unsafeVHDLBasicId "ix"
224 vecPar = AST.unsafeVHDLBasicId "vec"
225 nPar = AST.unsafeVHDLBasicId "n"
226 iId = AST.unsafeVHDLBasicId "i"
228 aPar = AST.unsafeVHDLBasicId "a"
229 resId = AST.unsafeVHDLBasicId "res"
230 exSpec = AST.Function (mkVHDLExtId exId) [AST.IfaceVarDec vecPar vectorTM,
231 AST.IfaceVarDec ixPar naturalTM] elemTM
232 exExpr = AST.ReturnSm (Just $ AST.PrimName $ AST.NIndexed
233 (AST.IndexedName (AST.NSimple vecPar) [AST.PrimName $
235 replaceSpec = AST.Function (mkVHDLExtId replaceId) [ AST.IfaceVarDec vecPar vectorTM
236 , AST.IfaceVarDec iPar naturalTM
237 , AST.IfaceVarDec aPar elemTM
239 -- variable res : fsvec_x (0 to vec'length-1);
242 (AST.SubtypeIn vectorTM
243 (Just $ AST.ConstraintIndex $ AST.IndexConstraint
244 [AST.ToRange (AST.PrimLit "0")
245 (AST.PrimName (AST.NAttribute $
246 AST.AttribName (AST.NSimple vecPar) (mkVHDLBasicId lengthId) Nothing) AST.:-:
247 (AST.PrimLit "1")) ]))
249 -- res AST.:= vec(0 to i-1) & a & vec(i+1 to length'vec-1)
250 replaceExpr = AST.NSimple resId AST.:=
251 (vecSlice (AST.PrimLit "0") (AST.PrimName (AST.NSimple iPar) AST.:-: AST.PrimLit "1") AST.:&:
252 AST.PrimName (AST.NSimple aPar) AST.:&:
253 vecSlice (AST.PrimName (AST.NSimple iPar) AST.:+: AST.PrimLit "1")
254 ((AST.PrimName (AST.NAttribute $
255 AST.AttribName (AST.NSimple vecPar) (mkVHDLBasicId lengthId) Nothing))
256 AST.:-: AST.PrimLit "1"))
257 replaceRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
258 vecSlice init last = AST.PrimName (AST.NSlice
261 (AST.ToRange init last)))
262 headSpec = AST.Function (mkVHDLExtId headId) [AST.IfaceVarDec vecPar vectorTM] elemTM
264 headExpr = AST.ReturnSm (Just $ (AST.PrimName $ AST.NIndexed (AST.IndexedName
265 (AST.NSimple vecPar) [AST.PrimLit "0"])))
266 lastSpec = AST.Function (mkVHDLExtId lastId) [AST.IfaceVarDec vecPar vectorTM] elemTM
267 -- return vec(vec'length-1);
268 lastExpr = AST.ReturnSm (Just $ (AST.PrimName $ AST.NIndexed (AST.IndexedName
270 [AST.PrimName (AST.NAttribute $
271 AST.AttribName (AST.NSimple vecPar) (mkVHDLBasicId lengthId) Nothing)
272 AST.:-: AST.PrimLit "1"])))
273 initSpec = AST.Function (mkVHDLExtId initId) [AST.IfaceVarDec vecPar vectorTM] vectorTM
274 -- variable res : fsvec_x (0 to vec'length-2);
277 (AST.SubtypeIn vectorTM
278 (Just $ AST.ConstraintIndex $ AST.IndexConstraint
279 [AST.ToRange (AST.PrimLit "0")
280 (AST.PrimName (AST.NAttribute $
281 AST.AttribName (AST.NSimple vecPar) (mkVHDLBasicId lengthId) Nothing) AST.:-:
282 (AST.PrimLit "2")) ]))
284 -- resAST.:= vec(0 to vec'length-2)
285 initExpr = AST.NSimple resId AST.:= (vecSlice
287 (AST.PrimName (AST.NAttribute $
288 AST.AttribName (AST.NSimple vecPar) (mkVHDLBasicId lengthId) Nothing)
289 AST.:-: AST.PrimLit "2"))
290 initRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
291 tailSpec = AST.Function (mkVHDLExtId tailId) [AST.IfaceVarDec vecPar vectorTM] vectorTM
292 -- variable res : fsvec_x (0 to vec'length-2);
295 (AST.SubtypeIn vectorTM
296 (Just $ AST.ConstraintIndex $ AST.IndexConstraint
297 [AST.ToRange (AST.PrimLit "0")
298 (AST.PrimName (AST.NAttribute $
299 AST.AttribName (AST.NSimple vecPar) (mkVHDLBasicId lengthId) Nothing) AST.:-:
300 (AST.PrimLit "2")) ]))
302 -- res AST.:= vec(1 to vec'length-1)
303 tailExpr = AST.NSimple resId AST.:= (vecSlice
305 (AST.PrimName (AST.NAttribute $
306 AST.AttribName (AST.NSimple vecPar) (mkVHDLBasicId lengthId) Nothing)
307 AST.:-: AST.PrimLit "1"))
308 tailRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
309 takeSpec = AST.Function (mkVHDLExtId takeId) [AST.IfaceVarDec nPar naturalTM,
310 AST.IfaceVarDec vecPar vectorTM ] vectorTM
311 -- variable res : fsvec_x (0 to n-1);
314 (AST.SubtypeIn vectorTM
315 (Just $ AST.ConstraintIndex $ AST.IndexConstraint
316 [AST.ToRange (AST.PrimLit "0")
317 ((AST.PrimName (AST.NSimple nPar)) AST.:-:
318 (AST.PrimLit "1")) ]))
320 -- res AST.:= vec(0 to n-1)
321 takeExpr = AST.NSimple resId AST.:=
322 (vecSlice (AST.PrimLit "1")
323 (AST.PrimName (AST.NSimple $ nPar) AST.:-: AST.PrimLit "1"))
324 takeRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
325 dropSpec = AST.Function (mkVHDLExtId dropId) [AST.IfaceVarDec nPar naturalTM,
326 AST.IfaceVarDec vecPar vectorTM ] vectorTM
327 -- variable res : fsvec_x (0 to vec'length-n-1);
330 (AST.SubtypeIn vectorTM
331 (Just $ AST.ConstraintIndex $ AST.IndexConstraint
332 [AST.ToRange (AST.PrimLit "0")
333 (AST.PrimName (AST.NAttribute $
334 AST.AttribName (AST.NSimple vecPar) (mkVHDLBasicId lengthId) Nothing) AST.:-:
335 (AST.PrimName $ AST.NSimple nPar)AST.:-: (AST.PrimLit "1")) ]))
337 -- res AST.:= vec(n to vec'length-1)
338 dropExpr = AST.NSimple resId AST.:= (vecSlice
339 (AST.PrimName $ AST.NSimple nPar)
340 (AST.PrimName (AST.NAttribute $
341 AST.AttribName (AST.NSimple vecPar) (mkVHDLBasicId lengthId) Nothing)
342 AST.:-: AST.PrimLit "1"))
343 dropRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
344 plusgtSpec = AST.Function (mkVHDLExtId plusgtId) [AST.IfaceVarDec aPar elemTM,
345 AST.IfaceVarDec vecPar vectorTM] vectorTM
346 -- variable res : fsvec_x (0 to vec'length);
349 (AST.SubtypeIn vectorTM
350 (Just $ AST.ConstraintIndex $ AST.IndexConstraint
351 [AST.ToRange (AST.PrimLit "0")
352 (AST.PrimName (AST.NAttribute $
353 AST.AttribName (AST.NSimple vecPar) (mkVHDLBasicId lengthId) Nothing))]))
355 plusgtExpr = AST.NSimple resId AST.:=
356 ((AST.PrimName $ AST.NSimple aPar) AST.:&:
357 (AST.PrimName $ AST.NSimple vecPar))
358 plusgtRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
359 emptySpec = AST.Function (mkVHDLExtId emptyId) [] vectorTM
362 (AST.SubtypeIn vectorTM Nothing)
363 (Just $ AST.PrimLit "\"\"")
364 emptyExpr = AST.ReturnSm (Just $ AST.PrimName (AST.NSimple resId))
365 singletonSpec = AST.Function (mkVHDLExtId singletonId) [AST.IfaceVarDec aPar elemTM ]
367 -- variable res : fsvec_x (0 to 0) := (others => a);
370 (AST.SubtypeIn vectorTM
371 (Just $ AST.ConstraintIndex $ AST.IndexConstraint
372 [AST.ToRange (AST.PrimLit "0") (AST.PrimLit "0")]))
373 (Just $ AST.Aggregate [AST.ElemAssoc (Just AST.Others)
374 (AST.PrimName $ AST.NSimple aPar)])
375 singletonRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
376 copySpec = AST.Function (mkVHDLExtId copyId) [AST.IfaceVarDec nPar naturalTM,
377 AST.IfaceVarDec aPar elemTM ] vectorTM
378 -- variable res : fsvec_x (0 to n-1) := (others => a);
381 (AST.SubtypeIn vectorTM
382 (Just $ AST.ConstraintIndex $ AST.IndexConstraint
383 [AST.ToRange (AST.PrimLit "0")
384 ((AST.PrimName (AST.NSimple nPar)) AST.:-:
385 (AST.PrimLit "1")) ]))
386 (Just $ AST.Aggregate [AST.ElemAssoc (Just AST.Others)
387 (AST.PrimName $ AST.NSimple aPar)])
389 copyExpr = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)