Make vhdl generation and normalization lazy.
authorMatthijs Kooijman <matthijs@stdin.nl>
Wed, 5 Aug 2009 10:12:28 +0000 (12:12 +0200)
committerMatthijs Kooijman <matthijs@stdin.nl>
Wed, 5 Aug 2009 10:12:28 +0000 (12:12 +0200)
Previously, first all function would be (recursively) normalized, and then
VHDL would be generated. Now, functions are normalized when needed, and
recursion is done while generating VHDL (so we know exactly which
components we are instantiating).

This disables the testbench and TFVec constructor for now, I'll fix that
in the next commits.

This also moves some code around, to prevent loops between Generate and
VHDL (again...).

The VHDLSession and NormalizeSession have been removed, and replaced with
the (previously unused) TranslatorSession. There are a few backward
compatibility aliases in place, so the next commit will probably remove
these and do a bunch of trivial replaces all over the code.

cλash/CLasH/Normalize.hs
cλash/CLasH/Normalize/NormalizeTools.hs
cλash/CLasH/Normalize/NormalizeTypes.hs
cλash/CLasH/Translator.hs
cλash/CLasH/Translator/TranslatorTypes.hs
cλash/CLasH/Utils.hs
cλash/CLasH/Utils/Pretty.hs
cλash/CLasH/VHDL.hs
cλash/CLasH/VHDL/Generate.hs
cλash/CLasH/VHDL/VHDLTools.hs
cλash/CLasH/VHDL/VHDLTypes.hs

index 8ec195b0ef936aadd89449571988da9e3c4f56e0..7571a6f3b0fbf21b33673fe59476bd217ab336ed 100644 (file)
@@ -4,7 +4,7 @@
 -- top level function "normalize", and defines the actual transformation passes that
 -- are performed.
 --
-module CLasH.Normalize (normalizeModule) where
+module CLasH.Normalize (getNormalized) where
 
 -- Standard modules
 import Debug.Trace
@@ -34,8 +34,10 @@ import Outputable ( showSDoc, ppr, nest )
 
 -- Local imports
 import CLasH.Normalize.NormalizeTypes
+import CLasH.Translator.TranslatorTypes
 import CLasH.Normalize.NormalizeTools
 import CLasH.VHDL.VHDLTypes
+import qualified CLasH.Utils as Utils
 import CLasH.Utils.Core.CoreTools
 import CLasH.Utils.Pretty
 
@@ -472,78 +474,36 @@ funextracttop = everywhere ("funextract", funextract)
 -- What transforms to run?
 transforms = [argproptop, funextracttop, etatop, betatop, castproptop, letremovetop, letrectop, letsimpltop, letflattop, scrutsimpltop, casesimpltop, caseremovetop, inlinenonreptop, appsimpltop]
 
--- Turns the given bind into VHDL
-normalizeModule ::
-  HscTypes.HscEnv
-  -> UniqSupply.UniqSupply -- ^ A UniqSupply we can use
-  -> [(CoreBndr, CoreExpr)]  -- ^ All bindings we know (i.e., in the current module)
-  -> [CoreExpr]
-  -> [CoreBndr]  -- ^ The bindings to generate VHDL for (i.e., the top level bindings)
-  -> [Bool] -- ^ For each of the bindings to generate VHDL for, if it is stateful
-  -> ([(CoreBndr, CoreExpr)], [(CoreBndr, CoreExpr)], TypeState) -- ^ The resulting VHDL
+-- | Returns the normalized version of the given function.
+getNormalized ::
+  CoreBndr -- ^ The function to get
+  -> TranslatorSession CoreExpr -- The normalized function body
 
