Merge git://github.com/darchon/clash into cλash
authorMatthijs Kooijman <m.kooijman@student.utwente.nl>
Thu, 25 Jun 2009 14:58:57 +0000 (16:58 +0200)
committerMatthijs Kooijman <m.kooijman@student.utwente.nl>
Thu, 25 Jun 2009 14:58:57 +0000 (16:58 +0200)
Disabled foldr generation again, it should either be updated to the
shorter form from my last commits, but preferably foldl should be
abstracted to handle both.

* git://github.com/darchon/clash:
  Added builtin function foldr
  Foldl correctly handles empty vectors

Conflicts:
Generate.hs
GlobalNameTable.hs

Generate.hs
GlobalNameTable.hs [deleted file]
HighOrdAlu.hs
VHDL.hs
VHDLTools.hs
VHDLTypes.hs

index fe581727b212c12f2884ffa39012ac864ce9fb59..b1aa491ccd1975e238bcde2022ad6a2eeaad7fb5 100644 (file)
@@ -4,6 +4,7 @@ module Generate where
 import qualified Control.Monad as Monad
 import qualified Data.Map as Map
 import qualified Maybe
+import qualified Data.Either as Either
 import Data.Accessor
 import Debug.Trace
 
@@ -14,6 +15,7 @@ import qualified ForSyDe.Backend.VHDL.AST as AST
 import CoreSyn
 import Type
 import qualified Var
+import qualified IdInfo
 
 -- Local imports
 import Constants
@@ -22,191 +24,185 @@ import VHDLTools
 import CoreTools
 import Pretty
 
+-----------------------------------------------------------------------------
+-- Functions to generate VHDL for builtin functions
+-----------------------------------------------------------------------------
+
 -- | A function to wrap a builder-like function that expects its arguments to
 -- be expressions.
 genExprArgs ::
   (dst -> func -> [AST.Expr] -> res)
-  -> (dst -> func -> [CoreSyn.CoreExpr] -> res)
+  -> (dst -> func -> [Either CoreSyn.CoreExpr AST.Expr] -> res)
 genExprArgs wrap dst func args = wrap dst func args'
-  where args' = map (varToVHDLExpr.exprToVar) args
+  where args' = map (either (varToVHDLExpr.exprToVar) id) args
   
 -- | A function to wrap a builder-like function that expects its arguments to
 -- be variables.
 genVarArgs ::
   (dst -> func -> [Var.Var] -> res)
-  -> (dst -> func -> [CoreSyn.CoreExpr] -> res)
+  -> (dst -> func -> [Either CoreSyn.CoreExpr AST.Expr] -> res)
 genVarArgs wrap dst func args = wrap dst func args'
-  where args' = map exprToVar args
+  where
+    args' = map exprToVar exprargs
+    -- Check (rather crudely) that all arguments are CoreExprs
+    (exprargs, []) = Either.partitionEithers args
 
 -- | A function to wrap a builder-like function that produces an expression
 -- and expects it to be assigned to the destination.
 genExprRes ::
-  (CoreSyn.CoreBndr -> func -> [arg] -> VHDLSession AST.Expr)
-  -> (CoreSyn.CoreBndr -> func -> [arg] -> VHDLSession [AST.ConcSm])
+  ((Either CoreSyn.CoreBndr AST.VHDLName) -> func -> [arg] -> VHDLSession AST.Expr)
+  -> ((Either CoreSyn.CoreBndr AST.VHDLName) -> func -> [arg] -> VHDLSession [AST.ConcSm])
 genExprRes wrap dst func args = do
   expr <- wrap dst func args
-  return $ [mkUncondAssign (Left dst) expr]
+  return $ [mkUncondAssign dst expr]
 
 -- | Generate a binary operator application. The first argument should be a
 -- constructor from the AST.Expr type, e.g. AST.And.
 genOperator2 :: (AST.Expr -> AST.Expr -> AST.Expr) -> BuiltinBuilder 
 genOperator2 op = genExprArgs $ genExprRes (genOperator2' op)
-genOperator2' :: (AST.Expr -> AST.Expr -> AST.Expr) -> CoreSyn.CoreBndr -> CoreSyn.CoreBndr -> [AST.Expr] -> VHDLSession AST.Expr
-genOperator2' op res f [arg1, arg2] = return $ op arg1 arg2
+genOperator2' :: (AST.Expr -> AST.Expr -> AST.Expr) -> dst -> CoreSyn.CoreBndr -> [AST.Expr] -> VHDLSession AST.Expr
+genOperator2' op _ f [arg1, arg2] = return $ op arg1 arg2
 
 -- | Generate a unary operator application
 genOperator1 :: (AST.Expr -> AST.Expr) -> BuiltinBuilder 
 genOperator1 op = genExprArgs $ genExprRes (genOperator1' op)
-genOperator1' :: (AST.Expr -> AST.Expr) -> CoreSyn.CoreBndr -> CoreSyn.CoreBndr -> [AST.Expr] -> VHDLSession AST.Expr
-genOperator1' op res f [arg] = return $ op arg
+genOperator1' :: (AST.Expr -> AST.Expr) -> dst -> CoreSyn.CoreBndr -> [AST.Expr] -> VHDLSession AST.Expr
+genOperator1' op _ f [arg] = return $ op arg
 
 -- | Generate a function call from the destination binder, function name and a
 -- list of expressions (its arguments)
 genFCall :: BuiltinBuilder 
 genFCall = genExprArgs $ genExprRes genFCall'
-genFCall' :: CoreSyn.CoreBndr -> CoreSyn.CoreBndr -> [AST.Expr] -> VHDLSession AST.Expr
-genFCall' res f args = do
+genFCall' :: Either CoreSyn.CoreBndr AST.VHDLName -> CoreSyn.CoreBndr -> [AST.Expr] -> VHDLSession AST.Expr
+genFCall' (Left res) f args = do
   let fname = varToString f
   let el_ty = (tfvec_elem . Var.varType) res
   id <- vectorFunId el_ty fname
   return $ AST.PrimFCall $ AST.FCall (AST.NSimple id)  $
              map (\exp -> Nothing AST.:=>: AST.ADExpr exp) args
+genFCall' (Right name) _ _ = error $ "Cannot generate builtin function call assigned to a VHDLName: " ++ show name
 
 -- | Generate a generate statement for the builtin function "map"
 genMap :: BuiltinBuilder
 genMap = genVarArgs genMap'
-genMap' res f [mapped_f, arg] = do
-  signatures <- getA vsSignatures
-  let entity = Maybe.fromMaybe
-        (error $ "Using function '" ++ (varToString mapped_f) ++ "' without signature? This should not happen!") 
-        (Map.lookup mapped_f signatures)
+genMap' :: (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> VHDLSession [AST.ConcSm]
+genMap' (Left res) f [mapped_f, arg] =
   let
     -- Setup the generate scheme
     len         = (tfvec_len . Var.varType) res
+    -- TODO: Use something better than varToString
     label       = mkVHDLExtId ("mapVector" ++ (varToString res))
-    nPar        = AST.unsafeVHDLBasicId "n"
+    n_id        = mkVHDLBasicId "n"
+    n_expr      = idToVHDLExpr n_id
     range       = AST.ToRange (AST.PrimLit "0") (AST.PrimLit $ show (len-1))
-    genScheme   = AST.ForGn nPar range
-    -- Get the entity name and port names
-    entity_id   = ent_id entity
-    argports   = map (Monad.liftM fst) (ent_args entity)
-    resport     = (Monad.liftM fst) (ent_res entity)
-    -- Assign the ports
-    inport      = mkAssocElemIndexed (argports!!0) (varToVHDLId arg) nPar
-    outport     = mkAssocElemIndexed resport (varToVHDLId res) nPar
-    portassigns = Maybe.catMaybes [inport,outport]
-    -- Generate the portmap
-    mapLabel    = "map" ++ (AST.fromVHDLId entity_id)
-    compins     = mkComponentInst mapLabel entity_id portassigns
-    -- Return the generate functions
-    genSm       = AST.CSGSm $ AST.GenerateSm label genScheme [] [compins]
-    in
-      return $ [genSm]
+    genScheme   = AST.ForGn n_id range
+
+    -- Create the content of the generate statement: Applying the mapped_f to
+    -- each of the elements in arg, storing to each element in res
+    resname     = mkIndexedName (varToVHDLName res) n_expr
+    argexpr     = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName arg) n_expr
+  in do
+    app_concsms <- genApplication (Right resname) mapped_f [Right argexpr]
+    -- Return the generate statement
+    return [AST.CSGSm $ AST.GenerateSm label genScheme [] app_concsms]
+
+genMap' (Right name) _ _ = error $ "Cannot generate map function call assigned to a VHDLName: " ++ show name
     
 genZipWith :: BuiltinBuilder
 genZipWith = genVarArgs genZipWith'
-genZipWith' res f args@[zipped_f, arg1, arg2] = do
-  signatures <- getA vsSignatures
-  let entity = Maybe.fromMaybe
-        (error $ "Using function '" ++ (varToString zipped_f) ++ "' without signature? This should not happen!") 
-        (Map.lookup zipped_f signatures)
+genZipWith' :: (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> VHDLSession [AST.ConcSm]
+genZipWith' (Left res) f args@[zipped_f, arg1, arg2] =
   let
     -- Setup the generate scheme
     len         = (tfvec_len . Var.varType) res
+    -- TODO: Use something better than varToString
     label       = mkVHDLExtId ("zipWithVector" ++ (varToString res))
-    nPar        = AST.unsafeVHDLBasicId "n"
+    n_id        = mkVHDLBasicId "n"
+    n_expr      = idToVHDLExpr n_id
     range       = AST.ToRange (AST.PrimLit "0") (AST.PrimLit $ show (len-1))
-    genScheme   = AST.ForGn nPar range
-    -- Get the entity name and port names
-    entity_id   = ent_id entity
-    argports    = map (Monad.liftM fst) (ent_args entity)
-    resport     = (Monad.liftM fst) (ent_res entity)
-    -- Assign the ports
-    inport1     = mkAssocElemIndexed (argports!!0) (varToVHDLId arg1) nPar
-    inport2     = mkAssocElemIndexed (argports!!1) (varToVHDLId arg2) nPar 
-    outport     = mkAssocElemIndexed resport (varToVHDLId res) nPar
-    portassigns = Maybe.catMaybes [inport1,inport2,outport]
-    -- Generate the portmap
-    mapLabel    = "zipWith" ++ (AST.fromVHDLId entity_id)
-    compins     = mkComponentInst mapLabel entity_id portassigns
+    genScheme   = AST.ForGn n_id range
+
+    -- Create the content of the generate statement: Applying the zipped_f to
+    -- each of the elements in arg1 and arg2, storing to each element in res
+    resname     = mkIndexedName (varToVHDLName res) n_expr
+    argexpr1    = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName arg1) n_expr
+    argexpr2    = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName arg2) n_expr
+  in do
+    app_concsms <- genApplication (Right resname) zipped_f [Right argexpr1, Right argexpr2]
     -- Return the generate functions
-    genSm       = AST.CSGSm $ AST.GenerateSm label genScheme [] [compins]
-    in
-      return $ [genSm]
+    return [AST.CSGSm $ AST.GenerateSm label genScheme [] app_concsms]
 
 genFoldl :: BuiltinBuilder
 genFoldl = genVarArgs genFoldl'
-genFoldl' resVal f [folded_f, startVal, inVec] = do
-  signatures <- getA vsSignatures
-  let entity = Maybe.fromMaybe
-        (error $ "Using function '" ++ (varToString folded_f) ++ "' without signature? This should not happen!") 
-        (Map.lookup folded_f signatures)
-  let (vec, _) = splitAppTy (Var.varType inVec)
-  let vecty = Type.mkAppTy vec (Var.varType startVal)
-  vecType <- vhdl_ty vecty
+genFoldl' :: (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> VHDLSession [AST.ConcSm]
+-- Special case for an empty input vector, just assign start to res
+genFoldl' (Left res) _ [_, start, vec] | len == 0 = return [mkUncondAssign (Left res) (varToVHDLExpr start)]
+    where len = (tfvec_len . Var.varType) vec
+genFoldl' (Left res) f [folded_f, start, vec] = do
+  -- evec is (TFVec n), so it still needs an element type
+  let (nvec, _) = splitAppTy (Var.varType vec)
+  -- Put the type of the start value in nvec, this will be the type of our
+  -- temporary vector
+  let tmp_ty = Type.mkAppTy nvec (Var.varType start)
+  tmp_vhdl_ty <- vhdl_ty tmp_ty
   -- 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 gen_label = mkVHDLExtId ("foldlVector" ++ (varToString vec))
+  let block_label = mkVHDLExtId ("foldlVector" ++ (varToString start))
+  let gen_range = AST.ToRange (AST.PrimLit "0") len_min_expr
+  let gen_scheme   = AST.ForGn n_id gen_range
   -- Make the intermediate vector
-  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.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])
-                      ]
-  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))]
+  let  tmp_dec     = AST.BDISD $ AST.SigDec tmp_id tmp_vhdl_ty Nothing
+  -- Create the generate statement
+  cells <- sequence [genFirstCell, genOtherCell]
+  let gen_sm = AST.GenerateSm gen_label gen_scheme [] (map AST.CSGSm cells)
+  -- Assign tmp[len-1] to res
+  let out_assign = mkUncondAssign (Left res) $ vhdlNameToVHDLExpr (mkIndexedName tmp_name (AST.PrimLit $ show (len-1)))
+  let block = AST.BlockSm block_label [] (AST.PMapAspect []) [tmp_dec] [AST.CSGSm gen_sm, out_assign]
+  return [AST.CSBSm block]
   where
-    genFirstCell (entity_id, argports, resport) [startVal, inVec, resVal] = cellGn
-      where
-        cellLabel   = mkVHDLExtId "firstcell"
-        cellGenScheme = AST.IfGn ((AST.PrimName $ AST.NSimple nPar)  AST.:=: (AST.PrimLit "0"))
-        tmpId       = mkVHDLExtId "tmp"
-        nPar        = AST.unsafeVHDLBasicId "n"
-        -- Assign the ports
-        inport1     = mkAssocElem (argports!!0) (varToString startVal)
-        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
-        -- Return the generate functions
-        cellGn       = AST.GenerateSm cellLabel cellGenScheme [] [compins]
-    genOtherCell (entity_id, argports, resport) [startVal, inVec, resVal] = cellGn
-      where
-        len         = (tfvec_len . Var.varType) inVec
-        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
-        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
-        -- Return the generate functions
-        cellGn      = AST.GenerateSm cellLabel cellGenScheme [] [compins]
+    -- The vector length
+    len         = (tfvec_len . Var.varType) vec
+    -- An id for the counter
+    n_id = mkVHDLBasicId "n"
+    n_expr = idToVHDLExpr n_id
+    -- An expression for n-1
+    n_min_expr = n_expr AST.:-: (AST.PrimLit "1")
+    -- An expression for len-1
+    len_min_expr = (AST.PrimLit $ show (len-1))
+    -- An id for the tmp result vector
+    tmp_id = mkVHDLBasicId "tmp"
+    tmp_name = AST.NSimple tmp_id
+    -- Generate parts of the fold
+    genFirstCell, genOtherCell :: VHDLSession AST.GenerateSm
+    genFirstCell = do
+      let cond_label = mkVHDLExtId "firstcell"
+      -- if n == 0
+      let cond_scheme = AST.IfGn $ n_expr AST.:=: (AST.PrimLit "0")
+      -- Output to tmp[n]
+      let resname = mkIndexedName tmp_name n_expr
+      -- Input from start
+      let argexpr1 = varToVHDLExpr start
+      -- Input from vec[n]
+      let argexpr2 = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName vec) n_expr
+      app_concsms <- genApplication (Right resname) folded_f [Right argexpr1, Right argexpr2]
+      -- Return the conditional generate part
+      return $ AST.GenerateSm cond_label cond_scheme [] app_concsms
+
+    genOtherCell = do
+      let cond_label = mkVHDLExtId "othercell"
+      -- if n > 0
+      let cond_scheme = AST.IfGn $ n_expr AST.:>: (AST.PrimLit "0")
+      -- Output to tmp[n]
+      let resname = mkIndexedName tmp_name n_expr
+      -- Input from tmp[n-1]
+      let argexpr1 = vhdlNameToVHDLExpr $ mkIndexedName tmp_name n_min_expr
+      -- Input from vec[n]
+      let argexpr2 = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName vec) n_expr
+      app_concsms <- genApplication (Right resname) folded_f [Right argexpr1, Right argexpr2]
+      -- Return the conditional generate part
+      return $ AST.GenerateSm cond_label cond_scheme [] app_concsms
 
+{-
 genFoldr :: BuiltinBuilder
 genFoldr = genVarArgs genFoldr'
 genFoldr' resVal f [folded_f, startVal, inVec] = do
@@ -280,6 +276,65 @@ genFoldr' resVal f [folded_f, startVal, inVec] = do
         -- Return the generate functions
         cellGn      = AST.GenerateSm cellLabel cellGenScheme [] [compins]
 
+-}
+
+
+-----------------------------------------------------------------------------
+-- Function to generate VHDL for applications
+-----------------------------------------------------------------------------
+genApplication ::
+  (Either CoreSyn.CoreBndr AST.VHDLName) -- ^ Where to store the result?
+  -> CoreSyn.CoreBndr -- ^ The function to apply
+  -> [Either CoreSyn.CoreExpr AST.Expr] -- ^ The arguments to apply
+  -> VHDLSession [AST.ConcSm] -- ^ The resulting concurrent statements
+genApplication dst f args =
+  case Var.globalIdVarDetails f of
+    IdInfo.DataConWorkId dc -> case dst of
+      -- It's a datacon. Create a record from its arguments.
+      Left bndr -> do
+        -- We have the bndr, so we can get at the type
+        labels <- getFieldLabels (Var.varType bndr)
+        return $ zipWith mkassign labels $ map (either exprToVHDLExpr id) args
+        where
+          mkassign :: AST.VHDLId -> AST.Expr -> AST.ConcSm
+          mkassign label arg =
+            let sel_name = mkSelectedName ((either varToVHDLName id) dst) label in
+            mkUncondAssign (Right sel_name) arg
+      Right _ -> error $ "Generate.genApplication Can't generate dataconstructor application without an original binder"
+    IdInfo.VanillaGlobal -> do
+      -- It's a global value imported from elsewhere. These can be builtin
+      -- functions. Look up the function name in the name table and execute
+      -- the associated builder if there is any and the argument count matches
+      -- (this should always be the case if it typechecks, but just to be
+      -- sure...).
+      case (Map.lookup (varToString f) globalNameTable) of
+        Just (arg_count, builder) ->
+          if length args == arg_count then
+            builder dst f args
+          else
+            error $ "Generate.genApplication Incorrect number of arguments to builtin function: " ++ pprString f ++ " Args: " ++ show args
+        Nothing -> error $ "Using function from another module that is not a known builtin: " ++ pprString f
+    IdInfo.NotGlobalId -> do
+      signatures <- getA vsSignatures
+      -- This is a local id, so it should be a function whose definition we
+      -- have and which can be turned into a component instantiation.
+      let  
+        signature = Maybe.fromMaybe 
+          (error $ "Using function '" ++ (varToString f) ++ "' without signature? This should not happen!") 
+          (Map.lookup f signatures)
+        entity_id = ent_id signature
+        -- TODO: Using show here isn't really pretty, but we'll need some
+        -- unique-ish value...
+        label = "comp_ins_" ++ (either show show) dst
+        portmaps = mkAssocElems (map (either exprToVHDLExpr id) args) ((either varToVHDLName id) dst) signature
+        in
+          return [mkComponentInst label entity_id portmaps]
+    details -> error $ "Calling unsupported function " ++ pprString f ++ " with GlobalIdDetails " ++ pprString details
+
+-----------------------------------------------------------------------------
+-- Functions to generate functions dealing with vectors.
+-----------------------------------------------------------------------------
+
 -- Returns the VHDLId of the vector function with the given name for the given
 -- element type. Generates -- this function if needed.
 vectorFunId :: Type.Type -> String -> VHDLSession AST.VHDLId
@@ -488,3 +543,33 @@ genUnconsVectorFuns elemTM vectorTM  =
                                           (AST.PrimName $ AST.NSimple aPar)])
     -- return res
     copyExpr = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
+
+-----------------------------------------------------------------------------
+-- A table of builtin functions
+-----------------------------------------------------------------------------
+
+-- | The builtin functions we support. Maps a name to an argument count and a
+-- builder function.
+globalNameTable :: NameTable
+globalNameTable = Map.fromList
+  [ (exId             , (2, genFCall                ) )
+  , (replaceId        , (3, genFCall                ) )
+  , (headId           , (1, genFCall                ) )
+  , (lastId           , (1, genFCall                ) )
+  , (tailId           , (1, genFCall                ) )
+  , (initId           , (1, genFCall                ) )
+  , (takeId           , (2, genFCall                ) )
+  , (dropId           , (2, genFCall                ) )
+  , (plusgtId         , (2, genFCall                ) )
+  , (mapId            , (2, genMap                  ) )
+  , (zipWithId        , (3, genZipWith              ) )
+  , (foldlId          , (3, genFoldl                ) )
+  --, (foldrId          , (3, genFoldr                ) )
+  , (emptyId          , (0, genFCall                ) )
+  , (singletonId      , (1, genFCall                ) )
+  , (copyId           , (2, genFCall                ) )
+  , (hwxorId          , (2, genOperator2 AST.Xor    ) )
+  , (hwandId          , (2, genOperator2 AST.And    ) )
+  , (hworId           , (2, genOperator2 AST.Or     ) )
+  , (hwnotId          , (1, genOperator1 AST.Not    ) )
+  ]
diff --git a/GlobalNameTable.hs b/GlobalNameTable.hs
deleted file mode 100644 (file)
index dd38a12..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-{-# LANGUAGE TemplateHaskell #-}
-
-module GlobalNameTable (globalNameTable) where
-
-import Language.Haskell.TH
-import qualified Data.Map as Map
-
-import qualified ForSyDe.Backend.VHDL.AST as AST
-import qualified Data.Param.TFVec as V
-
-import VHDLTypes
-import Constants
-import Generate
-
-mkGlobalNameTable :: [(String, (Int, BuiltinBuilder) )] -> NameTable
-mkGlobalNameTable = Map.fromList
-
-globalNameTable :: NameTable
-globalNameTable = mkGlobalNameTable
-  [ (exId             , (2, genFCall                ) )
-  , (replaceId        , (3, genFCall                ) )
-  , (headId           , (1, genFCall                ) )
-  , (lastId           , (1, genFCall                ) )
-  , (tailId           , (1, genFCall                ) )
-  , (initId           , (1, genFCall                ) )
-  , (takeId           , (2, genFCall                ) )
-  , (dropId           , (2, genFCall                ) )
-  , (plusgtId         , (2, genFCall                ) )
-  , (mapId            , (2, genMap                  ) )
-  , (zipWithId        , (3, genZipWith              ) )
-  , (foldlId          , (3, genFoldl                ) )
-  , (foldrId          , (3, genFoldr                ) )
-  , (emptyId          , (0, genFCall                ) )
-  , (singletonId      , (1, genFCall                ) )
-  , (copyId           , (2, genFCall                ) )
-  , (hwxorId          , (2, genOperator2 AST.Xor    ) )
-  , (hwandId          , (2, genOperator2 AST.And    ) )
-  , (hworId           , (2, genOperator2 AST.Or     ) )
-  , (hwnotId          , (1, genOperator1 AST.Not    ) )
-  ]
index 6458f3c968958b8f265057b1fe173c534cdbe3cb..331fa1debd0b4f20a071b126398ee498b552967d 100644 (file)
@@ -12,15 +12,21 @@ constant :: e -> Op D4 e
 constant e a b =
   e +> (e +> (e +> (singleton e )))
 
-inv = hwnot
-
 invop :: Op n Bit
-invop a b = map inv a
+invop a b = map hwnot a
 
-xand = hwand
 
 andop :: Op n Bit
-andop a b = zipWith xand a b
+andop a b = zipWith hwand a b
+
+-- Is any bit set?
+--anyset :: (PositiveT n) => Op n Bit
+anyset :: Op D4 Bit
+--anyset a b = copy undefined (a' `hwor` b')
+anyset a b = constant (a' `hwor` b') a b
+  where 
+    a' = foldl hwor Low a
+    b' = foldl hwor Low b
 
 type Op n e = (TFVec n e -> TFVec n e -> TFVec n e)
 type Opcode = Bit
@@ -32,4 +38,5 @@ alu op1 op2 opc a b =
     High -> op2 a b
 
 actual_alu :: Opcode -> TFVec D4 Bit -> TFVec D4 Bit -> TFVec D4 Bit
-actual_alu = alu (constant Low) andop
+--actual_alu = alu (constant Low) andop
+actual_alu = alu anyset andop
diff --git a/VHDL.hs b/VHDL.hs
index 4b69df5106071bc28c5c22ec343784f0610509d9..b6264dcf603266807297718c8e318a8e47dee878 100644 (file)
--- a/VHDL.hs
+++ b/VHDL.hs
@@ -37,7 +37,6 @@ import Pretty
 import CoreTools
 import Constants
 import Generate
-import GlobalNameTable
 
 createDesignFiles ::
   [(CoreSyn.CoreBndr, CoreSyn.CoreExpr)]
@@ -120,7 +119,7 @@ createEntity (fname, expr) = do
     mkMap ::
       --[(SignalId, SignalInfo)] 
       CoreSyn.CoreBndr 
-      -> VHDLSession VHDLSignalMapElement
+      -> VHDLSession Port
     -- We only need the vsTypes element from the state
     mkMap = (\bndr ->
       let
@@ -130,45 +129,35 @@ createEntity (fname, expr) = do
         --  Assume the bndr has a valid VHDL id already
         id = varToVHDLId bndr
         ty = Var.varType bndr
-      in
-        if True -- isPortSigUse $ sigUse info
-          then do
-            type_mark <- vhdl_ty ty
-            return $ Just (id, type_mark)
-          else
-            return $ Nothing
-       )
+      in do
+        type_mark <- vhdl_ty ty
+        return (id, type_mark)
+     )
 
   -- | Create the VHDL AST for an entity
 createEntityAST ::
   AST.VHDLId                   -- | The name of the function
-  -> [VHDLSignalMapElement]    -- | The entity's arguments
-  -> VHDLSignalMapElement      -- | The entity's result
+  -> [Port]                    -- | The entity's arguments
+  -> Port                      -- | The entity's result
   -> AST.EntityDec             -- | The entity with the ent_decl filled in as well
 
 createEntityAST vhdl_id args res =
   AST.EntityDec vhdl_id ports
   where
     -- Create a basic Id, since VHDL doesn't grok filenames with extended Ids.
-    ports = Maybe.catMaybes $ 
-              map (mkIfaceSigDec AST.In) args
+    ports = map (mkIfaceSigDec AST.In) args
               ++ [mkIfaceSigDec AST.Out res]
               ++ [clk_port]
     -- Add a clk port if we have state
-    clk_port = if True -- hasState hsfunc
-      then
-        Just $ AST.IfaceSigDec (mkVHDLExtId "clk") AST.In std_logicTM
-      else
-        Nothing
+    clk_port = AST.IfaceSigDec (mkVHDLExtId "clk") AST.In std_logicTM
 
 -- | Create a port declaration
 mkIfaceSigDec ::
   AST.Mode                         -- | The mode for the port (In / Out)
-  -> Maybe (AST.VHDLId, AST.TypeMark)    -- | The id and type for the port
-  -> Maybe AST.IfaceSigDec               -- | The resulting port declaration
+  -> (AST.VHDLId, AST.TypeMark)    -- | The id and type for the port
+  -> AST.IfaceSigDec               -- | The resulting port declaration
 
-mkIfaceSigDec mode (Just (id, ty)) = Just $ AST.IfaceSigDec id mode ty
-mkIfaceSigDec _ Nothing = Nothing
+mkIfaceSigDec mode (id, ty) = AST.IfaceSigDec id mode ty
 
 {-
 -- | Generate a VHDL entity name for the given hsfunc
@@ -275,52 +264,7 @@ mkConcSm (bndr, app@(CoreSyn.App _ _))= do
   let (CoreSyn.Var f, args) = CoreSyn.collectArgs app
   let valargs' = filter isValArg args
   let valargs = filter (\(CoreSyn.Var bndr) -> not (Id.isDictId bndr)) valargs'
-  case Var.globalIdVarDetails f of
-    IdInfo.DataConWorkId dc ->
-        -- It's a datacon. Create a record from its arguments.
-        -- First, filter out type args. TODO: Is this the best way to do this?
-        -- The types should already have been taken into acocunt when creating
-        -- the signal, so this should probably work...
-        --let valargs = filter isValArg args in
-        if all is_var valargs then do
-          labels <- getFieldLabels (CoreUtils.exprType app)
-          return $ zipWith mkassign labels valargs
-        else
-          error $ "VHDL.mkConcSm Not in normal form: One ore more complex arguments: " ++ pprString args
-      where
-        mkassign :: AST.VHDLId -> CoreExpr -> AST.ConcSm
-        mkassign label (Var arg) =
-          let sel_name = mkSelectedName bndr label in
-          mkUncondAssign (Right sel_name) (varToVHDLExpr arg)
-    IdInfo.VanillaGlobal -> do
-      -- It's a global value imported from elsewhere. These can be builtin
-      -- functions.
-      signatures <- getA vsSignatures
-      case (Map.lookup (varToString f) globalNameTable) of
-        Just (arg_count, builder) ->
-          if length valargs == arg_count then
-            builder bndr f valargs
-          else
-            error $ "VHDL.mkConcSm Incorrect number of arguments to builtin function: " ++ pprString f ++ " Args: " ++ pprString valargs
-        Nothing -> error $ "Using function from another module that is not a known builtin: " ++ pprString f
-    IdInfo.NotGlobalId -> do
-      signatures <- getA vsSignatures
-      -- This is a local id, so it should be a function whose definition we
-      -- have and which can be turned into a component instantiation.
-      let  
-        signature = Maybe.fromMaybe 
-          (error $ "Using function '" ++ (varToString f) ++ "' without signature? This should not happen!") 
-          (Map.lookup f signatures)
-        entity_id = ent_id signature
-        label = "comp_ins_" ++ varToString bndr
-        -- Add a clk port if we have state
-        --clk_port = Maybe.fromJust $ mkAssocElem (Just $ mkVHDLExtId "clk") "clk"
-        --clk_port = Maybe.fromJust $ mkAssocElem (Just $ mkVHDLExtId "clk") "clk"
-        --portmaps = mkAssocElems sigs args res signature ++ (if hasState hsfunc then [clk_port] else [])
-        portmaps = mkAssocElems args bndr signature
-        in
-          return [mkComponentInst label entity_id portmaps]
-    details -> error $ "Calling unsupported function " ++ pprString f ++ " with GlobalIdDetails " ++ pprString details
+  genApplication (Left bndr) f (map Left valargs)
 
 -- A single alt case must be a selector. This means thee scrutinee is a simple
 -- variable, the alternative is a dataalt with a single non-wild binder that
@@ -332,7 +276,7 @@ mkConcSm (bndr, expr@(Case (Var scrut) b ty [alt])) =
         Just i -> do
           labels <- getFieldLabels (Id.idType scrut)
           let label = labels!!i
-          let sel_name = mkSelectedName scrut label
+          let sel_name = mkSelectedName (varToVHDLName scrut) label
           let sel_expr = AST.PrimName sel_name
           return [mkUncondAssign (Left bndr) sel_expr]
         Nothing -> error $ "VHDL.mkConcSM Not in normal form: Not a selector case:\n" ++ (pprString expr)
index 178c743b6f6b439f0bece10519671b3d45d9d075..12681160b25b7556acd9cc5998590816fe4aeaa7 100644 (file)
@@ -76,13 +76,13 @@ mkAssign dst cond false_expr =
     AST.CSSASm assign
 
 mkAssocElems :: 
-  [CoreSyn.CoreExpr]            -- | The argument that are applied to function
-  -> CoreSyn.CoreBndr           -- | The binder in which to store the result
+  [AST.Expr]                    -- | The argument that are applied to function
+  -> AST.VHDLName               -- | The binder in which to store the result
   -> Entity                     -- | The entity to map against.
   -> [AST.AssocElem]            -- | The resulting port maps
 mkAssocElems args res entity =
     -- Create the actual AssocElems
-    Maybe.catMaybes $ zipWith mkAssocElem ports sigs
+    zipWith mkAssocElem ports sigs
   where
     -- Turn the ports and signals from a map into a flat list. This works,
     -- since the maps must have an identical form by definition. TODO: Check
@@ -90,20 +90,18 @@ mkAssocElems args res entity =
     arg_ports = ent_args entity
     res_port  = ent_res entity
     -- Extract the id part from the (id, type) tuple
-    ports     = map (Monad.liftM fst) (res_port : arg_ports)
+    ports     = map fst (res_port : arg_ports)
     -- Translate signal numbers into names
-    sigs      = (varToString res : map (varToString.exprToVar) args)
+    sigs      = (vhdlNameToVHDLExpr res : args)
 
 -- | Create an VHDL port -> signal association
-mkAssocElem :: Maybe AST.VHDLId -> String -> Maybe AST.AssocElem
-mkAssocElem (Just port) signal = Just $ Just port AST.:=>: (AST.ADName (AST.NSimple (mkVHDLExtId signal))) 
-mkAssocElem Nothing _ = Nothing
+mkAssocElem :: AST.VHDLId -> AST.Expr -> AST.AssocElem
+mkAssocElem port signal = Just port AST.:=>: (AST.ADExpr signal) 
 
 -- | Create an VHDL port -> signal association
-mkAssocElemIndexed :: Maybe AST.VHDLId -> AST.VHDLId -> AST.VHDLId -> Maybe AST.AssocElem
-mkAssocElemIndexed (Just port) signal index = Just $ Just port AST.:=>: (AST.ADName (AST.NIndexed (AST.IndexedName 
+mkAssocElemIndexed :: AST.VHDLId -> AST.VHDLId -> AST.VHDLId -> AST.AssocElem
+mkAssocElemIndexed port signal index = Just port AST.:=>: (AST.ADName (AST.NIndexed (AST.IndexedName 
                       (AST.NSimple signal) [AST.PrimName $ AST.NSimple index])))
-mkAssocElemIndexed Nothing _ _ = Nothing
 
 mkComponentInst ::
   String -- ^ The portmap label
@@ -113,7 +111,7 @@ mkComponentInst ::
 mkComponentInst label entity_id portassigns = AST.CSISm compins
   where
     -- We always have a clock port, so no need to map it anywhere but here
-    clk_port = Maybe.fromJust $ mkAssocElem (Just $ mkVHDLExtId "clk") "clk"
+    clk_port = mkAssocElem (mkVHDLExtId "clk") (idToVHDLExpr $ mkVHDLExtId "clk")
     compins = AST.CompInsSm (mkVHDLExtId label) (AST.IUEntity (AST.NSimple entity_id)) (AST.PMapAspect (portassigns ++ [clk_port]))
 
 -----------------------------------------------------------------------------
@@ -130,6 +128,15 @@ varToVHDLExpr var =
     -- local/global here as well?
     Nothing -> AST.PrimName $ AST.NSimple $ varToVHDLId var
 
+-- Turn a VHDLName into an AST expression
+vhdlNameToVHDLExpr = AST.PrimName
+
+-- Turn a VHDL Id into an AST expression
+idToVHDLExpr = vhdlNameToVHDLExpr . AST.NSimple
+
+-- Turn a Core expression into an AST expression
+exprToVHDLExpr = varToVHDLExpr . exprToVar
+
 -- Turn a alternative constructor into an AST expression. For
 -- dataconstructors, this is only the constructor itself, not any arguments it
 -- has. Should not be called with a DEFAULT constructor.
@@ -159,7 +166,13 @@ dataconToVHDLExpr dc = AST.PrimLit lit
 varToVHDLId ::
   CoreSyn.CoreBndr
   -> AST.VHDLId
-varToVHDLId = mkVHDLExtId . OccName.occNameString . Name.nameOccName . Var.varName
+varToVHDLId = mkVHDLExtId . varToString
+
+-- Creates a VHDL Name from a binder
+varToVHDLName ::
+  CoreSyn.CoreBndr
+  -> AST.VHDLName
+varToVHDLName = AST.NSimple . varToVHDLId
 
 -- Extracts the binder name as a String
 varToString ::
@@ -209,13 +222,17 @@ mkVHDLExtId s =
 
 -- Create a record field selector that selects the given label from the record
 -- stored in the given binder.
-mkSelectedName :: CoreBndr -> AST.VHDLId -> AST.VHDLName
-mkSelectedName bndr label =
-  let 
-    sel_prefix = AST.NSimple $ varToVHDLId bndr
-    sel_suffix = AST.SSimple $ label
-  in
-    AST.NSelected $ sel_prefix AST.:.: sel_suffix 
+mkSelectedName :: AST.VHDLName -> AST.VHDLId -> AST.VHDLName
+mkSelectedName name label =
+   AST.NSelected $ name AST.:.: (AST.SSimple label) 
+
+-- Create an indexed name that selects a given element from a vector.
+mkIndexedName :: AST.VHDLName -> AST.Expr -> AST.VHDLName
+-- Special case for already indexed names. Just add an index
+mkIndexedName (AST.NIndexed (AST.IndexedName name indexes)) index =
+ AST.NIndexed (AST.IndexedName name (indexes++[index]))
+-- General case for other names
+mkIndexedName name index = AST.NIndexed (AST.IndexedName name [index])
 
 -----------------------------------------------------------------------------
 -- Functions dealing with VHDL types
index 79d7675f68a48f3663782d0d6c6465d90c0ef871..e8a77377f87d4833963b817c6812a9e4b0699fd9 100644 (file)
@@ -18,21 +18,17 @@ import qualified CoreSyn
 import qualified ForSyDe.Backend.VHDL.AST as AST
 
 -- Local imports
-import FlattenTypes
-import HsValueMap
 
-type VHDLSignalMapElement = (Maybe (AST.VHDLId, AST.TypeMark))
--- | A mapping from a haskell structure to the corresponding VHDL port
---   signature, or Nothing for values that do not translate to a port.
-type VHDLSignalMap = HsValueMap VHDLSignalMapElement
+-- A description of a port of an entity
+type Port = (AST.VHDLId, AST.TypeMark)
 
 -- A description of a VHDL entity. Contains both the entity itself as well as
 -- info on how to map a haskell value (argument / result) on to the entity's
 -- ports.
 data Entity = Entity { 
   ent_id     :: AST.VHDLId,           -- The id of the entity
-  ent_args   :: [VHDLSignalMapElement],      -- A mapping of each function argument to port names
-  ent_res    :: VHDLSignalMapElement         -- A mapping of the function result to port names
+  ent_args   :: [Port],      -- A mapping of each function argument to port names
+  ent_res    :: Port         -- A mapping of the function result to port names
 } deriving (Show);
 
 -- A orderable equivalent of CoreSyn's Type for use as a map key
@@ -78,10 +74,10 @@ type TypeState = State.State TypeMap
 
 -- A function that generates VHDL for a builtin function
 type BuiltinBuilder = 
-  CoreSyn.CoreBndr -- ^ The destination value
+  (Either CoreSyn.CoreBndr AST.VHDLName) -- ^ The destination signal and it's original type
   -> CoreSyn.CoreBndr -- ^ The function called
-  -> [CoreSyn.CoreExpr] -- ^ The value arguments passed (excluding type and
-                        --   dictionary arguments).
+  -> [Either CoreSyn.CoreExpr AST.Expr] -- ^ The value arguments passed (excluding type and
+                    --   dictionary arguments).
   -> VHDLSession [AST.ConcSm] -- ^ The resulting concurrent statements.
 
 -- A map of a builtin function to VHDL function builder