Foldl correctly handles empty vectors
authorChristiaan Baaij <christiaan.baaij@gmail.com>
Thu, 25 Jun 2009 10:21:03 +0000 (12:21 +0200)
committerChristiaan Baaij <christiaan.baaij@gmail.com>
Thu, 25 Jun 2009 10:21:03 +0000 (12:21 +0200)
Generate.hs

index 7b8dcf0894fb0ca41296f08addd659d07868b651..5aa5097deedcf0f777c8cece6a2b9961a1888935 100644 (file)
@@ -145,31 +145,36 @@ genFoldl' resVal f [folded_f, startVal, inVec] = do
   let vecty = Type.mkAppTy vec (Var.varType startVal)
   vecType <- vhdl_ty vecty
   -- Setup the generate scheme
-  let  len         = (tfvec_len . Var.varType) inVec
-  let  genlabel       = mkVHDLExtId ("foldlVector" ++ (varToString inVec))
-  let  blockLabel  = mkVHDLExtId ("foldlVector" ++ (varToString startVal))
-  let  range       = AST.ToRange (AST.PrimLit "0") (AST.PrimLit $ show (len-1))
-  let  genScheme   = AST.ForGn (AST.unsafeVHDLBasicId "n") range
+  let  len        = (tfvec_len . Var.varType) inVec
+  let  genlabel   = mkVHDLExtId ("foldlVector" ++ (varToString inVec))
+  let  blockLabel = mkVHDLExtId ("foldlVector" ++ (varToString startVal))
+  let  range      = AST.ToRange (AST.PrimLit "0") (AST.PrimLit $ show (len-1))
+  let  genScheme  = AST.ForGn (AST.unsafeVHDLBasicId "n") range
   -- Make the intermediate vector
-  let  tmpVec      = AST.BDISD $ AST.SigDec (mkVHDLExtId "tmp") vecType Nothing
+  let tmpId       = mkVHDLExtId "tmp"
+  let  tmpVec     = AST.BDISD $ AST.SigDec tmpId vecType Nothing
   -- Get the entity name and port names
   let entity_id   = ent_id entity
   let argports    = map (Monad.liftM fst) (ent_args entity)
   let resport     = (Monad.liftM fst) (ent_res entity)
+  -- Generate the output assignment
+  let assign      = [mkUncondAssign (Left resVal) (AST.PrimName (AST.NIndexed (AST.IndexedName 
+                        (AST.NSimple tmpId) [AST.PrimLit $ show (len-1)])))]
   -- Return the generate functions
-  let genSm       = AST.GenerateSm genlabel genScheme [] 
+  let genSm       = AST.CSGSm $ AST.GenerateSm genlabel genScheme [] 
                       [ AST.CSGSm (genFirstCell (entity_id, argports, resport) 
                                     [startVal, inVec, resVal])
                       , AST.CSGSm (genOtherCell (entity_id, argports, resport) 
                                     [startVal, inVec, resVal])
-                      , AST.CSGSm (genLastCell (entity_id, argports, resport) 
-                                    [startVal, inVec, resVal])
                       ]
-  return $ [AST.CSBSm $ AST.BlockSm blockLabel [] (AST.PMapAspect []) [tmpVec] [AST.CSGSm genSm]]
+  return $  if len > 0 then
+              [AST.CSBSm $ AST.BlockSm blockLabel [] (AST.PMapAspect []) [tmpVec] (genSm : assign)]
+            else
+              [mkUncondAssign (Left resVal) (AST.PrimName $ AST.NSimple (varToVHDLId startVal))]
   where
     genFirstCell (entity_id, argports, resport) [startVal, inVec, resVal] = cellGn
       where
-        cellLabel    = mkVHDLExtId "firstcell"
+        cellLabel   = mkVHDLExtId "firstcell"
         cellGenScheme = AST.IfGn ((AST.PrimName $ AST.NSimple nPar)  AST.:=: (AST.PrimLit "0"))
         tmpId       = mkVHDLExtId "tmp"
         nPar        = AST.unsafeVHDLBasicId "n"
@@ -186,9 +191,9 @@ genFoldl' resVal f [folded_f, startVal, inVec] = do
     genOtherCell (entity_id, argports, resport) [startVal, inVec, resVal] = cellGn
       where
         len         = (tfvec_len . Var.varType) inVec
-        cellLabel    = mkVHDLExtId "othercell"
-        cellGenScheme = AST.IfGn $ AST.And ((AST.PrimName $ AST.NSimple nPar)  AST.:>: (AST.PrimLit "0"))
-                                ((AST.PrimName $ AST.NSimple nPar)  AST.:<: (AST.PrimLit $ show (len-1)))
+        cellLabel   = mkVHDLExtId "othercell"
+        cellGenScheme = AST.IfGn ((AST.PrimName $ AST.NSimple nPar)  AST.:/=: (AST.PrimLit "0"))
+                                -- ((AST.PrimName $ AST.NSimple nPar)  AST.:<: (AST.PrimLit $ show (len-1)))
         tmpId       = mkVHDLExtId "tmp"
         nPar        = AST.unsafeVHDLBasicId "n"
         -- Assign the ports
@@ -201,27 +206,6 @@ genFoldl' resVal f [folded_f, startVal, inVec] = do
         compins     = mkComponentInst mapLabel entity_id portassigns
         -- Return the generate functions
         cellGn      = AST.GenerateSm cellLabel cellGenScheme [] [compins]
-    genLastCell (entity_id, argports, resport) [startVal, inVec, resVal] = cellGn
-      where
-        len         = (tfvec_len . Var.varType) inVec
-        cellLabel    = mkVHDLExtId "lastCell"
-        cellGenScheme = AST.IfGn ((AST.PrimName $ AST.NSimple nPar)  AST.:=: (AST.PrimLit $ show (len-1)))
-        tmpId       = mkVHDLExtId "tmp"
-        nPar        = AST.unsafeVHDLBasicId "n"
-        -- Assign the ports
-        inport1     = mkAssocElemIndexed (argports!!0) tmpId (AST.unsafeVHDLBasicId "n-1")
-        inport2     = mkAssocElemIndexed (argports!!1) (varToVHDLId inVec) nPar 
-        outport     = mkAssocElemIndexed resport tmpId nPar
-        portassigns = Maybe.catMaybes [inport1,inport2,outport]
-        -- Generate the portmap
-        mapLabel    = "cell" ++ (AST.fromVHDLId entity_id)
-        compins     = mkComponentInst mapLabel entity_id portassigns
-        -- Generate the output assignment
-        assign      = mkUncondAssign (Left resVal) (AST.PrimName (AST.NIndexed (AST.IndexedName 
-                              (AST.NSimple tmpId) [AST.PrimLit $ show (len-1)])))
-        -- Return the generate functions
-        cellGn      = AST.GenerateSm cellLabel cellGenScheme [] [compins,assign]
-
 
 -- Returns the VHDLId of the vector function with the given name for the given
 -- element type. Generates -- this function if needed.