-normalizeModule env uniqsupply bindings testexprs generate_for statefuls = runTransformSession env uniqsupply $ do
-  testbinds <- mapM (\x -> do { v <- mkBinderFor' x "test" ; return (v,x) } ) testexprs
-  let testbinders = (map fst testbinds)
-  -- Put all the bindings in this module in the tsBindings map
-  putA tsBindings (Map.fromList (bindings ++ testbinds))
-  -- (Recursively) normalize each of the requested bindings
-  mapM normalizeBind (generate_for ++ testbinders)
-  -- Get all initial bindings and the ones we produced
-  bindings_map <- getA tsBindings
-  let bindings = Map.assocs bindings_map
-  normalized_binders' <- getA tsNormalized
-  let normalized_binders = VarSet.delVarSetList normalized_binders' testbinders
-  let ret_testbinds = zip testbinders (Maybe.catMaybes $ map (\x -> lookup x bindings) testbinders)
-  let ret_binds = filter ((`VarSet.elemVarSet` normalized_binders) . fst) bindings
-  typestate <- getA tsType
-  -- But return only the normalized bindings
-  return $ (ret_binds, ret_testbinds, typestate)
+getNormalized bndr = Utils.makeCached bndr tsNormalized $ do
+  if is_poly (Var bndr)
+    then
+      -- This should really only happen at the top level... TODO: Give
+      -- a different error if this happens down in the recursion.
+      error $ "\nNormalize.normalizeBind: Function " ++ show bndr ++ " is polymorphic, can't normalize"
+    else do
+      expr <- getBinding bndr
+      -- Introduce an empty Let at the top level, so there will always be
+      -- a let in the expression (none of the transformations will remove
+      -- the last let).
+      let expr' = Let (Rec []) expr
+      -- Normalize this expression
+      trace ("Transforming " ++ (show bndr) ++ "\nBefore:\n\n" ++ showSDoc ( ppr expr' ) ++ "\n") $ return ()
+      expr'' <- dotransforms transforms expr'
+      trace ("\nAfter:\n\n" ++ showSDoc ( ppr expr')) $ return ()
+      return expr''
 
-normalizeBind :: CoreBndr -> TransformSession ()
-normalizeBind bndr =
-  -- Don't normalize global variables, these should be either builtin
-  -- functions or data constructors.
-  Monad.when (Var.isLocalId bndr) $ do
-    -- Skip binders that have a polymorphic type, since it's impossible to
-    -- create polymorphic hardware.
-    if is_poly (Var bndr)
-      then
-        -- This should really only happen at the top level... TODO: Give
-        -- a different error if this happens down in the recursion.
-        error $ "\nNormalize.normalizeBind: Function " ++ show bndr ++ " is polymorphic, can't normalize"
-      else do
-        normalized_funcs <- getA tsNormalized
-        -- See if this function was normalized already
-        if VarSet.elemVarSet bndr normalized_funcs
-          then
-            -- Yup, don't do it again
-            return ()
-          else do
-            -- Nope, note that it has been and do it.
-            modA tsNormalized (flip VarSet.extendVarSet bndr)
-            expr_maybe <- getGlobalBind bndr
-            case expr_maybe of 
-              Just expr -> do
-                -- Introduce an empty Let at the top level, so there will always be
-                -- a let in the expression (none of the transformations will remove
-                -- the last let).
-                let expr' = Let (Rec []) expr
-                -- Normalize this expression
-                trace ("Transforming " ++ (show bndr) ++ "\nBefore:\n\n" ++ showSDoc ( ppr expr' ) ++ "\n") $ return ()
-                expr' <- dotransforms transforms expr'
-                trace ("\nAfter:\n\n" ++ showSDoc ( ppr expr')) $ return ()
-                -- And store the normalized version in the session
-                modA tsBindings (Map.insert bndr expr')
-                -- Find all vars used with a function type. All of these should be global
-                -- binders (i.e., functions used), since any local binders with a function
-                -- type should have been inlined already.
-                bndrs <- getGlobalBinders
-                let used_funcs_set = CoreFVs.exprSomeFreeVars (\v -> not (Id.isDictId v) && v `elem` bndrs) expr'
-                let used_funcs = VarSet.varSetElems used_funcs_set
-                -- Process each of the used functions recursively
-                mapM normalizeBind used_funcs
-                return ()
-              -- We don't have a value for this binder. This really shouldn't
-              -- happen for local id's...
-              Nothing -> error $ "\nNormalize.normalizeBind: No value found for binder " ++ pprString bndr ++ "? This should not happen!"
+-- | Get the value that is bound to the given binder at top level. Fails when
+--   there is no such binding.
+getBinding ::
+  CoreBndr -- ^ The binder to get the expression for
+  -> TranslatorSession CoreExpr -- ^ The value bound to the binder
+
+getBinding bndr = Utils.makeCached bndr tsBindings $ do
+  -- If the binding isn't in the "cache" (bindings map), then we can't create
+  -- it out of thin air, so return an error.
+  error $ "Normalize.getBinding: Unknown function requested: " ++ show bndr
index 7f575ade5480acb0b537599ddfab4f95d47d9841..0ae958abf456198c82ad7fdf3ed97394dd302441 100644 (file)
@@ -35,6 +35,7 @@ import Outputable ( showSDoc, ppr, nest )
 
 -- Local imports
 import CLasH.Normalize.NormalizeTypes
+import CLasH.Translator.TranslatorTypes
 import CLasH.Utils.Pretty
 import CLasH.VHDL.VHDLTypes
 import qualified CLasH.VHDL.VHDLTools as VHDLTools
@@ -258,14 +259,6 @@ substitute ((b, e):subss) expr = substitute subss' expr'
     -- substitutions
     subss' = map (Arrow.second (CoreSubst.substExpr subs)) subss
 
--- Run a given TransformSession. Used mostly to setup the right calls and
--- an initial state.
-runTransformSession :: HscTypes.HscEnv -> UniqSupply.UniqSupply -> TransformSession a -> a
-runTransformSession env uniqSupply session = State.evalState session emptyTransformState
-  where
-    emptyTypeState = TypeState Map.empty [] Map.empty Map.empty env
-    emptyTransformState = TransformState uniqSupply Map.empty VarSet.emptyVarSet emptyTypeState
-
 -- Is the given expression representable at runtime, based on the type?
 isRepr :: CoreSyn.CoreExpr -> TransformMonad Bool
 isRepr (Type ty) = return False
index 90589f85e16b74445058f9bf43a96d9d33714fae..2383cdf7086c8abc8a7d6c9653134ae8625e3552 100644 (file)
@@ -13,26 +13,14 @@ import Debug.Trace
 
 -- GHC API
 import CoreSyn
-import qualified UniqSupply
 import qualified VarSet
 import Outputable ( Outputable, showSDoc, ppr )
 
 -- Local imports
 import CLasH.Utils.Core.CoreShow
 import CLasH.Utils.Pretty
-import CLasH.VHDL.VHDLTypes -- For TypeState
+import CLasH.Translator.TranslatorTypes
 
-data TransformState = TransformState {
-    tsUniqSupply_ :: UniqSupply.UniqSupply
-  , tsBindings_ :: Map.Map CoreBndr CoreExpr
-  , tsNormalized_ :: VarSet.VarSet -- ^ The binders that have been normalized
-  , tsType_ :: TypeState
-}
-
-$( Data.Accessor.Template.deriveAccessors ''TransformState )
-
--- A session of multiple transformations over multiple expressions
-type TransformSession = (State.State TransformState)
 -- Wrap a writer around a TransformSession, to run a single transformation
 -- over a single expression and track if the expression was changed.
 type TransformMonad = Writer.WriterT Monoid.Any TransformSession
index 445dd9c23c32e91ef8fef94286e2770fbc29a5f9..20dab4f7c77de618a2faebc2e97dc392ea17d02a 100644 (file)
@@ -8,7 +8,10 @@ import qualified System.Directory as Directory
 import qualified Maybe
 import qualified Monad
 import qualified System.FilePath as FilePath
+import qualified Control.Monad.Trans.State as State
 import Text.PrettyPrint.HughesPJ (render)
+import Data.Accessor
+import qualified Data.Map as Map
 
 -- GHC API
 import qualified CoreSyn
@@ -23,6 +26,7 @@ import qualified Language.VHDL.Ppr as Ppr
 
 -- Local Imports
 import CLasH.Normalize
+import CLasH.Translator.TranslatorTypes
 import CLasH.Translator.Annotations
 import CLasH.Utils.Core.CoreTools
 import CLasH.Utils.GhcTools
@@ -92,27 +96,32 @@ moduleToVHDL ::
   -> [Maybe CoreSyn.CoreExpr] -- ^ The TestInput
   -> Bool                     -- ^ Is it stateful (in case InitState is not specified)
   -> IO [(AST.VHDLId, AST.DesignFile)]
-moduleToVHDL env cores top init test stateful = do
-  let topEntity = Maybe.catMaybes top
-  case topEntity of
-    [] -> error "Top Entity Not Found"
-    [topEnt] -> do
-      let initialState = Maybe.catMaybes init
-      let isStateful = not (null initialState) || stateful
-      let testInput = Maybe.catMaybes test
-      -- Generate a UniqSupply
-      -- Running 
-      --    egrep -r "(initTcRnIf|mkSplitUniqSupply)" .
-      -- on the compiler dir of ghc suggests that 'z' is not used to generate
-      -- a unique supply anywhere.
-      uniqSupply <- UniqSupply.mkSplitUniqSupply 'z'
-      let all_bindings = concat (map (\x -> CoreSyn.flattenBinds (HscTypes.cm_binds x)) cores)
-      let testexprs = case testInput of [] -> [] ; [x] -> reduceCoreListToHsList x
-      let (normalized_bindings, test_bindings, typestate) = normalizeModule env uniqSupply all_bindings testexprs [topEnt] [isStateful]
-      let vhdl = createDesignFiles typestate normalized_bindings topEnt test_bindings
-      mapM (putStr . render . Ppr.ppr . snd) vhdl
-      return vhdl
-    xs -> error "More than one topentity found"
+moduleToVHDL env cores topbinds' init test stateful = do
+  let topbinds = Maybe.catMaybes topbinds'
+  let initialState = Maybe.catMaybes init
+  let testInput = Maybe.catMaybes test
+  vhdl <- runTranslatorSession env $ do
+    let all_bindings = concat (map (\x -> CoreSyn.flattenBinds (HscTypes.cm_binds x)) cores)
+    -- Store the bindings we loaded
+    tsBindings %= Map.fromList all_bindings 
+    --let testexprs = case testInput of [] -> [] ; [x] -> reduceCoreListToHsList x
+    createDesignFiles topbinds 
+  mapM (putStr . render . Ppr.ppr . snd) vhdl
+  return vhdl
+
+-- Run the given translator session. Generates a new UniqSupply for that
+-- session.
+runTranslatorSession :: HscTypes.HscEnv -> TranslatorSession a -> IO a
+runTranslatorSession env session = do
+  -- Generate a UniqSupply
+  -- Running 
+  --    egrep -r "(initTcRnIf|mkSplitUniqSupply)" .
+  -- on the compiler dir of ghc suggests that 'z' is not used to generate
+  -- a unique supply anywhere.
+  uniqSupply <- UniqSupply.mkSplitUniqSupply 'z'
+  let init_typestate = TypeState Map.empty [] Map.empty Map.empty env
+  let init_state = TranslatorState uniqSupply init_typestate Map.empty Map.empty Map.empty Map.empty
+  return $ State.evalState session init_state
 
 -- | Prepares the directory for writing VHDL files. This means creating the
 --   dir if it does not exist and removing all existing .vhdl files from it.
index 0ab3b878a132542bbcd011b368dd254622394df8..5fb97c2b31831c4c1f5380d51f5250ceacd57517 100644 (file)
@@ -5,25 +5,99 @@
 {-# LANGUAGE TemplateHaskell #-}
 module CLasH.Translator.TranslatorTypes where
 
+-- Standard modules
 import qualified Control.Monad.Trans.State as State
 import qualified Data.Map as Map
 import qualified Data.Accessor.Template
 import Data.Accessor
 
+-- GHC API
+import qualified CoreSyn
+import qualified Type
 import qualified HscTypes
+import qualified UniqSupply
 
+-- ForSyDe
 import qualified Language.VHDL.AST as AST
 
+-- Local imports
 import CLasH.VHDL.VHDLTypes
 
-data TranslatorSession = TranslatorSession {
-  tsCoreModule_ :: HscTypes.CoreModule, -- ^ The current module
-  tsNameCount_ :: Int -- ^ A counter that can be used to generate unique names
+-- A orderable equivalent of CoreSyn's Type for use as a map key
+newtype OrdType = OrdType { getType :: Type.Type }
+instance Eq OrdType where
+  (OrdType a) == (OrdType b) = Type.tcEqType a b
+instance Ord OrdType where
+  compare (OrdType a) (OrdType b) = Type.tcCmpType a b
+
+data HType = StdType OrdType |
+             ADTType String [HType] |
+             VecType Int HType |
+             SizedWType Int |
+             RangedWType Int |
+             SizedIType Int |
+             BuiltinType String
+  deriving (Eq, Ord)
+
+-- A map of a Core type to the corresponding type name
+type TypeMap = Map.Map HType (AST.VHDLId, Either AST.TypeDef AST.SubtypeIn)
+
+-- A map of a vector Core element type and function name to the coressponding
+-- VHDLId of the function and the function body.
+type TypeFunMap = Map.Map (OrdType, String) (AST.VHDLId, AST.SubProgBody)
+
+type TfpIntMap = Map.Map OrdType Int
+-- A substate that deals with type generation
+data TypeState = TypeState {
+  -- | A map of Core type -> VHDL Type
+  tsTypes_      :: TypeMap,
+  -- | A list of type declarations
+  tsTypeDecls_  :: [AST.PackageDecItem],
+  -- | A map of vector Core type -> VHDL type function
+  tsTypeFuns_   :: TypeFunMap,
+  tsTfpInts_    :: TfpIntMap,
+  tsHscEnv_     :: HscTypes.HscEnv
+}
+
+-- Derive accessors
+$( Data.Accessor.Template.deriveAccessors ''TypeState )
+
+-- Compatibility with old VHDLSession
+vsTypes = tsTypes
+vsTypeDecls = tsTypeDecls
+vsTypeFuns = tsTypeFuns
+vsTfpInts = tsTfpInts
+vsHscEnv = tsHscEnv
+
+-- Define a session
+type TypeSession = State.State TypeState
+-- A global state for the translator
+data TranslatorState = TranslatorState {
+    tsUniqSupply_ :: UniqSupply.UniqSupply
+  , tsType_ :: TypeState
+  , tsBindings_ :: Map.Map CoreSyn.CoreBndr CoreSyn.CoreExpr
+  , tsNormalized_ :: Map.Map CoreSyn.CoreBndr CoreSyn.CoreExpr
+  , tsEntities_ :: Map.Map CoreSyn.CoreBndr Entity
+  , tsArchitectures_ :: Map.Map CoreSyn.CoreBndr (Architecture, [CoreSyn.CoreBndr])
 }
 
 -- Derive accessors
-$( Data.Accessor.Template.deriveAccessors ''TranslatorSession )
+$( Data.Accessor.Template.deriveAccessors ''TranslatorState )
+
+type TranslatorSession = State.State TranslatorState
+
+-- Compatibility for the old VHDLSesssion
+vsType = tsType
+type VHDLSession = TranslatorSession
+
+-- Compatibility for the old TransformSession
+type TransformSession = TranslatorSession
 
-type TranslatorState = State.State TranslatorSession
+-- Does the given binder reference a top level binder in the current
+-- module(s)?
+isTopLevelBinder :: CoreSyn.CoreBndr -> TranslatorSession Bool
+isTopLevelBinder bndr = do
+  bindings <- getA tsBindings
+  return $ Map.member bndr bindings
 
 -- vim: set ts=8 sw=2 sts=2 expandtab:
index c539c790125937b00363e77f0b333367a5c685ef..705a46603b42f3f4e4ab16dbbffecae7cd512dd2 100644 (file)
@@ -1,10 +1,14 @@
 module CLasH.Utils
   ( listBindings
   , listBind
+  , makeCached
   ) where
 
 -- Standard Imports
 import qualified Maybe
+import Data.Accessor
+import qualified Data.Map as Map
+import qualified Control.Monad.Trans.State as State
 
 -- GHC API
 import qualified CoreSyn
@@ -46,4 +50,22 @@ listBind libdir filenames name = do
   listBinding (Maybe.fromJust $ head corebind, Maybe.fromJust $ head coreexpr)
     where
       bindFinder  = findBind (hasVarName name)
-      exprFinder  = findExpr (hasVarName name)
\ No newline at end of file
+      exprFinder  = findExpr (hasVarName name)
+
+-- Make a caching version of a stateful computatation.
+makeCached :: (Monad m, Ord k) =>
+  k -- ^ The key to use for the cache
+  -> Accessor s (Map.Map k v) -- ^ The accessor to get at the cache
+  -> State.StateT s m v -- ^ How to compute the value to cache?
+  -> State.StateT s m v -- ^ The resulting value, from the cache or freshly
+                        --   computed.
+makeCached key accessor create = do
+  cache <- getA accessor
+  case Map.lookup key cache of
+    -- Found in cache, just return
+    Just value -> return value
+    -- Not found, compute it and put it in the cache
+    Nothing -> do
+      value <- create
+      modA accessor (Map.insert key value)
+      return value
index 4366b10f4c59ab696e2f9a39706daa83c45f727c..56b3aaf6238d536745bbeaa50dedf77a8be86cb7 100644 (file)
@@ -24,14 +24,6 @@ import CLasH.Utils.Core.CoreShow
 printList :: (a -> Doc) -> [a] -> Doc
 printList f = brackets . fsep . punctuate comma . map f
 
-instance Pretty TranslatorSession where
-  pPrint (TranslatorSession mod nameCount) =
-    text "Module: " $$ nest 15 (text modname)
-    $+$ text "NameCount: " $$ nest 15 (int nameCount)
-    where
-      ppfunc (hsfunc, flatfunc) =
-        pPrint hsfunc $+$ nest 5 (pPrint flatfunc)
-      modname = showSDoc $ Module.pprModule (HscTypes.cm_module mod)
 {-
 instance Pretty FuncData where
   pPrint (FuncData flatfunc entity arch) =
@@ -48,10 +40,11 @@ instance Pretty FuncData where
 -}
 
 instance Pretty Entity where
-  pPrint (Entity id args res) =
+  pPrint (Entity id args res decl) =
     text "Entity: " $$ nest 10 (pPrint id)
     $+$ text "Args: " $$ nest 10 (pPrint args)
     $+$ text "Result: " $$ nest 10 (pPrint res)
+    $+$ text "Declaration not shown"
 
 instance (OutputableBndr b, Show b) => Pretty (CoreSyn.Bind b) where
   pPrint (CoreSyn.NonRec b expr) =
index fd83899cee622a7ddc501afa598a87cc227e9eac..944d33f82c9ef3dee996419db7c3988bd229f44c 100644 (file)
@@ -4,7 +4,6 @@
 module CLasH.VHDL where
 
 -- Standard modules
-import qualified Data.List as List
 import qualified Data.Map as Map
 import qualified Maybe
 import qualified Control.Monad as Monad
@@ -23,7 +22,6 @@ import CoreSyn
 --import qualified Type
 import qualified Name
 import qualified Var
-import qualified Id
 import qualified IdInfo
 import qualified TyCon
 import qualified DataCon
@@ -32,6 +30,7 @@ import qualified CoreUtils
 import Outputable ( showSDoc, ppr )
 
 -- Local imports
+import CLasH.Translator.TranslatorTypes
 import CLasH.VHDL.VHDLTypes
 import CLasH.VHDL.VHDLTools
 import CLasH.Utils.Pretty
@@ -41,41 +40,59 @@ import CLasH.VHDL.Generate
 -- import CLasH.VHDL.Testbench
 
 createDesignFiles ::
-  TypeState
-  -> [(CoreSyn.CoreBndr, CoreSyn.CoreExpr)]
-  -> CoreSyn.CoreBndr -- ^ Top binder
-  -> [(CoreSyn.CoreBndr, CoreSyn.CoreExpr)] -- ^ Test Input
-  -> [(AST.VHDLId, AST.DesignFile)]
-
-createDesignFiles init_typestate binds topbind testinput =
-  (mkVHDLBasicId "types", AST.DesignFile ieee_context [type_package_dec, type_package_body]) :
-  map (Arrow.second $ AST.DesignFile full_context) (units ++ [testbench])
-  
+  [CoreSyn.CoreBndr] -- ^ Top binders
+  -> TranslatorSession [(AST.VHDLId, AST.DesignFile)]
+
+createDesignFiles topbndrs = do
+  bndrss <- mapM recurseArchitectures topbndrs
+  let bndrs = concat bndrss
+  lunits <- mapM createLibraryUnit bndrs
+  typepackage <- createTypesPackage
+  let files = map (Arrow.second $ AST.DesignFile full_context) lunits
+  return $ typepackage : files
   where
-    init_session = VHDLState init_typestate Map.empty
-    (units, final_session') = 
-      State.runState (createLibraryUnits binds) init_session
-    (testbench, final_session) =
-      State.runState (createTestBench Nothing testinput topbind) final_session'
-    tyfun_decls = mkBuiltInShow ++ (map snd $ Map.elems (final_session ^. vsType ^. vsTypeFuns))
-    ty_decls = final_session ^. vsType ^. vsTypeDecls
-    tfvec_index_decl = AST.PDISD $ AST.SubtypeDec tfvec_indexTM tfvec_index_def
-    tfvec_range = AST.ConstraintRange $ AST.SubTypeRange (AST.PrimLit "-1") (AST.PrimName $ AST.NAttribute $ AST.AttribName (AST.NSimple integerTM) (AST.NSimple $ highId) Nothing)
-    tfvec_index_def = AST.SubtypeIn integerTM (Just tfvec_range)
-    ieee_context = [
-        AST.Library $ mkVHDLBasicId "IEEE",
-        mkUseAll ["IEEE", "std_logic_1164"],
-        mkUseAll ["IEEE", "numeric_std"],
-        mkUseAll ["std", "textio"]
-      ]
     full_context =
       mkUseAll ["work", "types"]
       : (mkUseAll ["work"]
       : ieee_context)
-    type_package_dec = AST.LUPackageDec $ AST.PackageDec (mkVHDLBasicId "types") ([tfvec_index_decl] ++ ty_decls ++ subProgSpecs)
-    type_package_body = AST.LUPackageBody $ AST.PackageBody typesId tyfun_decls
-    subProgSpecs = map subProgSpec tyfun_decls
-    subProgSpec = \(AST.SubProgBody spec _ _) -> AST.PDISS spec
+
+ieee_context = [
+    AST.Library $ mkVHDLBasicId "IEEE",
+    mkUseAll ["IEEE", "std_logic_1164"],
+    mkUseAll ["IEEE", "numeric_std"],
+    mkUseAll ["std", "textio"]
+  ]
+
+-- | Find out which entities are needed for the given top level binders.
+recurseArchitectures ::
+  CoreSyn.CoreBndr -- ^ The top level binder
+  -> TranslatorSession [CoreSyn.CoreBndr] 
+  -- ^ The binders of all needed functions.
+recurseArchitectures bndr = do
+  -- See what this binder directly uses
+  (_, used) <- getArchitecture bndr
+  -- Recursively check what each of the used functions uses
+  useds <- mapM recurseArchitectures used
+  -- And return all of them
+  return $ bndr : (concat useds)
+
+-- | Creates the types package, based on the current type state.
+createTypesPackage ::
+  TranslatorSession (AST.VHDLId, AST.DesignFile) 
+  -- ^ The id and content of the types package
+createTypesPackage = do
+  tyfuns <- getA (tsType .> tsTypeFuns)
+  let tyfun_decls = mkBuiltInShow ++ (map snd $ Map.elems tyfuns)
+  ty_decls <- getA (tsType .> tsTypeDecls)
+  let subProgSpecs = map (\(AST.SubProgBody spec _ _) -> AST.PDISS spec) tyfun_decls
+  let type_package_dec = AST.LUPackageDec $ AST.PackageDec (mkVHDLBasicId "types") ([tfvec_index_decl] ++ ty_decls ++ subProgSpecs)
+  let type_package_body = AST.LUPackageBody $ AST.PackageBody typesId tyfun_decls
+  return $ (mkVHDLBasicId "types", AST.DesignFile ieee_context [type_package_dec, type_package_body])
+  where
+    tfvec_index_decl = AST.PDISD $ AST.SubtypeDec tfvec_indexTM tfvec_index_def
+    tfvec_range = AST.ConstraintRange $ AST.SubTypeRange (AST.PrimLit "-1") (AST.PrimName $ AST.NAttribute $ AST.AttribName (AST.NSimple integerTM) (AST.NSimple $ highId) Nothing)
+    tfvec_index_def = AST.SubtypeIn integerTM (Just tfvec_range)
 
 -- Create a use foo.bar.all statement. Takes a list of components in the used
 -- name. Must contain at least two components
@@ -87,122 +104,14 @@ mkUseAll ss =
     from = foldl select base_prefix (tail ss)
     select prefix s = AST.NSelected $ prefix AST.:.: (AST.SSimple $ mkVHDLBasicId s)
       
-createLibraryUnits ::
-  [(CoreSyn.CoreBndr, CoreSyn.CoreExpr)]
-  -> VHDLSession [(AST.VHDLId, [AST.LibraryUnit])]
-
-createLibraryUnits binds = do
-  entities <- Monad.mapM createEntity binds
-  archs <- Monad.mapM createArchitecture binds
-  return $ zipWith 
-    (\ent arch -> 
-      let AST.EntityDec id _ = ent in 
-      (id, [AST.LUEntity ent, AST.LUArch arch])
-    )
-    entities archs
+createLibraryUnit ::
+  CoreSyn.CoreBndr
+  -> TranslatorSession (AST.VHDLId, [AST.LibraryUnit])
 
--- | Create an entity for a given function
-createEntity ::
-  (CoreSyn.CoreBndr, CoreSyn.CoreExpr) -- ^ The function
-  -> VHDLSession AST.EntityDec -- ^ The resulting entity
-
-createEntity (fname, expr) = do
-      -- Strip off lambda's, these will be arguments
-      let (args, letexpr) = CoreSyn.collectBinders expr
-      args' <- Monad.mapM mkMap args
-      -- There must be a let at top level 
-      let (CoreSyn.Let binds (CoreSyn.Var res)) = letexpr
-      res' <- mkMap res
-      let vhdl_id = mkVHDLBasicId $ varToString fname ++ "_" ++ varToStringUniq fname
-      let ent_decl' = createEntityAST vhdl_id args' res'
-      let AST.EntityDec entity_id _ = ent_decl' 
-      let signature = Entity entity_id args' res'
-      modA vsSignatures (Map.insert fname signature)
-      return ent_decl'
-  where
-    mkMap ::
-      --[(SignalId, SignalInfo)] 
-      CoreSyn.CoreBndr 
-      -> VHDLSession Port
-    -- We only need the vsTypes element from the state
-    mkMap = (\bndr ->
-      let
-        --info = Maybe.fromMaybe
-        --  (error $ "Signal not found in the name map? This should not happen!")
-        --  (lookup id sigmap)
-        --  Assume the bndr has a valid VHDL id already
-        id = varToVHDLId bndr
-        ty = Var.varType bndr
-        error_msg = "\nVHDL.createEntity.mkMap: Can not create entity: " ++ pprString fname ++ "\nbecause no type can be created for port: " ++ pprString bndr 
-      in do
-        type_mark <- MonadState.lift vsType $ vhdl_ty error_msg ty
-        return (id, type_mark)
-     )
-
--- | Create the VHDL AST for an entity
-createEntityAST ::
-  AST.VHDLId                   -- ^ The name of the function
-  -> [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 = map (mkIfaceSigDec AST.In) args
-              ++ [mkIfaceSigDec AST.Out res]
-              ++ [clk_port]
-    -- Add a clk port if we have state
-    clk_port = AST.IfaceSigDec clockId AST.In std_logicTM
-
--- | Create a port declaration
-mkIfaceSigDec ::
-  AST.Mode                         -- ^ The mode for the port (In / Out)
-  -> (AST.VHDLId, AST.TypeMark)    -- ^ The id and type for the port
-  -> AST.IfaceSigDec               -- ^ The resulting port declaration
-
-mkIfaceSigDec mode (id, ty) = AST.IfaceSigDec id mode ty
-
-{-
--- | Generate a VHDL entity name for the given hsfunc
-mkEntityId hsfunc =
-  -- TODO: This doesn't work for functions with multiple signatures!
-  -- Use a Basic Id, since using extended id's for entities throws off
-  -- precision and causes problems when generating filenames.
-  mkVHDLBasicId $ hsFuncName hsfunc
--}
-
--- | Create an architecture for a given function
-createArchitecture ::
-  (CoreSyn.CoreBndr, CoreSyn.CoreExpr) -- ^ The function
-  -> VHDLSession AST.ArchBody -- ^ The architecture for this function
-
-createArchitecture (fname, expr) = do
-  signaturemap <- getA vsSignatures
-  let signature = Maybe.fromMaybe 
-        (error $ "\nVHDL.createArchitecture: Generating architecture for function \n" ++ (pprString fname) ++ "\nwithout signature? This should not happen!")
-        (Map.lookup fname signaturemap)
-  let entity_id = ent_id signature
-  -- Strip off lambda's, these will be arguments
-  let (args, letexpr) = CoreSyn.collectBinders expr
-  -- There must be a let at top level 
-  let (CoreSyn.Let (CoreSyn.Rec binds) (Var res)) = letexpr
-
-  -- Create signal declarations for all binders in the let expression, except
-  -- for the output port (that will already have an output port declared in
-  -- the entity).
-  sig_dec_maybes <- mapM (mkSigDec' . fst) (filter ((/=res).fst) binds)
-  let sig_decs = Maybe.catMaybes $ sig_dec_maybes
-
-  statementss <- Monad.mapM mkConcSm binds
-  let statements = concat statementss
-  return $ AST.ArchBody (mkVHDLBasicId "structural") (AST.NSimple entity_id) (map AST.BDISD sig_decs) (statements ++ procs')
-  where
-    procs = [] --map mkStateProcSm [] -- (makeStatePairs flatfunc)
-    procs' = map AST.CSPSm procs
-    -- mkSigDec only uses vsTypes from the state
-    mkSigDec' = mkSigDec
+createLibraryUnit bndr = do
+  entity <- getEntity bndr
+  (arch, _) <- getArchitecture bndr
+  return (ent_id entity, [AST.LUEntity (ent_dec entity), AST.LUArch arch])
 
 {-
 -- | Looks up all pairs of old state, new state signals, together with
@@ -241,60 +150,7 @@ getSignalId info =
     (sigName info)
 -}
 
--- | Transforms a core binding into a VHDL concurrent statement
-mkConcSm ::
-  (CoreSyn.CoreBndr, CoreSyn.CoreExpr) -- ^ The binding to process
-  -> VHDLSession [AST.ConcSm] -- ^ The corresponding VHDL component instantiations.
-
-
--- Ignore Cast expressions, they should not longer have any meaning as long as
--- the type works out.
-mkConcSm (bndr, Cast expr ty) = mkConcSm (bndr, expr)
-
--- Simple a = b assignments are just like applications, but without arguments.
--- We can't just generate an unconditional assignment here, since b might be a
--- top level binding (e.g., a function with no arguments).
-mkConcSm (bndr, Var v) = do
-  genApplication (Left bndr) v []
-
-mkConcSm (bndr, app@(CoreSyn.App _ _))= do
-  let (CoreSyn.Var f, args) = CoreSyn.collectArgs app
-  let valargs = get_val_args (Var.varType f) args
-  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
--- is also returned.
-mkConcSm (bndr, expr@(Case (Var scrut) b ty [alt])) =
-  case alt of
-    (DataAlt dc, bndrs, (Var sel_bndr)) -> do
-      case List.elemIndex sel_bndr bndrs of
-        Just i -> do
-          labels <- MonadState.lift vsType $ getFieldLabels (Id.idType scrut)
-          let label = labels!!i
-          let sel_name = mkSelectedName (varToVHDLName scrut) label
-          let sel_expr = AST.PrimName sel_name
-          return [mkUncondAssign (Left bndr) sel_expr]
-        Nothing -> error $ "\nVHDL.mkConcSM: Not in normal form: Not a selector case:\n" ++ (pprString expr)
-      
-    _ -> error $ "\nVHDL.mkConcSM: Not in normal form: Not a selector case:\n" ++ (pprString expr)
-
--- Multiple case alt are be conditional assignments and have only wild
--- binders in the alts and only variables in the case values and a variable
--- for a scrutinee. We check the constructor of the second alt, since the
--- first is the default case, if there is any.
-mkConcSm (bndr, (Case (Var scrut) b ty [(_, _, Var false), (con, _, Var true)])) = do
-  scrut' <- MonadState.lift vsType $ varToVHDLExpr scrut
-  let cond_expr = scrut' AST.:=: (altconToVHDLExpr con)
-  true_expr <- MonadState.lift vsType $ varToVHDLExpr true
-  false_expr <- MonadState.lift vsType $ varToVHDLExpr false
-  return [mkCondAssign (Left bndr) cond_expr true_expr false_expr]
-
-mkConcSm (_, (Case (Var _) _ _ alts)) = error "\nVHDL.mkConcSm: Not in normal form: Case statement with more than two alternatives"
-mkConcSm (_, Case _ _ _ _) = error "\nVHDL.mkConcSm: Not in normal form: Case statement has does not have a simple variable as scrutinee"
-mkConcSm (bndr, expr) = error $ "\nVHDL.mkConcSM: Unsupported binding in let expression: " ++ pprString bndr ++ " = " ++ pprString expr
-
-
+{-
 createTestBench :: 
   Maybe Int -- ^ Number of cycles to simulate
   -> [(CoreSyn.CoreBndr, CoreSyn.CoreExpr)] -- ^ Input stimuli
@@ -382,7 +238,7 @@ createStimulans (bndr, expr) cycl = do
   let block_label = mkVHDLExtId ("testcycle_" ++ (show cycl))
   let block = AST.BlockSm block_label [] (AST.PMapAspect []) sig_decs (concat stimulansbinds)  
   return (AST.CSBSm block, res)
-  
 -- | generates a clock process with a period of 10ns
 createClkProc :: AST.ProcSm
 createClkProc = AST.ProcSm (AST.unsafeVHDLBasicId "clkproc") [] sms
@@ -411,3 +267,5 @@ createOutputProc outs =
          genExprPCall2 writeId
                         (AST.PrimName $ AST.NSimple outputId)
                         ((genExprFCall showId (AST.PrimName $ AST.NSimple outSig)) AST.:&: suffix)
+
+-}
index 448308613a9df0b89a03965defb504112346a28b..df646352f83222bac13c8daa4601824e5f41c0ed 100644 (file)
@@ -1,7 +1,9 @@
 module CLasH.VHDL.Generate where
 
 -- Standard modules
+import qualified Data.List as List
 import qualified Data.Map as Map
+import qualified Control.Monad as Monad
 import qualified Maybe
 import qualified Data.Either as Either
 import Data.Accessor
@@ -15,17 +17,175 @@ import qualified Language.VHDL.AST as AST
 import qualified CoreSyn
 import qualified Type
 import qualified Var
+import qualified Id
 import qualified IdInfo
 import qualified Literal
 import qualified Name
 import qualified TyCon
 
 -- Local imports
+import CLasH.Translator.TranslatorTypes
 import CLasH.VHDL.Constants
 import CLasH.VHDL.VHDLTypes
 import CLasH.VHDL.VHDLTools
+import qualified CLasH.Utils as Utils
 import CLasH.Utils.Core.CoreTools
 import CLasH.Utils.Pretty
+import qualified CLasH.Normalize as Normalize
+
+-----------------------------------------------------------------------------
+-- Functions to generate VHDL for user-defined functions.
+-----------------------------------------------------------------------------
+
+-- | Create an entity for a given function
+getEntity ::
+  CoreSyn.CoreBndr
+  -> VHDLSession Entity -- ^ The resulting entity
+
+getEntity fname = Utils.makeCached fname tsEntities $ do
+      expr <- Normalize.getNormalized fname
+      -- Strip off lambda's, these will be arguments
+      let (args, letexpr) = CoreSyn.collectBinders expr
+      args' <- mapM mkMap args
+      -- There must be a let at top level 
+      let (CoreSyn.Let binds (CoreSyn.Var res)) = letexpr
+      res' <- mkMap res
+      let vhdl_id = mkVHDLBasicId $ varToString fname ++ "_" ++ varToStringUniq fname
+      let ent_decl' = createEntityAST vhdl_id args' res'
+      let AST.EntityDec entity_id _ = ent_decl' 
+      let signature = Entity entity_id args' res' ent_decl'
+      return signature
+  where
+    mkMap ::
+      --[(SignalId, SignalInfo)] 
+      CoreSyn.CoreBndr 
+      -> VHDLSession Port
+    -- We only need the vsTypes element from the state
+    mkMap = (\bndr ->
+      let
+        --info = Maybe.fromMaybe
+        --  (error $ "Signal not found in the name map? This should not happen!")
+        --  (lookup id sigmap)
+        --  Assume the bndr has a valid VHDL id already
+        id = varToVHDLId bndr
+        ty = Var.varType bndr
+        error_msg = "\nVHDL.createEntity.mkMap: Can not create entity: " ++ pprString fname ++ "\nbecause no type can be created for port: " ++ pprString bndr 
+      in do
+        type_mark <- MonadState.lift vsType $ vhdl_ty error_msg ty
+        return (id, type_mark)
+     )
+
+-- | Create the VHDL AST for an entity
+createEntityAST ::
+  AST.VHDLId                   -- ^ The name of the function
+  -> [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 = map (mkIfaceSigDec AST.In) args
+              ++ [mkIfaceSigDec AST.Out res]
+              ++ [clk_port]
+    -- Add a clk port if we have state
+    clk_port = AST.IfaceSigDec clockId AST.In std_logicTM
+
+-- | Create a port declaration
+mkIfaceSigDec ::
+  AST.Mode                         -- ^ The mode for the port (In / Out)
+  -> (AST.VHDLId, AST.TypeMark)    -- ^ The id and type for the port
+  -> AST.IfaceSigDec               -- ^ The resulting port declaration
+
+mkIfaceSigDec mode (id, ty) = AST.IfaceSigDec id mode ty
+
+-- | Create an architecture for a given function
+getArchitecture ::
+  CoreSyn.CoreBndr -- ^ The function to get an architecture for
+  -> VHDLSession (Architecture, [CoreSyn.CoreBndr])
+  -- ^ The architecture for this function
+
+getArchitecture fname = Utils.makeCached fname tsArchitectures $ do
+  expr <- Normalize.getNormalized fname
+  signature <- getEntity fname
+  let entity_id = ent_id signature
+  -- Strip off lambda's, these will be arguments
+  let (args, letexpr) = CoreSyn.collectBinders expr
+  -- There must be a let at top level 
+  let (CoreSyn.Let (CoreSyn.Rec binds) (CoreSyn.Var res)) = letexpr
+
+  -- Create signal declarations for all binders in the let expression, except
+  -- for the output port (that will already have an output port declared in
+  -- the entity).
+  sig_dec_maybes <- mapM (mkSigDec' . fst) (filter ((/=res).fst) binds)
+  let sig_decs = Maybe.catMaybes $ sig_dec_maybes
+
+  (statementss, used_entitiess) <- Monad.mapAndUnzipM mkConcSm binds
+  let statements = concat statementss
+  let used_entities = concat used_entitiess
+  let arch = AST.ArchBody (mkVHDLBasicId "structural") (AST.NSimple entity_id) (map AST.BDISD sig_decs) (statements ++ procs')
+  return (arch, used_entities)
+  where
+    procs = [] --map mkStateProcSm [] -- (makeStatePairs flatfunc)
+    procs' = map AST.CSPSm procs
+    -- mkSigDec only uses vsTypes from the state
+    mkSigDec' = mkSigDec
+
+-- | Transforms a core binding into a VHDL concurrent statement
+mkConcSm ::
+  (CoreSyn.CoreBndr, CoreSyn.CoreExpr) -- ^ The binding to process
+  -> TranslatorSession ([AST.ConcSm], [CoreSyn.CoreBndr]) 
+  -- ^ The corresponding VHDL concurrent statements and entities
+  --   instantiated.
+
+
+-- Ignore Cast expressions, they should not longer have any meaning as long as
+-- the type works out.
+mkConcSm (bndr, CoreSyn.Cast expr ty) = mkConcSm (bndr, expr)
+
+-- Simple a = b assignments are just like applications, but without arguments.
+-- We can't just generate an unconditional assignment here, since b might be a
+-- top level binding (e.g., a function with no arguments).
+mkConcSm (bndr, CoreSyn.Var v) = do
+  genApplication (Left bndr) v []
+
+mkConcSm (bndr, app@(CoreSyn.App _ _))= do
+  let (CoreSyn.Var f, args) = CoreSyn.collectArgs app
+  let valargs = get_val_args (Var.varType f) args
+  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
+-- is also returned.
+mkConcSm (bndr, expr@(CoreSyn.Case (CoreSyn.Var scrut) b ty [alt])) =
+  case alt of
+    (CoreSyn.DataAlt dc, bndrs, (CoreSyn.Var sel_bndr)) -> do
+      case List.elemIndex sel_bndr bndrs of
+        Just i -> do
+          labels <- MonadState.lift vsType $ getFieldLabels (Id.idType scrut)
+          let label = labels!!i
+          let sel_name = mkSelectedName (varToVHDLName scrut) label
+          let sel_expr = AST.PrimName sel_name
+          return ([mkUncondAssign (Left bndr) sel_expr], [])
+        Nothing -> error $ "\nVHDL.mkConcSM: Not in normal form: Not a selector case:\n" ++ (pprString expr)
+      
+    _ -> error $ "\nVHDL.mkConcSM: Not in normal form: Not a selector case:\n" ++ (pprString expr)
+
+-- Multiple case alt are be conditional assignments and have only wild
+-- binders in the alts and only variables in the case values and a variable
+-- for a scrutinee. We check the constructor of the second alt, since the
+-- first is the default case, if there is any.
+mkConcSm (bndr, (CoreSyn.Case (CoreSyn.Var scrut) b ty [(_, _, CoreSyn.Var false), (con, _, CoreSyn.Var true)])) = do
+  scrut' <- MonadState.lift vsType $ varToVHDLExpr scrut
+  let cond_expr = scrut' AST.:=: (altconToVHDLExpr con)
+  true_expr <- MonadState.lift vsType $ varToVHDLExpr true
+  false_expr <- MonadState.lift vsType $ varToVHDLExpr false
+  return ([mkCondAssign (Left bndr) cond_expr true_expr false_expr], [])
+
+mkConcSm (_, (CoreSyn.Case (CoreSyn.Var _) _ _ alts)) = error "\nVHDL.mkConcSm: Not in normal form: Case statement with more than two alternatives"
+mkConcSm (_, CoreSyn.Case _ _ _ _) = error "\nVHDL.mkConcSm: Not in normal form: Case statement has does not have a simple variable as scrutinee"
+mkConcSm (bndr, expr) = error $ "\nVHDL.mkConcSM: Unsupported binding in let expression: " ++ pprString bndr ++ " = " ++ pprString expr
 
 -----------------------------------------------------------------------------
 -- Functions to generate VHDL for builtin functions
@@ -40,6 +200,15 @@ genExprArgs wrap dst func args = do
 eitherCoreOrExprArgs :: [Either CoreSyn.CoreExpr AST.Expr] -> VHDLSession [AST.Expr]
 eitherCoreOrExprArgs args = mapM (Either.either ((MonadState.lift vsType) . varToVHDLExpr . exprToVar) return) args
 
+-- A function to wrap a builder-like function that generates no component
+-- instantiations
+genNoInsts ::
+  (dst -> func -> args -> TranslatorSession [AST.ConcSm])
+  -> (dst -> func -> args -> TranslatorSession ([AST.ConcSm], [CoreSyn.CoreBndr]))
+genNoInsts wrap dst func args = do
+  concsms <- wrap dst func args
+  return (concsms, [])
+
 -- | A function to wrap a builder-like function that expects its arguments to
 -- be variables.
 genVarArgs ::
@@ -75,19 +244,19 @@ genExprRes wrap dst func args = do
 -- | 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 op = genNoInsts $ genExprArgs $ genExprRes (genOperator2' op)
 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 op = genNoInsts $ genExprArgs $ genExprRes (genOperator1' op)
 genOperator1' :: (AST.Expr -> AST.Expr) -> dst -> CoreSyn.CoreBndr -> [AST.Expr] -> VHDLSession AST.Expr
 genOperator1' op _ f [arg] = return $ op arg
 
 -- | Generate a unary operator application
 genNegation :: BuiltinBuilder 
-genNegation = genVarArgs $ genExprRes genNegation'
+genNegation = genNoInsts $ genVarArgs $ genExprRes genNegation'
 genNegation' :: dst -> CoreSyn.CoreBndr -> [Var.Var] -> VHDLSession AST.Expr
 genNegation' _ f [arg] = do
   arg1 <- MonadState.lift vsType $ varToVHDLExpr arg
@@ -101,7 +270,7 @@ genNegation' _ f [arg] = do
 -- | Generate a function call from the destination binder, function name and a
 -- list of expressions (its arguments)
 genFCall :: Bool -> BuiltinBuilder 
-genFCall switch = genExprArgs $ genExprRes (genFCall' switch)
+genFCall switch = genNoInsts $ genExprArgs $ genExprRes (genFCall' switch)
 genFCall' :: Bool -> Either CoreSyn.CoreBndr AST.VHDLName -> CoreSyn.CoreBndr -> [AST.Expr] -> VHDLSession AST.Expr
 genFCall' switch (Left res) f args = do
   let fname = varToString f
@@ -112,7 +281,7 @@ genFCall' switch (Left res) f args = do
 genFCall' _ (Right name) _ _ = error $ "\nGenerate.genFCall': Cannot generate builtin function call assigned to a VHDLName: " ++ show name
 
 genFromSizedWord :: BuiltinBuilder
-genFromSizedWord = genExprArgs $ genExprRes genFromSizedWord'
+genFromSizedWord = genNoInsts $ genExprArgs $ genExprRes genFromSizedWord'
 genFromSizedWord' :: Either CoreSyn.CoreBndr AST.VHDLName -> CoreSyn.CoreBndr -> [AST.Expr] -> VHDLSession AST.Expr
 genFromSizedWord' (Left res) f args = do
   let fname = varToString f
@@ -121,7 +290,7 @@ genFromSizedWord' (Left res) f args = do
 genFromSizedWord' (Right name) _ _ = error $ "\nGenerate.genFromSizedWord': Cannot generate builtin function call assigned to a VHDLName: " ++ show name
 
 genResize :: BuiltinBuilder
-genResize = genExprArgs $ genExprRes genResize'
+genResize = genNoInsts $ genExprArgs $ genExprRes genResize'
 genResize' :: Either CoreSyn.CoreBndr AST.VHDLName -> CoreSyn.CoreBndr -> [AST.Expr] -> VHDLSession AST.Expr
 genResize' (Left res) f [arg] = do {
   ; let { ty = Var.varType res
@@ -139,7 +308,7 @@ genResize' (Right name) _ _ = error $ "\nGenerate.genFromSizedWord': Cannot gene
 -- FIXME: I'm calling genLitArgs which is very specific function,
 -- which needs to be fixed as well
 genFromInteger :: BuiltinBuilder
-genFromInteger = genLitArgs $ genExprRes genFromInteger'
+genFromInteger = genNoInsts $ genLitArgs $ genExprRes genFromInteger'
 genFromInteger' :: Either CoreSyn.CoreBndr AST.VHDLName -> CoreSyn.CoreBndr -> [Literal.Literal] -> VHDLSession AST.Expr
 genFromInteger' (Left res) f lits = do {
   ; let { ty = Var.varType res
@@ -159,6 +328,7 @@ genFromInteger' (Right name) _ _ = error $ "\nGenerate.genFromInteger': Cannot g
 genSizedInt :: BuiltinBuilder
 genSizedInt = genFromInteger
 
+{-
 -- | Generate a Builder for the builtin datacon TFVec
 genTFVec :: BuiltinBuilder
 genTFVec (Left res) f [Left (CoreSyn.Let (CoreSyn.Rec letBinders) letRes)] = do {
@@ -228,7 +398,7 @@ genTFVec (Left res) f [Left app@(CoreSyn.App _ _)] = do {
 genTFVec (Left name) _ [Left xs] = error $ "\nGenerate.genTFVec: Cannot generate TFVec: " ++ show name ++ ", with elems:\n" ++ show xs ++ "\n" ++ pprString xs
 
 genTFVec (Right name) _ _ = error $ "\nGenerate.genTFVec: Cannot generate TFVec assigned to VHDLName: " ++ show name
-
+-}
 -- | Generate a generate statement for the builtin function "map"
 genMap :: BuiltinBuilder
 genMap (Left res) f [Left mapped_f, Left (CoreSyn.Var arg)] = do {
@@ -251,16 +421,16 @@ genMap (Left res) f [Left mapped_f, Left (CoreSyn.Var arg)] = do {
         ; (CoreSyn.Var real_f, already_mapped_args) = CoreSyn.collectArgs mapped_f
         ; valargs = get_val_args (Var.varType real_f) already_mapped_args
         } ;
-  ; app_concsms <- genApplication (Right resname) real_f (map Left valargs ++ [Right argexpr])
+  ; (app_concsms, used) <- genApplication (Right resname) real_f (map Left valargs ++ [Right argexpr])
     -- Return the generate statement
-  ; return [AST.CSGSm $ AST.GenerateSm label genScheme [] app_concsms]
+  ; return ([AST.CSGSm $ AST.GenerateSm label genScheme [] app_concsms], used)
   }
 
 genMap' (Right name) _ _ = error $ "\nGenerate.genMap': Cannot generate map function call assigned to a VHDLName: " ++ show name
     
 genZipWith :: BuiltinBuilder
 genZipWith = genVarArgs genZipWith'
-genZipWith' :: (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> VHDLSession [AST.ConcSm]
+genZipWith' :: (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> VHDLSession ([AST.ConcSm], [CoreSyn.CoreBndr])
 genZipWith' (Left res) f args@[zipped_f, arg1, arg2] = do {
   -- Setup the generate scheme
   ; len <- MonadState.lift vsType $ tfp_to_int $ (tfvec_len_ty . Var.varType) res
@@ -276,9 +446,9 @@ genZipWith' (Left res) f args@[zipped_f, arg1, arg2] = do {
         ; argexpr1    = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName arg1) n_expr
         ; argexpr2    = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName arg2) n_expr
         } ;
-  ; app_concsms <- genApplication (Right resname) zipped_f [Right argexpr1, Right argexpr2]
+  ; (app_concsms, used) <- genApplication (Right resname) zipped_f [Right argexpr1, Right argexpr2]
     -- Return the generate functions
-  ; return [AST.CSGSm $ AST.GenerateSm label genScheme [] app_concsms]
+  ; return ([AST.CSGSm $ AST.GenerateSm label genScheme [] app_concsms], used)
   }
 
 genFoldl :: BuiltinBuilder
@@ -290,16 +460,16 @@ genFoldr = genFold False
 genFold :: Bool -> BuiltinBuilder
 genFold left = genVarArgs (genFold' left)
 
-genFold' :: Bool -> (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> VHDLSession [AST.ConcSm]
+genFold' :: Bool -> (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> VHDLSession ([AST.ConcSm], [CoreSyn.CoreBndr])
 genFold' left res f args@[folded_f , start ,vec]= do
   len <- MonadState.lift vsType $ tfp_to_int $ (tfvec_len_ty (Var.varType vec))
   genFold'' len left res f args
 
-genFold'' :: Int -> Bool -> (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> VHDLSession [AST.ConcSm]
+genFold'' :: Int -> Bool -> (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> VHDLSession ([AST.ConcSm], [CoreSyn.CoreBndr])
 -- Special case for an empty input vector, just assign start to res
 genFold'' len left (Left res) _ [_, start, vec] | len == 0 = do
   arg <- MonadState.lift vsType $ varToVHDLExpr start
-  return [mkUncondAssign (Left res) arg]
+  return ([mkUncondAssign (Left res) arg], [])
     
 genFold'' len left (Left res) f [folded_f, start, vec] = do
   -- The vector length
@@ -322,14 +492,15 @@ genFold'' len left (Left res) f [folded_f, start, vec] = do
   -- Make the intermediate vector
   let  tmp_dec     = AST.BDISD $ AST.SigDec tmp_id tmp_vhdl_ty Nothing
   -- Create the generate statement
-  cells <- sequence [genFirstCell, genOtherCell]
+  cells' <- sequence [genFirstCell, genOtherCell]
+  let (cells, useds) = unzip cells'
   let gen_sm = AST.GenerateSm gen_label gen_scheme [] (map AST.CSGSm cells)
   -- Assign tmp[len-1] or tmp[0] to res
   let out_assign = mkUncondAssign (Left res) $ vhdlNameToVHDLExpr (if left then
                     (mkIndexedName tmp_name (AST.PrimLit $ show (len-1))) else
                     (mkIndexedName tmp_name (AST.PrimLit "0")))      
   let block = AST.BlockSm block_label [] (AST.PMapAspect []) [tmp_dec] [AST.CSGSm gen_sm, out_assign]
-  return [AST.CSBSm block]
+  return ([AST.CSBSm block], concat useds)
   where
     -- An id for the counter
     n_id = mkVHDLBasicId "n"
@@ -341,7 +512,7 @@ genFold'' len left (Left res) f [folded_f, start, vec] = do
     tmp_id = mkVHDLBasicId "tmp"
     tmp_name = AST.NSimple tmp_id
     -- Generate parts of the fold
-    genFirstCell, genOtherCell :: VHDLSession AST.GenerateSm
+    genFirstCell, genOtherCell :: VHDLSession (AST.GenerateSm, [CoreSyn.CoreBndr])
     genFirstCell = do
       len <- MonadState.lift vsType $ tfp_to_int $ (tfvec_len_ty . Var.varType) vec
       let cond_label = mkVHDLExtId "firstcell"
@@ -354,13 +525,13 @@ genFold'' len left (Left res) f [folded_f, start, vec] = do
       argexpr1 <- MonadState.lift vsType $ varToVHDLExpr start
       -- Input from vec[current n]
       let argexpr2 = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName vec) n_cur
-      app_concsms <- genApplication (Right resname) folded_f  ( if left then
+      (app_concsms, used) <- genApplication (Right resname) folded_f  ( if left then
                                                                   [Right argexpr1, Right argexpr2]
                                                                 else
                                                                   [Right argexpr2, Right argexpr1]
                                                               )
       -- Return the conditional generate part
-      return $ AST.GenerateSm cond_label cond_scheme [] app_concsms
+      return $ (AST.GenerateSm cond_label cond_scheme [] app_concsms, used)
 
     genOtherCell = do
       len <- MonadState.lift vsType $ tfp_to_int $ (tfvec_len_ty . Var.varType) vec
@@ -374,17 +545,17 @@ genFold'' len left (Left res) f [folded_f, start, vec] = do
       let argexpr1 = vhdlNameToVHDLExpr $ mkIndexedName tmp_name n_prev
       -- Input from vec[current n]
       let argexpr2 = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName vec) n_cur
-      app_concsms <- genApplication (Right resname) folded_f  ( if left then
+      (app_concsms, used) <- genApplication (Right resname) folded_f  ( if left then
                                                                   [Right argexpr1, Right argexpr2]
                                                                 else
                                                                   [Right argexpr2, Right argexpr1]
                                                               )
       -- Return the conditional generate part
-      return $ AST.GenerateSm cond_label cond_scheme [] app_concsms
+      return $ (AST.GenerateSm cond_label cond_scheme [] app_concsms, used)
 
 -- | Generate a generate statement for the builtin function "zip"
 genZip :: BuiltinBuilder
-genZip = genVarArgs genZip'
+genZip = genNoInsts $ genVarArgs genZip'
 genZip' :: (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> VHDLSession [AST.ConcSm]
 genZip' (Left res) f args@[arg1, arg2] = do {
     -- Setup the generate scheme
@@ -411,7 +582,7 @@ genZip' (Left res) f args@[arg1, arg2] = do {
     
 -- | Generate a generate statement for the builtin function "unzip"
 genUnzip :: BuiltinBuilder
-genUnzip = genVarArgs genUnzip'
+genUnzip = genNoInsts $ genVarArgs genUnzip'
 genUnzip' :: (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> VHDLSession [AST.ConcSm]
 genUnzip' (Left res) f args@[arg] = do {
     -- Setup the generate scheme
@@ -439,7 +610,7 @@ genUnzip' (Left res) f args@[arg] = do {
   }
 
 genCopy :: BuiltinBuilder 
-genCopy = genVarArgs genCopy'
+genCopy = genNoInsts $ genVarArgs genCopy'
 genCopy' :: (Either CoreSyn.CoreBndr AST.VHDLName ) -> CoreSyn.CoreBndr -> [Var.Var] -> VHDLSession [AST.ConcSm]
 genCopy' (Left res) f args@[arg] =
   let
@@ -450,7 +621,7 @@ genCopy' (Left res) f args@[arg] =
     return [out_assign]
     
 genConcat :: BuiltinBuilder
-genConcat = genVarArgs genConcat'
+genConcat = genNoInsts $ genVarArgs genConcat'
 genConcat' :: (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> VHDLSession [AST.ConcSm]
 genConcat' (Left res) f args@[arg] = do {
     -- Setup the generate scheme
@@ -493,14 +664,14 @@ genGenerate = genIterateOrGenerate False
 genIterateOrGenerate :: Bool -> BuiltinBuilder
 genIterateOrGenerate iter = genVarArgs (genIterateOrGenerate' iter)
 
-genIterateOrGenerate' :: Bool -> (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> VHDLSession [AST.ConcSm]
+genIterateOrGenerate' :: Bool -> (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> VHDLSession ([AST.ConcSm], [CoreSyn.CoreBndr])
 genIterateOrGenerate' iter (Left res) f args = do
   len <- MonadState.lift vsType $ tfp_to_int ((tfvec_len_ty . Var.varType) res)
   genIterateOrGenerate'' len iter (Left res) f args
 
-genIterateOrGenerate'' :: Int -> Bool -> (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> VHDLSession [AST.ConcSm]
+genIterateOrGenerate'' :: Int -> Bool -> (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> VHDLSession ([AST.ConcSm], [CoreSyn.CoreBndr])
 -- Special case for an empty input vector, just assign start to res
-genIterateOrGenerate'' len iter (Left res) _ [app_f, start] | len == 0 = return [mkUncondAssign (Left res) (AST.PrimLit "\"\"")]
+genIterateOrGenerate'' len iter (Left res) _ [app_f, start] | len == 0 = return ([mkUncondAssign (Left res) (AST.PrimLit "\"\"")], [])
 
 genIterateOrGenerate'' len iter (Left res) f [app_f, start] = do
   -- The vector length
@@ -522,12 +693,13 @@ genIterateOrGenerate'' len iter (Left res) f [app_f, start] = do
   -- Make the intermediate vector
   let  tmp_dec     = AST.BDISD $ AST.SigDec tmp_id tmp_vhdl_ty Nothing
   -- Create the generate statement
-  cells <- sequence [genFirstCell, genOtherCell]
+  cells' <- sequence [genFirstCell, genOtherCell]
+  let (cells, useds) = unzip cells'
   let gen_sm = AST.GenerateSm gen_label gen_scheme [] (map AST.CSGSm cells)
   -- Assign tmp[len-1] or tmp[0] to res
   let out_assign = mkUncondAssign (Left res) $ vhdlNameToVHDLExpr tmp_name    
   let block = AST.BlockSm block_label [] (AST.PMapAspect []) [tmp_dec] [AST.CSGSm gen_sm, out_assign]
-  return [AST.CSBSm block]
+  return ([AST.CSBSm block], concat useds)
   where
     -- An id for the counter
     n_id = mkVHDLBasicId "n"
@@ -538,7 +710,7 @@ genIterateOrGenerate'' len iter (Left res) f [app_f, start] = do
     tmp_id = mkVHDLBasicId "tmp"
     tmp_name = AST.NSimple tmp_id
     -- Generate parts of the fold
-    genFirstCell, genOtherCell :: VHDLSession AST.GenerateSm
+    genFirstCell, genOtherCell :: VHDLSession (AST.GenerateSm, [CoreSyn.CoreBndr])
     genFirstCell = do
       let cond_label = mkVHDLExtId "firstcell"
       -- if n == 0 or n == len-1
@@ -548,13 +720,14 @@ genIterateOrGenerate'' len iter (Left res) f [app_f, start] = do
       -- Input from start
       argexpr <- MonadState.lift vsType $ varToVHDLExpr start
       let startassign = mkUncondAssign (Right resname) argexpr
-      app_concsms <- genApplication (Right resname) app_f  [Right argexpr]
+      (app_concsms, used) <- genApplication (Right resname) app_f  [Right argexpr]
       -- Return the conditional generate part
-      return $ AST.GenerateSm cond_label cond_scheme [] (if iter then 
+      let gensm = AST.GenerateSm cond_label cond_scheme [] (if iter then 
                                                           [startassign]
                                                          else 
                                                           app_concsms
                                                         )
+      return (gensm, used)
 
     genOtherCell = do
       let cond_label = mkVHDLExtId "othercell"
@@ -564,9 +737,9 @@ genIterateOrGenerate'' len iter (Left res) f [app_f, start] = do
       let resname = mkIndexedName tmp_name n_cur
       -- Input from tmp[previous n]
       let argexpr = vhdlNameToVHDLExpr $ mkIndexedName tmp_name n_prev
-      app_concsms <- genApplication (Right resname) app_f [Right argexpr]
+      (app_concsms, used) <- genApplication (Right resname) app_f [Right argexpr]
       -- Return the conditional generate part
-      return $ AST.GenerateSm cond_label cond_scheme [] app_concsms
+      return $ (AST.GenerateSm cond_label cond_scheme [] app_concsms, used)
 
 
 -----------------------------------------------------------------------------
@@ -576,31 +749,32 @@ 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
+  -> TranslatorSession ([AST.ConcSm], [CoreSyn.CoreBndr]) 
+  -- ^ The corresponding VHDL concurrent statements and entities
+  --   instantiated.
 genApplication dst f args = do
   case Var.isGlobalId f of
-    False -> 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.
-      case (Map.lookup f signatures) of
-        Just signature -> do
-          args' <- eitherCoreOrExprArgs args
-          -- We have a signature, this is a top level binding. Generate a
+    False -> do 
+      top <- isTopLevelBinder f
+      case top of
+        True -> do
+          -- Local binder that references a top level binding.  Generate a
           -- component instantiation.
+          signature <- getEntity f
+          args' <- eitherCoreOrExprArgs args
           let entity_id = ent_id signature
           -- TODO: Using show here isn't really pretty, but we'll need some
           -- unique-ish value...
           let label = "comp_ins_" ++ (either show prettyShow) dst
           let portmaps = mkAssocElems args' ((either varToVHDLName id) dst) signature
-          return [mkComponentInst label entity_id portmaps]
-        Nothing -> do
-          -- No signature, so this must be a local variable reference. It
-          -- should have a representable type (and thus, no arguments) and a
-          -- signal should be generated for it. Just generate an
-          -- unconditional assignment here.
+          return ([mkComponentInst label entity_id portmaps], [f])
+        False -> do
+          -- Not a top level binder, so this must be a local variable reference.
+          -- It should have a representable type (and thus, no arguments) and a
+          -- signal should be generated for it. Just generate an unconditional
+          -- assignment here.
           f' <- MonadState.lift vsType $ varToVHDLExpr f
-          return $ [mkUncondAssign dst f']
+          return $ ([mkUncondAssign dst f'], [])
     True ->
       case Var.idDetails f of
         IdInfo.DataConWorkId dc -> case dst of
@@ -609,7 +783,7 @@ genApplication dst f args = do
             -- We have the bndr, so we can get at the type
             labels <- MonadState.lift vsType $ getFieldLabels (Var.varType bndr)
             args' <- eitherCoreOrExprArgs args
-            return $ zipWith mkassign labels $ args'
+            return $ (zipWith mkassign labels $ args', [])
             where
               mkassign :: AST.VHDLId -> AST.Expr -> AST.ConcSm
               mkassign label arg =
@@ -1041,6 +1215,19 @@ genUnconsVectorFuns elemTM vectorTM  =
 -- A table of builtin functions
 -----------------------------------------------------------------------------
 
+-- A function that generates VHDL for a builtin function
+type BuiltinBuilder = 
+  (Either CoreSyn.CoreBndr AST.VHDLName) -- ^ The destination signal and it's original type
+  -> CoreSyn.CoreBndr -- ^ The function called
+  -> [Either CoreSyn.CoreExpr AST.Expr] -- ^ The value arguments passed (excluding type and
+                    --   dictionary arguments).
+  -> TranslatorSession ([AST.ConcSm], [CoreSyn.CoreBndr]) 
+  -- ^ The corresponding VHDL concurrent statements and entities
+  --   instantiated.
+
+-- A map of a builtin function to VHDL function builder 
+type NameTable = Map.Map String (Int, BuiltinBuilder )
+
 -- | The builtin functions we support. Maps a name to an argument count and a
 -- builder function.
 globalNameTable :: NameTable
@@ -1091,5 +1278,5 @@ globalNameTable = Map.fromList
   , (fromIntegerId    , (1, genFromInteger          ) )
   , (resizeId         , (1, genResize               ) )
   , (sizedIntId       , (1, genSizedInt             ) )
-  , (tfvecId          , (1, genTFVec                ) )
+  --, (tfvecId          , (1, genTFVec                ) )
   ]
index 9c10afd93349c805eb676bf36f4ec41f03b77db7..3991a3f3110e1fe25fd847f117c072934d4f414e 100644 (file)
@@ -30,6 +30,7 @@ import qualified CoreSubst
 
 -- Local imports
 import CLasH.VHDL.VHDLTypes
+import CLasH.Translator.TranslatorTypes
 import CLasH.Utils.Core.CoreTools
 import CLasH.Utils.Pretty
 import CLasH.VHDL.Constants
index 52adab7f944dfbeb8b164ed0983eda67a6216053..64fb7ab10bd8d063a9954997946e3e34bfbcb5cb 100644 (file)
@@ -11,8 +11,6 @@ import Data.Accessor
 import qualified Data.Accessor.Template
 
 -- GHC API imports
-import qualified Type
-import qualified CoreSyn
 import qualified HscTypes
 
 -- ForSyDe imports
@@ -29,75 +27,10 @@ type Port = (AST.VHDLId, AST.TypeMark)
 data Entity = Entity { 
   ent_id     :: AST.VHDLId,           -- The id of the entity
   ent_args   :: [Port],      -- A mapping of each function argument to port names
-  ent_res    :: Port         -- A mapping of the function result to port names
+  ent_res    :: Port,         -- A mapping of the function result to port names
+  ent_dec    :: AST.EntityDec -- ^ The complete entity declaration
 } deriving (Show);
 
--- A orderable equivalent of CoreSyn's Type for use as a map key
-newtype OrdType = OrdType { getType :: Type.Type }
-instance Eq OrdType where
-  (OrdType a) == (OrdType b) = Type.tcEqType a b
-instance Ord OrdType where
-  compare (OrdType a) (OrdType b) = Type.tcCmpType a b
-
-data HType = StdType OrdType |
-             ADTType String [HType] |
-             VecType Int HType |
-             SizedWType Int |
-             RangedWType Int |
-             SizedIType Int |
-             BuiltinType String
-  deriving (Eq, Ord)
-
--- A map of a Core type to the corresponding type name
-type TypeMap = Map.Map HType (AST.VHDLId, Either AST.TypeDef AST.SubtypeIn)
-
--- A map of a vector Core element type and function name to the coressponding
--- VHDLId of the function and the function body.
-type TypeFunMap = Map.Map (OrdType, String) (AST.VHDLId, AST.SubProgBody)
-
--- A map of a Haskell function to a hardware signature
-type SignatureMap = Map.Map CoreSyn.CoreBndr Entity
-
-type TfpIntMap = Map.Map OrdType Int
-
-data TypeState = TypeState {
-  -- | A map of Core type -> VHDL Type
-  vsTypes_      :: TypeMap,
-  -- | A list of type declarations
-  vsTypeDecls_  :: [AST.PackageDecItem],
-  -- | A map of vector Core type -> VHDL type function
-  vsTypeFuns_   :: TypeFunMap,
-  vsTfpInts_    :: TfpIntMap,
-  vsHscEnv_     :: HscTypes.HscEnv
-}
--- Derive accessors
-$( Data.Accessor.Template.deriveAccessors ''TypeState )
--- Define a session
-type TypeSession = State.State TypeState
-
-data VHDLState = VHDLState {
-  -- | A subtype with typing info
-  vsType_       :: TypeState,
-  -- | A map of HsFunction -> hardware signature (entity name, port names,
-  --   etc.)
-  vsSignatures_ :: SignatureMap
-}
-
--- Derive accessors
-$( Data.Accessor.Template.deriveAccessors ''VHDLState )
-
--- | The state containing a VHDL Session
-type VHDLSession = State.State VHDLState
-
--- A function that generates VHDL for a builtin function
-type BuiltinBuilder = 
-  (Either CoreSyn.CoreBndr AST.VHDLName) -- ^ The destination signal and it's original type
-  -> CoreSyn.CoreBndr -- ^ The function called
-  -> [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 
-type NameTable = Map.Map String (Int, BuiltinBuilder )
+type Architecture = AST.ArchBody
 
 -- vim: set ts=8 sw=2 sts=2 expandtab: