Merge branch 'master' of git://github.com/christiaanb/clash
authorMatthijs Kooijman <matthijs@stdin.nl>
Tue, 8 Jun 2010 13:48:06 +0000 (15:48 +0200)
committerMatthijs Kooijman <matthijs@stdin.nl>
Tue, 8 Jun 2010 13:48:06 +0000 (15:48 +0200)
* 'master' of git://github.com/christiaanb/clash:
  Do not be overzealous with inlining results of polymorphic functions
  Do not function extract functions that still have free type variables
  Add setup file
  Fix cabal file to reflect temp bug fixes
  Temporarily disable "inlinenonrepresult" transformation, and apply eta-expansion transformation to all expressions
  Rename cλash dir to clash so it behaves well within the ghc build tree
  update cabal file to upload to hackage
  Remove defunct makeVHDLStrings function, messes with haddock
  Update reducer to use new integer types
  Reflect moving TFVec and TFP Integers into clash in sourcefiles related to builtin types
  Update package dependencies
  Move TFVec and TFP integers (Signed, Unsiged and Index) into clash

53 files changed:
clash/CLasH/HardwareTypes.hs [new file with mode: 0644]
clash/CLasH/Normalize.hs [new file with mode: 0644]
clash/CLasH/Normalize/NormalizeTools.hs [new file with mode: 0644]
clash/CLasH/Normalize/NormalizeTypes.hs [new file with mode: 0644]
clash/CLasH/Translator.hs [new file with mode: 0644]
clash/CLasH/Translator/Annotations.hs [new file with mode: 0644]
clash/CLasH/Translator/TranslatorTypes.hs [new file with mode: 0644]
clash/CLasH/Utils.hs [new file with mode: 0644]
clash/CLasH/Utils/Core/BinderTools.hs [new file with mode: 0644]
clash/CLasH/Utils/Core/CoreShow.hs [new file with mode: 0644]
clash/CLasH/Utils/Core/CoreTools.hs [new file with mode: 0644]
clash/CLasH/Utils/GhcTools.hs [new file with mode: 0644]
clash/CLasH/Utils/HsTools.hs [new file with mode: 0644]
clash/CLasH/Utils/Pretty.hs [new file with mode: 0644]
clash/CLasH/VHDL.hs [new file with mode: 0644]
clash/CLasH/VHDL/Constants.hs [new file with mode: 0644]
clash/CLasH/VHDL/Generate.hs [new file with mode: 0644]
clash/CLasH/VHDL/Testbench.hs [new file with mode: 0644]
clash/CLasH/VHDL/VHDLTools.hs [new file with mode: 0644]
clash/CLasH/VHDL/VHDLTypes.hs [new file with mode: 0644]
clash/Data/Param/Index.hs [new file with mode: 0644]
clash/Data/Param/Integer.hs [new file with mode: 0644]
clash/Data/Param/Signed.hs [new file with mode: 0644]
clash/Data/Param/Unsigned.hs [new file with mode: 0644]
clash/Data/Param/Vector.hs [new file with mode: 0644]
clash/LICENSE [new file with mode: 0644]
clash/Setup.lhs [new file with mode: 0644]
clash/clash.cabal [new file with mode: 0644]
clash/ghc-stage [new file with mode: 0644]
cλash/CLasH/HardwareTypes.hs [deleted file]
cλash/CLasH/Normalize.hs [deleted file]
cλash/CLasH/Normalize/NormalizeTools.hs [deleted file]
cλash/CLasH/Normalize/NormalizeTypes.hs [deleted file]
cλash/CLasH/Translator.hs [deleted file]
cλash/CLasH/Translator/Annotations.hs [deleted file]
cλash/CLasH/Translator/TranslatorTypes.hs [deleted file]
cλash/CLasH/Utils.hs [deleted file]
cλash/CLasH/Utils/Core/BinderTools.hs [deleted file]
cλash/CLasH/Utils/Core/CoreShow.hs [deleted file]
cλash/CLasH/Utils/Core/CoreTools.hs [deleted file]
cλash/CLasH/Utils/GhcTools.hs [deleted file]
cλash/CLasH/Utils/HsTools.hs [deleted file]
cλash/CLasH/Utils/Pretty.hs [deleted file]
cλash/CLasH/VHDL.hs [deleted file]
cλash/CLasH/VHDL/Constants.hs [deleted file]
cλash/CLasH/VHDL/Generate.hs [deleted file]
cλash/CLasH/VHDL/Testbench.hs [deleted file]
cλash/CLasH/VHDL/VHDLTools.hs [deleted file]
cλash/CLasH/VHDL/VHDLTypes.hs [deleted file]
cλash/LICENSE [deleted file]
cλash/clash.cabal [deleted file]
cλash/ghc-stage [deleted file]
reducer.hs

diff --git a/clash/CLasH/HardwareTypes.hs b/clash/CLasH/HardwareTypes.hs
new file mode 100644 (file)
index 0000000..2912e50
--- /dev/null
@@ -0,0 +1,93 @@
+{-# LANGUAGE TemplateHaskell, DeriveDataTypeable, FlexibleContexts, TypeFamilies, TypeOperators #-}
+
+module CLasH.HardwareTypes
+  ( module Types
+  , module Data.Param.Vector
+  , module Data.Param.Index
+  , module Data.Param.Signed
+  , module Data.Param.Unsigned
+  , module Prelude
+  , Bit(..)
+  , State(..)
+  , resizeInt
+  , resizeWord
+  , hwand
+  , hwor
+  , hwxor
+  , hwnot
+  , RAM
+  , MemState
+  , blockRAM
+  ) where
+
+import qualified Prelude as P
+import Prelude hiding (
+  null, length, head, tail, last, init, take, drop, (++), map, foldl, foldr,
+  zipWith, zip, unzip, concat, reverse, iterate )
+import Types
+import Data.Param.Vector
+import Data.Param.Index
+import qualified Data.Param.Signed as Signed
+import Data.Param.Signed hiding (resize)
+import qualified Data.Param.Unsigned as Unsigned
+import Data.Param.Unsigned hiding (resize) 
+
+import Language.Haskell.TH.Lift
+import Data.Typeable
+
+newtype State s = State s deriving (P.Show)
+
+resizeInt :: (NaturalT nT, NaturalT nT') => Signed nT -> Signed nT'
+resizeInt = Signed.resize
+
+resizeWord :: (NaturalT nT, NaturalT nT') => Unsigned nT -> Unsigned nT'
+resizeWord = Unsigned.resize
+
+-- The plain Bit type
+data Bit = High | Low
+  deriving (P.Show, P.Eq, P.Read, Typeable)
+
+deriveLift ''Bit
+
+hwand :: Bit -> Bit -> Bit
+hwor  :: Bit -> Bit -> Bit
+hwxor :: Bit -> Bit -> Bit
+hwnot :: Bit -> Bit
+
+High `hwand` High = High
+_ `hwand` _ = Low
+
+High `hwor` _  = High
+_ `hwor` High  = High
+Low `hwor` Low = Low
+
+High `hwxor` Low = High
+Low `hwxor` High = High
+_ `hwxor` _      = Low
+
+hwnot High = Low
+hwnot Low  = High
+
+type RAM s a          = Vector (s :+: D1) a
+
+type MemState s a      = State (RAM s a)
+
+blockRAM :: 
+  (NaturalT s
+  ,PositiveT (s :+: D1)
+  ,((s :+: D1) :>: s) ~ True ) =>
+  (MemState s a) -> 
+  a ->
+  Index s ->
+  Index s ->
+  Bool -> 
+  ((MemState s a), a )
+blockRAM (State mem) data_in rdaddr wraddr wrenable = 
+  ((State mem'), data_out)
+  where
+    data_out  = mem!rdaddr
+    -- Only write data_in to memory if write is enabled
+    mem' =  if wrenable then
+              replace mem wraddr data_in
+            else
+              mem
diff --git a/clash/CLasH/Normalize.hs b/clash/CLasH/Normalize.hs
new file mode 100644 (file)
index 0000000..11212f9
--- /dev/null
@@ -0,0 +1,1051 @@
+--
+-- Functions to bring a Core expression in normal form. This module provides a
+-- top level function "normalize", and defines the actual transformation passes that
+-- are performed.
+--
+module CLasH.Normalize (getNormalized, normalizeExpr, splitNormalized) where
+
+-- Standard modules
+import Debug.Trace
+import qualified Maybe
+import qualified List
+import qualified Control.Monad.Trans.Class as Trans
+import qualified Control.Monad as Monad
+import qualified Control.Monad.Trans.Writer as Writer
+import qualified Data.Accessor.Monad.Trans.State as MonadState
+import qualified Data.Monoid as Monoid
+import qualified Data.Map as Map
+
+-- GHC API
+import CoreSyn
+import qualified CoreUtils
+import qualified BasicTypes
+import qualified Type
+import qualified TysWiredIn
+import qualified Id
+import qualified Var
+import qualified Name
+import qualified DataCon
+import qualified VarSet
+import qualified CoreFVs
+import qualified Class
+import qualified MkCore
+import Outputable ( showSDoc, ppr, nest )
+
+-- Local imports
+import CLasH.Normalize.NormalizeTypes
+import CLasH.Translator.TranslatorTypes
+import CLasH.Normalize.NormalizeTools
+import CLasH.VHDL.Constants (builtinIds)
+import qualified CLasH.Utils as Utils
+import CLasH.Utils.Core.CoreTools
+import CLasH.Utils.Core.BinderTools
+import CLasH.Utils.Pretty
+
+----------------------------------------------------------------
+-- Cleanup transformations
+----------------------------------------------------------------
+
+--------------------------------
+-- β-reduction
+--------------------------------
+beta :: Transform
+-- Substitute arg for x in expr. For value lambda's, also clone before
+-- substitution.
+beta c (App (Lam x expr) arg) | CoreSyn.isTyVar x = setChanged >> substitute x arg c expr
+                              | otherwise         = setChanged >> substitute_clone x arg c expr
+-- Leave all other expressions unchanged
+beta c expr = return expr
+
+--------------------------------
+-- Unused let binding removal
+--------------------------------
+letremoveunused :: Transform
+letremoveunused c expr@(Let (NonRec b bound) res) = do
+  let used = expr_uses_binders [b] res
+  if used
+    then return expr
+    else change res
+letremoveunused c expr@(Let (Rec binds) res) = do
+  -- Filter out all unused binds.
+  let binds' = filter dobind binds
+  -- Only set the changed flag if binds got removed
+  changeif (length binds' /= length binds) (Let (Rec binds') res)
+    where
+      bound_exprs = map snd binds
+      -- For each bind check if the bind is used by res or any of the bound
+      -- expressions
+      dobind (bndr, _) = any (expr_uses_binders [bndr]) (res:bound_exprs)
+-- Leave all other expressions unchanged
+letremoveunused c expr = return expr
+
+--------------------------------
+-- empty let removal
+--------------------------------
+-- Remove empty (recursive) lets
+letremove :: Transform
+letremove c (Let (Rec []) res) = change res
+-- Leave all other expressions unchanged
+letremove c expr = return expr
+
+--------------------------------
+-- Simple let binding removal
+--------------------------------
+-- Remove a = b bindings from let expressions everywhere
+letremovesimple :: Transform
+letremovesimple = inlinebind (\(b, e) -> Trans.lift $ is_local_var e)
+
+--------------------------------
+-- Cast propagation
+--------------------------------
+-- Try to move casts as much downward as possible.
+castprop :: Transform
+castprop c (Cast (Let binds expr) ty) = change $ Let binds (Cast expr ty)
+castprop c expr@(Cast (Case scrut b _ alts) ty) = change (Case scrut b ty alts')
+  where
+    alts' = map (\(con, bndrs, expr) -> (con, bndrs, (Cast expr ty))) alts
+-- Leave all other expressions unchanged
+castprop c expr = return expr
+
+--------------------------------
+-- Cast simplification. Mostly useful for state packing and unpacking, but
+-- perhaps for others as well.
+--------------------------------
+castsimpl :: Transform
+castsimpl c expr@(Cast val ty) = do
+  -- Don't extract values that are already simpl
+  local_var <- Trans.lift $ is_local_var val
+  -- Don't extract values that are not representable, to prevent loops with
+  -- inlinenonrep
+  repr <- isRepr val
+  if (not local_var) && repr
+    then do
+      -- Generate a binder for the expression
+      id <- Trans.lift $ mkBinderFor val "castval"
+      -- Extract the expression
+      change $ Let (NonRec id val) (Cast (Var id) ty)
+    else
+      return expr
+-- Leave all other expressions unchanged
+castsimpl c expr = return expr
+
+--------------------------------
+-- Top level function inlining
+--------------------------------
+-- This transformation inlines simple top level bindings. Simple
+-- currently means that the body is only a single application (though
+-- the complexity of the arguments is not currently checked) or that the
+-- normalized form only contains a single binding. This should catch most of the
+-- cases where a top level function is created that simply calls a type class
+-- method with a type and dictionary argument, e.g.
+--   fromInteger = GHC.Num.fromInteger (SizedWord D8) $dNum
+-- which is later called using simply
+--   fromInteger (smallInteger 10)
+--
+-- These useless wrappers are created by GHC automatically. If we don't
+-- inline them, we get loads of useless components cluttering the
+-- generated VHDL.
+--
+-- Note that the inlining could also inline simple functions defined by
+-- the user, not just GHC generated functions. It turns out to be near
+-- impossible to reliably determine what functions are generated and
+-- what functions are user-defined. Instead of guessing (which will
+-- inline less than we want) we will just inline all simple functions.
+--
+-- Only functions that are actually completely applied and bound by a
+-- variable in a let expression are inlined. These are the expressions
+-- that will eventually generate instantiations of trivial components.
+-- By not inlining any other reference, we also prevent looping problems
+-- with funextract and inlinedict.
+inlinetoplevel :: Transform
+inlinetoplevel (LetBinding:_) expr | not (is_fun expr) =
+  case collectArgs expr of
+       (Var f, args) -> do
+         body_maybe <- needsInline f
+         case body_maybe of
+               Just body -> do
+                       -- Regenerate all uniques in the to-be-inlined expression
+                       body_uniqued <- Trans.lift $ genUniques body
+                       -- And replace the variable reference with the unique'd body.
+                       change (mkApps body_uniqued args)
+                       -- No need to inline
+               Nothing -> return expr
+       -- This is not an application of a binder, leave it unchanged.
+       _ -> return expr
+
+-- Leave all other expressions unchanged
+inlinetoplevel c expr = return expr
+
+-- | Does the given binder need to be inlined? If so, return the body to
+-- be used for inlining.
+needsInline :: CoreBndr -> TransformMonad (Maybe CoreExpr)
+needsInline f = do
+  body_maybe <- Trans.lift $ getGlobalBind f
+  case body_maybe of
+    -- No body available?
+    Nothing -> return Nothing
+    Just body -> case CoreSyn.collectArgs body of
+      -- The body is some (top level) binder applied to 0 or more
+      -- arguments. That should be simple enough to inline.
+      (Var f, args) -> return $ Just body
+      -- Body is more complicated, try normalizing it
+      _ -> do
+        norm_maybe <- Trans.lift $ getNormalized_maybe False f
+        case norm_maybe of
+          -- Noth normalizeable
+          Nothing -> return Nothing 
+          Just norm -> case splitNormalizedNonRep norm of
+            -- The function has just a single binding, so that's simple
+            -- enough to inline.
+            (args, [bind], Var res) -> return $ Just norm
+            -- More complicated function, don't inline
+            _ -> return Nothing
+
+
+----------------------------------------------------------------
+-- Program structure transformations
+----------------------------------------------------------------
+
+--------------------------------
+-- η expansion
+--------------------------------
+-- Make sure all parameters to the normalized functions are named by top
+-- level lambda expressions. For this we apply η expansion to the
+-- function body (possibly enclosed in some lambda abstractions) while
+-- it has a function type. Eventually this will result in a function
+-- body consisting of a bunch of nested lambdas containing a
+-- non-function value (e.g., a complete application).
+eta :: Transform
+eta (AppFirst:_) expr = return expr
+-- Also don't apply to arguments, since this can cause loops with
+-- funextract. This isn't the proper solution, but due to an
+-- implementation bug in notappargs, this is how it used to work so far.
+eta (AppSecond:_) expr = return expr
+eta c expr | is_fun expr && not (is_lam expr) = do
+ let arg_ty = (fst . Type.splitFunTy . CoreUtils.exprType) expr
+ id <- Trans.lift $ mkInternalVar "param" arg_ty
+ change (Lam id (App expr (Var id)))
+-- Leave all other expressions unchanged
+eta c e = return e
+
+--------------------------------
+-- Application propagation
+--------------------------------
+-- Move applications into let and case expressions.
+appprop :: Transform
+-- Propagate the application into the let
+appprop c (App (Let binds expr) arg) = change $ Let binds (App expr arg)
+-- Propagate the application into each of the alternatives
+appprop c (App (Case scrut b ty alts) arg) = change $ Case scrut b ty' alts'
+  where 
+    alts' = map (\(con, bndrs, expr) -> (con, bndrs, (App expr arg))) alts
+    ty' = CoreUtils.applyTypeToArg ty arg
+-- Leave all other expressions unchanged
+appprop c expr = return expr
+
+--------------------------------
+-- Let recursification
+--------------------------------
+-- Make all lets recursive, so other transformations don't need to
+-- handle non-recursive lets
+letrec :: Transform
+letrec c expr@(Let (NonRec bndr val) res) = 
+  change $ Let (Rec [(bndr, val)]) res
+
+-- Leave all other expressions unchanged
+letrec c expr = return expr
+
+--------------------------------
+-- let flattening
+--------------------------------
+-- Takes a let that binds another let, and turns that into two nested lets.
+-- e.g., from:
+-- let b = (let b' = expr' in res') in res
+-- to:
+-- let b' = expr' in (let b = res' in res)
+letflat :: Transform
+-- Turn a nonrec let that binds a let into two nested lets.
+letflat c (Let (NonRec b (Let binds  res')) res) = 
+  change $ Let binds (Let (NonRec b res') res)
+letflat c (Let (Rec binds) expr) = do
+  -- Flatten each binding.
+  binds' <- Utils.concatM $ Monad.mapM flatbind binds
+  -- Return the new let. We don't use change here, since possibly nothing has
+  -- changed. If anything has changed, flatbind has already flagged that
+  -- change.
+  return $ Let (Rec binds') expr
+  where
+    -- Turns a binding of a let into a multiple bindings, or any other binding
+    -- into a list with just that binding
+    flatbind :: (CoreBndr, CoreExpr) -> TransformMonad [(CoreBndr, CoreExpr)]
+    flatbind (b, Let (Rec binds) expr) = change ((b, expr):binds)
+    flatbind (b, Let (NonRec b' expr') expr) = change [(b, expr), (b', expr')]
+    flatbind (b, expr) = return [(b, expr)]
+-- Leave all other expressions unchanged
+letflat c expr = return expr
+
+--------------------------------
+-- Return value simplification
+--------------------------------
+-- Ensure the return value of a function follows proper normal form. eta
+-- expansion ensures the body starts with lambda abstractions, this
+-- transformation ensures that the lambda abstractions always contain a
+-- recursive let and that, when the return value is representable, the
+-- let contains a local variable reference in its body.
+
+-- Extract the return value from the body of the top level lambdas (of
+-- which ther could be zero), unless it is a let expression (in which
+-- case the next clause applies).
+retvalsimpl c expr | all (== LambdaBody) c && not (is_lam expr) && not (is_let expr) = do
+  local_var <- Trans.lift $ is_local_var expr
+  repr <- isRepr expr
+  if not local_var && repr
+    then do
+      id <- Trans.lift $ mkBinderFor expr "res" 
+      change $ Let (Rec [(id, expr)]) (Var id)
+    else
+      return expr
+-- Extract the return value from the body of a let expression, which is
+-- itself the body of the top level lambdas (of which there could be
+-- zero).
+retvalsimpl c expr@(Let (Rec binds) body) | all (== LambdaBody) c = do
+  -- Don't extract values that are already a local variable, to prevent
+  -- loops with ourselves.
+  local_var <- Trans.lift $ is_local_var body
+  -- Don't extract values that are not representable, to prevent loops with
+  -- inlinenonrep
+  repr <- isRepr body
+  if not local_var && repr
+    then do
+      id <- Trans.lift $ mkBinderFor body "res" 
+      change $ Let (Rec ((id, body):binds)) (Var id)
+    else
+      return expr
+-- Leave all other expressions unchanged
+retvalsimpl c expr = return expr
+
+--------------------------------
+-- Representable arguments simplification
+--------------------------------
+-- Make sure that all arguments of a representable type are simple variables.
+appsimpl :: Transform
+-- Simplify all representable arguments. Do this by introducing a new Let
+-- that binds the argument and passing the new binder in the application.
+appsimpl c expr@(App f arg) = do
+  -- Check runtime representability
+  repr <- isRepr arg
+  local_var <- Trans.lift $ is_local_var arg
+  if repr && not local_var
+    then do -- Extract representable arguments
+      id <- Trans.lift $ mkBinderFor arg "arg"
+      change $ Let (NonRec id arg) (App f (Var id))
+    else -- Leave non-representable arguments unchanged
+      return expr
+-- Leave all other expressions unchanged
+appsimpl c expr = return expr
+
+----------------------------------------------------------------
+-- Built-in function transformations
+----------------------------------------------------------------
+
+--------------------------------
+-- Function-typed argument extraction
+--------------------------------
+-- This transform takes any function-typed argument that cannot be propagated
+-- (because the function that is applied to it is a builtin function), and
+-- puts it in a brand new top level binder. This allows us to for example
+-- apply map to a lambda expression This will not conflict with inlinenonrep,
+-- since that only inlines local let bindings, not top level bindings.
+funextract :: Transform
+funextract c expr@(App _ _) | is_var fexpr = do
+  body_maybe <- Trans.lift $ getGlobalBind f
+  case body_maybe of
+    -- We don't have a function body for f, so we can perform this transform.
+    Nothing -> do
+      -- Find the new arguments
+      args' <- mapM doarg args
+      -- And update the arguments. We use return instead of changed, so the
+      -- changed flag doesn't get set if none of the args got changed.
+      return $ MkCore.mkCoreApps fexpr args'
+    -- We have a function body for f, leave this application to funprop
+    Just _ -> return expr
+  where
+    -- Find the function called and the arguments
+    (fexpr, args) = collectArgs expr
+    Var f = fexpr
+    -- Change any arguments that have a function type, but are not simple yet
+    -- (ie, a variable or application). This means to create a new function
+    -- for map (\f -> ...) b, but not for map (foo a) b.
+    --
+    -- We could use is_applicable here instead of is_fun, but I think
+    -- arguments to functions could only have forall typing when existential
+    -- typing is enabled. Not sure, though.
+    doarg arg | not (is_simple arg) && is_fun arg && not (has_free_tyvars arg) = do
+      -- Create a new top level binding that binds the argument. Its body will
+      -- be extended with lambda expressions, to take any free variables used
+      -- by the argument expression.
+      let free_vars = VarSet.varSetElems $ CoreFVs.exprFreeVars arg
+      let body = MkCore.mkCoreLams free_vars arg
+      id <- Trans.lift $ mkBinderFor body "fun"
+      Trans.lift $ addGlobalBind id body
+      -- Replace the argument with a reference to the new function, applied to
+      -- all vars it uses.
+      change $ MkCore.mkCoreApps (Var id) (map Var free_vars)
+    -- Leave all other arguments untouched
+    doarg arg = return arg
+
+-- Leave all other expressions unchanged
+funextract c expr = return expr
+
+
+
+
+----------------------------------------------------------------
+-- Case normalization transformations
+----------------------------------------------------------------
+
+--------------------------------
+-- Scrutinee simplification
+--------------------------------
+-- Make sure the scrutinee of a case expression is a local variable
+-- reference.
+scrutsimpl :: Transform
+-- Replace a case expression with a let that binds the scrutinee and a new
+-- simple scrutinee, but only when the scrutinee is representable (to prevent
+-- loops with inlinenonrep, though I don't think a non-representable scrutinee
+-- will be supported anyway...) and is not a local variable already.
+scrutsimpl c expr@(Case scrut b ty alts) = do
+  repr <- isRepr scrut
+  local_var <- Trans.lift $ is_local_var scrut
+  if repr && not local_var
+    then do
+      id <- Trans.lift $ mkBinderFor scrut "scrut"
+      change $ Let (NonRec id scrut) (Case (Var id) b ty alts)
+    else
+      return expr
+-- Leave all other expressions unchanged
+scrutsimpl c expr = return expr
+
+--------------------------------
+-- Scrutinee binder removal
+--------------------------------
+-- A case expression can have an extra binder, to which the scrutinee is bound
+-- after bringing it to WHNF. This is used for forcing evaluation of strict
+-- arguments. Since strictness does not matter for us (rather, everything is
+-- sort of strict), this binder is ignored when generating VHDL, and must thus
+-- be wild in the normal form.
+scrutbndrremove :: Transform
+-- If the scrutinee is already simple, and the bndr is not wild yet, replace
+-- all occurences of the binder with the scrutinee variable.
+scrutbndrremove c (Case (Var scrut) bndr ty alts) | bndr_used = do
+    alts' <- mapM subs_bndr alts
+    change $ Case (Var scrut) wild ty alts'
+  where
+    is_used (_, _, expr) = expr_uses_binders [bndr] expr
+    bndr_used = or $ map is_used alts
+    subs_bndr (con, bndrs, expr) = do
+      expr' <- substitute bndr (Var scrut) c expr
+      return (con, bndrs, expr')
+    wild = MkCore.mkWildBinder (Id.idType bndr)
+-- Leave all other expressions unchanged
+scrutbndrremove c expr = return expr
+
+--------------------------------
+-- Case normalization
+--------------------------------
+-- Turn a case expression with any number of alternatives with any
+-- number of non-wild binders into as set of case and let expressions,
+-- all of which are in normal form (e.g., a bunch of extractor case
+-- expressions to extract all fields from the scrutinee, a number of let
+-- bindings to bind each alternative and a single selector case to
+-- select the right value.
+casesimpl :: Transform
+-- This is already a selector case (or, if x does not appear in bndrs, a very
+-- simple case statement that will be removed by caseremove below). Just leave
+-- it be.
+casesimpl c expr@(Case scrut b ty [(con, bndrs, Var x)]) = return expr
+-- Make sure that all case alternatives have only wild binders and simple
+-- expressions.
+-- This is done by creating a new let binding for each non-wild binder, which
+-- is bound to a new simple selector case statement and for each complex
+-- expression. We do this only for representable types, to prevent loops with
+-- inlinenonrep.
+casesimpl c expr@(Case scrut bndr ty alts) | not bndr_used = do
+  (bindingss, alts') <- (Monad.liftM unzip) $ mapM doalt alts
+  let bindings = concat bindingss
+  -- Replace the case with a let with bindings and a case
+  let newlet = mkNonRecLets bindings (Case scrut bndr ty alts')
+  -- If there are no non-wild binders, or this case is already a simple
+  -- selector (i.e., a single alt with exactly one binding), already a simple
+  -- selector altan no bindings (i.e., no wild binders in the original case),
+  -- don't change anything, otherwise, replace the case.
+  if null bindings then return expr else change newlet 
+  where
+  -- Check if the scrutinee binder is used
+  is_used (_, _, expr) = expr_uses_binders [bndr] expr
+  bndr_used = or $ map is_used alts
+  -- Generate a single wild binder, since they are all the same
+  wild = MkCore.mkWildBinder
+  -- Wilden the binders of one alt, producing a list of bindings as a
+  -- sideeffect.
+  doalt :: CoreAlt -> TransformMonad ([(CoreBndr, CoreExpr)], CoreAlt)
+  doalt (con, bndrs, expr) = do
+    -- Make each binder wild, if possible
+    bndrs_res <- Monad.zipWithM dobndr bndrs [0..]
+    let (newbndrs, bindings_maybe) = unzip bndrs_res
+    -- Extract a complex expression, if possible. For this we check if any of
+    -- the new list of bndrs are used by expr. We can't use free_vars here,
+    -- since that looks at the old bndrs.
+    let uses_bndrs = not $ VarSet.isEmptyVarSet $ CoreFVs.exprSomeFreeVars (`elem` newbndrs) expr
+    (exprbinding_maybe, expr') <- doexpr expr uses_bndrs
+    -- Create a new alternative
+    let newalt = (con, newbndrs, expr')
+    let bindings = Maybe.catMaybes (bindings_maybe ++ [exprbinding_maybe])
+    return (bindings, newalt)
+    where
+      -- Make wild alternatives for each binder
+      wildbndrs = map (\bndr -> MkCore.mkWildBinder (Id.idType bndr)) bndrs
+      -- A set of all the binders that are used by the expression
+      free_vars = CoreFVs.exprSomeFreeVars (`elem` bndrs) expr
+      -- Look at the ith binder in the case alternative. Return a new binder
+      -- for it (either the same one, or a wild one) and optionally a let
+      -- binding containing a case expression.
+      dobndr :: CoreBndr -> Int -> TransformMonad (CoreBndr, Maybe (CoreBndr, CoreExpr))
+      dobndr b i = do
+        repr <- isRepr b
+        -- Is b wild (e.g., not a free var of expr. Since b is only in scope
+        -- in expr, this means that b is unused if expr does not use it.)
+        let wild = not (VarSet.elemVarSet b free_vars)
+        -- Create a new binding for any representable binder that is not
+        -- already wild and is representable (to prevent loops with
+        -- inlinenonrep).
+        if (not wild) && repr
+          then do
+            caseexpr <- Trans.lift $ mkSelCase scrut i
+            -- Create a new binder that will actually capture a value in this
+            -- case statement, and return it.
+            return (wildbndrs!!i, Just (b, caseexpr))
+          else 
+            -- Just leave the original binder in place, and don't generate an
+            -- extra selector case.
+            return (b, Nothing)
+      -- Process the expression of a case alternative. Accepts an expression
+      -- and whether this expression uses any of the binders in the
+      -- alternative. Returns an optional new binding and a new expression.
+      doexpr :: CoreExpr -> Bool -> TransformMonad (Maybe (CoreBndr, CoreExpr), CoreExpr)
+      doexpr expr uses_bndrs = do
+        local_var <- Trans.lift $ is_local_var expr
+        repr <- isRepr expr
+        -- Extract any expressions that do not use any binders from this
+        -- alternative, is not a local var already and is representable (to
+        -- prevent loops with inlinenonrep).
+        if (not uses_bndrs) && (not local_var) && repr
+          then do
+            id <- Trans.lift $ mkBinderFor expr "caseval"
+            -- We don't flag a change here, since casevalsimpl will do that above
+            -- based on Just we return here.
+            return (Just (id, expr), Var id)
+          else
+            -- Don't simplify anything else
+            return (Nothing, expr)
+-- Leave all other expressions unchanged
+casesimpl c expr = return expr
+
+--------------------------------
+-- Case removal
+--------------------------------
+-- Remove case statements that have only a single alternative and only wild
+-- binders.
+caseremove :: Transform
+-- Replace a useless case by the value of its single alternative
+caseremove c (Case scrut b ty [(con, bndrs, expr)]) | not usesvars = change expr
+    -- Find if any of the binders are used by expr
+    where usesvars = (not . VarSet.isEmptyVarSet . (CoreFVs.exprSomeFreeVars (`elem` b:bndrs))) expr
+-- Leave all other expressions unchanged
+caseremove c expr = return expr
+
+--------------------------------
+-- Case of known constructor simplification
+--------------------------------
+-- If a case expressions scrutinizes a datacon application, we can
+-- determine which alternative to use and remove the case alltogether.
+-- We replace it with a let expression the binds every binder in the
+-- alternative bound to the corresponding argument of the datacon. We do
+-- this instead of substituting the binders, to prevent duplication of
+-- work and preserve sharing wherever appropriate.
+knowncase :: Transform
+knowncase context expr@(Case scrut@(App _ _) bndr ty alts) | not bndr_used = do
+    case collectArgs scrut of
+      (Var f, args) -> case Id.isDataConId_maybe f of
+        -- Not a dataconstructor? Don't change anything (probably a
+        -- function, then)
+        Nothing -> return expr
+        Just dc -> do
+          let (altcon, bndrs, res) =  case List.find (\(altcon, bndrs, res) -> altcon == (DataAlt dc)) alts of
+                Just alt -> alt -- Return the alternative found
+                Nothing -> head alts -- If the datacon is not present, the first must be the default alternative
+          -- Double check if we have either the correct alternative, or
+          -- the default.
+          if altcon /= (DataAlt dc) && altcon /= DEFAULT then error ("Normalize.knowncase: Invalid core, datacon not found in alternatives and DEFAULT alternative is not first? " ++ pprString expr) else return ()
+          -- Find out how many arguments to drop (type variables and
+          -- predicates like dictionaries).
+          let (tvs, preds, _, _) = DataCon.dataConSig dc
+          let count = length tvs + length preds
+          -- Create a let expression that binds each of the binders in
+          -- this alternative to the corresponding argument of the data
+          -- constructor.
+          let binds = zip bndrs (drop count args)
+          change $ Let (Rec binds) res
+      _ -> return expr -- Scrutinee is not an application of a var
+  where
+    is_used (_, _, expr) = expr_uses_binders [bndr] expr
+    bndr_used = or $ map is_used alts
+
+-- Leave all other expressions unchanged
+knowncase c expr = return expr
+
+
+
+
+----------------------------------------------------------------
+-- Unrepresentable value removal transformations
+----------------------------------------------------------------
+
+--------------------------------
+-- Non-representable binding inlining
+--------------------------------
+-- Remove a = B bindings, with B of a non-representable type, from let
+-- expressions everywhere. This means that any value that we can't generate a
+-- signal for, will be inlined and hopefully turned into something we can
+-- represent.
+--
+-- This is a tricky function, which is prone to create loops in the
+-- transformations. To fix this, we make sure that no transformation will
+-- create a new let binding with a non-representable type. These other
+-- transformations will just not work on those function-typed values at first,
+-- but the other transformations (in particular β-reduction) should make sure
+-- that the type of those values eventually becomes representable.
+inlinenonrep :: Transform
+inlinenonrep = inlinebind ((Monad.liftM not) . isRepr . snd)
+
+--------------------------------
+-- Function specialization
+--------------------------------
+-- Remove all applications to non-representable arguments, by duplicating the
+-- function called with the non-representable parameter replaced by the free
+-- variables of the argument passed in.
+argprop :: Transform
+-- Transform any application of a named function (i.e., skip applications of
+-- lambda's). Also skip applications that have arguments with free type
+-- variables, since we can't inline those.
+argprop c expr@(App _ _) | is_var fexpr = do
+  -- Find the body of the function called
+  body_maybe <- Trans.lift $ getGlobalBind f
+  case body_maybe of
+    Just body -> do
+      -- Process each of the arguments in turn
+      (args', changed) <- Writer.listen $ mapM doarg args
+      -- See if any of the arguments changed
+      case Monoid.getAny changed of
+        True -> do
+          let (newargs', newparams', oldargs) = unzip3 args'
+          let newargs = concat newargs'
+          let newparams = concat newparams'
+          -- Create a new body that consists of a lambda for all new arguments and
+          -- the old body applied to some arguments.
+          let newbody = MkCore.mkCoreLams newparams (MkCore.mkCoreApps body oldargs)
+          -- Create a new function with the same name but a new body
+          newf <- Trans.lift $ mkFunction f newbody
+
+          Trans.lift $ MonadState.modify tsInitStates (\ismap ->
+            let init_state_maybe = Map.lookup f ismap in
+            case init_state_maybe of
+              Nothing -> ismap
+              Just init_state -> Map.insert newf init_state ismap)
+          -- Replace the original application with one of the new function to the
+          -- new arguments.
+          change $ MkCore.mkCoreApps (Var newf) newargs
+        False ->
+          -- Don't change the expression if none of the arguments changed
+          return expr
+      
+    -- If we don't have a body for the function called, leave it unchanged (it
+    -- should be a primitive function then).
+    Nothing -> return expr
+  where
+    -- Find the function called and the arguments
+    (fexpr, args) = collectArgs expr
+    Var f = fexpr
+
+    -- Process a single argument and return (args, bndrs, arg), where args are
+    -- the arguments to replace the given argument in the original
+    -- application, bndrs are the binders to include in the top-level lambda
+    -- in the new function body, and arg is the argument to apply to the old
+    -- function body.
+    doarg :: CoreExpr -> TransformMonad ([CoreExpr], [CoreBndr], CoreExpr)
+    doarg arg = do
+      repr <- isRepr arg
+      bndrs <- Trans.lift getGlobalBinders
+      let interesting var = Var.isLocalVar var && (var `notElem` bndrs)
+      if not repr && not (is_var arg && interesting (exprToVar arg)) && not (has_free_tyvars arg) 
+        then do
+          -- Propagate all complex arguments that are not representable, but not
+          -- arguments with free type variables (since those would require types
+          -- not known yet, which will always be known eventually).
+          -- Find interesting free variables, each of which should be passed to
+          -- the new function instead of the original function argument.
+          -- 
+          -- Interesting vars are those that are local, but not available from the
+          -- top level scope (functions from this module are defined as local, but
+          -- they're not local to this function, so we can freely move references
+          -- to them into another function).
+          let free_vars = VarSet.varSetElems $ CoreFVs.exprSomeFreeVars interesting arg
+          -- Mark the current expression as changed
+          setChanged
+          -- TODO: Clone the free_vars (and update references in arg), since
+          -- this might cause conflicts if two arguments that are propagated
+          -- share a free variable. Also, we are now introducing new variables
+          -- into a function that are not fresh, which violates the binder
+          -- uniqueness invariant.
+          return (map Var free_vars, free_vars, arg)
+        else do
+          -- Representable types will not be propagated, and arguments with free
+          -- type variables will be propagated later.
+          -- Note that we implicitly remove any type variables in the type of
+          -- the original argument by using the type of the actual argument
+          -- for the new formal parameter.
+          -- TODO: preserve original naming?
+          id <- Trans.lift $ mkBinderFor arg "param"
+          -- Just pass the original argument to the new function, which binds it
+          -- to a new id and just pass that new id to the old function body.
+          return ([arg], [id], mkReferenceTo id) 
+-- Leave all other expressions unchanged
+argprop c expr = return expr
+
+--------------------------------
+-- Non-representable result inlining
+--------------------------------
+-- This transformation takes a function (top level binding) that has a
+-- non-representable result (e.g., a tuple containing a function, or an
+-- Integer. The latter can occur in some cases as the result of the
+-- fromIntegerT function) and inlines enough of the function to make the
+-- result representable again.
+--
+-- This is done by first normalizing the function and then "inlining"
+-- the result. Since no unrepresentable let bindings are allowed in
+-- normal form, we can be sure that all free variables of the result
+-- expression will be representable (Note that we probably can't
+-- guarantee that all representable parts of the expression will be free
+-- variables, so we might inline more than strictly needed).
+--
+-- The new function result will be a tuple containing all free variables
+-- of the old result, so the old result can be rebuild at the caller.
+--
+-- We take care not to inline dictionary id's, which are top level
+-- bindings with a non-representable result type as well, since those
+-- will never become VHDL signals directly. There is a separate
+-- transformation (inlinedict) that specifically inlines dictionaries
+-- only when it is useful.
+inlinenonrepresult :: Transform
+
+-- Apply to any (application of) a reference to a top level function
+-- that is fully applied (i.e., dos not have a function type) but is not
+-- representable. We apply in any context, since non-representable
+-- expressions are generally left alone and can occur anywhere.
+inlinenonrepresult context expr | not (is_applicable expr) && not (has_free_tyvars expr) =
+  case collectArgs expr of
+    (Var f, args) | not (Id.isDictId f) -> do
+      repr <- isRepr expr
+      if not repr
+        then do
+          body_maybe <- Trans.lift $ getNormalized_maybe True f
+          case body_maybe of
+            Just body -> do
+              let (bndrs, binds, res) = splitNormalizedNonRep body
+              if has_free_tyvars res 
+                then
+                  -- Don't touch anything with free type variables, since
+                  -- we can't return those. We'll wait until argprop
+                  -- removed those variables.
+                  return expr
+                else do
+                  -- Get the free local variables of res
+                  global_bndrs <- Trans.lift getGlobalBinders
+                  let interesting var = Var.isLocalVar var && (var `notElem` global_bndrs)
+                  let free_vars = VarSet.varSetElems $ CoreFVs.exprSomeFreeVars interesting res
+                  let free_var_types = map Id.idType free_vars
+                  let n_free_vars = length free_vars
+                  -- Get a tuple datacon to wrap around the free variables
+                  let fvs_datacon = TysWiredIn.tupleCon BasicTypes.Boxed n_free_vars
+                  let fvs_datacon_id = DataCon.dataConWorkId fvs_datacon
+                  -- Let the function now return a tuple with references to
+                  -- all free variables of the old return value. First pass
+                  -- all the types of the variables, since tuple
+                  -- constructors are polymorphic.
+                  let newres = mkApps (Var fvs_datacon_id) (map Type free_var_types ++  map Var free_vars)
+                  -- Recreate the function body with the changed return value
+                  let newbody = mkLams bndrs (Let (Rec binds) newres) 
+                  -- Create the new function
+                  f' <- Trans.lift $ mkFunction f newbody
+
+                  -- Call the new function
+                  let newapp = mkApps (Var f') args
+                  res_bndr <- Trans.lift $ mkBinderFor newapp "res"
+                  -- Create extractor case expressions to extract each of the
+                  -- free variables from the tuple.
+                  sel_cases <- Trans.lift $ mapM (mkSelCase (Var res_bndr)) [0..n_free_vars-1]
+
+                  -- Bind the res_bndr to the result of the new application
+                  -- and each of the free variables to the corresponding
+                  -- selector case. Replace the let body with the original
+                  -- body of the called function (which can still access all
+                  -- of its free variables, from the let).
+                  let binds = (res_bndr, newapp):(zip free_vars sel_cases)
+                  let letexpr = Let (Rec binds) res
+
+                  -- Finally, regenarate all uniques in the new expression,
+                  -- since the free variables could otherwise become
+                  -- duplicated. It is not strictly necessary to regenerate
+                  -- res, since we're moving that expression, but it won't
+                  -- hurt.
+                  letexpr_uniqued <- Trans.lift $ genUniques letexpr
+                  change letexpr_uniqued
+            Nothing -> return expr
+        else
+          -- Don't touch representable expressions or (applications of)
+          -- dictionary ids.
+          return expr
+    -- Not a reference to or application of a top level function
+    _ -> return expr
+-- Leave all other expressions unchanged
+inlinenonrepresult c expr = return expr
+
+----------------------------------------------------------------
+-- Type-class transformations
+----------------------------------------------------------------
+
+--------------------------------
+-- ClassOp resolution
+--------------------------------
+-- Resolves any class operation to the actual operation whenever
+-- possible. Class methods (as well as parent dictionary selectors) are
+-- special "functions" that take a type and a dictionary and evaluate to
+-- the corresponding method. A dictionary is nothing more than a
+-- special dataconstructor applied to the type the dictionary is for,
+-- each of the superclasses and all of the class method definitions for
+-- that particular type. Since dictionaries all always inlined (top
+-- levels dictionaries are inlined by inlinedict, local dictionaries are
+-- inlined by inlinenonrep), we will eventually have something like:
+--
+--   baz
+--     @ CLasH.HardwareTypes.Bit
+--     (D:Baz @ CLasH.HardwareTypes.Bit bitbaz)
+--
+-- Here, baz is the method selector for the baz method, while
+-- D:Baz is the dictionary constructor for the Baz and bitbaz is the baz
+-- method defined in the Baz Bit instance declaration.
+--
+-- To resolve this, we can look at the ClassOp IdInfo from the baz Id,
+-- which contains the Class it is defined for. From the Class, we can
+-- get a list of all selectors (both parent class selectors as well as
+-- method selectors). Since the arguments to D:Baz (after the type
+-- argument) correspond exactly to this list, we then look up baz in
+-- that list and replace the entire expression by the corresponding 
+-- argument to D:Baz.
+--
+-- We don't resolve methods that have a builtin translation (such as
+-- ==), since the actual implementation is not always (easily)
+-- translateable. For example, when deriving ==, GHC generates code
+-- using $con2tag functions to translate a datacon to an int and compare
+-- that with GHC.Prim.==# . Better to avoid that for now.
+classopresolution :: Transform
+classopresolution c expr@(App (App (Var sel) ty) dict) | not is_builtin =
+  case Id.isClassOpId_maybe sel of
+    -- Not a class op selector
+    Nothing -> return expr
+    Just cls -> case collectArgs dict of
+      (_, []) -> return expr -- Dict is not an application (e.g., not inlined yet)
+      (Var dictdc, (ty':selectors)) | not (Maybe.isJust (Id.isDataConId_maybe dictdc)) -> return expr -- Dictionary is not a datacon yet (but e.g., a top level binder)
+                                | tyargs_neq ty ty' -> error $ "Normalize.classopresolution: Applying class selector to dictionary without matching type?\n" ++ pprString expr
+                                | otherwise ->
+        let selector_ids = Class.classSelIds cls in
+        -- Find the selector used in the class' list of selectors
+        case List.elemIndex sel selector_ids of
+          Nothing -> error $ "Normalize.classopresolution: Selector not found in class' selector list? This should not happen!\nExpression: " ++ pprString expr ++ "\nClass: " ++ show cls ++ "\nSelectors: " ++ show selector_ids
+          -- Get the corresponding argument from the dictionary
+          Just n -> change (selectors!!n)
+      (_, _) -> return expr -- Not applying a variable? Don't touch
+  where
+    -- Compare two type arguments, returning True if they are _not_
+    -- equal
+    tyargs_neq (Type ty1) (Type ty2) = not $ Type.coreEqType ty1 ty2
+    tyargs_neq _ _ = True
+    -- Is this a builtin function / method?
+    is_builtin = elem (Name.getOccString sel) builtinIds
+
+-- Leave all other expressions unchanged
+classopresolution c expr = return expr
+
+--------------------------------
+-- Dictionary inlining
+--------------------------------
+-- Inline all top level dictionaries, that are in a position where
+-- classopresolution can actually resolve them. This makes this
+-- transformation look similar to classoperesolution below, but we'll
+-- keep them separated for clarity. By not inlining other dictionaries,
+-- we prevent expression sizes exploding when huge type level integer
+-- dictionaries are inlined which can never be expanded (in casts, for
+-- example).
+inlinedict c expr@(App (App (Var sel) ty) (Var dict)) | not is_builtin && is_classop = do
+  body_maybe <- Trans.lift $ getGlobalBind dict
+  case body_maybe of
+    -- No body available (no source available, or a local variable /
+    -- argument)
+    Nothing -> return expr
+    Just body -> change (App (App (Var sel) ty) body)
+  where
+    -- Is this a builtin function / method?
+    is_builtin = elem (Name.getOccString sel) builtinIds
+    -- Are we dealing with a class operation selector?
+    is_classop = Maybe.isJust (Id.isClassOpId_maybe sel)
+
+-- Leave all other expressions unchanged
+inlinedict c expr = return expr
+
+
+{-
+--------------------------------
+-- Identical let binding merging
+--------------------------------
+-- Merge two bindings in a let if they are identical 
+-- TODO: We would very much like to use GHC's CSE module for this, but that
+-- doesn't track if something changed or not, so we can't use it properly.
+letmerge :: Transform
+letmerge c expr@(Let _ _) = do
+  let (binds, res) = flattenLets expr
+  binds' <- domerge binds
+  return $ mkNonRecLets binds' res
+  where
+    domerge :: [(CoreBndr, CoreExpr)] -> TransformMonad [(CoreBndr, CoreExpr)]
+    domerge [] = return []
+    domerge (e:es) = do 
+      es' <- mapM (mergebinds e) es
+      es'' <- domerge es'
+      return (e:es'')
+
+    -- Uses the second bind to simplify the second bind, if applicable.
+    mergebinds :: (CoreBndr, CoreExpr) -> (CoreBndr, CoreExpr) -> TransformMonad (CoreBndr, CoreExpr)
+    mergebinds (b1, e1) (b2, e2)
+      -- Identical expressions? Replace the second binding with a reference to
+      -- the first binder.
+      | CoreUtils.cheapEqExpr e1 e2 = change $ (b2, Var b1)
+      -- Different expressions? Don't change
+      | otherwise = return (b2, e2)
+-- Leave all other expressions unchanged
+letmerge c expr = return expr
+-}
+
+--------------------------------
+-- End of transformations
+--------------------------------
+
+
+
+
+-- What transforms to run?
+transforms = [ ("inlinedict", inlinedict)
+             , ("inlinetoplevel", inlinetoplevel)
+             , ("inlinenonrepresult", inlinenonrepresult)
+             , ("knowncase", knowncase)
+             , ("classopresolution", classopresolution)
+             , ("argprop", argprop)
+             , ("funextract", funextract)
+             , ("eta", eta)
+             , ("beta", beta)
+             , ("appprop", appprop)
+             , ("castprop", castprop)
+             , ("letremovesimple", letremovesimple)
+             , ("letrec", letrec)
+             , ("letremove", letremove)
+             , ("retvalsimpl", retvalsimpl)
+             , ("letflat", letflat)
+             , ("scrutsimpl", scrutsimpl)
+             , ("scrutbndrremove", scrutbndrremove)
+             , ("casesimpl", casesimpl)
+             , ("caseremove", caseremove)
+             , ("inlinenonrep", inlinenonrep)
+             , ("appsimpl", appsimpl)
+             , ("letremoveunused", letremoveunused)
+             , ("castsimpl", castsimpl)
+             ]
+
+-- | Returns the normalized version of the given function, or an error
+-- if it is not a known global binder.
+getNormalized ::
+  Bool -- ^ Allow the result to be unrepresentable?
+  -> CoreBndr -- ^ The function to get
+  -> TranslatorSession CoreExpr -- The normalized function body
+getNormalized result_nonrep bndr = do
+  norm <- getNormalized_maybe result_nonrep bndr
+  return $ Maybe.fromMaybe
+    (error $ "Normalize.getNormalized: Unknown or non-representable function requested: " ++ show bndr)
+    norm
+
+-- | Returns the normalized version of the given function, or Nothing
+-- when the binder is not a known global binder or is not normalizeable.
+getNormalized_maybe ::
+  Bool -- ^ Allow the result to be unrepresentable?
+  -> CoreBndr -- ^ The function to get
+  -> TranslatorSession (Maybe CoreExpr) -- The normalized function body
+
+getNormalized_maybe result_nonrep bndr = do
+    expr_maybe <- getGlobalBind bndr
+    normalizeable <- isNormalizeable result_nonrep bndr
+    if not normalizeable || Maybe.isNothing expr_maybe
+      then
+        -- Binder not normalizeable or not found
+        return Nothing
+      else do
+        -- Binder found and is monomorphic. Normalize the expression
+        -- and cache the result.
+        normalized <- Utils.makeCached bndr tsNormalized $ 
+          normalizeExpr (show bndr) (Maybe.fromJust expr_maybe)
+        return (Just normalized)
+
+-- | Normalize an expression
+normalizeExpr ::
+  String -- ^ What are we normalizing? For debug output only.
+  -> CoreSyn.CoreExpr -- ^ The expression to normalize 
+  -> TranslatorSession CoreSyn.CoreExpr -- ^ The normalized expression
+
+normalizeExpr what expr = do
+      startcount <- MonadState.get tsTransformCounter 
+      expr_uniqued <- genUniques expr
+      -- Do a debug print, if requested
+      let expr_uniqued' = Utils.traceIf (normalize_debug >= NormDbgFinal) (what ++ " before normalization:\n\n" ++ showSDoc ( ppr expr_uniqued ) ++ "\n") expr_uniqued
+      -- Normalize this expression
+      expr' <- dotransforms transforms expr_uniqued'
+      endcount <- MonadState.get tsTransformCounter 
+      -- Do a debug print, if requested
+      Utils.traceIf (normalize_debug >= NormDbgFinal)  (what ++ " after normalization:\n\n" ++ showSDoc ( ppr expr') ++ "\nNeeded " ++ show (endcount - startcount) ++ " transformations to normalize " ++ what) $
+        return expr'
+
+-- | Split a normalized expression into the argument binders, top level
+--   bindings and the result binder. This function returns an error if
+--   the type of the expression is not representable.
+splitNormalized ::
+  CoreExpr -- ^ The normalized expression
+  -> ([CoreBndr], [Binding], CoreBndr)
+splitNormalized expr = 
+  case splitNormalizedNonRep expr of
+    (args, binds, Var res) -> (args, binds, res)
+    _ -> error $ "Normalize.splitNormalized: Not in normal form: " ++ pprString expr ++ "\n"
+
+-- Split a normalized expression, whose type can be unrepresentable.
+splitNormalizedNonRep::
+  CoreExpr -- ^ The normalized expression
+  -> ([CoreBndr], [Binding], CoreExpr)
+splitNormalizedNonRep expr = (args, binds, resexpr)
+  where
+    (args, letexpr) = CoreSyn.collectBinders expr
+    (binds, resexpr) = flattenLets letexpr
diff --git a/clash/CLasH/Normalize/NormalizeTools.hs b/clash/CLasH/Normalize/NormalizeTools.hs
new file mode 100644 (file)
index 0000000..cdb7ee0
--- /dev/null
@@ -0,0 +1,245 @@
+-- 
+-- This module provides functions for program transformations.
+--
+module CLasH.Normalize.NormalizeTools where
+
+-- Standard modules
+import qualified Data.Monoid as Monoid
+import qualified Data.Either as Either
+import qualified Control.Monad as Monad
+import qualified Control.Monad.Trans.Writer as Writer
+import qualified Control.Monad.Trans.Class as Trans
+import qualified Data.Accessor.Monad.Trans.State as MonadState
+
+-- GHC API
+import CoreSyn
+import qualified Name
+import qualified Id
+import qualified CoreSubst
+import qualified Type
+import qualified CoreUtils
+import Outputable ( showSDoc, ppr, nest )
+
+-- Local imports
+import CLasH.Normalize.NormalizeTypes
+import CLasH.Translator.TranslatorTypes
+import CLasH.VHDL.Constants (builtinIds)
+import CLasH.Utils
+import qualified CLasH.Utils.Core.CoreTools as CoreTools
+import qualified CLasH.VHDL.VHDLTools as VHDLTools
+
+-- Apply the given transformation to all expressions in the given expression,
+-- including the expression itself.
+everywhere :: Transform -> Transform
+everywhere trans = applyboth (subeverywhere (everywhere trans)) trans
+
+data NormDbgLevel = 
+    NormDbgNone         -- ^ No debugging
+  | NormDbgFinal        -- ^ Print functions before / after normalization
+  | NormDbgApplied      -- ^ Print expressions before / after applying transformations
+  | NormDbgAll          -- ^ Print expressions when a transformation does not apply
+  deriving (Eq, Ord)
+normalize_debug = NormDbgFinal
+
+-- Applies a transform, optionally showing some debug output.
+apply :: (String, Transform) -> Transform
+apply (name, trans) ctx expr =  do
+    -- Apply the transformation and find out if it changed anything
+    (expr', any_changed) <- Writer.listen $ trans ctx expr
+    let changed = Monoid.getAny any_changed
+    -- If it changed, increase the transformation counter 
+    Monad.when changed $ Trans.lift (MonadState.modify tsTransformCounter (+1))
+    -- Prepare some debug strings
+    let before = showSDoc (nest 4 $ ppr expr) ++ "\nType: \n" ++ (showSDoc $ nest 4 $ ppr $ CoreUtils.exprType expr) ++ "\n"
+    let context = "Context: " ++ show ctx ++ "\n"
+    let after  = showSDoc (nest 4 $ ppr expr') ++ "\nType: \n" ++ (showSDoc $ nest 4 $ ppr $ CoreUtils.exprType expr') ++ "\n"
+    traceIf (normalize_debug >= NormDbgApplied && changed) ("Changes when applying transform " ++ name ++ " to:\n" ++ before ++ context ++ "Result:\n" ++ after) $ 
+     traceIf (normalize_debug >= NormDbgAll && not changed) ("No changes when applying transform " ++ name ++ " to:\n" ++ before  ++ context) $
+     return expr'
+
+-- Apply the first transformation, followed by the second transformation, and
+-- keep applying both for as long as expression still changes.
+applyboth :: Transform -> Transform -> Transform
+applyboth first second context expr = do
+  -- Apply the first
+  expr' <- first context expr
+  -- Apply the second
+  (expr'', changed) <- Writer.listen $ second context expr'
+  if Monoid.getAny $ changed
+    then
+      applyboth first second context expr'' 
+    else 
+      return expr''
+
+-- Apply the given transformation to all direct subexpressions (only), not the
+-- expression itself.
+subeverywhere :: Transform -> Transform
+subeverywhere trans c (App a b) = do
+  a' <- trans (AppFirst:c) a
+  b' <- trans (AppSecond:c) b
+  return $ App a' b'
+
+subeverywhere trans c (Let (NonRec b bexpr) expr) = do
+  bexpr' <- trans (LetBinding:c) bexpr
+  expr' <- trans (LetBody:c) expr
+  return $ Let (NonRec b bexpr') expr'
+
+subeverywhere trans c (Let (Rec binds) expr) = do
+  expr' <- trans (LetBody:c) expr
+  binds' <- mapM transbind binds
+  return $ Let (Rec binds') expr'
+  where
+    transbind :: (CoreBndr, CoreExpr) -> TransformMonad (CoreBndr, CoreExpr)
+    transbind (b, e) = do
+      e' <- trans (LetBinding:c) e
+      return (b, e')
+
+subeverywhere trans c (Lam x expr) = do
+  expr' <- trans (LambdaBody:c) expr
+  return $ Lam x expr'
+
+subeverywhere trans c (Case scrut b t alts) = do
+  scrut' <- trans (Other:c) scrut
+  alts' <- mapM transalt alts
+  return $ Case scrut' b t alts'
+  where
+    transalt :: CoreAlt -> TransformMonad CoreAlt
+    transalt (con, binders, expr) = do
+      expr' <- trans (Other:c) expr
+      return (con, binders, expr')
+
+subeverywhere trans c (Var x) = return $ Var x
+subeverywhere trans c (Lit x) = return $ Lit x
+subeverywhere trans c (Type x) = return $ Type x
+
+subeverywhere trans c (Cast expr ty) = do
+  expr' <- trans (Other:c) expr
+  return $ Cast expr' ty
+
+subeverywhere trans c expr = error $ "\nNormalizeTools.subeverywhere: Unsupported expression: " ++ show expr
+
+-- Runs each of the transforms repeatedly inside the State monad.
+dotransforms :: [(String, Transform)] -> CoreExpr -> TranslatorSession CoreExpr
+dotransforms transs expr = do
+  (expr', changed) <- Writer.runWriterT $ Monad.foldM (\e trans -> everywhere (apply trans) [] e) expr transs
+  if Monoid.getAny changed then dotransforms transs expr' else return expr'
+
+-- Inline all let bindings that satisfy the given condition
+inlinebind :: ((CoreBndr, CoreExpr) -> TransformMonad Bool) -> Transform
+inlinebind condition context expr@(Let (Rec binds) res) = do
+    -- Find all bindings that adhere to the condition
+    res_eithers <- mapM docond binds
+    case Either.partitionEithers res_eithers of
+      -- No replaces? No change
+      ([], _) -> return expr
+      (replace, others) -> do
+        -- Substitute the to be replaced binders with their expression
+        newexpr <- do_substitute replace (Let (Rec others) res)
+        change newexpr
+  where 
+    -- Apply the condition to a let binding and return an Either
+    -- depending on whether it needs to be inlined or not.
+    docond :: (CoreBndr, CoreExpr) -> TransformMonad (Either (CoreBndr, CoreExpr) (CoreBndr, CoreExpr))
+    docond b = do
+      res <- condition b
+      return $ case res of True -> Left b; False -> Right b
+
+    -- Apply the given list of substitutions to the the given expression
+    do_substitute :: [(CoreBndr, CoreExpr)] -> CoreExpr -> TransformMonad CoreExpr
+    do_substitute [] expr = return expr
+    do_substitute ((bndr, val):reps) expr = do
+      -- Perform this substitution in the expression
+      expr' <- substitute_clone bndr val context expr
+      -- And in the substitution values we will be using next
+      reps' <- mapM (subs_bind bndr val) reps
+      -- And then perform the remaining substitutions
+      do_substitute reps' expr'
+   
+    -- Replace the given binder with the given expression in the
+    -- expression oft the given let binding
+    subs_bind :: CoreBndr -> CoreExpr -> (CoreBndr, CoreExpr) -> TransformMonad (CoreBndr, CoreExpr)
+    subs_bind bndr expr (b, v) = do
+      v' <- substitute_clone  bndr expr (LetBinding:context) v
+      return (b, v')
+
+
+-- Leave all other expressions unchanged
+inlinebind _ context expr = return expr
+
+-- Sets the changed flag in the TransformMonad, to signify that some
+-- transform has changed the result
+setChanged :: TransformMonad ()
+setChanged = Writer.tell (Monoid.Any True)
+
+-- Sets the changed flag and returns the given value.
+change :: a -> TransformMonad a
+change val = do
+  setChanged
+  return val
+
+-- Returns the given value and sets the changed flag if the bool given is
+-- True. Note that this will not unset the changed flag if the bool is False.
+changeif :: Bool -> a -> TransformMonad a
+changeif True val = change val
+changeif False val = return val
+
+-- | Creates a transformation that substitutes the given binder with the given
+-- expression (This can be a type variable, replace by a Type expression).
+-- Does not set the changed flag.
+substitute :: CoreBndr -> CoreExpr -> Transform
+-- Use CoreSubst to subst a type var in an expression
+substitute find repl context expr = do
+  let subst = CoreSubst.extendSubst CoreSubst.emptySubst find repl
+  return $ CoreSubst.substExpr subst expr 
+
+-- | Creates a transformation that substitutes the given binder with the given
+-- expression. This does only work for value expressions! All binders in the
+-- expression are cloned before the replacement, to guarantee uniqueness.
+substitute_clone :: CoreBndr -> CoreExpr -> Transform
+-- If we see the var to find, replace it by a uniqued version of repl
+substitute_clone find repl context (Var var) | find == var = do
+  repl' <- Trans.lift $ CoreTools.genUniques repl
+  change repl'
+
+-- For all other expressions, just look in subexpressions
+substitute_clone find repl context expr = subeverywhere (substitute_clone find repl) context expr
+
+-- Is the given expression representable at runtime, based on the type?
+isRepr :: (CoreTools.TypedThing t) => t -> TransformMonad Bool
+isRepr tything = Trans.lift (isRepr' tything)
+
+isRepr' :: (CoreTools.TypedThing t) => t -> TranslatorSession Bool
+isRepr' tything = case CoreTools.getType tything of
+  Nothing -> return False
+  Just ty -> MonadState.lift tsType $ VHDLTools.isReprType ty 
+
+is_local_var :: CoreSyn.CoreExpr -> TranslatorSession Bool
+is_local_var (CoreSyn.Var v) = do
+  bndrs <- getGlobalBinders
+  return $ v `notElem` bndrs
+is_local_var _ = return False
+
+-- Is the given binder defined by the user?
+isUserDefined :: CoreSyn.CoreBndr -> Bool
+-- System names are certain to not be user defined
+isUserDefined bndr | Name.isSystemName (Id.idName bndr) = False
+-- Builtin functions are usually not user-defined either (and would
+-- break currently if they are...)
+isUserDefined bndr = str `notElem` builtinIds
+  where
+    str = Name.getOccString bndr
+
+-- | Is the given binder normalizable? This means that its type signature can be
+-- represented in hardware, which should (?) guarantee that it can be made
+-- into hardware. This checks whether all the arguments and (optionally)
+-- the return value are
+-- representable.
+isNormalizeable :: 
+  Bool -- ^ Allow the result to be unrepresentable?
+  -> CoreBndr  -- ^ The binder to check
+  -> TranslatorSession Bool  -- ^ Is it normalizeable?
+isNormalizeable result_nonrep bndr = do
+  let ty = Id.idType bndr
+  let (arg_tys, res_ty) = Type.splitFunTys ty
+  let check_tys = if result_nonrep then arg_tys else (res_ty:arg_tys) 
+  andM $ mapM isRepr' check_tys
diff --git a/clash/CLasH/Normalize/NormalizeTypes.hs b/clash/CLasH/Normalize/NormalizeTypes.hs
new file mode 100644 (file)
index 0000000..4e98709
--- /dev/null
@@ -0,0 +1,34 @@
+module CLasH.Normalize.NormalizeTypes where
+
+-- Standard modules
+import qualified Control.Monad.Trans.Writer as Writer
+import qualified Data.Monoid as Monoid
+
+-- GHC API
+import qualified CoreSyn
+
+-- Local imports
+import CLasH.Translator.TranslatorTypes
+
+-- Wrap a writer around a TranslatorSession, to run a single transformation
+-- over a single expression and track if the expression was changed.
+type TransformMonad = Writer.WriterT Monoid.Any TranslatorSession
+
+-- | In what context does a core expression occur?
+data CoreContext = AppFirst        -- ^ The expression is the first
+                                   -- argument of an application (i.e.,
+                                   -- it is applied)
+                 | AppSecond       -- ^ The expression is the second
+                                   --   argument of an application
+                                   --   (i.e., something is applied to it)
+                 | LetBinding      -- ^ The expression is bound in a
+                                   --   (recursive or non-recursive) let
+                                   --   expression.
+                 | LetBody         -- ^ The expression is the body of a
+                                   --   let expression
+                 | LambdaBody      -- ^ The expression is the body of a
+                                   --   lambda abstraction
+                 | Other           -- ^ Another context
+  deriving (Eq, Show)
+-- | Transforms a CoreExpr and keeps track if it has changed.
+type Transform = [CoreContext] -> CoreSyn.CoreExpr -> TransformMonad CoreSyn.CoreExpr
diff --git a/clash/CLasH/Translator.hs b/clash/CLasH/Translator.hs
new file mode 100644 (file)
index 0000000..6177dab
--- /dev/null
@@ -0,0 +1,142 @@
+module CLasH.Translator 
+  (
+   makeVHDLAnnotations
+  ) where
+
+-- Standard Modules
+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.Monad.Trans.State
+import qualified Data.Map as Map
+import qualified Data.Time.Clock as Clock
+import Debug.Trace
+
+-- GHC API
+import qualified CoreSyn
+import qualified HscTypes
+import qualified UniqSupply
+
+-- VHDL Imports
+import qualified Language.VHDL.AST as AST
+import qualified Language.VHDL.FileIO as FileIO
+import qualified Language.VHDL.Ppr as Ppr
+
+-- Local Imports
+import CLasH.Translator.TranslatorTypes
+import CLasH.Translator.Annotations
+import CLasH.Utils
+import CLasH.Utils.GhcTools
+import CLasH.VHDL
+import CLasH.VHDL.VHDLTools
+import CLasH.VHDL.Testbench
+
+-- | Turn Haskell to VHDL, Using the Annotations for Top Entity, Initial State
+--   and Test Inputs found in the Files. 
+makeVHDLAnnotations :: 
+  FilePath      -- ^ The GHC Library Dir
+  -> [FilePath] -- ^ The FileNames
+  -> IO ()
+makeVHDLAnnotations libdir filenames =
+  makeVHDL libdir filenames finder
+    where
+      finder = findSpec (hasCLasHAnnotation isTopEntity)
+                        (hasCLasHAnnotation isInitState)
+                        (isCLasHAnnotation isInitState)
+                        (hasCLasHAnnotation isTestInput)
+
+-- | Turn Haskell to VHDL, using the given finder functions to find the Top
+--   Entity, Initial State and Test Inputs in the Haskell Files.
+makeVHDL ::
+  FilePath      -- ^ The GHC Library Dir
+  -> [FilePath] -- ^ The Filenames
+  -> Finder
+  -> IO ()
+makeVHDL libdir filenames finder = do
+  start <- Clock.getCurrentTime
+  -- Load the modules
+  (cores, env, specs) <- loadModules libdir filenames (Just finder)
+  -- Translate to VHDL
+  vhdl <- moduleToVHDL env cores specs
+  -- Write VHDL to file. Just use the first entity for the name
+  let top_entity = head $ Maybe.catMaybes $ map (\(t, _, _) -> t) specs
+  let dir = "./vhdl/" ++ (show top_entity) ++ "/"
+  prepareDir dir
+  mapM_ (writeVHDL dir) vhdl
+  end <- Clock.getCurrentTime
+  trace ("\nTotal compilation took " ++ show (Clock.diffUTCTime end start)) $
+    return ()
+
+-- | Translate the specified entities in the given modules to VHDL.
+moduleToVHDL ::
+  HscTypes.HscEnv             -- ^ The GHC Environment
+  -> [HscTypes.CoreModule]    -- ^ The Core Modules
+  -> [EntitySpec]             -- ^ The entities to generate
+  -> IO [(AST.VHDLId, AST.DesignFile)]
+moduleToVHDL env cores specs = do
+  (vhdl, count) <- runTranslatorSession env $ do
+    let all_bindings = concatMap (\x -> CoreSyn.flattenBinds (HscTypes.cm_binds x)) cores
+    -- Store the bindings we loaded
+    tsBindings %= Map.fromList all_bindings
+    let all_initstates = concatMap (\x -> case x of (_, Nothing, _) -> []; (_, Just inits, _) -> inits) specs 
+    tsInitStates %= Map.fromList all_initstates
+    test_binds <- catMaybesM $ Monad.mapM mkTest specs
+    let topbinds = Maybe.catMaybes $ map (\(top, _, _) -> top) specs
+    vhdl <- case topbinds of
+      []  -> error "Could not find top entity requested"
+      tops -> createDesignFiles (tops ++ test_binds)
+    count <- get tsTransformCounter 
+    return (vhdl, count)
+  mapM_ (putStr . render . Ppr.ppr . snd) vhdl
+  putStr $ "Total number of transformations applied: " ++ (show count) ++ "\n"
+  return vhdl
+  where
+    mkTest :: EntitySpec -> TranslatorSession (Maybe CoreSyn.CoreBndr)
+    -- Create a testbench for any entry that has test input
+    mkTest (_, _, Nothing) = return Nothing
+    mkTest (Nothing, _, _) = return Nothing
+    mkTest (Just top, _, Just input) = do
+      bndr <- createTestbench Nothing cores input top
+      return $ Just bndr
+
+-- 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 builtin_types [] Map.empty Map.empty env
+  let init_state = TranslatorState uniqSupply init_typestate Map.empty Map.empty 0 Map.empty Map.empty Map.empty 0
+  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.
+prepareDir :: String -> IO()
+prepareDir dir = do
+  -- Create the dir if needed
+  Directory.createDirectoryIfMissing True dir
+  -- Find all .vhdl files in the directory
+  files <- Directory.getDirectoryContents dir
+  let to_remove = filter ((==".vhdl") . FilePath.takeExtension) files
+  -- Prepend the dirname to the filenames
+  let abs_to_remove = map (FilePath.combine dir) to_remove
+  -- Remove the files
+  mapM_ Directory.removeFile abs_to_remove
+
+-- | Write the given design file to a file with the given name inside the
+--   given dir
+writeVHDL :: String -> (AST.VHDLId, AST.DesignFile) -> IO ()
+writeVHDL dir (name, vhdl) = do
+  -- Find the filename
+  let fname = dir ++ (AST.fromVHDLId name) ++ ".vhdl"
+  -- Write the file
+  FileIO.writeDesignFile vhdl fname
+
+-- vim: set ts=8 sw=2 sts=2 expandtab:
diff --git a/clash/CLasH/Translator/Annotations.hs b/clash/CLasH/Translator/Annotations.hs
new file mode 100644 (file)
index 0000000..2c87550
--- /dev/null
@@ -0,0 +1,24 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+module CLasH.Translator.Annotations where
+  
+import qualified Language.Haskell.TH as TH
+import Data.Data
+
+data CLasHAnn = TopEntity | InitState TH.Name | TestInput | TestCycles
+  deriving (Show, Data, Typeable)
+  
+isTopEntity :: CLasHAnn -> Bool
+isTopEntity TopEntity = True
+isTopEntity _         = False
+
+isInitState :: CLasHAnn -> Bool
+isInitState (InitState _) = True
+isInitState _             = False
+
+isTestInput :: CLasHAnn -> Bool
+isTestInput TestInput = True
+isTestInput _         = False
+
+isTestCycles :: CLasHAnn -> Bool
+isTestCycles TestCycles = True
+isTestCycles _          = False
\ No newline at end of file
diff --git a/clash/CLasH/Translator/TranslatorTypes.hs b/clash/CLasH/Translator/TranslatorTypes.hs
new file mode 100644 (file)
index 0000000..eabb004
--- /dev/null
@@ -0,0 +1,131 @@
+{-# LANGUAGE TemplateHaskell #-}
+--
+-- Simple module providing some types used by Translator. These are in a
+-- separate module to prevent circular dependencies in Pretty for example.
+--
+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 qualified Data.Accessor.Monad.Trans.State as MonadState
+
+-- GHC API
+import qualified GHC
+import qualified CoreSyn
+import qualified Type
+import qualified HscTypes
+import qualified UniqSupply
+
+-- VHDL Imports
+import qualified Language.VHDL.AST as AST
+
+-- Local imports
+import CLasH.VHDL.VHDLTypes
+
+-- | A specification of an entity we can generate VHDL for. Consists of the
+--   binder of the top level entity, an optional initial state and an optional
+--   test input.
+type EntitySpec = (Maybe CoreSyn.CoreBndr, Maybe [(CoreSyn.CoreBndr, CoreSyn.CoreBndr)], Maybe CoreSyn.CoreExpr)
+
+-- | A function that knows which parts of a module to compile
+type Finder =
+  HscTypes.CoreModule -- ^ The module to look at
+  -> GHC.Ghc [EntitySpec]
+
+-----------------------------------------------------------------------------
+-- The TranslatorSession
+-----------------------------------------------------------------------------
+
+-- A orderable equivalent of CoreSyn's Type for use as a map key
+newtype OrdType = OrdType 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 = AggrType String [HType] |
+             EnumType String [String] |
+             VecType Int HType |
+             UVecType HType |
+             SizedWType Int |
+             RangedWType Int |
+             SizedIType Int |
+             BuiltinType String |
+             StateType
+  deriving (Eq, Ord, Show)
+
+-- A map of a Core type to the corresponding type name, or Nothing when the
+-- type would be empty.
+type TypeMapRec   = Maybe (AST.VHDLId, Maybe (Either AST.TypeDef AST.SubtypeIn))
+type TypeMap      = Map.Map HType TypeMapRec
+
+-- 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 (HType, 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_  :: [Maybe 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
+
+-- 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
+  , tsEntityCounter_ :: Integer
+  , tsEntities_ :: Map.Map CoreSyn.CoreBndr Entity
+  , tsArchitectures_ :: Map.Map CoreSyn.CoreBndr (Architecture, [CoreSyn.CoreBndr])
+  , tsInitStates_ :: Map.Map CoreSyn.CoreBndr CoreSyn.CoreBndr
+  , tsTransformCounter_ :: Int -- ^ How many transformations were applied?
+}
+
+-- Derive accessors
+Data.Accessor.Template.deriveAccessors ''TranslatorState
+
+type TranslatorSession = State.State TranslatorState
+
+-----------------------------------------------------------------------------
+-- Some accessors
+-----------------------------------------------------------------------------
+
+-- Does the given binder reference a top level binder in the current
+-- module(s)?
+isTopLevelBinder :: CoreSyn.CoreBndr -> TranslatorSession Bool
+isTopLevelBinder bndr = do
+  bindings <- MonadState.get tsBindings
+  return $ Map.member bndr bindings
+
+-- Finds the value of a global binding, if available
+getGlobalBind :: CoreSyn.CoreBndr -> TranslatorSession (Maybe CoreSyn.CoreExpr)
+getGlobalBind bndr = do
+  bindings <- MonadState.get tsBindings
+  return $ Map.lookup bndr bindings 
+
+-- Adds a new global binding with the given value
+addGlobalBind :: CoreSyn.CoreBndr -> CoreSyn.CoreExpr -> TranslatorSession ()
+addGlobalBind bndr expr = MonadState.modify tsBindings (Map.insert bndr expr)
+
+-- Returns a list of all global binders
+getGlobalBinders :: TranslatorSession [CoreSyn.CoreBndr]
+getGlobalBinders = do
+  bindings <- MonadState.get tsBindings
+  return $ Map.keys bindings
+
+-- vim: set ts=8 sw=2 sts=2 expandtab:
diff --git a/clash/CLasH/Utils.hs b/clash/CLasH/Utils.hs
new file mode 100644 (file)
index 0000000..d85b25b
--- /dev/null
@@ -0,0 +1,69 @@
+module CLasH.Utils where
+
+-- Standard Imports
+import qualified Maybe
+import Data.Accessor
+import qualified Data.Accessor.Monad.Trans.State as MonadState
+import qualified Data.Map as Map
+import qualified Control.Monad as Monad
+import qualified Control.Monad.Trans.State as State
+import qualified Debug.Trace as Trace
+  
+-- 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 <- MonadState.get 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
+      MonadState.modify accessor (Map.insert key value)
+      return value
+
+unzipM :: (Monad m) =>
+  m [(a, b)]
+  -> m ([a], [b])
+unzipM = Monad.liftM unzip
+
+catMaybesM :: (Monad m) =>
+  m [Maybe a]
+  -> m [a]
+catMaybesM = Monad.liftM Maybe.catMaybes
+
+concatM :: (Monad m) =>
+  m [[a]]
+  -> m [a]
+concatM = Monad.liftM concat
+
+isJustM :: (Monad m) => m (Maybe a) -> m Bool
+isJustM = Monad.liftM Maybe.isJust
+
+andM, orM :: (Monad m) => m [Bool] -> m Bool
+andM = Monad.liftM and
+orM = Monad.liftM or
+
+-- | Monadic versions of any and all. We reimplement them, since there
+-- is no ready-made lifting function for them.
+allM, anyM :: (Monad m) => (a -> m Bool) -> [a] -> m Bool
+allM f = andM . (mapM f)
+anyM f = orM . (mapM f)
+
+mapAccumLM :: (Monad m) => (acc -> x -> m (acc, y)) -> acc -> [x] -> m (acc, [y])
+mapAccumLM _ s []        =  return (s, [])
+mapAccumLM f s (x:xs)    =  do
+  (s',  y ) <- f s x
+  (s'', ys) <- mapAccumLM f s' xs
+  return (s'', y:ys)
+
+-- Trace the given string if the given bool is True, do nothing
+-- otherwise.
+traceIf :: Bool -> String -> a -> a
+traceIf True = Trace.trace
+traceIf False = flip const
diff --git a/clash/CLasH/Utils/Core/BinderTools.hs b/clash/CLasH/Utils/Core/BinderTools.hs
new file mode 100644 (file)
index 0000000..cd01675
--- /dev/null
@@ -0,0 +1,95 @@
+--
+-- This module contains functions that manipulate binders in various ways.
+--
+module CLasH.Utils.Core.BinderTools where
+
+-- Standard modules
+import qualified Data.Accessor.Monad.Trans.State as MonadState
+
+-- GHC API
+import qualified CoreSyn
+import qualified Type
+import qualified UniqSupply
+import qualified Unique
+import qualified OccName
+import qualified Name
+import qualified Module
+import qualified Var
+import qualified SrcLoc
+import qualified IdInfo
+import qualified CoreUtils
+
+-- Local imports
+import CLasH.Translator.TranslatorTypes
+
+-- Create a new Unique
+mkUnique :: TranslatorSession Unique.Unique    
+mkUnique = do
+  us <- MonadState.get tsUniqSupply 
+  let (us', us'') = UniqSupply.splitUniqSupply us
+  MonadState.set tsUniqSupply us'
+  return $ UniqSupply.uniqFromSupply us''
+
+-- Create a new internal var with the given name and type. A Unique is
+-- appended to the given name, to ensure uniqueness (not strictly neccesary,
+-- since the Unique is also stored in the name, but this ensures variable
+-- names are unique in the output).
+mkInternalVar :: String -> Type.Type -> TranslatorSession Var.Var
+mkInternalVar str ty = do
+  uniq <- mkUnique
+  let occname = OccName.mkVarOcc (str ++ show uniq)
+  let name = Name.mkInternalName uniq occname SrcLoc.noSrcSpan
+  return $ Var.mkLocalVar IdInfo.VanillaId name ty IdInfo.vanillaIdInfo
+
+-- Create a new type variable with the given name and kind. A Unique is
+-- appended to the given name, to ensure uniqueness (not strictly neccesary,
+-- since the Unique is also stored in the name, but this ensures variable
+-- names are unique in the output).
+mkTypeVar :: String -> Type.Kind -> TranslatorSession Var.Var
+mkTypeVar str kind = do
+  uniq <- mkUnique
+  let occname = OccName.mkVarOcc (str ++ show uniq)
+  let name = Name.mkInternalName uniq occname SrcLoc.noSrcSpan
+  return $ Var.mkTyVar name kind
+
+-- Creates a binder for the given expression with the given name. This
+-- works for both value and type level expressions, so it can return a Var or
+-- TyVar (which is just an alias for Var).
+mkBinderFor :: CoreSyn.CoreExpr -> String -> TranslatorSession Var.Var
+mkBinderFor (CoreSyn.Type ty) string = mkTypeVar string (Type.typeKind ty)
+mkBinderFor expr string = mkInternalVar string (CoreUtils.exprType expr)
+
+-- Creates a reference to the given variable. This works for both a normal
+-- variable as well as a type variable
+mkReferenceTo :: Var.Var -> CoreSyn.CoreExpr
+mkReferenceTo var | Var.isTyVar var = (CoreSyn.Type $ Type.mkTyVarTy var)
+                  | otherwise       = (CoreSyn.Var var)
+
+cloneVar :: Var.Var -> TranslatorSession Var.Var
+cloneVar v = do
+  uniq <- mkUnique
+  -- Swap out the unique, and reset the IdInfo (I'm not 100% sure what it
+  -- contains, but vannillaIdInfo is always correct, since it means "no info").
+  return $ Var.lazySetIdInfo (Var.setVarUnique v uniq) IdInfo.vanillaIdInfo
+
+-- Creates a new function with the same name as the given binder (but with a
+-- new unique) and with the given function body. Returns the new binder for
+-- this function.
+mkFunction :: CoreSyn.CoreBndr -> CoreSyn.CoreExpr -> TranslatorSession CoreSyn.CoreBndr
+mkFunction bndr body = do
+  let ty = CoreUtils.exprType body
+  id <- cloneVar bndr
+  let newid = Var.setVarType id ty
+  addGlobalBind newid body
+  return newid
+
+-- Returns the full name of a NamedThing, in the forum
+-- modulename.occname
+getFullString :: Name.NamedThing a => a -> String
+getFullString thing = modstr ++ occstr
+  where
+    name    = Name.getName thing
+    modstr  = case Name.nameModule_maybe name of
+      Nothing -> ""
+      Just mod -> Module.moduleNameString (Module.moduleName mod) ++ "."
+    occstr  = Name.getOccString name
diff --git a/clash/CLasH/Utils/Core/CoreShow.hs b/clash/CLasH/Utils/Core/CoreShow.hs
new file mode 100644 (file)
index 0000000..ca2a7fb
--- /dev/null
@@ -0,0 +1,80 @@
+{-# LANGUAGE StandaloneDeriving,FlexibleInstances, UndecidableInstances, OverlappingInstances #-}
+--
+-- This module derives Show instances for CoreSyn types.
+--
+module CLasH.Utils.Core.CoreShow where
+
+-- GHC API
+import qualified BasicTypes
+import qualified CoreSyn
+import qualified TypeRep
+import qualified TyCon
+import qualified HsTypes
+import qualified HsExpr
+import qualified HsBinds
+import qualified SrcLoc
+import qualified RdrName
+import Outputable ( Outputable, OutputableBndr, showSDoc, ppr)
+
+-- Derive Show for core expressions and binders, so we can see the actual
+-- structure.
+deriving instance (Show b) => Show (CoreSyn.Expr b)
+deriving instance (Show b) => Show (CoreSyn.Bind b)
+deriving instance Show TypeRep.Type
+deriving instance (Show n, OutputableBndr n) => Show (HsTypes.HsType n)
+deriving instance (Show n, OutputableBndr n) => Show (HsTypes.ConDeclField n)
+deriving instance (Show x) => Show (SrcLoc.Located x)
+deriving instance (Show x, OutputableBndr x) => Show (HsExpr.StmtLR x x)
+deriving instance (Show x, OutputableBndr x) => Show (HsExpr.HsTupArg x)
+deriving instance (Show x, OutputableBndr x) => Show (HsExpr.HsExpr x)
+deriving instance Show (RdrName.RdrName)
+deriving instance (Show idL, Show idR, OutputableBndr idL, OutputableBndr idR) => Show (HsBinds.HsBindLR idL idR)
+deriving instance Show CoreSyn.Note
+deriving instance Show TyCon.SynTyConRhs
+
+
+-- Implement dummy shows, since deriving them will need loads of other shows
+-- as well.
+instance Show TypeRep.PredType where
+  show t = "_PredType:(" ++ showSDoc (ppr t) ++ ")"
+instance Show TyCon.TyCon where
+  show t | TyCon.isAlgTyCon t && not (TyCon.isTupleTyCon t) =
+           showtc "AlgTyCon" ""
+         | TyCon.isCoercionTyCon t =
+           showtc "CoercionTyCon" ""
+         | TyCon.isSynTyCon t =
+           showtc "SynTyCon" (", synTcRhs = " ++ synrhs)
+         | TyCon.isTupleTyCon t =
+           showtc "TupleTyCon" ""
+         | TyCon.isFunTyCon t =
+           showtc "FunTyCon" ""
+         | TyCon.isPrimTyCon t =
+           showtc "PrimTyCon" ""
+         | TyCon.isSuperKindTyCon t =
+           showtc "SuperKindTyCon" ""
+         | otherwise = 
+           "_Nonexistant tycon?:(" ++ showSDoc (ppr t) ++ ")_"
+      where
+        showtc con extra = "(" ++ con ++ " {tyConName = " ++ name ++ extra ++ ", ...})"
+        name = show (TyCon.tyConName t)
+        synrhs = show (TyCon.synTyConRhs t)
+instance Show BasicTypes.Boxity where
+  show b = "_Boxity"
+instance Show HsTypes.HsExplicitForAll where
+  show b = "_HsExplicitForAll"
+instance Show HsExpr.HsArrAppType where
+  show b = "_HsArrAppType"
+instance Show (HsExpr.MatchGroup x) where
+  show b = "_HsMatchGroup"
+instance Show (HsExpr.GroupByClause x) where
+  show b = "_GroupByClause"
+instance Show (HsExpr.HsStmtContext x) where
+  show b = "_HsStmtContext"
+instance Show (HsBinds.Prag) where
+  show b = "_Prag"
+instance Show (HsExpr.GRHSs id) where
+  show b = "_GRHSs"
+
+
+instance (Outputable x) => Show x where
+  show x = "__" ++ showSDoc (ppr x) ++ "__"
diff --git a/clash/CLasH/Utils/Core/CoreTools.hs b/clash/CLasH/Utils/Core/CoreTools.hs
new file mode 100644 (file)
index 0000000..2bb688b
--- /dev/null
@@ -0,0 +1,463 @@
+{-# LANGUAGE PatternGuards, TypeSynonymInstances #-}
+-- | This module provides a number of functions to find out things about Core
+-- programs. This module does not provide the actual plumbing to work with
+-- Core and Haskell (it uses HsTools for this), but only the functions that
+-- know about various libraries and know which functions to call.
+module CLasH.Utils.Core.CoreTools where
+
+--Standard modules
+import qualified Maybe
+import qualified System.IO.Unsafe
+import qualified Data.Map as Map
+import qualified Data.Accessor.Monad.Trans.State as MonadState
+
+-- GHC API
+import qualified GHC
+import qualified Type
+import qualified TcType
+import qualified HsExpr
+import qualified HsTypes
+import qualified HscTypes
+import qualified Name
+import qualified Id
+import qualified TyCon
+import qualified DataCon
+import qualified TysWiredIn
+import qualified DynFlags
+import qualified SrcLoc
+import qualified CoreSyn
+import qualified Var
+import qualified IdInfo
+import qualified VarSet
+import qualified CoreUtils
+import qualified CoreFVs
+import qualified Literal
+import qualified MkCore
+import qualified VarEnv
+
+-- Local imports
+import CLasH.Translator.TranslatorTypes
+import CLasH.Utils.GhcTools
+import CLasH.Utils.Core.BinderTools
+import CLasH.Utils.HsTools
+import CLasH.Utils.Pretty
+import CLasH.Utils
+import qualified CLasH.Utils.Core.BinderTools as BinderTools
+
+-- | A single binding, used as a shortcut to simplify type signatures.
+type Binding = (CoreSyn.CoreBndr, CoreSyn.CoreExpr)
+
+-- | Evaluate a core Type representing type level int from the tfp
+-- library to a real int. Checks if the type really is a Dec type and
+-- caches the results.
+tfp_to_int :: Type.Type -> TypeSession Int
+tfp_to_int ty = do
+  hscenv <- MonadState.get tsHscEnv
+  let norm_ty = normalize_tfp_int hscenv ty
+  case Type.splitTyConApp_maybe norm_ty of
+    Just (tycon, args) -> do
+      let name = Name.getOccString (TyCon.tyConName tycon)
+      case name of
+        "Dec" ->
+          tfp_to_int' ty
+        otherwise -> do
+          return $ error ("Callin tfp_to_int on non-dec:" ++ (show ty))
+    Nothing -> return $ error ("Callin tfp_to_int on non-dec:" ++ (show ty))
+
+-- | Evaluate a core Type representing type level int from the tfp
+-- library to a real int. Caches the results. Do not use directly, use
+-- tfp_to_int instead.
+tfp_to_int' :: Type.Type -> TypeSession Int
+tfp_to_int' ty = do
+  lens <- MonadState.get tsTfpInts
+  hscenv <- MonadState.get tsHscEnv
+  let norm_ty = normalize_tfp_int hscenv ty
+  let existing_len = Map.lookup (OrdType norm_ty) lens
+  case existing_len of
+    Just len -> return len
+    Nothing -> do
+      let new_len = eval_tfp_int hscenv ty
+      MonadState.modify tsTfpInts (Map.insert (OrdType norm_ty) (new_len))
+      return new_len
+      
+-- | Evaluate a core Type representing type level int from the tfp
+-- library to a real int. Do not use directly, use tfp_to_int instead.
+eval_tfp_int :: HscTypes.HscEnv -> Type.Type -> Int
+eval_tfp_int env ty =
+  unsafeRunGhc libdir $ do
+    GHC.setSession env
+    -- Automatically import modules for any fully qualified identifiers
+    setDynFlag DynFlags.Opt_ImplicitImportQualified
+
+    let from_int_t_name = mkRdrName "Types.Data.Num.Ops" "fromIntegerT"
+    let from_int_t = SrcLoc.noLoc $ HsExpr.HsVar from_int_t_name
+    let undef = hsTypedUndef $ coreToHsType ty
+    let app = SrcLoc.noLoc $ HsExpr.HsApp (from_int_t) (undef)
+    let int_ty = SrcLoc.noLoc $ HsTypes.HsTyVar TysWiredIn.intTyCon_RDR
+    let expr = HsExpr.ExprWithTySig app int_ty
+    core <- toCore expr
+    execCore core
+  where
+    libdir = DynFlags.topDir dynflags
+    dynflags = HscTypes.hsc_dflags env
+
+normalize_tfp_int :: HscTypes.HscEnv -> Type.Type -> Type.Type
+normalize_tfp_int env ty =
+   System.IO.Unsafe.unsafePerformIO $
+     normalizeType env ty
+
+sized_word_len_ty :: Type.Type -> Type.Type
+sized_word_len_ty ty = len
+  where
+    args = case Type.splitTyConApp_maybe ty of
+      Just (tycon, args) -> args
+      Nothing -> error $ "\nCoreTools.sized_word_len_ty: Not a sized word type: " ++ (pprString ty)
+    [len]         = args
+
+sized_int_len_ty :: Type.Type -> Type.Type
+sized_int_len_ty ty = len
+  where
+    args = case Type.splitTyConApp_maybe ty of
+      Just (tycon, args) -> args
+      Nothing -> error $ "\nCoreTools.sized_int_len_ty: Not a sized int type: " ++ (pprString ty)
+    [len]         = args
+    
+ranged_word_bound_ty :: Type.Type -> Type.Type
+ranged_word_bound_ty ty = len
+  where
+    args = case Type.splitTyConApp_maybe ty of
+      Just (tycon, args) -> args
+      Nothing -> error $ "\nCoreTools.ranged_word_bound_ty: Not a sized word type: " ++ (pprString ty)
+    [len]         = args
+
+tfvec_len_ty :: Type.Type -> Type.Type
+tfvec_len_ty ty = len
+  where  
+    args = case Type.splitTyConApp_maybe ty of
+      Just (tycon, args) -> args
+      Nothing -> error $ "\nCoreTools.tfvec_len_ty: Not a vector type: " ++ (pprString ty)
+    [len, el_ty] = args
+    
+-- | Get the element type of a TFVec type
+tfvec_elem :: Type.Type -> Type.Type
+tfvec_elem ty = el_ty
+  where
+    args = case Type.splitTyConApp_maybe ty of
+      Just (tycon, args) -> args
+      Nothing -> error $ "\nCoreTools.tfvec_len: Not a vector type: " ++ (pprString ty)
+    [len, el_ty] = args
+
+-- Is the given core expression a lambda abstraction?
+is_lam :: CoreSyn.CoreExpr -> Bool
+is_lam (CoreSyn.Lam _ _) = True
+is_lam _ = False
+
+-- Is the given core expression a let expression?
+is_let :: CoreSyn.CoreExpr -> Bool
+is_let (CoreSyn.Let _ _) = True
+is_let _ = False
+
+-- Is the given core expression of a function type?
+is_fun :: CoreSyn.CoreExpr -> Bool
+-- Treat Type arguments differently, because exprType is not defined for them.
+is_fun (CoreSyn.Type _) = False
+is_fun expr = (Type.isFunTy . CoreUtils.exprType) expr
+
+-- Is the given core expression polymorphic (i.e., does it accept type
+-- arguments?).
+is_poly :: CoreSyn.CoreExpr -> Bool
+-- Treat Type arguments differently, because exprType is not defined for them.
+is_poly (CoreSyn.Type _) = False
+is_poly expr = (Maybe.isJust . Type.splitForAllTy_maybe . CoreUtils.exprType) expr
+
+-- Is the given core expression a variable reference?
+is_var :: CoreSyn.CoreExpr -> Bool
+is_var (CoreSyn.Var _) = True
+is_var _ = False
+
+is_lit :: CoreSyn.CoreExpr -> Bool
+is_lit (CoreSyn.Lit _) = True
+is_lit _ = False
+
+-- Can the given core expression be applied to something? This is true for
+-- applying to a value as well as a type.
+is_applicable :: CoreSyn.CoreExpr -> Bool
+is_applicable expr = is_fun expr || is_poly expr
+
+-- Is the given core expression a variable or an application?
+is_simple :: CoreSyn.CoreExpr -> Bool
+is_simple (CoreSyn.App _ _) = True
+is_simple (CoreSyn.Var _) = True
+is_simple (CoreSyn.Cast expr _) = is_simple expr
+is_simple _ = False
+
+-- Does the given CoreExpr have any free type vars?
+has_free_tyvars :: CoreSyn.CoreExpr -> Bool
+has_free_tyvars = not . VarSet.isEmptyVarSet . (CoreFVs.exprSomeFreeVars Var.isTyVar)
+
+-- Does the given type have any free type vars?
+ty_has_free_tyvars :: Type.Type -> Bool
+ty_has_free_tyvars = not . VarSet.isEmptyVarSet . Type.tyVarsOfType
+
+-- Does the given CoreExpr have any free local vars?
+has_free_vars :: CoreSyn.CoreExpr -> Bool
+has_free_vars = not . VarSet.isEmptyVarSet . CoreFVs.exprFreeVars
+
+-- Does the given expression use any of the given binders?
+expr_uses_binders :: [CoreSyn.CoreBndr] -> CoreSyn.CoreExpr -> Bool
+expr_uses_binders bndrs = not . VarSet.isEmptyVarSet . (CoreFVs.exprSomeFreeVars (`elem` bndrs))
+
+-- Turns a Var CoreExpr into the Id inside it. Will of course only work for
+-- simple Var CoreExprs, not complexer ones.
+exprToVar :: CoreSyn.CoreExpr -> Var.Id
+exprToVar (CoreSyn.Var id) = id
+exprToVar expr = error $ "\nCoreTools.exprToVar: Not a var: " ++ show expr
+
+-- Turns a Lit CoreExpr into the Literal inside it.
+exprToLit :: CoreSyn.CoreExpr -> Literal.Literal
+exprToLit (CoreSyn.Lit lit) = lit
+exprToLit expr = error $ "\nCoreTools.exprToLit: Not a lit: " ++ show expr
+
+-- Removes all the type and dictionary arguments from the given argument list,
+-- leaving only the normal value arguments. The type given is the type of the
+-- expression applied to this argument list.
+get_val_args :: Type.Type -> [CoreSyn.CoreExpr] -> [CoreSyn.CoreExpr]
+get_val_args ty args = drop n args
+  where
+    (tyvars, predtypes, _) = TcType.tcSplitSigmaTy ty
+    -- The first (length tyvars) arguments should be types, the next 
+    -- (length predtypes) arguments should be dictionaries. We drop this many
+    -- arguments, to get at the value arguments.
+    n = length tyvars + length predtypes
+
+-- Finds out what literal Integer this expression represents.
+getIntegerLiteral :: CoreSyn.CoreExpr -> TranslatorSession Integer
+getIntegerLiteral expr =
+  case CoreSyn.collectArgs expr of
+    (CoreSyn.Var f, [CoreSyn.Lit (Literal.MachInt integer)]) 
+      | getFullString f == "GHC.Integer.smallInteger" -> return integer
+    (CoreSyn.Var f, [CoreSyn.Lit (Literal.MachInt64 integer)]) 
+      | getFullString f == "GHC.Integer.int64ToInteger" -> return integer
+    (CoreSyn.Var f, [CoreSyn.Lit (Literal.MachWord integer)]) 
+      | getFullString f == "GHC.Integer.wordToInteger" -> return integer
+    (CoreSyn.Var f, [CoreSyn.Lit (Literal.MachWord64 integer)]) 
+      | getFullString f == "GHC.Integer.word64ToInteger" -> return integer
+    -- fromIntegerT returns the integer corresponding to the type of its
+    -- (third) argument. Since it is polymorphic, the type of that
+    -- argument is passed as the first argument, so we can just use that
+    -- one.
+    (CoreSyn.Var f, [CoreSyn.Type dec_ty, dec_dict, CoreSyn.Type num_ty, num_dict, arg]) 
+      | getFullString f == "Types.Data.Num.Ops.fromIntegerT" -> do
+          int <- MonadState.lift tsType $ tfp_to_int dec_ty
+          return $ toInteger int
+    _ -> error $ "CoreTools.getIntegerLiteral: Unsupported Integer literal: " ++ pprString expr
+
+reduceCoreListToHsList :: 
+  [HscTypes.CoreModule] -- ^ The modules where parts of the list are hidden
+  -> CoreSyn.CoreExpr   -- ^ The refence to atleast one of the nodes
+  -> TranslatorSession [CoreSyn.CoreExpr]
+reduceCoreListToHsList cores app@(CoreSyn.App _ _) = do {
+  ; let { (fun, args) = CoreSyn.collectArgs app
+        ; len         = length args 
+        } ;
+  ; case len of
+      3 -> do {
+        ; let topelem = args!!1
+        ; case (args!!2) of
+            (varz@(CoreSyn.Var id)) -> do {
+              ; binds <- mapM (findExpr (isVarName id)) cores
+              ; otherelems <- reduceCoreListToHsList cores (head (Maybe.catMaybes binds))
+              ; return (topelem:otherelems)
+              }
+            (appz@(CoreSyn.App _ _)) -> do {
+              ; otherelems <- reduceCoreListToHsList cores appz
+              ; return (topelem:otherelems)
+              }
+            otherwise -> return [topelem]
+        }
+      otherwise -> return []
+  }
+  where
+    isVarName :: Monad m => Var.Var -> Var.Var -> m Bool
+    isVarName lookfor bind = return $ (Var.varName lookfor) == (Var.varName bind)
+
+reduceCoreListToHsList _ _ = return []
+
+-- Is the given var the State data constructor?
+isStateCon :: Var.Var -> Bool
+isStateCon var =
+  -- See if it is a DataConWrapId (not DataConWorkId, since State is a
+  -- newtype).
+  case Id.idDetails var of
+    IdInfo.DataConWrapId dc -> 
+      -- See if the datacon is the State datacon from the State type.
+      let tycon = DataCon.dataConTyCon dc
+          tyname = Name.getOccString tycon
+          dcname = Name.getOccString dc
+      in case (tyname, dcname) of
+        ("State", "State") -> True
+        _ -> False
+    _ -> False
+
+-- | Is the given type a State type?
+isStateType :: Type.Type -> Bool
+-- Resolve any type synonyms remaining
+isStateType ty | Just ty' <- Type.tcView ty = isStateType ty'
+isStateType ty  = Maybe.isJust $ do
+  -- Split the type. Don't use normal splitAppTy, since that looks through
+  -- newtypes, and we want to see the State newtype.
+  (typef, _) <- Type.repSplitAppTy_maybe ty
+  -- See if the applied type is a type constructor
+  (tycon, _) <- Type.splitTyConApp_maybe typef
+  if TyCon.isNewTyCon tycon && Name.getOccString tycon == "State"
+    then
+      Just ()
+    else
+      Nothing
+
+-- | Does the given TypedThing have a State type?
+hasStateType :: (TypedThing t) => t -> Bool
+hasStateType expr = case getType expr of
+  Nothing -> False
+  Just ty -> isStateType ty
+
+
+-- | Flattens nested lets into a single list of bindings. The expression
+--   passed does not have to be a let expression, if it isn't an empty list of
+--   bindings is returned.
+flattenLets ::
+  CoreSyn.CoreExpr -- ^ The expression to flatten.
+  -> ([Binding], CoreSyn.CoreExpr) -- ^ The bindings and resulting expression.
+flattenLets (CoreSyn.Let binds expr) = 
+  (bindings ++ bindings', expr')
+  where
+    -- Recursively flatten the contained expression
+    (bindings', expr') =flattenLets expr
+    -- Flatten our own bindings to remove the Rec / NonRec constructors
+    bindings = CoreSyn.flattenBinds [binds]
+flattenLets expr = ([], expr)
+
+-- | Create bunch of nested non-recursive let expressions from the given
+-- bindings. The first binding is bound at the highest level (and thus
+-- available in all other bindings).
+mkNonRecLets :: [Binding] -> CoreSyn.CoreExpr -> CoreSyn.CoreExpr
+mkNonRecLets bindings expr = MkCore.mkCoreLets binds expr
+  where
+    binds = map (uncurry CoreSyn.NonRec) bindings
+
+-- | A class of things that (optionally) have a core Type. The type is
+-- optional, since Type expressions don't have a type themselves.
+class TypedThing t where
+  getType :: t -> Maybe Type.Type
+
+instance TypedThing CoreSyn.CoreExpr where
+  getType (CoreSyn.Type _) = Nothing
+  getType expr = Just $ CoreUtils.exprType expr
+
+instance TypedThing CoreSyn.CoreBndr where
+  getType = return . Id.idType
+
+instance TypedThing Type.Type where
+  getType = return . id
+
+-- | Generate new uniques for all binders in the given expression.
+-- Does not support making type variables unique, though this could be
+-- supported if required (by passing a CoreSubst.Subst instead of VarEnv to
+-- genUniques' below).
+genUniques :: CoreSyn.CoreExpr -> TranslatorSession CoreSyn.CoreExpr
+genUniques = genUniques' VarEnv.emptyVarEnv
+
+-- | A helper function to generate uniques, that takes a VarEnv containing the
+--   substitutions already performed.
+genUniques' :: VarEnv.VarEnv CoreSyn.CoreBndr -> CoreSyn.CoreExpr -> TranslatorSession CoreSyn.CoreExpr
+genUniques' subst (CoreSyn.Var f) = do
+  -- Replace the binder with its new value, if applicable.
+  let f' = VarEnv.lookupWithDefaultVarEnv subst f f
+  return (CoreSyn.Var f')
+-- Leave literals untouched
+genUniques' subst (CoreSyn.Lit l) = return $ CoreSyn.Lit l
+genUniques' subst (CoreSyn.App f arg) = do
+  -- Only work on subexpressions
+  f' <- genUniques' subst f
+  arg' <- genUniques' subst arg
+  return (CoreSyn.App f' arg')
+-- Don't change type abstractions
+genUniques' subst expr@(CoreSyn.Lam bndr res) | CoreSyn.isTyVar bndr = return expr
+genUniques' subst (CoreSyn.Lam bndr res) = do
+  -- Generate a new unique for the bound variable
+  (subst', bndr') <- genUnique subst bndr
+  res' <- genUniques' subst' res
+  return (CoreSyn.Lam bndr' res')
+genUniques' subst (CoreSyn.Let (CoreSyn.NonRec bndr bound) res) = do
+  -- Make the binders unique
+  (subst', bndr') <- genUnique subst bndr
+  bound' <- genUniques' subst' bound
+  res' <- genUniques' subst' res
+  return $ CoreSyn.Let (CoreSyn.NonRec bndr' bound') res'
+genUniques' subst (CoreSyn.Let (CoreSyn.Rec binds) res) = do
+  -- Make each of the binders unique
+  (subst', bndrs') <- mapAccumLM genUnique subst (map fst binds)
+  bounds' <- mapM (genUniques' subst' . snd) binds
+  res' <- genUniques' subst' res
+  let binds' = zip bndrs' bounds'
+  return $ CoreSyn.Let (CoreSyn.Rec binds') res'
+genUniques' subst (CoreSyn.Case scrut bndr ty alts) = do
+  -- Process the scrutinee with the original substitution, since non of the
+  -- binders bound in the Case statement is in scope in the scrutinee.
+  scrut' <- genUniques' subst scrut
+  -- Generate a new binder for the scrutinee
+  (subst', bndr') <- genUnique subst bndr
+  -- Process each of the alts
+  alts' <- mapM (doalt subst') alts
+  return $ CoreSyn.Case scrut' bndr' ty alts'
+  where
+    doalt subst (con, bndrs, expr) = do
+      (subst', bndrs') <- mapAccumLM genUnique subst bndrs
+      expr' <- genUniques' subst' expr
+      -- Note that we don't return subst', since bndrs are only in scope in
+      -- expr.
+      return (con, bndrs', expr')
+genUniques' subst (CoreSyn.Cast expr coercion) = do
+  expr' <- genUniques' subst expr
+  -- Just process the casted expression
+  return $ CoreSyn.Cast expr' coercion
+genUniques' subst (CoreSyn.Note note expr) = do
+  expr' <- genUniques' subst expr
+  -- Just process the annotated expression
+  return $ CoreSyn.Note note expr'
+-- Leave types untouched
+genUniques' subst expr@(CoreSyn.Type _) = return expr
+
+-- Generate a new unique for the given binder, and extend the given
+-- substitution to reflect this.
+genUnique :: VarEnv.VarEnv CoreSyn.CoreBndr -> CoreSyn.CoreBndr -> TranslatorSession (VarEnv.VarEnv CoreSyn.CoreBndr, CoreSyn.CoreBndr)
+genUnique subst bndr = do
+  bndr' <- BinderTools.cloneVar bndr
+  -- Replace all occurences of the old binder with a reference to the new
+  -- binder.
+  let subst' = VarEnv.extendVarEnv subst bndr bndr'
+  return (subst', bndr')
+
+-- Create a "selector" case that selects the ith field from a datacon
+mkSelCase :: CoreSyn.CoreExpr -> Int -> TranslatorSession CoreSyn.CoreExpr
+mkSelCase scrut i = do
+  let scrut_ty = CoreUtils.exprType scrut
+  case Type.splitTyConApp_maybe scrut_ty of
+    -- The scrutinee should have a type constructor. We keep the type
+    -- arguments around so we can instantiate the field types below
+    Just (tycon, tyargs) -> case TyCon.tyConDataCons tycon of
+      -- The scrutinee type should have a single dataconstructor,
+      -- otherwise we can't construct a valid selector case.
+      [datacon] -> do
+        let field_tys = DataCon.dataConInstOrigArgTys datacon tyargs
+        -- Create a list of wild binders for the fields we don't want
+        let wildbndrs = map MkCore.mkWildBinder field_tys
+        -- Create a single binder for the field we want
+        sel_bndr <- mkInternalVar "sel" (field_tys!!i)
+        -- Create a wild binder for the scrutinee
+        let scrut_bndr = MkCore.mkWildBinder scrut_ty
+        -- Create the case expression
+        let binders = take i wildbndrs ++ [sel_bndr] ++ drop (i+1) wildbndrs
+        return $ CoreSyn.Case scrut scrut_bndr scrut_ty [(CoreSyn.DataAlt datacon, binders, CoreSyn.Var sel_bndr)]
+      dcs -> error $ "CoreTools.mkSelCase: Scrutinee type must have exactly one datacon. Extracting element " ++ (show i) ++ " from '" ++ pprString scrut ++ "' Datacons: " ++ (show dcs) ++ " Type: " ++ (pprString scrut_ty)
+    Nothing -> error $ "CoreTools.mkSelCase: Creating extractor case, but scrutinee has no tycon? Extracting element " ++ (show i) ++ " from '" ++ pprString scrut ++ "'" ++ " Type: " ++ (pprString scrut_ty)
diff --git a/clash/CLasH/Utils/GhcTools.hs b/clash/CLasH/Utils/GhcTools.hs
new file mode 100644 (file)
index 0000000..022a997
--- /dev/null
@@ -0,0 +1,256 @@
+{-# LANGUAGE ScopedTypeVariables #-}
+
+module CLasH.Utils.GhcTools where
+  
+-- Standard modules
+import qualified Monad
+import qualified System.IO.Unsafe
+import qualified Language.Haskell.TH as TH
+import qualified Maybe
+
+-- GHC API
+import qualified Annotations
+import qualified CoreSyn
+import qualified CoreUtils
+import qualified DynFlags
+import qualified HscTypes
+import qualified GHC
+import qualified Name
+import qualified Serialized
+import qualified Var
+import qualified Outputable
+import Outputable(($+$), (<+>), nest, empty, text, vcat)
+import qualified Class
+
+-- Local Imports
+import CLasH.Utils.Pretty
+import CLasH.Translator.TranslatorTypes
+import CLasH.Translator.Annotations
+import CLasH.Utils
+
+-- How far to indent the values after a Foo: header
+align = 20
+-- How far to indent all lines after the first
+indent = 5
+
+listBindings :: FilePath -> [FilePath] -> IO ()
+listBindings libdir filenames = do
+  (cores,_,_) <- loadModules libdir filenames Nothing
+  let binds = concatMap (CoreSyn.flattenBinds . HscTypes.cm_binds) cores
+  mapM listBinding binds
+  putStr "\n=========================\n"
+  let classes = concatMap (HscTypes.typeEnvClasses . HscTypes.cm_types) cores
+  mapM listClass classes
+  return ()
+
+-- Slightly different version of hang, that always uses vcat instead of
+-- sep, so the first line of d2 preserves its nesting.
+hang' d1 n d2 = vcat [d1, nest n d2]
+
+listBinding :: (CoreSyn.CoreBndr, CoreSyn.CoreExpr) -> IO ()
+listBinding (b, e) = putStr $ Outputable.showSDoc $
+  (text "Binder:") <+> (text $ show b ++ "[" ++ show (Var.varUnique b) ++ "]")
+  $+$ nest indent (
+    hang' (text "Type of Binder:") align (Outputable.ppr $ Var.varType b)
+    $+$ hang' (text "Expression:") align (text $ prettyShow e)
+    $+$ nest align (Outputable.ppr e)
+    $+$ hang' (text "Type of Expression:") align (Outputable.ppr $ CoreUtils.exprType e)
+  )
+  $+$ (text "\n") -- Add an empty line
+
+listClass :: Class.Class -> IO ()
+listClass c = putStr $ Outputable.showSDoc $
+  (text "Class:") <+> (text $ show (Class.className c))
+  $+$ nest indent (
+    hang' (text "Selectors:") align (text $ show (Class.classSelIds c))
+  )
+  $+$ (text "\n") -- Add an empty line
+  
+-- | Show the core structure of the given binds in the given file.
+listBind :: FilePath -> [FilePath] -> String -> IO ()
+listBind libdir filenames name = do
+  (cores,_,_) <- loadModules libdir filenames Nothing
+  bindings <- concatM $ mapM (findBinder (hasVarName name)) cores
+  mapM_ listBinding bindings
+  return ()
+
+-- Change a DynFlag from within the Ghc monad. Strangely enough there seems to
+-- be no standard function to do exactly this.
+setDynFlag :: DynFlags.DynFlag -> GHC.Ghc ()
+setDynFlag dflag = do
+  dflags <- GHC.getSessionDynFlags
+  let dflags' = DynFlags.dopt_set dflags dflag
+  GHC.setSessionDynFlags dflags'
+  return ()
+
+-- We don't want the IO monad sprinkled around everywhere, so we hide it.
+-- This should be safe as long as we only do simple things in the GhcMonad
+-- such as interface lookups and evaluating simple expressions that
+-- don't have side effects themselves (Or rather, that don't use
+-- unsafePerformIO themselves, since normal side effectful function would
+-- just return an IO monad when they are evaluated).
+unsafeRunGhc :: FilePath -> GHC.Ghc a -> a
+unsafeRunGhc libDir m =
+  System.IO.Unsafe.unsafePerformIO $
+      GHC.runGhc (Just libDir) $ do
+        dflags <- GHC.getSessionDynFlags
+        GHC.setSessionDynFlags dflags
+        m
+  
+-- | Loads the given files and turns it into a core module
+loadModules ::
+  FilePath      -- ^ The GHC Library directory 
+  -> [String]   -- ^ The files that need to be loaded
+  -> Maybe Finder -- ^ What entities to build?
+  -> IO ( [HscTypes.CoreModule]
+        , HscTypes.HscEnv
+        , [EntitySpec]
+        ) -- ^ ( The loaded modules, the resulting ghc environment, the entities to build)
+loadModules libdir filenames finder =
+  GHC.defaultErrorHandler DynFlags.defaultDynFlags $
+    GHC.runGhc (Just libdir) $ do
+      dflags <- GHC.getSessionDynFlags
+      GHC.setSessionDynFlags dflags
+      cores <- mapM GHC.compileToCoreModule filenames
+      env <- GHC.getSession
+      specs <- case finder of
+        Nothing -> return []
+        Just f -> concatM $ mapM f cores
+      return (cores, env, specs)
+
+findBinds ::
+  Monad m =>
+  (Var.Var -> m Bool)
+  -> HscTypes.CoreModule
+  -> m (Maybe [CoreSyn.CoreBndr])
+findBinds criteria core = do
+  binders <- findBinder criteria core
+  case binders of
+    [] -> return Nothing
+    bndrs -> return $ Just $ map fst bndrs
+
+findBind ::
+  Monad m =>
+  (Var.Var -> m Bool)
+  -> HscTypes.CoreModule
+  -> m (Maybe CoreSyn.CoreBndr)
+findBind criteria core = do
+  binders <- findBinds criteria core
+  case binders of
+    Nothing -> return Nothing
+    (Just bndrs) -> return $ Just $ head bndrs
+
+findExprs ::
+  Monad m =>
+  (Var.Var -> m Bool)
+  -> HscTypes.CoreModule
+  -> m (Maybe [CoreSyn.CoreExpr])
+findExprs criteria core = do
+  binders <- findBinder criteria core
+  case binders of
+    [] -> return Nothing
+    bndrs -> return $ Just (map snd bndrs)
+
+findExpr ::
+  Monad m =>
+  (Var.Var -> m Bool)
+  -> HscTypes.CoreModule
+  -> m (Maybe CoreSyn.CoreExpr)
+findExpr criteria core = do
+  exprs <- findExprs criteria core
+  case exprs of
+    Nothing -> return Nothing
+    (Just exprs) -> return $ Just $ head exprs
+
+findAnns ::
+  Monad m =>
+  (Var.Var -> m [CLasHAnn])
+  -> HscTypes.CoreModule
+  -> m [CLasHAnn]
+findAnns criteria core = do
+  let binds = CoreSyn.flattenBinds $ HscTypes.cm_binds core
+  anns <- Monad.mapM (criteria . fst) binds
+  case anns of
+    [] -> return []
+    xs -> return $ concat xs
+
+-- | Find a binder in module according to a certain criteria
+findBinder :: 
+  Monad m =>
+  (Var.Var -> m Bool)     -- ^ The criteria to filter the binders on
+  -> HscTypes.CoreModule  -- ^ The module to be inspected
+  -> m [(CoreSyn.CoreBndr, CoreSyn.CoreExpr)] -- ^ The binders to meet the criteria
+findBinder criteria core = do
+  let binds = CoreSyn.flattenBinds $ HscTypes.cm_binds core
+  Monad.filterM (criteria . fst) binds
+
+-- | Determine if a binder has an Annotation meeting a certain criteria
+isCLasHAnnotation ::
+  GHC.GhcMonad m =>
+  (CLasHAnn -> Bool)  -- ^ The criteria the Annotation has to meet
+  -> Var.Var          -- ^ The Binder
+  -> m [CLasHAnn]           -- ^ Indicates if binder has the Annotation
+isCLasHAnnotation clashAnn var = do
+  let deserializer = Serialized.deserializeWithData
+  let target = Annotations.NamedTarget (Var.varName var)
+  (anns :: [CLasHAnn]) <- GHC.findGlobalAnns deserializer target
+  let annEnts = filter clashAnn anns
+  return annEnts
+
+-- | Determine if a binder has an Annotation meeting a certain criteria
+hasCLasHAnnotation ::
+  GHC.GhcMonad m =>
+  (CLasHAnn -> Bool)  -- ^ The criteria the Annotation has to meet
+  -> Var.Var          -- ^ The Binder
+  -> m Bool           -- ^ Indicates if binder has the Annotation
+hasCLasHAnnotation clashAnn var = do
+  anns <- isCLasHAnnotation clashAnn var
+  case anns of
+    [] -> return False
+    xs -> return True
+
+-- | Determine if a binder has a certain name
+hasVarName ::   
+  Monad m =>
+  String        -- ^ The name the binder has to have
+  -> Var.Var    -- ^ The Binder
+  -> m Bool     -- ^ Indicate if the binder has the name
+hasVarName lookfor bind = return $ lookfor == Name.occNameString (Name.nameOccName $ Name.getName bind)
+
+
+findInitStates ::
+  (Var.Var -> GHC.Ghc Bool) -> 
+  (Var.Var -> GHC.Ghc [CLasHAnn]) -> 
+  HscTypes.CoreModule -> 
+  GHC.Ghc (Maybe [(CoreSyn.CoreBndr, CoreSyn.CoreBndr)])
+findInitStates statec annsc mod = do
+  states <- findBinds statec mod
+  anns  <- findAnns annsc mod
+  let funs = Maybe.catMaybes (map extractInits anns)
+  exprs' <- mapM (\x -> findBind (hasVarName (TH.nameBase x)) mod) funs
+  let exprs = Maybe.catMaybes exprs'
+  let inits = zipMWith (\a b -> (a,b)) states exprs
+  return inits
+  where
+    extractInits :: CLasHAnn -> Maybe TH.Name
+    extractInits (InitState x)  = Just x
+    extractInits _              = Nothing
+    zipMWith :: (a -> b -> c) -> (Maybe [a]) -> [b] -> (Maybe [c])
+    zipMWith _ Nothing   _  = Nothing
+    zipMWith f (Just as) bs = Just $ zipWith f as bs
+
+-- | Make a complete spec out of a three conditions
+findSpec ::
+  (Var.Var -> GHC.Ghc Bool) -> (Var.Var -> GHC.Ghc Bool) -> (Var.Var -> GHC.Ghc [CLasHAnn]) -> (Var.Var -> GHC.Ghc Bool)
+  -> Finder
+
+findSpec topc statec annsc testc mod = do
+  top <- findBind topc mod
+  state <- findExprs statec mod
+  anns <- findAnns annsc mod
+  test <- findExpr testc mod
+  inits <- findInitStates statec annsc mod
+  return [(top, inits, test)]
+  -- case top of
+  --   Just t -> return [(t, state, test)]
+  --   Nothing -> return error $ "Could not find top entity requested"
diff --git a/clash/CLasH/Utils/HsTools.hs b/clash/CLasH/Utils/HsTools.hs
new file mode 100644 (file)
index 0000000..22b1382
--- /dev/null
@@ -0,0 +1,212 @@
+module CLasH.Utils.HsTools where
+
+-- Standard modules
+import qualified Unsafe.Coerce
+import qualified Maybe
+
+-- GHC API
+import qualified GHC
+import qualified HscMain
+import qualified HscTypes
+import qualified DynFlags
+import qualified FastString
+import qualified StringBuffer
+import qualified MonadUtils
+import Outputable ( showSDoc, ppr )
+import qualified Outputable
+-- Lexer & Parser, i.e. up to HsExpr
+import qualified Lexer
+import qualified Parser
+-- HsExpr representation, renaming, typechecking and desugaring
+-- (i.e., everything up to Core).
+import qualified HsSyn
+import qualified HsExpr
+import qualified HsTypes
+import qualified HsBinds
+import qualified TcRnMonad
+import qualified TcRnTypes
+import qualified RnExpr
+import qualified RnEnv
+import qualified TcExpr
+import qualified TcEnv
+import qualified TcSimplify
+import qualified TcTyFuns
+import qualified Desugar
+import qualified PrelNames
+import qualified Module
+import qualified OccName
+import qualified RdrName
+import qualified Name
+import qualified SrcLoc
+import qualified LoadIface
+import qualified BasicTypes
+-- Core representation and handling
+import qualified CoreSyn
+import qualified Id
+import qualified Type
+import qualified TyCon
+
+-- | Translate a HsExpr to a Core expression. This does renaming, type
+-- checking, simplification of class instances and desugaring. The result is
+-- a let expression that holds the given expression and a number of binds that
+-- are needed for any type classes used to work. For example, the HsExpr:
+--  \x = x == (1 :: Int)
+-- will result in the CoreExpr
+--  let 
+--    $dInt = ...
+--    (==) = Prelude.(==) Int $dInt 
+--  in 
+--    \x = (==) x 1
+toCore ::
+  HsSyn.HsExpr RdrName.RdrName -- ^ The expression to translate to Core.
+  -> GHC.Ghc CoreSyn.CoreExpr -- ^ The resulting core expression.
+toCore expr = do
+  env <- GHC.getSession
+  let icontext = HscTypes.hsc_IC env
+  
+  (binds, tc_expr) <- HscTypes.ioMsgMaybe $ MonadUtils.liftIO $ 
+    -- Translage the TcRn (typecheck-rename) monad into an IO monad
+    TcRnMonad.initTcPrintErrors env PrelNames.iNTERACTIVE $ do
+      (tc_expr, insts) <- TcRnMonad.getLIE $ do
+        -- Rename the expression, resulting in a HsExpr Name
+        (rn_expr, freevars) <- RnExpr.rnExpr expr
+        -- Typecheck the expression, resulting in a HsExpr Id and a list of
+        -- Insts
+        (res, _) <- TcExpr.tcInferRho (SrcLoc.noLoc rn_expr)
+        return res
+      -- Translate the instances into bindings
+      --(insts', binds) <- TcSimplify.tcSimplifyRuleLhs insts
+      binds <- TcSimplify.tcSimplifyTop insts
+      return (binds, tc_expr)
+  
+  -- Create a let expression with the extra binds (for polymorphism etc.) and
+  -- the resulting expression.
+  let letexpr = SrcLoc.noLoc $ HsExpr.HsLet 
+        (HsBinds.HsValBinds $ HsBinds.ValBindsOut [(BasicTypes.NonRecursive, binds)] [])
+        tc_expr
+  -- Desugar the expression, resulting in core.
+  let rdr_env  = HscTypes.ic_rn_gbl_env icontext
+  HscTypes.ioMsgMaybe $ Desugar.deSugarExpr env PrelNames.iNTERACTIVE rdr_env HscTypes.emptyTypeEnv letexpr
+
+
+-- | Create an Id from a RdrName. Might not work for DataCons...
+mkId :: RdrName.RdrName -> GHC.Ghc Id.Id
+mkId rdr_name = do
+  env <- GHC.getSession
+  HscTypes.ioMsgMaybe $ MonadUtils.liftIO $ 
+    -- Translage the TcRn (typecheck-rename) monad in an IO monad
+    TcRnMonad.initTcPrintErrors env PrelNames.iNTERACTIVE $ 
+      -- Automatically import all available modules, so fully qualified names
+      -- always work
+      TcRnMonad.setOptM DynFlags.Opt_ImplicitImportQualified $ do
+        -- Lookup a Name for the RdrName. This finds the package (version) in
+        -- which the name resides.
+        name <- RnEnv.lookupGlobalOccRn rdr_name
+        -- Lookup an Id for the Name. This finds out the the type of the thing
+        -- we're looking for.
+        --
+        -- Note that tcLookupId doesn't seem to work for DataCons. See source for
+        -- tcLookupId to find out.
+        TcEnv.tcLookupId name 
+
+normalizeType ::
+  HscTypes.HscEnv
+  -> Type.Type
+  -> IO Type.Type
+normalizeType env ty = do
+   (err, nty) <- MonadUtils.liftIO $
+     -- Initialize the typechecker monad
+     TcRnMonad.initTcPrintErrors env PrelNames.iNTERACTIVE $ do
+       -- Normalize the type
+       (_, nty) <- TcTyFuns.tcNormaliseFamInst ty
+       return nty
+   let normalized_ty = Maybe.fromJust nty
+   return normalized_ty
+
+-- | Translate a core Type to an HsType. Far from complete so far.
+coreToHsType :: Type.Type -> HsTypes.LHsType RdrName.RdrName
+--  Translate TyConApps
+coreToHsType ty = case Type.splitTyConApp_maybe ty of
+  Just (tycon, tys) ->
+    foldl (\t a -> SrcLoc.noLoc $ HsTypes.HsAppTy t a) tycon_ty (map coreToHsType tys)
+    where
+      tycon_name = TyCon.tyConName tycon
+      mod_name = Module.moduleName $ Name.nameModule tycon_name
+      occ_name = Name.nameOccName tycon_name
+      tycon_rdrname = RdrName.mkRdrQual mod_name occ_name
+      tycon_ty = SrcLoc.noLoc $ HsTypes.HsTyVar tycon_rdrname
+  Nothing -> error "HsTools.coreToHsType Cannot translate non-tycon type"
+
+-- | Evaluate a CoreExpr and return its value. For this to work, the caller
+--   should already know the result type for sure, since the result value is
+--   unsafely coerced into this type.
+execCore :: CoreSyn.CoreExpr -> GHC.Ghc a
+execCore expr = do
+        -- Setup session flags (yeah, this seems like a noop, but
+        -- setSessionDynFlags really does some extra work...)
+        dflags <- GHC.getSessionDynFlags
+        GHC.setSessionDynFlags dflags
+        -- Compile the expressions. This runs in the IO monad, but really wants
+        -- to run an IO-monad-inside-a-GHC-monad for some reason. I don't really
+        -- understand what it means, but it works.
+        env <- GHC.getSession
+        let srcspan = SrcLoc.noSrcSpan
+        hval <- MonadUtils.liftIO $ HscMain.compileExpr env srcspan expr
+        let res = Unsafe.Coerce.unsafeCoerce hval :: Int
+        return $ Unsafe.Coerce.unsafeCoerce hval
+
+-- These functions build (parts of) a LHSExpr RdrName.
+
+-- | A reference to the Prelude.undefined function.
+hsUndef :: HsExpr.LHsExpr RdrName.RdrName
+hsUndef = SrcLoc.noLoc $ HsExpr.HsVar PrelNames.undefined_RDR
+
+-- | A typed reference to the Prelude.undefined function.
+hsTypedUndef :: HsTypes.LHsType RdrName.RdrName -> HsExpr.LHsExpr RdrName.RdrName
+hsTypedUndef ty = SrcLoc.noLoc $ HsExpr.ExprWithTySig hsUndef ty
+
+-- | Create a qualified RdrName from a module name and a variable name
+mkRdrName :: String -> String -> RdrName.RdrName
+mkRdrName mod var =
+    RdrName.mkRdrQual (Module.mkModuleName mod) (OccName.mkVarOcc var)
+
+-- These three functions are simplified copies of those in HscMain, because
+-- those functions are not exported. These versions have all error handling
+-- removed.
+hscParseType = hscParseThing Parser.parseType
+hscParseStmt = hscParseThing Parser.parseStmt
+
+hscParseThing :: Lexer.P thing -> DynFlags.DynFlags -> String -> GHC.Ghc thing
+hscParseThing parser dflags str = do
+    buf <- MonadUtils.liftIO $ StringBuffer.stringToStringBuffer str
+    let loc  = SrcLoc.mkSrcLoc (FastString.fsLit "<interactive>") 1 0
+    let Lexer.POk _ thing = Lexer.unP parser (Lexer.mkPState buf loc dflags)
+    return thing
+
+-- | This function imports the module with the given name, for the renamer /
+-- typechecker to use. It also imports any "orphans" and "family instances"
+-- from modules included by this module, but not the actual modules
+-- themselves. I'm not 100% sure how this works, but it seems that any
+-- functions defined in included modules are available just by loading the
+-- original module, and by doing this orphan stuff, any (type family or class)
+-- instances are available as well.
+--
+-- Most of the code is based on tcRnImports and rnImportDecl, but those
+-- functions do a lot more (which I hope we won't need...).
+importModule :: Module.ModuleName -> TcRnTypes.RnM ()
+importModule mod = do
+  let reason = Outputable.text "Hardcoded import" -- Used for trace output
+  let pkg = Nothing
+  -- Load the interface.
+  iface <- LoadIface.loadSrcInterface reason mod False pkg
+  -- Load orphan an familiy instance dependencies as well. I think these
+  -- dependencies are needed for the type checker to know all instances. Any
+  -- other instances (on other packages) are only useful to the
+  -- linker, so we can probably safely ignore them here. Dependencies within
+  -- the same package are also listed in deps, but I'm not so sure what to do
+  -- with them.
+  let deps = HscTypes.mi_deps iface
+  let orphs = HscTypes.dep_orphs deps
+  let finsts = HscTypes.dep_finsts deps
+  LoadIface.loadOrphanModules orphs False
+  LoadIface.loadOrphanModules finsts True
diff --git a/clash/CLasH/Utils/Pretty.hs b/clash/CLasH/Utils/Pretty.hs
new file mode 100644 (file)
index 0000000..df78ad9
--- /dev/null
@@ -0,0 +1,81 @@
+module CLasH.Utils.Pretty (prettyShow, pprString, pprStringDebug) where
+
+-- Standard imports
+import qualified Data.Map as Map
+import Text.PrettyPrint.HughesPJClass
+
+-- GHC API
+import qualified CoreSyn
+import Outputable ( showSDoc, showSDocDebug, ppr, Outputable, OutputableBndr)
+
+-- VHDL Imports 
+import qualified Language.VHDL.Ppr as Ppr
+import qualified Language.VHDL.AST as AST
+import qualified Language.VHDL.AST.Ppr
+
+-- Local imports
+import CLasH.VHDL.VHDLTypes
+import CLasH.Utils.Core.CoreShow
+
+-- | A version of the default pPrintList method, which uses a custom function
+--   f instead of pPrint to print elements.
+printList :: (a -> Doc) -> [a] -> Doc
+printList f = brackets . fsep . punctuate comma . map f
+
+{-
+instance Pretty FuncData where
+  pPrint (FuncData flatfunc entity arch) =
+    text "Flattened: " $$ nest 15 (ppffunc flatfunc)
+    $+$ text "Entity" $$ nest 15 (ppent entity)
+    $+$ pparch arch
+    where
+      ppffunc (Just f) = pPrint f
+      ppffunc Nothing  = text "Nothing"
+      ppent (Just e)   = pPrint e
+      ppent Nothing    = text "Nothing"
+      pparch Nothing = text "VHDL architecture not present"
+      pparch (Just _) = text "VHDL architecture present"
+-}
+
+instance Pretty Entity where
+  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) =
+    text "NonRec: " $$ nest 10 (prettyBind (b, expr))
+  pPrint (CoreSyn.Rec binds) =
+    text "Rec: " $$ nest 10 (vcat $ map (prettyBind) binds)
+
+instance (OutputableBndr b, Show b) => Pretty (CoreSyn.Expr b) where
+  pPrint = text . show
+
+instance Pretty AST.VHDLId where
+  pPrint id = Ppr.ppr id
+  
+instance Pretty AST.VHDLName where
+  pPrint name = Ppr.ppr name
+
+prettyBind :: (Show b, Show e) => (b, e) -> Doc
+prettyBind (b, expr) =
+  text b' <> text " = " <> text expr'
+  where
+    b' = show b
+    expr' = show expr
+
+instance (Pretty k, Pretty v) => Pretty (Map.Map k v) where
+  pPrint = 
+    vcat . map ppentry . Map.toList
+    where
+      ppentry (k, v) =
+        pPrint k <> text " : " $$ nest 15 (pPrint v)
+
+-- Convenience method for turning an Outputable into a string
+pprString :: (Outputable x) => x -> String
+pprString = showSDoc . ppr
+
+pprStringDebug :: (Outputable x) => x -> String
+pprStringDebug = showSDocDebug . ppr
diff --git a/clash/CLasH/VHDL.hs b/clash/CLasH/VHDL.hs
new file mode 100644 (file)
index 0000000..56342fc
--- /dev/null
@@ -0,0 +1,99 @@
+--
+-- Functions to generate VHDL from FlatFunctions
+--
+module CLasH.VHDL where
+
+-- Standard modules
+import qualified Data.Map as Map
+import qualified Maybe
+import qualified Control.Arrow as Arrow
+import Data.Accessor
+import qualified Data.Accessor.Monad.Trans.State as MonadState
+
+-- VHDL Imports
+import qualified Language.VHDL.AST as AST
+
+-- GHC API
+import qualified CoreSyn
+
+-- Local imports
+import CLasH.Translator.TranslatorTypes
+import CLasH.VHDL.VHDLTypes
+import CLasH.VHDL.VHDLTools
+import CLasH.VHDL.Constants
+import CLasH.VHDL.Generate
+
+createDesignFiles ::
+  [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
+    full_context =
+      mkUseAll ["work", "types"]
+      : (mkUseAll ["work"]
+      : ieee_context)
+
+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 <- MonadState.get (tsType .> tsTypeFuns)
+  let tyfun_decls = mkBuiltInShow ++ map snd (Map.elems tyfuns)
+  ty_decls_maybes <- MonadState.get (tsType .> tsTypeDecls)
+  let ty_decls = Maybe.catMaybes ty_decls_maybes
+  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
+mkUseAll :: [String] -> AST.ContextItem
+mkUseAll ss = 
+  AST.Use $ from AST.:.: AST.All
+  where
+    base_prefix = (AST.NSimple $ mkVHDLBasicId $ head ss)
+    from = foldl select base_prefix (tail ss)
+    select prefix s = AST.NSelected $ prefix AST.:.: (AST.SSimple $ mkVHDLBasicId s)
+      
+createLibraryUnit ::
+  CoreSyn.CoreBndr
+  -> TranslatorSession (AST.VHDLId, [AST.LibraryUnit])
+
+createLibraryUnit bndr = do
+  entity <- getEntity bndr
+  (arch, _) <- getArchitecture bndr
+  return (ent_id entity, [AST.LUEntity (ent_dec entity), AST.LUArch arch])
diff --git a/clash/CLasH/VHDL/Constants.hs b/clash/CLasH/VHDL/Constants.hs
new file mode 100644 (file)
index 0000000..c70ca71
--- /dev/null
@@ -0,0 +1,399 @@
+module CLasH.VHDL.Constants where
+
+-- VHDL Imports  
+import qualified Language.VHDL.AST as AST
+
+-- | A list of all builtin functions. Partly duplicates the name table
+-- in VHDL.Generate, but we can't use that map everywhere due to
+-- circular dependencie.
+builtinIds = [ exId, replaceId, headId, lastId, tailId, initId, takeId, dropId
+             , selId, plusgtId, ltplusId, plusplusId, mapId, zipWithId, foldlId
+             , foldrId, zipId, unzipId, shiftlId, shiftrId, rotlId, rotrId
+             , concatId, reverseId, iteratenId, iterateId, generatenId, generateId
+             , emptyId, singletonId, copynId, copyId, lengthTId, nullId
+             , hwxorId, hwandId, hworId, hwnotId, equalityId, inEqualityId, ltId
+             , lteqId, gtId, gteqId, boolOrId, boolAndId, plusId, timesId
+             , negateId, minusId, fromSizedWordId, fromIntegerId, resizeWordId
+             , resizeIntId, sizedIntId, smallIntegerId, fstId, sndId, blockRAMId
+             , splitId, minimumId, fromRangedWordId 
+             ]
+--------------
+-- Identifiers
+--------------
+
+-- | reset and clock signal identifiers in String form
+resetStr, clockStr :: String
+resetStr = "resetn"
+clockStr = "clock"
+
+-- | reset and clock signal identifiers in basic AST.VHDLId form
+resetId, clockId :: AST.VHDLId
+resetId = AST.unsafeVHDLBasicId resetStr
+clockId = AST.unsafeVHDLBasicId clockStr
+
+integerId :: AST.VHDLId
+integerId = AST.unsafeVHDLBasicId "integer"
+
+-- | \"types\" identifier
+typesId :: AST.VHDLId
+typesId = AST.unsafeVHDLBasicId "types"
+
+-- | work identifier
+workId :: AST.VHDLId
+workId = AST.unsafeVHDLBasicId "work"
+
+-- | std identifier
+stdId :: AST.VHDLId
+stdId = AST.unsafeVHDLBasicId "std"
+
+
+-- | textio identifier
+textioId :: AST.VHDLId
+textioId = AST.unsafeVHDLBasicId "textio"
+
+-- | range attribute identifier
+rangeId :: AST.VHDLId
+rangeId = AST.unsafeVHDLBasicId "range"
+
+
+-- | high attribute identifier
+highId :: AST.VHDLId
+highId = AST.unsafeVHDLBasicId "high"
+
+-- | range attribute identifier
+imageId :: AST.VHDLId
+imageId = AST.unsafeVHDLBasicId "image"
+
+-- | event attribute identifie
+eventId :: AST.VHDLId
+eventId = AST.unsafeVHDLBasicId "event"
+
+
+-- | default function identifier
+defaultId :: AST.VHDLId
+defaultId = AST.unsafeVHDLBasicId "default"
+
+-- FSVec function identifiers
+
+-- | ex (operator ! in original Haskell source) function identifier
+exId :: String
+exId = "!"
+
+-- | sel (function select in original Haskell source) function identifier
+selId :: String
+selId = "select"
+
+
+-- | ltplus (function (<+) in original Haskell source) function identifier
+ltplusId :: String
+ltplusId = "<+"
+
+
+-- | plusplus (function (++) in original Haskell source) function identifier
+plusplusId :: String
+plusplusId = "++"
+
+
+-- | empty function identifier
+emptyId :: String
+emptyId = "empty"
+
+-- | plusgt (function (+>) in original Haskell source) function identifier
+plusgtId :: String
+plusgtId = "+>"
+
+-- | singleton function identifier
+singletonId :: String
+singletonId = "singleton"
+
+-- | length function identifier
+lengthId :: String
+lengthId = "length"
+
+
+-- | isnull (function null in original Haskell source) function identifier
+nullId :: String
+nullId = "null"
+
+
+-- | replace function identifier
+replaceId :: String
+replaceId = "replace"
+
+
+-- | head function identifier
+headId :: String
+headId = "head"
+
+
+-- | last function identifier
+lastId :: String
+lastId = "last"
+
+
+-- | init function identifier
+initId :: String
+initId = "init"
+
+
+-- | tail function identifier
+tailId :: String
+tailId = "tail"
+
+-- | minimum ftp function identifier
+minimumId :: String
+minimumId = "minimum"
+
+-- | take function identifier
+takeId :: String
+takeId = "take"
+
+
+-- | drop function identifier
+dropId :: String
+dropId = "drop"
+
+-- | shiftl function identifier
+shiftlId :: String
+shiftlId = "shiftl"
+
+-- | shiftr function identifier
+shiftrId :: String
+shiftrId = "shiftr"
+
+-- | rotl function identifier
+rotlId :: String
+rotlId = "rotl"
+
+-- | reverse function identifier
+rotrId :: String
+rotrId = "rotr"
+
+-- | concatenate the vectors in a vector
+concatId :: String
+concatId = "concat"
+
+-- | reverse function identifier
+reverseId :: String
+reverseId = "reverse"
+
+-- | iterate function identifier
+iterateId :: String
+iterateId = "iterate"
+
+-- | iteraten function identifier
+iteratenId :: String
+iteratenId = "iteraten"
+
+-- | iterate function identifier
+generateId :: String
+generateId = "generate"
+
+-- | iteraten function identifier
+generatenId :: String
+generatenId = "generaten"
+
+-- | copy function identifier
+copyId :: String
+copyId = "copy"
+
+-- | copyn function identifier
+copynId :: String
+copynId = "copyn"
+
+-- | map function identifier
+mapId :: String
+mapId = "map"
+
+-- | zipwith function identifier
+zipWithId :: String
+zipWithId = "zipWith"
+
+-- | foldl function identifier
+foldlId :: String
+foldlId = "foldl"
+
+-- | foldr function identifier
+foldrId :: String
+foldrId = "foldr"
+
+-- | zip function identifier
+zipId :: String
+zipId = "zip"
+
+-- | unzip function identifier
+unzipId :: String
+unzipId = "unzip"
+
+-- | hwxor function identifier
+hwxorId :: String
+hwxorId = "hwxor"
+
+-- | hwor function identifier
+hworId :: String
+hworId = "hwor"
+
+-- | hwnot function identifier
+hwnotId :: String
+hwnotId = "hwnot"
+
+-- | hwand function identifier
+hwandId :: String
+hwandId = "hwand"
+
+lengthTId :: String
+lengthTId = "lengthT"
+
+fstId :: String
+fstId = "fst"
+
+sndId :: String
+sndId = "snd"
+
+splitId :: String
+splitId = "split"
+
+-- Equality Operations
+equalityId :: String
+equalityId = "=="
+
+inEqualityId :: String
+inEqualityId = "/="
+
+gtId :: String
+gtId = ">"
+
+ltId :: String
+ltId = "<"
+
+gteqId :: String
+gteqId = ">="
+
+lteqId :: String
+lteqId = "<="
+
+boolOrId :: String
+boolOrId = "||"
+
+boolAndId :: String
+boolAndId = "&&"
+
+boolNot :: String
+boolNot = "not"
+
+-- Numeric Operations
+
+-- | plus operation identifier
+plusId :: String
+plusId = "+"
+
+-- | times operation identifier
+timesId :: String
+timesId = "*"
+
+-- | negate operation identifier
+negateId :: String
+negateId = "negate"
+
+-- | minus operation identifier
+minusId :: String
+minusId = "-"
+
+-- | convert sizedword to ranged
+fromSizedWordId :: String
+fromSizedWordId = "fromUnsigned"
+
+fromRangedWordId :: String
+fromRangedWordId = "fromIndex"
+
+toIntegerId :: String
+toIntegerId = "to_integer"
+
+fromIntegerId :: String
+fromIntegerId = "fromInteger"
+
+toSignedId :: String
+toSignedId = "to_signed"
+
+toUnsignedId :: String
+toUnsignedId = "to_unsigned"
+
+resizeId :: String
+resizeId = "resize"
+
+resizeWordId :: String
+resizeWordId = "resizeWord"
+
+resizeIntId :: String
+resizeIntId = "resizeInt"
+
+smallIntegerId :: String
+smallIntegerId = "smallInteger"
+
+sizedIntId :: String
+sizedIntId = "Signed"
+
+tfvecId :: String
+tfvecId = "Vector"
+
+blockRAMId :: String
+blockRAMId = "blockRAM"
+
+-- | output file identifier (from std.textio)
+showIdString :: String
+showIdString = "show"
+
+showId :: AST.VHDLId
+showId = AST.unsafeVHDLExtId showIdString
+
+-- | write function identifier (from std.textio)
+writeId :: AST.VHDLId
+writeId = AST.unsafeVHDLBasicId "write"
+
+-- | output file identifier (from std.textio)
+outputId :: AST.VHDLId
+outputId = AST.unsafeVHDLBasicId "output"
+
+------------------
+-- VHDL type marks
+------------------
+
+-- | The Bit type mark
+bitTM :: AST.TypeMark
+bitTM = AST.unsafeVHDLBasicId "Bit"
+
+-- | Stardard logic type mark
+std_logicTM :: AST.TypeMark
+std_logicTM = AST.unsafeVHDLBasicId "std_logic"
+
+-- | boolean type mark
+booleanTM :: AST.TypeMark
+booleanTM = AST.unsafeVHDLBasicId "boolean"
+
+-- | fsvec_index AST. TypeMark
+tfvec_indexTM :: AST.TypeMark
+tfvec_indexTM = AST.unsafeVHDLBasicId "tfvec_index"
+
+-- | natural AST. TypeMark
+naturalTM :: AST.TypeMark
+naturalTM = AST.unsafeVHDLBasicId "natural"
+
+-- | integer TypeMark
+integerTM :: AST.TypeMark
+integerTM = AST.unsafeVHDLBasicId "integer"
+
+-- | signed TypeMark
+signedTM :: AST.TypeMark
+signedTM = AST.unsafeVHDLBasicId "signed"
+
+-- | unsigned TypeMark
+unsignedTM :: AST.TypeMark
+unsignedTM = AST.unsafeVHDLBasicId "unsigned"
+
+-- | string TypeMark
+stringTM :: AST.TypeMark
+stringTM = AST.unsafeVHDLBasicId "string"
+
+-- | tup VHDLName suffix
+tupVHDLSuffix :: AST.VHDLId -> AST.Suffix
+tupVHDLSuffix id = AST.SSimple id
diff --git a/clash/CLasH/VHDL/Generate.hs b/clash/CLasH/VHDL/Generate.hs
new file mode 100644 (file)
index 0000000..3d31529
--- /dev/null
@@ -0,0 +1,1634 @@
+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 qualified Data.Accessor.Monad.Trans.State as MonadState
+
+-- VHDL Imports
+import qualified Language.VHDL.AST as AST
+
+-- GHC API
+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 CLasH.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
+  -> TranslatorSession Entity -- ^ The resulting entity
+
+getEntity fname = makeCached fname tsEntities $ do
+      expr <- Normalize.getNormalized False fname
+      -- Split the normalized expression
+      let (args, binds, res) = Normalize.splitNormalized expr
+      -- Generate ports for all non-empty types
+      args' <- catMaybesM $ mapM mkMap args
+      -- TODO: Handle Nothing
+      res' <- mkMap res
+      count <- MonadState.get tsEntityCounter 
+      let vhdl_id = mkVHDLBasicId $ varToString fname ++ "Component_" ++ show count
+      MonadState.set tsEntityCounter (count + 1)
+      let ent_decl = createEntityAST vhdl_id args' res'
+      let signature = Entity vhdl_id args' res' ent_decl
+      return signature
+  where
+    mkMap ::
+      --[(SignalId, SignalInfo)] 
+      CoreSyn.CoreBndr 
+      -> TranslatorSession (Maybe Port)
+    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_maybe <- MonadState.lift tsType $ vhdlTy error_msg ty
+        case type_mark_maybe of 
+          Just type_mark -> return $ Just (id, type_mark)
+          Nothing -> return Nothing
+     )
+
+-- | Create the VHDL AST for an entity
+createEntityAST ::
+  AST.VHDLId                   -- ^ The name of the function
+  -> [Port]                    -- ^ The entity's arguments
+  -> Maybe 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
+              ++ (Maybe.maybeToList res_port)
+              ++ [clk_port,resetn_port]
+    -- Add a clk port if we have state
+    clk_port = AST.IfaceSigDec clockId AST.In std_logicTM
+    resetn_port = AST.IfaceSigDec resetId AST.In std_logicTM
+    res_port = fmap (mkIfaceSigDec AST.Out) res
+
+-- | Create a port declaration
+mkIfaceSigDec ::
+  AST.Mode                         -- ^ The mode for the port (In / Out)
+  -> Port                          -- ^ 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
+  -> TranslatorSession (Architecture, [CoreSyn.CoreBndr])
+  -- ^ The architecture for this function
+
+getArchitecture fname = makeCached fname tsArchitectures $ do
+  expr <- Normalize.getNormalized False fname
+  -- Split the normalized expression
+  let (args, binds, res) = Normalize.splitNormalized expr
+  
+  -- Get the entity for this function
+  signature <- getEntity fname
+  let entity_id = ent_id signature
+
+  -- 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
+  -- Process each bind, resulting in info about state variables and concurrent
+  -- statements.
+  (state_vars, sms) <- Monad.mapAndUnzipM dobind binds
+  let (in_state_maybes, out_state_maybes) = unzip state_vars
+  let (statementss, used_entitiess) = unzip sms
+  -- Get initial state, if it's there
+  initSmap <- MonadState.get tsInitStates
+  let init_state = Map.lookup fname initSmap
+  -- Create a state proc, if needed
+  (state_proc, resbndr) <- case (Maybe.catMaybes in_state_maybes, Maybe.catMaybes out_state_maybes, init_state) of
+        ([in_state], [out_state], Nothing) -> do 
+          nonEmpty <- hasNonEmptyType in_state
+          if nonEmpty 
+            then error ("No initial state defined for: " ++ show fname) 
+            else return ([],[])
+        ([in_state], [out_state], Just resetval) -> do
+          nonEmpty <- hasNonEmptyType in_state
+          if nonEmpty 
+            then mkStateProcSm (in_state, out_state, resetval)
+            else error ("Initial state defined for function with only substate: " ++ show fname)
+        ([], [], Just _) -> error $ "Initial state defined for state-less function: " ++ show fname
+        ([], [], Nothing) -> return ([],[])
+        (ins, outs, res) -> error $ "Weird use of state in " ++ show fname ++ ". In: " ++ show ins ++ " Out: " ++ show outs
+  -- Join the create statements and the (optional) state_proc
+  let statements = concat statementss ++ state_proc
+  -- Create the architecture
+  let arch = AST.ArchBody (mkVHDLBasicId "structural") (AST.NSimple entity_id) (map AST.BDISD sig_decs) statements
+  let used_entities = (concat used_entitiess) ++ resbndr
+  return (arch, used_entities)
+  where
+    dobind :: (CoreSyn.CoreBndr, CoreSyn.CoreExpr) -- ^ The bind to process
+              -> TranslatorSession ((Maybe CoreSyn.CoreBndr, Maybe CoreSyn.CoreBndr), ([AST.ConcSm], [CoreSyn.CoreBndr]))
+              -- ^ ((Input state variable, output state variable), (statements, used entities))
+    -- newtype unpacking is just a cast
+    dobind (bndr, unpacked@(CoreSyn.Cast packed coercion)) 
+      | hasStateType packed && not (hasStateType unpacked)
+      = return ((Just bndr, Nothing), ([], []))
+    -- With simplCore, newtype packing is just a cast
+    dobind (bndr, packed@(CoreSyn.Cast unpacked@(CoreSyn.Var state) coercion)) 
+      | hasStateType packed && not (hasStateType unpacked)
+      = return ((Nothing, Just state), ([], []))
+    -- Without simplCore, newtype packing uses a data constructor
+    dobind (bndr, (CoreSyn.App (CoreSyn.App (CoreSyn.Var con) (CoreSyn.Type _)) (CoreSyn.Var state))) 
+      | isStateCon con
+      = return ((Nothing, Just state), ([], []))
+    -- Anything else is handled by mkConcSm
+    dobind bind = do
+      sms <- mkConcSm bind
+      return ((Nothing, Nothing), sms)
+
+mkStateProcSm :: 
+  (CoreSyn.CoreBndr, CoreSyn.CoreBndr, CoreSyn.CoreBndr) -- ^ The current state, new state and reset variables
+  -> TranslatorSession ([AST.ConcSm], [CoreSyn.CoreBndr]) -- ^ The resulting statements
+mkStateProcSm (old, new, res) = do
+  let error_msg = "\nVHDL.mkSigDec: Can not make signal declaration for type: \n" ++ pprString res 
+  type_mark_old_maybe <- MonadState.lift tsType $ vhdlTy error_msg (Var.varType old)
+  let type_mark_old = Maybe.fromMaybe 
+                        (error $ "\nGenerate.mkStateProcSm: empty type for state? Type: " ++ pprString (Var.varType old))
+                        type_mark_old_maybe
+  type_mark_res_maybe <- MonadState.lift tsType $ vhdlTy error_msg (Var.varType res)
+  let type_mark_res' = Maybe.fromMaybe 
+                        (error $ "\nGenerate.mkStateProcSm: empty type for initial state? Type: " ++ pprString (Var.varType res))
+                        type_mark_res_maybe
+  let type_mark_res = if type_mark_old == type_mark_res' then
+                        type_mark_res'
+                      else 
+                        error $ "Initial state has different type than state type, state type: " ++ show type_mark_old ++ ", init type: "  ++ show type_mark_res'    
+  let resvalid  = mkVHDLExtId $ varToString res ++ "val"
+  let resvaldec = AST.BDISD $ AST.SigDec resvalid type_mark_res Nothing
+  let reswform  = AST.Wform [AST.WformElem (AST.PrimName $ AST.NSimple resvalid) Nothing]
+  let res_assign = AST.SigAssign (varToVHDLName old) reswform
+  let blocklabel       = mkVHDLBasicId "state"
+  let statelabel  = mkVHDLBasicId "stateupdate"
+  let rising_edge = AST.NSimple $ mkVHDLBasicId "rising_edge"
+  let wform       = AST.Wform [AST.WformElem (AST.PrimName $ varToVHDLName new) Nothing]
+  let clk_assign      = AST.SigAssign (varToVHDLName old) wform
+  let rising_edge_clk = AST.PrimFCall $ AST.FCall rising_edge [Nothing AST.:=>: (AST.ADName $ AST.NSimple clockId)]
+  let resetn_is_low  = (AST.PrimName $ AST.NSimple resetId) AST.:=: (AST.PrimLit "'0'")
+  signature <- getEntity res
+  let entity_id = ent_id signature
+  let reslabel = "resetval_" ++ ((prettyShow . varToVHDLName) res)
+  let portmaps = mkAssocElems [] (AST.NSimple resvalid) signature
+  let reset_statement = mkComponentInst reslabel entity_id portmaps
+  let clk_statement = [AST.ElseIf rising_edge_clk [clk_assign]]
+  let statement   = AST.IfSm resetn_is_low [res_assign] clk_statement Nothing
+  let stateupdate = AST.CSPSm $ AST.ProcSm statelabel [clockId,resetId,resvalid] [statement]
+  let block = AST.CSBSm $ AST.BlockSm blocklabel [] (AST.PMapAspect []) [resvaldec] [reset_statement,stateupdate]
+  return ([block],[res])
+
+-- | 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. Throw away state repacking
+mkConcSm (bndr, to@(CoreSyn.Cast from ty))
+  | hasStateType to && hasStateType from
+  = return ([],[])
+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) =
+  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 the 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])) 
+                -- Don't generate VHDL for substate extraction
+                | hasStateType bndr = return ([], [])
+                | otherwise =
+  case alt of
+    (CoreSyn.DataAlt dc, bndrs, (CoreSyn.Var sel_bndr)) -> do
+      nonemptysel <- hasNonEmptyType sel_bndr 
+      if nonemptysel 
+        then do
+          bndrs' <- Monad.filterM hasNonEmptyType bndrs
+          case List.elemIndex sel_bndr bndrs' of
+            Just i -> do
+              htypeScrt <- MonadState.lift tsType $ mkHTypeEither (Var.varType scrut)
+              htypeBndr <- MonadState.lift tsType $ mkHTypeEither (Var.varType bndr)
+              case htypeScrt == htypeBndr of
+                True -> do
+                  let sel_name = varToVHDLName scrut
+                  let sel_expr = AST.PrimName sel_name
+                  return ([mkUncondAssign (Left bndr) sel_expr], [])
+                otherwise ->
+                  case htypeScrt of
+                    Right (AggrType _ _) -> do
+                      labels <- MonadState.lift tsType $ 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], [])
+                    _ -> do -- error $ "DIE!"
+                      let sel_name = varToVHDLName scrut
+                      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: result is not one of the binders\n" ++ (pprString expr)
+          else
+            -- A selector case that selects a state value, ignore it.
+            return ([], [])
+      
+    _ -> error $ "\nVHDL.mkConcSM: Not in normal form: Not a selector case:\n" ++ (pprString expr)
+
+-- Multiple case alt become 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) _ _ (alt:alts))) = do
+  scrut' <- MonadState.lift tsType $ varToVHDLExpr scrut
+  -- Omit first condition, which is the default
+  altcons <- MonadState.lift tsType $ mapM (altconToVHDLExpr . (\(con,_,_) -> con)) alts
+  let cond_exprs = map (\x -> scrut' AST.:=: x) altcons
+  -- Rotate expressions to the left, so that the expression related to the default case is the last
+  exprs <- MonadState.lift tsType $ mapM (varToVHDLExpr . (\(_,_,CoreSyn.Var expr) -> expr)) (alts ++ [alt])
+  return ([mkAltsAssign (Left bndr) cond_exprs exprs], [])
+
+mkConcSm (_, CoreSyn.Case _ _ _ _) = error "\nVHDL.mkConcSm: Not in normal form: Case statement 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
+-----------------------------------------------------------------------------
+
+-- | A function to wrap a builder-like function that expects its arguments to
+-- be expressions.
+genExprArgs wrap dst func args = do
+  args' <- argsToVHDLExprs args
+  wrap dst func args'
+
+-- | Turn the all lefts into VHDL Expressions.
+argsToVHDLExprs :: [Either CoreSyn.CoreExpr AST.Expr] -> TranslatorSession [AST.Expr]
+argsToVHDLExprs = catMaybesM . (mapM argToVHDLExpr)
+
+argToVHDLExpr :: Either CoreSyn.CoreExpr AST.Expr -> TranslatorSession (Maybe AST.Expr)
+argToVHDLExpr (Left expr) = MonadState.lift tsType $ do
+  let errmsg = "Generate.argToVHDLExpr: Using non-representable type? Should not happen!"
+  ty_maybe <- vhdlTy errmsg expr
+  case ty_maybe of
+    Just _ -> do
+      vhdl_expr <- varToVHDLExpr $ exprToVar expr
+      return $ Just vhdl_expr
+    Nothing -> return Nothing
+
+argToVHDLExpr (Right expr) = return $ Just expr
+
+-- 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 ::
+  (dst -> func -> [Var.Var] -> res)
+  -> (dst -> func -> [Either CoreSyn.CoreExpr AST.Expr] -> res)
+genVarArgs wrap = genCoreArgs $ \dst func args -> let
+    args' = map exprToVar args
+  in
+    wrap dst func args'
+
+-- | A function to wrap a builder-like function that expects its arguments to
+-- be core expressions.
+genCoreArgs ::
+  (dst -> func -> [CoreSyn.CoreExpr] -> res)
+  -> (dst -> func -> [Either CoreSyn.CoreExpr AST.Expr] -> res)
+genCoreArgs wrap dst func args = wrap dst func args'
+  where
+    -- Check (rather crudely) that all arguments are CoreExprs
+    args' = case Either.partitionEithers args of 
+      (exprargs, []) -> exprargs
+      (exprsargs, rest) -> error $ "\nGenerate.genCoreArgs: expect core expression arguments but found ast exprs:" ++ (show rest)
+
+-- | A function to wrap a builder-like function that produces an expression
+-- and expects it to be assigned to the destination.
+genExprRes ::
+  ((Either CoreSyn.CoreBndr AST.VHDLName) -> func -> [arg] -> TranslatorSession AST.Expr)
+  -> ((Either CoreSyn.CoreBndr AST.VHDLName) -> func -> [arg] -> TranslatorSession [AST.ConcSm])
+genExprRes wrap dst func args = do
+  expr <- wrap dst func args
+  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 = genNoInsts $ genExprArgs $ genExprRes (genOperator2' op)
+genOperator2' :: (AST.Expr -> AST.Expr -> AST.Expr) -> dst -> CoreSyn.CoreBndr -> [AST.Expr] -> TranslatorSession AST.Expr
+genOperator2' op _ f [arg1, arg2] = return $ op arg1 arg2
+
+-- | Generate a unary operator application
+genOperator1 :: (AST.Expr -> AST.Expr) -> BuiltinBuilder 
+genOperator1 op = genNoInsts $ genExprArgs $ genExprRes (genOperator1' op)
+genOperator1' :: (AST.Expr -> AST.Expr) -> dst -> CoreSyn.CoreBndr -> [AST.Expr] -> TranslatorSession AST.Expr
+genOperator1' op _ f [arg] = return $ op arg
+
+-- | Generate a unary operator application
+genNegation :: BuiltinBuilder 
+genNegation = genNoInsts $ genVarArgs $ genExprRes genNegation'
+genNegation' :: dst -> CoreSyn.CoreBndr -> [Var.Var] -> TranslatorSession AST.Expr
+genNegation' _ f [arg] = do
+  arg1 <- MonadState.lift tsType $ varToVHDLExpr arg
+  let ty = Var.varType arg
+  let (tycon, args) = Type.splitTyConApp ty
+  let name = Name.getOccString (TyCon.tyConName tycon)
+  case name of
+    "Signed" -> return $ AST.Neg arg1
+    otherwise -> error $ "\nGenerate.genNegation': Negation not allowed for type: " ++ show name 
+
+-- | Generate a function call from the destination binder, function name and a
+-- list of expressions (its arguments)
+genFCall :: Bool -> BuiltinBuilder 
+genFCall switch = genNoInsts $ genExprArgs $ genExprRes (genFCall' switch)
+genFCall' :: Bool -> Either CoreSyn.CoreBndr AST.VHDLName -> CoreSyn.CoreBndr -> [AST.Expr] -> TranslatorSession AST.Expr
+genFCall' switch (Left res) f args = do
+  let fname = varToString f
+  let el_ty = if switch then (Var.varType res) else ((tfvec_elem . Var.varType) res)
+  id <- MonadState.lift tsType $ vectorFunId el_ty fname
+  return $ AST.PrimFCall $ AST.FCall (AST.NSimple id)  $
+             map (\exp -> Nothing AST.:=>: AST.ADExpr exp) args
+genFCall' _ (Right name) _ _ = error $ "\nGenerate.genFCall': Cannot generate builtin function call assigned to a VHDLName: " ++ show name
+
+genFromSizedWord :: BuiltinBuilder
+genFromSizedWord = genNoInsts $ genExprArgs genFromSizedWord'
+genFromSizedWord' :: Either CoreSyn.CoreBndr AST.VHDLName -> CoreSyn.CoreBndr -> [AST.Expr] -> TranslatorSession [AST.ConcSm]
+genFromSizedWord' (Left res) f args@[arg] =
+  return [mkUncondAssign (Left res) arg]
+  -- let fname = varToString f
+  -- return $ AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLBasicId toIntegerId))  $
+  --            map (\exp -> Nothing AST.:=>: AST.ADExpr exp) args
+genFromSizedWord' (Right name) _ _ = error $ "\nGenerate.genFromSizedWord': Cannot generate builtin function call assigned to a VHDLName: " ++ show name
+
+genFromRangedWord :: BuiltinBuilder
+genFromRangedWord = genNoInsts $ genExprArgs $ genExprRes genFromRangedWord'
+genFromRangedWord' :: Either CoreSyn.CoreBndr AST.VHDLName -> CoreSyn.CoreBndr -> [AST.Expr] -> TranslatorSession AST.Expr
+genFromRangedWord' (Left res) f [arg] = do {
+  ; let { ty = Var.varType res
+        ; (tycon, args) = Type.splitTyConApp ty
+        ; name = Name.getOccString (TyCon.tyConName tycon)
+        } ;
+  ; len <- MonadState.lift tsType $ tfp_to_int (sized_word_len_ty ty)
+  ; return $ AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLBasicId resizeId))
+             [Nothing AST.:=>: AST.ADExpr arg, Nothing AST.:=>: AST.ADExpr( AST.PrimLit (show len))]
+  }
+genFromRangedWord' (Right name) _ _ = error $ "\nGenerate.genFromRangedWord': Cannot generate builtin function call assigned to a VHDLName: " ++ show name
+
+genResize :: BuiltinBuilder
+genResize = genNoInsts $ genExprArgs $ genExprRes genResize'
+genResize' :: Either CoreSyn.CoreBndr AST.VHDLName -> CoreSyn.CoreBndr -> [AST.Expr] -> TranslatorSession AST.Expr
+genResize' (Left res) f [arg] = do {
+  ; let { ty = Var.varType res
+        ; (tycon, args) = Type.splitTyConApp ty
+        ; name = Name.getOccString (TyCon.tyConName tycon)
+        } ;
+  ; len <- case name of
+      "Signed" -> MonadState.lift tsType $ tfp_to_int (sized_int_len_ty ty)
+      "Unsigned" -> MonadState.lift tsType $ tfp_to_int (sized_word_len_ty ty)
+  ; return $ AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLBasicId resizeId))
+             [Nothing AST.:=>: AST.ADExpr arg, Nothing AST.:=>: AST.ADExpr( AST.PrimLit (show len))]
+  }
+genResize' (Right name) _ _ = error $ "\nGenerate.genFromSizedWord': Cannot generate builtin function call assigned to a VHDLName: " ++ show name
+
+genTimes :: BuiltinBuilder
+genTimes = genNoInsts $ genExprArgs $ genExprRes genTimes'
+genTimes' :: Either CoreSyn.CoreBndr AST.VHDLName -> CoreSyn.CoreBndr -> [AST.Expr] -> TranslatorSession AST.Expr
+genTimes' (Left res) f [arg1,arg2] = do {
+  ; let { ty = Var.varType res
+        ; (tycon, args) = Type.splitTyConApp ty
+        ; name = Name.getOccString (TyCon.tyConName tycon)
+        } ;
+  ; len <- case name of
+      "Signed" -> MonadState.lift tsType $ tfp_to_int (sized_int_len_ty ty)
+      "Unsigned" -> MonadState.lift tsType $ tfp_to_int (sized_word_len_ty ty)
+      "Index" -> do {  ubound <- MonadState.lift tsType $ tfp_to_int (ranged_word_bound_ty ty)
+                         ;  let bitsize = floor (logBase 2 (fromInteger (toInteger ubound)))
+                         ;  return bitsize
+                         }
+  ; return $ AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLBasicId resizeId))
+             [Nothing AST.:=>: AST.ADExpr (arg1 AST.:*: arg2), Nothing AST.:=>: AST.ADExpr( AST.PrimLit (show len))]
+  }
+genTimes' (Right name) _ _ = error $ "\nGenerate.genTimes': Cannot generate builtin function call assigned to a VHDLName: " ++ show name
+
+-- fromInteger turns an Integer into a Num instance. Since Integer is
+-- not representable and is only allowed for literals, the actual
+-- Integer should be inlined entirely into the fromInteger argument.
+genFromInteger :: BuiltinBuilder
+genFromInteger = genNoInsts $ genCoreArgs $ genExprRes genFromInteger'
+genFromInteger' :: Either CoreSyn.CoreBndr AST.VHDLName -> CoreSyn.CoreBndr -> [CoreSyn.CoreExpr] -> TranslatorSession AST.Expr
+genFromInteger' (Left res) f args = do
+  let ty = Var.varType res
+  let (tycon, tyargs) = Type.splitTyConApp ty
+  let name = Name.getOccString (TyCon.tyConName tycon)
+  len <- case name of
+    "Signed" -> MonadState.lift tsType $ tfp_to_int (sized_int_len_ty ty)
+    "Unsigned" -> MonadState.lift tsType $ tfp_to_int (sized_word_len_ty ty)
+    "Index" -> do
+      bound <- MonadState.lift tsType $ tfp_to_int (ranged_word_bound_ty ty)
+      return $ floor (logBase 2 (fromInteger (toInteger (bound)))) + 1
+  let fname = case name of "Signed" -> toSignedId ; "Unsigned" -> toUnsignedId ; "Index" -> toUnsignedId
+  case args of
+    [integer] -> do -- The type and dictionary arguments are removed by genApplication
+      literal <- getIntegerLiteral integer
+      return $ AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLBasicId fname))
+              [Nothing AST.:=>: AST.ADExpr (AST.PrimLit (show literal)), Nothing AST.:=>: AST.ADExpr( AST.PrimLit (show len))]
+    _ -> error $ "\nGenerate.genFromInteger': Wrong number of arguments to genInteger. Applying " ++ pprString f ++ " to " ++ pprString args
+
+genFromInteger' (Right name) _ _ = error $ "\nGenerate.genFromInteger': Cannot generate builtin function call assigned to a VHDLName: " ++ show name
+
+genSizedInt :: BuiltinBuilder
+genSizedInt = genFromInteger
+
+{-
+-- This function is useful for use with vectorTH, since that generates
+-- explicit references to the TFVec constructor (which is normally
+-- hidden). Below implementation is probably not current anymore, but
+-- kept here in case we start using vectorTH again.
+-- | Generate a Builder for the builtin datacon TFVec
+genTFVec :: BuiltinBuilder
+genTFVec (Left res) f [Left (CoreSyn.Let (CoreSyn.Rec letBinders) letRes)] = do {
+  -- Generate Assignments for all the binders
+  ; letAssigns <- mapM genBinderAssign letBinders
+  -- Generate assignments for the result (which might be another let binding)
+  ; (resBinders,resAssignments) <- genResAssign letRes
+  -- Get all the Assigned binders
+  ; let assignedBinders = Maybe.catMaybes (map fst letAssigns)
+  -- Make signal names for all the assigned binders
+  ; sigs <- mapM (\x -> MonadState.lift tsType $ varToVHDLExpr x) (assignedBinders ++ resBinders)
+  -- Assign all the signals to the resulting vector
+  ; let { vecsigns = mkAggregateSignal sigs
+        ; vecassign = mkUncondAssign (Left res) vecsigns
+        } ;
+  -- Generate all the signal declaration for the assigned binders
+  ; sig_dec_maybes <- mapM mkSigDec (assignedBinders ++ resBinders)
+  ; let { sig_decs = map (AST.BDISD) (Maybe.catMaybes $ sig_dec_maybes)
+  -- Setup the VHDL Block
+        ; block_label = mkVHDLExtId ("TFVec_" ++ show (varToString res))
+        ; block = AST.BlockSm block_label [] (AST.PMapAspect []) sig_decs ((concat (map snd letAssigns)) ++ resAssignments ++ [vecassign])
+        } ;
+  -- Return the block statement coressponding to the TFVec literal
+  ; return $ [AST.CSBSm block]
+  }
+  where
+    genBinderAssign :: (CoreSyn.CoreBndr, CoreSyn.CoreExpr) -> TranslatorSession (Maybe CoreSyn.CoreBndr, [AST.ConcSm])
+    -- For now we only translate applications
+    genBinderAssign (bndr, app@(CoreSyn.App _ _)) = do
+      let (CoreSyn.Var f, args) = CoreSyn.collectArgs app
+      let valargs = get_val_args (Var.varType f) args
+      apps <- genApplication (Left bndr) f (map Left valargs)
+      return (Just bndr, apps)
+    genBinderAssign _ = return (Nothing,[])
+    genResAssign :: CoreSyn.CoreExpr -> TranslatorSession ([CoreSyn.CoreBndr], [AST.ConcSm])
+    genResAssign app@(CoreSyn.App _ letexpr) = do
+      case letexpr of
+        (CoreSyn.Let (CoreSyn.Rec letbndrs) letres) -> do
+          letapps <- mapM genBinderAssign letbndrs
+          let bndrs = Maybe.catMaybes (map fst letapps)
+          let app = (map snd letapps)
+          (vars, apps) <- genResAssign letres
+          return ((bndrs ++ vars),((concat app) ++ apps))
+        otherwise -> return ([],[])
+    genResAssign _ = return ([],[])
+
+genTFVec (Left res) f [Left app@(CoreSyn.App _ _)] = do {
+  ; let { elems = reduceCoreListToHsList app
+  -- Make signal names for all the binders
+        ; binders = map (\expr -> case expr of 
+                          (CoreSyn.Var b) -> b
+                          otherwise -> error $ "\nGenerate.genTFVec: Cannot generate TFVec: " 
+                            ++ show res ++ ", with elems:\n" ++ show elems ++ "\n" ++ pprString elems) elems
+        } ;
+  ; sigs <- mapM (\x -> MonadState.lift tsType $ varToVHDLExpr x) binders
+  -- Assign all the signals to the resulting vector
+  ; let { vecsigns = mkAggregateSignal sigs
+        ; vecassign = mkUncondAssign (Left res) vecsigns
+  -- Setup the VHDL Block
+        ; block_label = mkVHDLExtId ("TFVec_" ++ show (varToString res))
+        ; block = AST.BlockSm block_label [] (AST.PMapAspect []) [] [vecassign]
+        } ;
+  -- Return the block statement coressponding to the TFVec literal
+  ; return $ [AST.CSBSm block]
+  }
+  
+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 {
+  -- mapped_f must be a CoreExpr (since we can't represent functions as VHDL
+  -- expressions). arg must be a CoreExpr (and should be a CoreSyn.Var), since
+  -- we must index it (which we couldn't if it was a VHDL Expr, since only
+  -- VHDLNames can be indexed).
+  -- Setup the generate scheme
+  ; len <- MonadState.lift tsType $ tfp_to_int $ (tfvec_len_ty . Var.varType) res
+          -- TODO: Use something better than varToString
+  ; let { label       = mkVHDLExtId ("mapVector" ++ (varToString res))
+        ; n_id        = mkVHDLBasicId "n"
+        ; n_expr      = idToVHDLExpr n_id
+        ; range       = AST.ToRange (AST.PrimLit "0") (AST.PrimLit $ show (len-1))
+        ; 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
+        ; (CoreSyn.Var real_f, already_mapped_args) = CoreSyn.collectArgs mapped_f
+        ; valargs = get_val_args (Var.varType real_f) already_mapped_args
+        } ;
+  ; (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], used)
+  }
+
+genMap' (Right name) _ _ = error $ "\nGenerate.genMap': Cannot generate map function call assigned to a VHDLName: " ++ show name
+    
+genZipWith :: BuiltinBuilder
+genZipWith (Left res) f args@[Left zipped_f, Left (CoreSyn.Var arg1), Left (CoreSyn.Var arg2)] = do {
+  -- Setup the generate scheme
+  ; len <- MonadState.lift tsType $ tfp_to_int $ (tfvec_len_ty . Var.varType) res
+          -- TODO: Use something better than varToString
+  ; let { label       = mkVHDLExtId ("zipWithVector" ++ (varToString res))
+        ; n_id        = mkVHDLBasicId "n"
+        ; n_expr      = idToVHDLExpr n_id
+        ; range       = AST.ToRange (AST.PrimLit "0") (AST.PrimLit $ show (len-1))
+        ; 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
+        ; (CoreSyn.Var real_f, already_mapped_args) = CoreSyn.collectArgs zipped_f
+        ; valargs     = get_val_args (Var.varType real_f) already_mapped_args
+        ; argexpr1    = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName arg1) n_expr
+        ; argexpr2    = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName arg2) n_expr
+        } ;
+  ; (app_concsms, used) <- genApplication (Right resname) real_f (map Left valargs ++ [Right argexpr1, Right argexpr2])
+    -- Return the generate functions
+  ; return ([AST.CSGSm $ AST.GenerateSm label genScheme [] app_concsms], used)
+  }
+
+genFoldl :: BuiltinBuilder
+genFoldl = genFold True
+
+genFoldr :: BuiltinBuilder
+genFoldr = genFold False
+
+genFold :: Bool -> BuiltinBuilder
+genFold left = genVarArgs (genFold' left)
+
+genFold' :: Bool -> (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> TranslatorSession ([AST.ConcSm], [CoreSyn.CoreBndr])
+genFold' left res f args@[folded_f , start ,vec]= do
+  len <- MonadState.lift tsType $ 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] -> TranslatorSession ([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 tsType $ varToVHDLExpr start
+  return ([mkUncondAssign (Left res) arg], [])
+    
+genFold'' len left (Left res) f [folded_f, start, vec] = do
+  -- The vector length
+  --len <- MonadState.lift tsType $ tfp_to_int $ (tfvec_len_ty . Var.varType) vec
+  -- An expression for len-1
+  let len_min_expr = (AST.PrimLit $ show (len-1))
+  -- evec is (TFVec n), so it still needs an element type
+  let (nvec, _) = Type.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)
+  let error_msg = "\nGenerate.genFold': Can not construct temp vector for element type: " ++ pprString tmp_ty 
+  -- TODO: Handle Nothing
+  Just tmp_vhdl_ty <- MonadState.lift tsType $ vhdlTy error_msg tmp_ty
+  -- Setup the generate scheme
+  let gen_label = mkVHDLExtId ("foldlVector" ++ (varToString vec))
+  let block_label = mkVHDLExtId ("foldlVector" ++ (varToString res))
+  let gen_range = if left then AST.ToRange (AST.PrimLit "0") len_min_expr
+                  else AST.DownRange len_min_expr (AST.PrimLit "0")
+  let gen_scheme   = AST.ForGn n_id gen_range
+  -- 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]
+  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], concat useds)
+  where
+    -- An id for the counter
+    n_id = mkVHDLBasicId "n"
+    n_cur = idToVHDLExpr n_id
+    -- An expression for previous n
+    n_prev = if left then (n_cur AST.:-: (AST.PrimLit "1"))
+                     else (n_cur AST.:+: (AST.PrimLit "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 :: TranslatorSession (AST.GenerateSm, [CoreSyn.CoreBndr])
+    genFirstCell = do
+      len <- MonadState.lift tsType $ tfp_to_int $ (tfvec_len_ty . Var.varType) vec
+      let cond_label = mkVHDLExtId "firstcell"
+      -- if n == 0 or n == len-1
+      let cond_scheme = AST.IfGn $ n_cur AST.:=: (if left then (AST.PrimLit "0")
+                                                  else (AST.PrimLit $ show (len-1)))
+      -- Output to tmp[current n]
+      let resname = mkIndexedName tmp_name n_cur
+      -- Input from start
+      argexpr1 <- MonadState.lift tsType $ varToVHDLExpr start
+      -- Input from vec[current n]
+      let argexpr2 = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName vec) n_cur
+      (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, used)
+
+    genOtherCell = do
+      len <- MonadState.lift tsType $ tfp_to_int $ (tfvec_len_ty . Var.varType) vec
+      let cond_label = mkVHDLExtId "othercell"
+      -- if n > 0 or n < len-1
+      let cond_scheme = AST.IfGn $ n_cur AST.:/=: (if left then (AST.PrimLit "0")
+                                                   else (AST.PrimLit $ show (len-1)))
+      -- Output to tmp[current n]
+      let resname = mkIndexedName tmp_name n_cur
+      -- Input from tmp[previous n]
+      let argexpr1 = vhdlNameToVHDLExpr $ mkIndexedName tmp_name n_prev
+      -- Input from vec[current n]
+      let argexpr2 = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName vec) n_cur
+      (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, used)
+
+-- | Generate a generate statement for the builtin function "zip"
+genZip :: BuiltinBuilder
+genZip = genNoInsts $ genVarArgs genZip'
+genZip' :: (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> TranslatorSession [AST.ConcSm]
+genZip' (Left res) f args@[arg1, arg2] = do {
+    -- Setup the generate scheme
+  ; len <- MonadState.lift tsType $ tfp_to_int $ (tfvec_len_ty . Var.varType) res
+          -- TODO: Use something better than varToString
+  ; let { label           = mkVHDLExtId ("zipVector" ++ (varToString res))
+        ; n_id            = mkVHDLBasicId "n"
+        ; n_expr          = idToVHDLExpr n_id
+        ; range           = AST.ToRange (AST.PrimLit "0") (AST.PrimLit $ show (len-1))
+        ; genScheme       = AST.ForGn n_id range
+        ; resname'        = mkIndexedName (varToVHDLName res) n_expr
+        ; argexpr1        = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName arg1) n_expr
+        ; argexpr2        = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName arg2) n_expr
+        } ; 
+  ; labels <- MonadState.lift tsType $ getFieldLabels (tfvec_elem (Var.varType res))
+  ; let { resnameA    = mkSelectedName resname' (labels!!0)
+        ; resnameB    = mkSelectedName resname' (labels!!1)
+        ; resA_assign = mkUncondAssign (Right resnameA) argexpr1
+        ; resB_assign = mkUncondAssign (Right resnameB) argexpr2
+        } ;
+    -- Return the generate functions
+  ; return [AST.CSGSm $ AST.GenerateSm label genScheme [] [resA_assign,resB_assign]]
+  }
+  
+-- | Generate a generate statement for the builtin function "fst"
+genFst :: BuiltinBuilder
+genFst = genNoInsts $ genVarArgs genFst'
+genFst' :: (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> TranslatorSession [AST.ConcSm]
+genFst' (Left res) f args@[arg] = do {
+  ; labels <- MonadState.lift tsType $ getFieldLabels (Var.varType arg)
+  ; let { argexpr'    = varToVHDLName arg
+        ; argexprA    = vhdlNameToVHDLExpr $ mkSelectedName argexpr' (labels!!0)
+        ; assign      = mkUncondAssign (Left res) argexprA
+        } ;
+    -- Return the generate functions
+  ; return [assign]
+  }
+  
+-- | Generate a generate statement for the builtin function "snd"
+genSnd :: BuiltinBuilder
+genSnd = genNoInsts $ genVarArgs genSnd'
+genSnd' :: (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> TranslatorSession [AST.ConcSm]
+genSnd' (Left res) f args@[arg] = do {
+  ; labels <- MonadState.lift tsType $ getFieldLabels (Var.varType arg)
+  ; let { argexpr'    = varToVHDLName arg
+        ; argexprB    = vhdlNameToVHDLExpr $ mkSelectedName argexpr' (labels!!1)
+        ; assign      = mkUncondAssign (Left res) argexprB
+        } ;
+    -- Return the generate functions
+  ; return [assign]
+  }
+    
+-- | Generate a generate statement for the builtin function "unzip"
+genUnzip :: BuiltinBuilder
+genUnzip = genNoInsts $ genVarArgs genUnzip'
+genUnzip' :: (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> TranslatorSession [AST.ConcSm]
+genUnzip' (Left res) f args@[arg] = do
+  let error_msg = "\nGenerate.genUnzip: Cannot generate unzip call: " ++ pprString res ++ " = " ++ pprString f ++ " " ++ pprString arg
+  htype <- MonadState.lift tsType $ mkHType error_msg (Var.varType arg)
+  -- Prepare a unconditional assignment, for the case when either part
+  -- of the unzip is a state variable, which will disappear in the
+  -- resulting VHDL, making the the unzip no longer required.
+  case htype of
+    -- A normal vector containing two-tuples
+    VecType _ (AggrType _ [_, _]) -> do {
+        -- Setup the generate scheme
+      ; len <- MonadState.lift tsType $ tfp_to_int $ (tfvec_len_ty . Var.varType) arg
+        -- TODO: Use something better than varToString
+      ; let { label           = mkVHDLExtId ("unzipVector" ++ (varToString res))
+            ; n_id            = mkVHDLBasicId "n"
+            ; n_expr          = idToVHDLExpr n_id
+            ; range           = AST.ToRange (AST.PrimLit "0") (AST.PrimLit $ show (len-1))
+            ; genScheme       = AST.ForGn n_id range
+            ; resname'        = varToVHDLName res
+            ; argexpr'        = mkIndexedName (varToVHDLName arg) n_expr
+            } ;
+      ; reslabels <- MonadState.lift tsType $ getFieldLabels (Var.varType res)
+      ; arglabels <- MonadState.lift tsType $ getFieldLabels (tfvec_elem (Var.varType arg))
+      ; let { resnameA    = mkIndexedName (mkSelectedName resname' (reslabels!!0)) n_expr
+            ; resnameB    = mkIndexedName (mkSelectedName resname' (reslabels!!1)) n_expr
+            ; argexprA    = vhdlNameToVHDLExpr $ mkSelectedName argexpr' (arglabels!!0)
+            ; argexprB    = vhdlNameToVHDLExpr $ mkSelectedName argexpr' (arglabels!!1)
+            ; resA_assign = mkUncondAssign (Right resnameA) argexprA
+            ; resB_assign = mkUncondAssign (Right resnameB) argexprB
+            } ;
+        -- Return the generate functions
+      ; return [AST.CSGSm $ AST.GenerateSm label genScheme [] [resA_assign,resB_assign]]
+      }
+    -- Both elements of the tuple were state, so they've disappeared. No
+    -- need to do anything
+    VecType _ (AggrType _ []) -> return []
+    -- A vector containing aggregates with more than two elements?
+    VecType _ (AggrType _ _) -> error $ "Unzipping a value that is not a vector of two-tuples? Value: " ++ pprString arg ++ "\nType: " ++ pprString (Var.varType arg)
+    -- One of the elements of the tuple was state, so there won't be a
+    -- tuple (record) in the VHDL output. We can just do a plain
+    -- assignment, then.
+    VecType _ _ -> do
+      argexpr <- MonadState.lift tsType $ varToVHDLExpr arg
+      return [mkUncondAssign (Left res) argexpr]
+    _ -> error $ "Unzipping a value that is not a vector? Value: " ++ pprString arg ++ "\nType: " ++ pprString (Var.varType arg) ++ "\nhtype: " ++ show htype
+
+genCopy :: BuiltinBuilder 
+genCopy = genNoInsts genCopy'
+genCopy' :: (Either CoreSyn.CoreBndr AST.VHDLName ) -> CoreSyn.CoreBndr -> [Either CoreSyn.CoreExpr AST.Expr] -> TranslatorSession [AST.ConcSm]
+genCopy' (Left res) f [arg] = do {
+  ; [arg'] <- argsToVHDLExprs [arg]
+  ; let { resExpr = AST.Aggregate [AST.ElemAssoc (Just AST.Others) arg']
+        ; out_assign = mkUncondAssign (Left res) resExpr
+        }
+  ; return [out_assign]
+  }
+    
+genConcat :: BuiltinBuilder
+genConcat = genNoInsts $ genVarArgs genConcat'
+genConcat' :: (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> TranslatorSession [AST.ConcSm]
+genConcat' (Left res) f args@[arg] = do {
+    -- Setup the generate scheme
+  ; len1 <- MonadState.lift tsType $ tfp_to_int $ (tfvec_len_ty . Var.varType) arg
+  ; let (_, nvec) = Type.splitAppTy (Var.varType arg)
+  ; len2 <- MonadState.lift tsType $ tfp_to_int $ tfvec_len_ty nvec
+          -- TODO: Use something better than varToString
+  ; let { label       = mkVHDLExtId ("concatVector" ++ (varToString res))
+        ; n_id        = mkVHDLBasicId "n"
+        ; n_expr      = idToVHDLExpr n_id
+        ; fromRange   = n_expr AST.:*: (AST.PrimLit $ show len2)
+        ; 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
+        ; toRange     = (n_expr AST.:*: (AST.PrimLit $ show len2)) AST.:+: (AST.PrimLit $ show (len2-1))
+        ; range       = AST.ToRange (AST.PrimLit "0") (AST.PrimLit $ show (len1-1))
+        ; resname     = vecSlice fromRange toRange
+        ; argexpr     = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName arg) n_expr
+        ; out_assign  = mkUncondAssign (Right resname) argexpr
+        } ;
+    -- Return the generate statement
+  ; return [AST.CSGSm $ AST.GenerateSm label genScheme [] [out_assign]]
+  }
+  where
+    vecSlice init last =  AST.NSlice (AST.SliceName (varToVHDLName res) 
+                            (AST.ToRange init last))
+
+genIteraten :: BuiltinBuilder
+genIteraten dst f args = genIterate dst f (tail args)
+
+genIterate :: BuiltinBuilder
+genIterate = genIterateOrGenerate True
+
+genGeneraten :: BuiltinBuilder
+genGeneraten dst f args = genGenerate dst f (tail args)
+
+genGenerate :: BuiltinBuilder
+genGenerate = genIterateOrGenerate False
+
+genIterateOrGenerate :: Bool -> BuiltinBuilder
+genIterateOrGenerate iter = genVarArgs (genIterateOrGenerate' iter)
+
+genIterateOrGenerate' :: Bool -> (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> TranslatorSession ([AST.ConcSm], [CoreSyn.CoreBndr])
+genIterateOrGenerate' iter (Left res) f args = do
+  len <- MonadState.lift tsType $ 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] -> TranslatorSession ([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) f [app_f, start] = do
+  -- The vector length
+  -- len <- MonadState.lift tsType $ tfp_to_int ((tfvec_len_ty . Var.varType) res)
+  -- An expression for len-1
+  let len_min_expr = (AST.PrimLit $ show (len-1))
+  -- -- 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 = Var.varType res
+  let error_msg = "\nGenerate.genFold': Can not construct temp vector for element type: " ++ pprString tmp_ty 
+  -- TODO: Handle Nothing
+  Just tmp_vhdl_ty <- MonadState.lift tsType $ vhdlTy error_msg tmp_ty
+  -- Setup the generate scheme
+  let gen_label = mkVHDLExtId ("iterateVector" ++ (varToString start))
+  let block_label = mkVHDLExtId ("iterateVector" ++ (varToString res))
+  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  tmp_dec     = AST.BDISD $ AST.SigDec tmp_id tmp_vhdl_ty Nothing
+  -- Create the generate statement
+  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], concat useds)
+  where
+    -- An id for the counter
+    n_id = mkVHDLBasicId "n"
+    n_cur = idToVHDLExpr n_id
+    -- An expression for previous n
+    n_prev = n_cur AST.:-: (AST.PrimLit "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 :: TranslatorSession (AST.GenerateSm, [CoreSyn.CoreBndr])
+    genFirstCell = do
+      let cond_label = mkVHDLExtId "firstcell"
+      -- if n == 0 or n == len-1
+      let cond_scheme = AST.IfGn $ n_cur AST.:=: (AST.PrimLit "0")
+      -- Output to tmp[current n]
+      let resname = mkIndexedName tmp_name n_cur
+      -- Input from start
+      argexpr <- MonadState.lift tsType $ varToVHDLExpr start
+      let startassign = mkUncondAssign (Right resname) argexpr
+      (app_concsms, used) <- genApplication (Right resname) app_f  [Right argexpr]
+      -- Return the conditional generate part
+      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"
+      -- if n > 0 or n < len-1
+      let cond_scheme = AST.IfGn $ n_cur AST.:/=: (AST.PrimLit "0")
+      -- Output to tmp[current n]
+      let resname = mkIndexedName tmp_name n_cur
+      -- Input from tmp[previous n]
+      let argexpr = vhdlNameToVHDLExpr $ mkIndexedName tmp_name n_prev
+      (app_concsms, used) <- genApplication (Right resname) app_f [Right argexpr]
+      -- Return the conditional generate part
+      return (AST.GenerateSm cond_label cond_scheme [] app_concsms, used)
+
+genBlockRAM :: BuiltinBuilder
+genBlockRAM = genNoInsts $ genExprArgs genBlockRAM'
+
+genBlockRAM' :: (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [AST.Expr] -> TranslatorSession [AST.ConcSm]
+genBlockRAM' (Left res) f args@[data_in,rdaddr,wraddr,wrenable] = do
+  -- Get the ram type
+  let (tup,data_out) = Type.splitAppTy (Var.varType res)
+  let (tup',ramvec) = Type.splitAppTy tup
+  let Just realram = Type.coreView ramvec
+  let Just (tycon, types) = Type.splitTyConApp_maybe realram
+  Just ram_vhdl_ty <- MonadState.lift tsType $ vhdlTy "wtf" (head types)
+  -- Make the intermediate vector
+  let ram_dec = AST.BDISD $ AST.SigDec ram_id ram_vhdl_ty Nothing
+  -- Get the data_out name
+  -- reslabels <- MonadState.lift tsType $ getFieldLabels (Var.varType res)
+  let resname = varToVHDLName res
+  -- let resname = mkSelectedName resname' (reslabels!!0)
+  let rdaddr_int = genExprFCall (mkVHDLBasicId toIntegerId) rdaddr
+  let argexpr = vhdlNameToVHDLExpr $ mkIndexedName (AST.NSimple ram_id) rdaddr_int
+  let assign = mkUncondAssign (Right resname) argexpr
+  let block_label = mkVHDLExtId ("blockRAM" ++ (varToString res))
+  let block = AST.BlockSm block_label [] (AST.PMapAspect []) [ram_dec] [assign, mkUpdateProcSm]
+  return [AST.CSBSm block]
+  where
+    ram_id = mkVHDLBasicId "ram"
+    mkUpdateProcSm :: AST.ConcSm
+    mkUpdateProcSm = AST.CSPSm $ AST.ProcSm proclabel [clockId] [statement]
+      where
+        proclabel   = mkVHDLBasicId "updateRAM"
+        rising_edge = mkVHDLBasicId "rising_edge"
+        wraddr_int  = genExprFCall (mkVHDLBasicId toIntegerId) wraddr
+        ramloc      = mkIndexedName (AST.NSimple ram_id) wraddr_int
+        wform       = AST.Wform [AST.WformElem data_in Nothing]
+        ramassign      = AST.SigAssign ramloc wform
+        rising_edge_clk = genExprFCall rising_edge (AST.PrimName $ AST.NSimple clockId)
+        statement   = AST.IfSm (AST.And rising_edge_clk wrenable) [ramassign] [] Nothing
+        
+genSplit :: BuiltinBuilder
+genSplit = genNoInsts $ genVarArgs genSplit'
+
+genSplit' :: (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> TranslatorSession [AST.ConcSm]
+genSplit' (Left res) f args@[vecIn] = do {
+  ; labels <- MonadState.lift tsType $ getFieldLabels (Var.varType res)
+  ; len <- MonadState.lift tsType $ tfp_to_int $ (tfvec_len_ty . Var.varType) vecIn
+  ; let { block_label = mkVHDLExtId ("split" ++ (varToString vecIn))
+        ; halflen   = round ((fromIntegral len) / 2)
+        ; rangeL    = vecSlice (AST.PrimLit "0") (AST.PrimLit $ show (halflen - 1))
+        ; rangeR    = vecSlice (AST.PrimLit $ show halflen) (AST.PrimLit $ show (len - 1))
+        ; resname   = varToVHDLName res
+        ; resnameL  = mkSelectedName resname (labels!!0)
+        ; resnameR  = mkSelectedName resname (labels!!1)
+        ; argexprL  = vhdlNameToVHDLExpr rangeL
+        ; argexprR  = vhdlNameToVHDLExpr rangeR
+        ; out_assignL = mkUncondAssign (Right resnameL) argexprL
+        ; out_assignR = mkUncondAssign (Right resnameR) argexprR
+        ; block = AST.BlockSm block_label [] (AST.PMapAspect []) [] [out_assignL, out_assignR]
+        }
+  ; return [AST.CSBSm block]
+  }
+  where
+    vecSlice init last =  AST.NSlice (AST.SliceName (varToVHDLName res) 
+                            (AST.ToRange init last))
+-----------------------------------------------------------------------------
+-- 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
+  -> TranslatorSession ([AST.ConcSm], [CoreSyn.CoreBndr]) 
+  -- ^ The corresponding VHDL concurrent statements and entities
+  --   instantiated.
+genApplication dst f args = do
+  nonemptydst <- case dst of
+    Left bndr -> hasNonEmptyType bndr 
+    Right _ -> return True
+  if nonemptydst
+    then
+      if Var.isGlobalId f then
+        case Var.idDetails 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
+              htype <- MonadState.lift tsType $ mkHTypeEither (Var.varType bndr)
+              let argsNostate = filter (\x -> not (either hasStateType (\x -> False) x)) args
+              case argsNostate of
+                [arg] -> do
+                  [arg'] <- argsToVHDLExprs [arg]
+                  return ([mkUncondAssign dst arg'], [])
+                otherwise ->
+                  case htype of
+                    Right (AggrType _ _) -> do
+                      labels <- MonadState.lift tsType $ getFieldLabels (Var.varType bndr)
+                      args' <- argsToVHDLExprs argsNostate
+                      return (zipWith mkassign labels 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
+                    _ -> do -- error $ "DIE!"
+                      args' <- argsToVHDLExprs argsNostate
+                      return ([mkUncondAssign dst (head args')], [])            
+            Right _ -> error "\nGenerate.genApplication(DataConWorkId): Can't generate dataconstructor application without an original binder"
+          IdInfo.DataConWrapId dc -> case dst of
+            -- It's a datacon. Create a record from its arguments.
+            Left bndr ->
+              case (Map.lookup (varToString f) globalNameTable) of
+               Just (arg_count, builder) ->
+                if length args == arg_count then
+                  builder dst f args
+                else
+                  error $ "\nGenerate.genApplication(DataConWrapId): Incorrect number of arguments to builtin function: " ++ pprString f ++ " Args: " ++ show args
+               Nothing -> error $ "\nGenerate.genApplication(DataConWrapId): Can't generate dataconwrapper: " ++ (show dc)
+            Right _ -> error "\nGenerate.genApplication(DataConWrapId): Can't generate dataconwrapper application without an original binder"
+          IdInfo.VanillaId ->
+            -- 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 $ "\nGenerate.genApplication(VanillaId): Incorrect number of arguments to builtin function: " ++ pprString f ++ " Args: " ++ show args
+              Nothing -> do
+                top <- isTopLevelBinder f
+                if top then
+                  do
+                    -- Local binder that references a top level binding.  Generate a
+                    -- component instantiation.
+                    signature <- getEntity f
+                    args' <- argsToVHDLExprs 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], [f])
+                  else
+                    -- 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.
+                    -- FIXME : I DONT KNOW IF THE ABOVE COMMENT HOLDS HERE, SO FOR NOW JUST ERROR!
+                    -- f' <- MonadState.lift tsType $ varToVHDLExpr f
+                    --                   return $ ([mkUncondAssign dst f'], [])
+                  do errtype <- case dst of 
+                        Left bndr -> do 
+                          htype <- MonadState.lift tsType $ mkHTypeEither (Var.varType bndr)
+                          return (show htype)
+                        Right vhd -> return $ show vhd
+                     error ("\nGenerate.genApplication(VanillaId): Using function from another module that is not a known builtin: " ++ (pprString f) ++ "::" ++ errtype) 
+          IdInfo.ClassOpId cls ->
+            -- FIXME: Not looking for what instance this class op is called for
+            -- Is quite stupid of course.
+            case (Map.lookup (varToString f) globalNameTable) of
+              Just (arg_count, builder) ->
+                if length args == arg_count then
+                  builder dst f args
+                else
+                  error $ "\nGenerate.genApplication(ClassOpId): Incorrect number of arguments to builtin function: " ++ pprString f ++ " Args: " ++ show args
+              Nothing -> error $ "\nGenerate.genApplication(ClassOpId): Using function from another module that is not a known builtin: " ++ pprString f
+          details -> error $ "\nGenerate.genApplication: Calling unsupported function " ++ pprString f ++ " with GlobalIdDetails " ++ pprString details
+        else do
+          top <- isTopLevelBinder f
+          if top then
+            do
+               -- Local binder that references a top level binding.  Generate a
+               -- component instantiation.
+               signature <- getEntity f
+               args' <- argsToVHDLExprs 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 (prettyShow . varToVHDLName) prettyShow) dst
+               let portmaps = mkAssocElems args' ((either varToVHDLName id) dst) signature
+               return ([mkComponentInst label entity_id portmaps], [f])
+            else
+              -- 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.
+            do f' <- MonadState.lift tsType $ varToVHDLExpr f
+               return ([mkUncondAssign dst f'], [])
+    else -- Destination has empty type, don't generate anything
+      return ([], [])
+-----------------------------------------------------------------------------
+-- 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 -> TypeSession AST.VHDLId
+vectorFunId el_ty fname = do
+  let error_msg = "\nGenerate.vectorFunId: Can not construct vector function for element: " ++ pprString el_ty
+  -- TODO: Handle the Nothing case?
+  elemTM_maybe <- vhdlTy error_msg el_ty
+  let elemTM = Maybe.fromMaybe
+                 (error $ "\nGenerate.vectorFunId: Cannot generate vector function \"" ++ fname ++ "\" for the empty type \"" ++ (pprString el_ty) ++ "\"")
+                 elemTM_maybe
+  -- TODO: This should not be duplicated from mk_vector_ty. Probably but it in
+  -- the VHDLState or something.
+  let vectorTM = mkVHDLExtId $ "vector_" ++ (AST.fromVHDLId elemTM)
+  typefuns <- MonadState.get tsTypeFuns
+  el_htype <- mkHType error_msg el_ty
+  case Map.lookup (UVecType el_htype, fname) typefuns of
+    -- Function already generated, just return it
+    Just (id, _) -> return id
+    -- Function not generated yet, generate it
+    Nothing -> do
+      let functions = genUnconsVectorFuns elemTM vectorTM
+      case lookup fname functions of
+        Just body -> do
+          MonadState.modify tsTypeFuns $ Map.insert (UVecType el_htype, fname) (function_id, (fst body))
+          mapM_ (vectorFunId el_ty) (snd body)
+          return function_id
+        Nothing -> error $ "\nGenerate.vectorFunId: I don't know how to generate vector function " ++ fname
+  where
+    function_id = mkVHDLExtId fname
+
+genUnconsVectorFuns :: AST.TypeMark -- ^ type of the vector elements
+                    -> AST.TypeMark -- ^ type of the vector
+                    -> [(String, (AST.SubProgBody, [String]))]
+genUnconsVectorFuns elemTM vectorTM  = 
+  [ (exId, (AST.SubProgBody exSpec      []                  [exExpr],[]))
+  , (replaceId, (AST.SubProgBody replaceSpec [AST.SPVD replaceVar] [replaceExpr1,replaceExpr2,replaceRet],[]))
+  , (lastId, (AST.SubProgBody lastSpec    []                  [lastExpr],[]))
+  , (initId, (AST.SubProgBody initSpec    [AST.SPVD initVar]  [initExpr, initRet],[]))
+  , (minimumId, (AST.SubProgBody minimumSpec [] [minimumExpr],[]))
+  , (takeId, (AST.SubProgBody takeSpec    [AST.SPVD takeVar]  [takeExpr, takeRet],[minimumId]))
+  , (dropId, (AST.SubProgBody dropSpec    [AST.SPVD dropVar]  [dropExpr, dropRet],[]))
+  , (plusgtId, (AST.SubProgBody plusgtSpec  [AST.SPVD plusgtVar] [plusgtExpr, plusgtRet],[]))
+  , (emptyId, (AST.SubProgBody emptySpec   [AST.SPVD emptyVar] [emptyExpr],[]))
+  , (singletonId, (AST.SubProgBody singletonSpec [AST.SPVD singletonVar] [singletonRet],[]))
+  , (copynId, (AST.SubProgBody copynSpec    [AST.SPVD copynVar]      [copynExpr],[]))
+  , (selId, (AST.SubProgBody selSpec  [AST.SPVD selVar] [selFor, selRet],[]))
+  , (ltplusId, (AST.SubProgBody ltplusSpec [AST.SPVD ltplusVar] [ltplusExpr, ltplusRet],[]))  
+  , (plusplusId, (AST.SubProgBody plusplusSpec [AST.SPVD plusplusVar] [plusplusExpr, plusplusRet],[]))
+  , (lengthTId, (AST.SubProgBody lengthTSpec [] [lengthTExpr],[]))
+  , (shiftlId, (AST.SubProgBody shiftlSpec [AST.SPVD shiftlVar] [shiftlExpr, shiftlRet], [initId]))
+  , (shiftrId, (AST.SubProgBody shiftrSpec [AST.SPVD shiftrVar] [shiftrExpr, shiftrRet], [tailId]))
+  , (nullId, (AST.SubProgBody nullSpec [] [nullExpr], []))
+  , (rotlId, (AST.SubProgBody rotlSpec [AST.SPVD rotlVar] [rotlExpr, rotlRet], [nullId, lastId, initId]))
+  , (rotrId, (AST.SubProgBody rotrSpec [AST.SPVD rotrVar] [rotrExpr, rotrRet], [nullId, tailId, headId]))
+  , (reverseId, (AST.SubProgBody reverseSpec [AST.SPVD reverseVar] [reverseFor, reverseRet], []))
+  ]
+  where 
+    ixPar   = AST.unsafeVHDLBasicId "ix"
+    vecPar  = AST.unsafeVHDLBasicId "vec"
+    vec1Par = AST.unsafeVHDLBasicId "vec1"
+    vec2Par = AST.unsafeVHDLBasicId "vec2"
+    nPar    = AST.unsafeVHDLBasicId "n"
+    leftPar = AST.unsafeVHDLBasicId "nLeft"
+    rightPar = AST.unsafeVHDLBasicId "nRight"
+    iId     = AST.unsafeVHDLBasicId "i"
+    iPar    = iId
+    aPar    = AST.unsafeVHDLBasicId "a"
+    fPar = AST.unsafeVHDLBasicId "f"
+    sPar = AST.unsafeVHDLBasicId "s"
+    resId   = AST.unsafeVHDLBasicId "res"    
+    exSpec = AST.Function (mkVHDLExtId exId) [AST.IfaceVarDec vecPar vectorTM,
+                               AST.IfaceVarDec ixPar  unsignedTM] elemTM
+    exExpr = AST.ReturnSm (Just $ AST.PrimName $ AST.NIndexed 
+              (AST.IndexedName (AST.NSimple vecPar) [genExprFCall (mkVHDLBasicId toIntegerId) (AST.PrimName $ AST.NSimple ixPar)]))
+    replaceSpec = AST.Function (mkVHDLExtId replaceId)  [ AST.IfaceVarDec vecPar vectorTM
+                                          , AST.IfaceVarDec iPar   unsignedTM
+                                          , AST.IfaceVarDec aPar   elemTM
+                                          ] vectorTM 
+       -- variable res : fsvec_x (0 to vec'length-1);
+    replaceVar =
+         AST.VarDec resId 
+                (AST.SubtypeIn vectorTM
+                  (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
+                   [AST.ToRange (AST.PrimLit "0")
+                            (AST.PrimName (AST.NAttribute $ 
+                              AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:-:
+                                (AST.PrimLit "1"))   ]))
+                Nothing
+       --  res AST.:= vec(0 to i-1) & a & vec(i+1 to length'vec-1)
+    replaceExpr1 = AST.NSimple resId AST.:= AST.PrimName (AST.NSimple vecPar)
+    replaceExpr2 = AST.NIndexed (AST.IndexedName (AST.NSimple resId) [genExprFCall (mkVHDLBasicId toIntegerId) (AST.PrimName $ AST.NSimple iPar)]) AST.:= AST.PrimName (AST.NSimple aPar)
+    replaceRet =  AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
+    vecSlice init last =  AST.PrimName (AST.NSlice 
+                                        (AST.SliceName 
+                                              (AST.NSimple vecPar) 
+                                              (AST.ToRange init last)))
+    lastSpec = AST.Function (mkVHDLExtId lastId) [AST.IfaceVarDec vecPar vectorTM] elemTM
+       -- return vec(vec'length-1);
+    lastExpr = AST.ReturnSm (Just (AST.PrimName $ AST.NIndexed (AST.IndexedName 
+                    (AST.NSimple vecPar) 
+                    [AST.PrimName (AST.NAttribute $ 
+                                AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) 
+                                                             AST.:-: AST.PrimLit "1"])))
+    initSpec = AST.Function (mkVHDLExtId initId) [AST.IfaceVarDec vecPar vectorTM] vectorTM 
+       -- variable res : fsvec_x (0 to vec'length-2);
+    initVar = 
+         AST.VarDec resId 
+                (AST.SubtypeIn vectorTM
+                  (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
+                   [AST.ToRange (AST.PrimLit "0")
+                            (AST.PrimName (AST.NAttribute $ 
+                              AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:-:
+                                (AST.PrimLit "2"))   ]))
+                Nothing
+       -- resAST.:= vec(0 to vec'length-2)
+    initExpr = AST.NSimple resId AST.:= (vecSlice 
+                               (AST.PrimLit "0") 
+                               (AST.PrimName (AST.NAttribute $ 
+                                  AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) 
+                                                             AST.:-: AST.PrimLit "2"))
+    initRet =  AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
+    minimumSpec = AST.Function (mkVHDLExtId minimumId) [AST.IfaceVarDec leftPar   naturalTM,
+                                   AST.IfaceVarDec rightPar naturalTM ] naturalTM
+    minimumExpr = AST.IfSm ((AST.PrimName $ AST.NSimple leftPar) AST.:<: (AST.PrimName $ AST.NSimple rightPar))
+                        [AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple leftPar)]
+                        []
+                        (Just $ AST.Else [minimumExprRet])
+      where minimumExprRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple rightPar)
+    takeSpec = AST.Function (mkVHDLExtId takeId) [AST.IfaceVarDec nPar   naturalTM,
+                                   AST.IfaceVarDec vecPar vectorTM ] vectorTM
+       -- variable res : fsvec_x (0 to (minimum (n,vec'length))-1);
+    minLength = AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLExtId minimumId))  
+                              [Nothing AST.:=>: AST.ADExpr (AST.PrimName $ AST.NSimple nPar)
+                              ,Nothing AST.:=>: AST.ADExpr (AST.PrimName (AST.NAttribute $ 
+                                AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing))]
+    takeVar = 
+         AST.VarDec resId 
+                (AST.SubtypeIn vectorTM
+                  (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
+                   [AST.ToRange (AST.PrimLit "0")
+                               (minLength AST.:-:
+                                (AST.PrimLit "1"))   ]))
+                Nothing
+       -- res AST.:= vec(0 to n-1)
+    takeExpr = AST.NSimple resId AST.:= 
+                    (vecSlice (AST.PrimLit "0") 
+                              (minLength AST.:-: AST.PrimLit "1"))
+    takeRet =  AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
+    dropSpec = AST.Function (mkVHDLExtId dropId) [AST.IfaceVarDec nPar   naturalTM,
+                                   AST.IfaceVarDec vecPar vectorTM ] vectorTM 
+       -- variable res : fsvec_x (0 to vec'length-n-1);
+    dropVar = 
+         AST.VarDec resId 
+                (AST.SubtypeIn vectorTM
+                  (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
+                   [AST.ToRange (AST.PrimLit "0")
+                            (AST.PrimName (AST.NAttribute $ 
+                              AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:-:
+                               (AST.PrimName $ AST.NSimple nPar)AST.:-: (AST.PrimLit "1")) ]))
+               Nothing
+       -- res AST.:= vec(n to vec'length-1)
+    dropExpr = AST.NSimple resId AST.:= (vecSlice 
+                               (AST.PrimName $ AST.NSimple nPar) 
+                               (AST.PrimName (AST.NAttribute $ 
+                                  AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) 
+                                                             AST.:-: AST.PrimLit "1"))
+    dropRet =  AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
+    plusgtSpec = AST.Function (mkVHDLExtId plusgtId) [AST.IfaceVarDec aPar   elemTM,
+                                       AST.IfaceVarDec vecPar vectorTM] vectorTM 
+    -- variable res : fsvec_x (0 to vec'length);
+    plusgtVar = 
+      AST.VarDec resId 
+             (AST.SubtypeIn vectorTM
+               (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
+                [AST.ToRange (AST.PrimLit "0")
+                        (AST.PrimName (AST.NAttribute $ 
+                          AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing))]))
+             Nothing
+    plusgtExpr = AST.NSimple resId AST.:= 
+                   ((AST.PrimName $ AST.NSimple aPar) AST.:&: 
+                    (AST.PrimName $ AST.NSimple vecPar))
+    plusgtRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
+    emptySpec = AST.Function (mkVHDLExtId emptyId) [] vectorTM
+    emptyVar = 
+          AST.VarDec resId
+            (AST.SubtypeIn vectorTM
+              (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
+                [AST.ToRange (AST.PrimLit "0") (AST.PrimLit "-1")]))
+             Nothing
+    emptyExpr = AST.ReturnSm (Just $ AST.PrimName (AST.NSimple resId))
+    singletonSpec = AST.Function (mkVHDLExtId singletonId) [AST.IfaceVarDec aPar elemTM ] 
+                                         vectorTM
+    -- variable res : fsvec_x (0 to 0) := (others => a);
+    singletonVar = 
+      AST.VarDec resId 
+             (AST.SubtypeIn vectorTM
+               (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
+                [AST.ToRange (AST.PrimLit "0") (AST.PrimLit "0")]))
+             (Just $ AST.Aggregate [AST.ElemAssoc (Just AST.Others) 
+                                          (AST.PrimName $ AST.NSimple aPar)])
+    singletonRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
+    copynSpec = AST.Function (mkVHDLExtId copynId) [AST.IfaceVarDec nPar   naturalTM,
+                                   AST.IfaceVarDec aPar   elemTM   ] vectorTM 
+    -- variable res : fsvec_x (0 to n-1) := (others => a);
+    copynVar = 
+      AST.VarDec resId 
+             (AST.SubtypeIn vectorTM
+               (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
+                [AST.ToRange (AST.PrimLit "0")
+                            ((AST.PrimName (AST.NSimple nPar)) AST.:-:
+                             (AST.PrimLit "1"))   ]))
+             (Just $ AST.Aggregate [AST.ElemAssoc (Just AST.Others) 
+                                          (AST.PrimName $ AST.NSimple aPar)])
+    -- return res
+    copynExpr = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
+    selSpec = AST.Function (mkVHDLExtId selId) [AST.IfaceVarDec fPar   naturalTM,
+                               AST.IfaceVarDec sPar   naturalTM,
+                               AST.IfaceVarDec nPar   naturalTM,
+                               AST.IfaceVarDec vecPar vectorTM ] vectorTM
+    -- variable res : fsvec_x (0 to n-1);
+    selVar = 
+      AST.VarDec resId 
+                (AST.SubtypeIn vectorTM
+                  (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
+                    [AST.ToRange (AST.PrimLit "0")
+                      ((AST.PrimName (AST.NSimple nPar)) AST.:-:
+                      (AST.PrimLit "1"))   ])
+                )
+                Nothing
+    -- for i res'range loop
+    --   res(i) := vec(f+i*s);
+    -- end loop;
+    selFor = AST.ForSM iId (AST.AttribRange $ AST.AttribName (AST.NSimple resId) (AST.NSimple rangeId) Nothing) [selAssign]
+    -- res(i) := vec(f+i*s);
+    selAssign = let origExp = AST.PrimName (AST.NSimple fPar) AST.:+: 
+                                (AST.PrimName (AST.NSimple iId) AST.:*: 
+                                  AST.PrimName (AST.NSimple sPar)) in
+                                  AST.NIndexed (AST.IndexedName (AST.NSimple resId) [AST.PrimName (AST.NSimple iId)]) AST.:=
+                                    (AST.PrimName $ AST.NIndexed (AST.IndexedName (AST.NSimple vecPar) [origExp]))
+    -- return res;
+    selRet =  AST.ReturnSm (Just $ AST.PrimName (AST.NSimple resId))
+    ltplusSpec = AST.Function (mkVHDLExtId ltplusId) [AST.IfaceVarDec vecPar vectorTM,
+                                        AST.IfaceVarDec aPar   elemTM] vectorTM 
+     -- variable res : fsvec_x (0 to vec'length);
+    ltplusVar = 
+      AST.VarDec resId 
+        (AST.SubtypeIn vectorTM
+          (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
+            [AST.ToRange (AST.PrimLit "0")
+              (AST.PrimName (AST.NAttribute $ 
+                AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing))]))
+        Nothing
+    ltplusExpr = AST.NSimple resId AST.:= 
+                     ((AST.PrimName $ AST.NSimple vecPar) AST.:&: 
+                      (AST.PrimName $ AST.NSimple aPar))
+    ltplusRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
+    plusplusSpec = AST.Function (mkVHDLExtId plusplusId) [AST.IfaceVarDec vec1Par vectorTM,
+                                             AST.IfaceVarDec vec2Par vectorTM] 
+                                             vectorTM 
+    -- variable res : fsvec_x (0 to vec1'length + vec2'length -1);
+    plusplusVar = 
+      AST.VarDec resId 
+        (AST.SubtypeIn vectorTM
+          (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
+            [AST.ToRange (AST.PrimLit "0")
+              (AST.PrimName (AST.NAttribute $ 
+                AST.AttribName (AST.NSimple vec1Par) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:+:
+                  AST.PrimName (AST.NAttribute $ 
+                AST.AttribName (AST.NSimple vec2Par) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:-:
+                  AST.PrimLit "1")]))
+       Nothing
+    plusplusExpr = AST.NSimple resId AST.:= 
+                     ((AST.PrimName $ AST.NSimple vec1Par) AST.:&: 
+                      (AST.PrimName $ AST.NSimple vec2Par))
+    plusplusRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
+    lengthTSpec = AST.Function (mkVHDLExtId lengthTId) [AST.IfaceVarDec vecPar vectorTM] naturalTM
+    lengthTExpr = AST.ReturnSm (Just $ AST.PrimName (AST.NAttribute $ 
+                                AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing))
+    shiftlSpec = AST.Function (mkVHDLExtId shiftlId) [AST.IfaceVarDec vecPar vectorTM,
+                                   AST.IfaceVarDec aPar   elemTM  ] vectorTM 
+    -- variable res : fsvec_x (0 to vec'length-1);
+    shiftlVar = 
+     AST.VarDec resId 
+            (AST.SubtypeIn vectorTM
+              (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
+               [AST.ToRange (AST.PrimLit "0")
+                        (AST.PrimName (AST.NAttribute $ 
+                          AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:-:
+                           (AST.PrimLit "1")) ]))
+            Nothing
+    -- res := a & init(vec)
+    shiftlExpr = AST.NSimple resId AST.:=
+                    (AST.PrimName (AST.NSimple aPar) AST.:&:
+                     (AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLExtId initId))  
+                       [Nothing AST.:=>: AST.ADExpr (AST.PrimName $ AST.NSimple vecPar)]))
+    shiftlRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)       
+    shiftrSpec = AST.Function (mkVHDLExtId shiftrId) [AST.IfaceVarDec vecPar vectorTM,
+                                       AST.IfaceVarDec aPar   elemTM  ] vectorTM 
+    -- variable res : fsvec_x (0 to vec'length-1);
+    shiftrVar = 
+     AST.VarDec resId 
+            (AST.SubtypeIn vectorTM
+              (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
+               [AST.ToRange (AST.PrimLit "0")
+                        (AST.PrimName (AST.NAttribute $ 
+                          AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:-:
+                           (AST.PrimLit "1")) ]))
+            Nothing
+    -- res := tail(vec) & a
+    shiftrExpr = AST.NSimple resId AST.:=
+                  ((AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLExtId tailId))  
+                    [Nothing AST.:=>: AST.ADExpr (AST.PrimName $ AST.NSimple vecPar)]) AST.:&:
+                  (AST.PrimName (AST.NSimple aPar)))
+                
+    shiftrRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)      
+    nullSpec = AST.Function (mkVHDLExtId nullId) [AST.IfaceVarDec vecPar vectorTM] booleanTM
+    -- return vec'length = 0
+    nullExpr = AST.ReturnSm (Just $ 
+                AST.PrimName (AST.NAttribute $ 
+                  AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:=:
+                    AST.PrimLit "0")
+    rotlSpec = AST.Function (mkVHDLExtId rotlId) [AST.IfaceVarDec vecPar vectorTM] vectorTM 
+    -- variable res : fsvec_x (0 to vec'length-1);
+    rotlVar = 
+     AST.VarDec resId 
+            (AST.SubtypeIn vectorTM
+              (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
+               [AST.ToRange (AST.PrimLit "0")
+                        (AST.PrimName (AST.NAttribute $ 
+                          AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:-:
+                           (AST.PrimLit "1")) ]))
+            Nothing
+    -- if null(vec) then res := vec else res := last(vec) & init(vec)
+    rotlExpr = AST.IfSm (AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLExtId nullId))  
+                          [Nothing AST.:=>: AST.ADExpr (AST.PrimName $ AST.NSimple vecPar)])
+                        [AST.NSimple resId AST.:= (AST.PrimName $ AST.NSimple vecPar)]
+                        []
+                        (Just $ AST.Else [rotlExprRet])
+      where rotlExprRet = 
+                AST.NSimple resId AST.:= 
+                      ((AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLExtId lastId))  
+                        [Nothing AST.:=>: AST.ADExpr (AST.PrimName $ AST.NSimple vecPar)]) AST.:&:
+                      (AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLExtId initId))  
+                        [Nothing AST.:=>: AST.ADExpr (AST.PrimName $ AST.NSimple vecPar)]))
+    rotlRet =  AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)       
+    rotrSpec = AST.Function (mkVHDLExtId rotrId) [AST.IfaceVarDec vecPar vectorTM] vectorTM 
+    -- variable res : fsvec_x (0 to vec'length-1);
+    rotrVar = 
+     AST.VarDec resId 
+            (AST.SubtypeIn vectorTM
+              (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
+               [AST.ToRange (AST.PrimLit "0")
+                        (AST.PrimName (AST.NAttribute $ 
+                          AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:-:
+                           (AST.PrimLit "1")) ]))
+            Nothing
+    -- if null(vec) then res := vec else res := tail(vec) & head(vec)
+    rotrExpr = AST.IfSm (AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLExtId nullId))  
+                          [Nothing AST.:=>: AST.ADExpr (AST.PrimName $ AST.NSimple vecPar)])
+                        [AST.NSimple resId AST.:= (AST.PrimName $ AST.NSimple vecPar)]
+                        []
+                        (Just $ AST.Else [rotrExprRet])
+      where rotrExprRet = 
+                AST.NSimple resId AST.:= 
+                      ((AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLExtId tailId))  
+                        [Nothing AST.:=>: AST.ADExpr (AST.PrimName $ AST.NSimple vecPar)]) AST.:&:
+                      (AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLExtId headId))  
+                        [Nothing AST.:=>: AST.ADExpr (AST.PrimName $ AST.NSimple vecPar)]))
+    rotrRet =  AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
+    reverseSpec = AST.Function (mkVHDLExtId reverseId) [AST.IfaceVarDec vecPar vectorTM] vectorTM
+    reverseVar = 
+      AST.VarDec resId 
+             (AST.SubtypeIn vectorTM
+               (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
+                [AST.ToRange (AST.PrimLit "0")
+                         (AST.PrimName (AST.NAttribute $ 
+                           AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:-:
+                            (AST.PrimLit "1")) ]))
+             Nothing
+    -- for i in 0 to res'range loop
+    --   res(vec'length-i-1) := vec(i);
+    -- end loop;
+    reverseFor = 
+       AST.ForSM iId (AST.AttribRange $ AST.AttribName (AST.NSimple resId) (AST.NSimple rangeId) Nothing) [reverseAssign]
+    -- res(vec'length-i-1) := vec(i);
+    reverseAssign = AST.NIndexed (AST.IndexedName (AST.NSimple resId) [destExp]) AST.:=
+      (AST.PrimName $ AST.NIndexed (AST.IndexedName (AST.NSimple vecPar) 
+                           [AST.PrimName $ AST.NSimple iId]))
+        where destExp = AST.PrimName (AST.NAttribute $ AST.AttribName (AST.NSimple vecPar) 
+                                   (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:-: 
+                        AST.PrimName (AST.NSimple iId) AST.:-: 
+                        (AST.PrimLit "1") 
+    -- return res;
+    reverseRet = AST.ReturnSm (Just $ AST.PrimName (AST.NSimple resId))
+
+    
+-----------------------------------------------------------------------------
+-- 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. If you add a name to this map, don't forget to add
+-- it to VHDL.Constants/builtinIds as well.
+globalNameTable :: NameTable
+globalNameTable = Map.fromList
+  [ (exId             , (2, genFCall True          ) )
+  , (replaceId        , (3, genFCall False          ) )
+  , (headId           , (1, genFCall True           ) )
+  , (lastId           , (1, genFCall True           ) )
+  , (tailId           , (1, genFCall False          ) )
+  , (initId           , (1, genFCall False          ) )
+  , (takeId           , (2, genFCall False          ) )
+  , (dropId           , (2, genFCall False          ) )
+  , (selId            , (4, genFCall False          ) )
+  , (plusgtId         , (2, genFCall False          ) )
+  , (ltplusId         , (2, genFCall False          ) )
+  , (plusplusId       , (2, genFCall False          ) )
+  , (mapId            , (2, genMap                  ) )
+  , (zipWithId        , (3, genZipWith              ) )
+  , (foldlId          , (3, genFoldl                ) )
+  , (foldrId          , (3, genFoldr                ) )
+  , (zipId            , (2, genZip                  ) )
+  , (unzipId          , (1, genUnzip                ) )
+  , (shiftlId         , (2, genFCall False          ) )
+  , (shiftrId         , (2, genFCall False          ) )
+  , (rotlId           , (1, genFCall False          ) )
+  , (rotrId           , (1, genFCall False          ) )
+  , (concatId         , (1, genConcat               ) )
+  , (reverseId        , (1, genFCall False          ) )
+  , (iteratenId       , (3, genIteraten             ) )
+  , (iterateId        , (2, genIterate              ) )
+  , (generatenId      , (3, genGeneraten            ) )
+  , (generateId       , (2, genGenerate             ) )
+  , (emptyId          , (0, genFCall False          ) )
+  , (singletonId      , (1, genFCall False          ) )
+  , (copynId          , (2, genFCall False          ) )
+  , (copyId           , (1, genCopy                 ) )
+  , (lengthTId        , (1, genFCall False          ) )
+  , (nullId           , (1, genFCall False          ) )
+  , (hwxorId          , (2, genOperator2 AST.Xor    ) )
+  , (hwandId          , (2, genOperator2 AST.And    ) )
+  , (hworId           , (2, genOperator2 AST.Or     ) )
+  , (hwnotId          , (1, genOperator1 AST.Not    ) )
+  , (equalityId       , (2, genOperator2 (AST.:=:)  ) )
+  , (inEqualityId     , (2, genOperator2 (AST.:/=:) ) )
+  , (ltId             , (2, genOperator2 (AST.:<:)  ) )
+  , (lteqId           , (2, genOperator2 (AST.:<=:) ) )
+  , (gtId             , (2, genOperator2 (AST.:>:)  ) )
+  , (gteqId           , (2, genOperator2 (AST.:>=:) ) )
+  , (boolOrId         , (2, genOperator2 AST.Or     ) )
+  , (boolAndId        , (2, genOperator2 AST.And    ) )
+  , (boolNot          , (1, genOperator1 AST.Not    ) )
+  , (plusId           , (2, genOperator2 (AST.:+:)  ) )
+  , (timesId          , (2, genTimes                ) )
+  , (negateId         , (1, genNegation             ) )
+  , (minusId          , (2, genOperator2 (AST.:-:)  ) )
+  , (fromSizedWordId  , (1, genFromSizedWord        ) )
+  , (fromRangedWordId , (1, genFromRangedWord       ) )
+  , (fromIntegerId    , (1, genFromInteger          ) )
+  , (resizeWordId     , (1, genResize               ) )
+  , (resizeIntId      , (1, genResize               ) )
+  , (sizedIntId       , (1, genSizedInt             ) )
+  , (smallIntegerId   , (1, genFromInteger          ) )
+  , (fstId            , (1, genFst                  ) )
+  , (sndId            , (1, genSnd                  ) )
+  , (blockRAMId       , (5, genBlockRAM             ) )
+  , (splitId          , (1, genSplit                ) )
+  --, (tfvecId          , (1, genTFVec                ) )
+  , (minimumId        , (2, error "\nFunction name: \"minimum\" is used internally, use another name"))
+  ]
diff --git a/clash/CLasH/VHDL/Testbench.hs b/clash/CLasH/VHDL/Testbench.hs
new file mode 100644 (file)
index 0000000..fa2e9dc
--- /dev/null
@@ -0,0 +1,173 @@
+-- 
+-- Functions to create a VHDL testbench from a list of test input.
+--
+module CLasH.VHDL.Testbench where
+
+-- Standard modules
+import qualified Control.Monad as Monad
+import qualified Maybe
+import qualified Data.Map as Map
+import qualified Data.Accessor.Monad.Trans.State as MonadState
+
+-- VHDL Imports
+import qualified Language.VHDL.AST as AST
+
+-- GHC API
+import qualified CoreSyn
+import qualified HscTypes
+import qualified Var
+import qualified TysWiredIn
+
+-- Local imports
+import CLasH.Translator.TranslatorTypes
+import CLasH.VHDL.Constants
+import CLasH.VHDL.Generate
+import CLasH.VHDL.VHDLTools
+import CLasH.VHDL.VHDLTypes
+import CLasH.Normalize
+import CLasH.Utils.Core.BinderTools
+import CLasH.Utils.Core.CoreTools
+import CLasH.Utils
+
+createTestbench :: 
+  Maybe Int -- ^ Number of cycles to simulate
+  -> [HscTypes.CoreModule] -- ^ Compiled modules
+  -> CoreSyn.CoreExpr -- ^ Input stimuli
+  -> CoreSyn.CoreBndr -- ^ Top Entity
+  -> TranslatorSession CoreSyn.CoreBndr -- ^ The id of the generated archictecture
+createTestbench mCycles cores stimuli top = do
+  stimuli' <- reduceCoreListToHsList cores stimuli
+  -- Create a binder for the testbench. We use the unit type (), since the
+  -- testbench has no outputs and no inputs.
+  bndr <- mkInternalVar "testbench" TysWiredIn.unitTy
+  let entity = createTestbenchEntity bndr
+  MonadState.modify tsEntities (Map.insert bndr entity)
+  arch <- createTestbenchArch mCycles stimuli' top entity
+  MonadState.modify tsArchitectures (Map.insert bndr arch)
+  return bndr
+
+createTestbenchEntity :: 
+  CoreSyn.CoreBndr
+  -> Entity
+createTestbenchEntity bndr = entity
+  where
+    vhdl_id = mkVHDLBasicId "testbench"
+    -- Create an AST entity declaration with no ports
+    ent_decl = AST.EntityDec vhdl_id []
+    -- Create a signature with no input and no output ports
+    entity = Entity vhdl_id [] undefined ent_decl
+
+createTestbenchArch ::
+  Maybe Int -- ^ Number of cycles to simulate
+  -> [CoreSyn.CoreExpr] -- ^ Imput stimuli
+  -> CoreSyn.CoreBndr -- ^ Top Entity
+  -> Entity -- ^ The signature to create an architecture for
+  -> TranslatorSession (Architecture, [CoreSyn.CoreBndr])
+  -- ^ The architecture and any other entities used.
+createTestbenchArch mCycles stimuli top testent= do
+  signature <- getEntity top
+  let entId   = ent_id signature
+      iIface  = ent_args signature
+      oIface  = ent_res signature
+      iIds    = map fst iIface
+  let (oId, oDec, oProc) = case oIface of
+        Just (id, ty) -> ( id
+                         , [AST.SigDec id ty Nothing]
+                         , [createOutputProc [id]])
+        -- No output port? Just use undefined for the output id, since it won't be
+        -- used by mkAssocElems when there is no output port.
+        Nothing -> (undefined, [], [])
+  let iDecs   = map (\(vId, tm) -> AST.SigDec vId tm Nothing) iIface
+  let finalIDecs = iDecs ++
+                    [AST.SigDec clockId std_logicTM (Just $ AST.PrimLit "'0'"),
+                     AST.SigDec resetId std_logicTM (Just $ AST.PrimLit "'0'")]
+  let portmaps = mkAssocElems (map idToVHDLExpr iIds) (AST.NSimple oId) signature
+  let mIns    = mkComponentInst "totest" entId portmaps
+  (stimuliAssigns, stimuliDecs, cycles, used) <- createStimuliAssigns mCycles stimuli (head iIds)
+  let finalAssigns = (AST.CSSASm (AST.NSimple resetId AST.:<==:
+                      AST.ConWforms []
+                                    (AST.Wform [AST.WformElem (AST.PrimLit "'0'") (Just $ AST.PrimLit "0 ns"), AST.WformElem (AST.PrimLit "'1'") (Just $ AST.PrimLit "3 ns")])
+                                    Nothing)) : stimuliAssigns
+  let clkProc     = createClkProc
+  let arch = AST.ArchBody
+              (AST.unsafeVHDLBasicId "test")
+              (AST.NSimple $ ent_id testent)
+              (map AST.BDISD (finalIDecs ++ stimuliDecs ++ oDec))
+              (mIns :
+                ( (AST.CSPSm clkProc) : (fmap AST.CSPSm oProc) ++ finalAssigns ) )
+  return (arch, top : used)
+
+createStimuliAssigns ::
+  Maybe Int -- ^ Number of cycles to simulate
+  -> [CoreSyn.CoreExpr] -- ^ Input stimuli
+  -> AST.VHDLId -- ^ Input signal
+  -> TranslatorSession ( [AST.ConcSm]
+                       , [AST.SigDec]
+                       , Int
+                       , [CoreSyn.CoreBndr]) -- ^ (Resulting statements, Needed signals, The number of cycles to simulate, Any entities used)
+createStimuliAssigns mCycles [] _ = return ([], [], Maybe.maybe 0 id mCycles, [])
+
+createStimuliAssigns mCycles stimuli signal = do
+  let genWformElem time stim = (AST.WformElem stim (Just $ AST.PrimLit (show time ++ " ns")))
+  let inputlen = length stimuli
+  assigns <- Monad.zipWithM createStimulans stimuli [0..inputlen]
+  let (stimuli_sms, resvars, useds) = unzip3 assigns
+  sig_dec_maybes <- mapM mkSigDec resvars
+  let sig_decs = Maybe.catMaybes sig_dec_maybes
+  outps <- mapM (\x -> MonadState.lift tsType (varToVHDLExpr x)) resvars
+  let wformelems = zipWith genWformElem [0,10..] outps
+  let inassign = AST.CSSASm $ AST.NSimple signal AST.:<==: AST.ConWforms [] (AST.Wform wformelems) Nothing
+  case (concat stimuli_sms) of
+    []        -> return ([inassign], [], inputlen, concat useds)
+    stims     -> return (stims ++ [inassign], sig_decs, inputlen, concat useds)
+
+createStimulans ::
+  CoreSyn.CoreExpr -- ^ The stimulans
+  -> Int -- ^ The cycle for this stimulans
+  -> TranslatorSession ( [AST.ConcSm]
+                       , Var.Var 
+                       , [CoreSyn.CoreBndr]) -- ^ (The statement, the variable it assigns to (assumed to be available!), Any entities used by this stimulans)
+
+createStimulans expr cycl = do 
+  -- There must be a let at top level 
+  expr <- normalizeExpr ("test input #" ++ show cycl) expr
+  -- Split the normalized expression. It can't have a function type, so match
+  -- an empty list of argument binders
+  let ([], binds, res) = splitNormalized expr
+  (stimulansbindss, useds) <- unzipM $ Monad.mapM mkConcSm binds
+  sig_dec_maybes <- mapM (mkSigDec . fst) (filter ((/=res).fst) binds)
+  let sig_decs = map (AST.BDISD) (Maybe.catMaybes sig_dec_maybes)
+  let block_label = mkVHDLExtId ("testcycle_" ++ (show cycl))
+  let block = AST.BlockSm block_label [] (AST.PMapAspect []) sig_decs (concat stimulansbindss)
+  case (sig_decs,(concat stimulansbindss)) of
+    ([],[])   ->  return ([], res, concat useds)
+    otherwise ->  return ([AST.CSBSm block], res, concat useds)
+-- | generates a clock process with a period of 10ns
+createClkProc :: AST.ProcSm
+createClkProc = AST.ProcSm (AST.unsafeVHDLBasicId "clkproc") [] sms
+ where sms = -- wait for 5 ns -- (half a cycle)
+             [AST.WaitFor $ AST.PrimLit "5 ns",
+              -- clk <= not clk;
+              AST.NSimple clockId `AST.SigAssign` 
+                 AST.Wform [AST.WformElem (AST.Not (AST.PrimName $ AST.NSimple clockId)) Nothing]]
+
+-- | generate the output process
+createOutputProc :: [AST.VHDLId] -- ^ output signal
+              -> AST.ProcSm  
+createOutputProc outs = 
+  AST.ProcSm (AST.unsafeVHDLBasicId "writeoutput") 
+         [clockId]
+         [AST.IfSm clkPred (writeOuts outs) [] Nothing]
+ where clkPred = AST.PrimName (AST.NAttribute $ AST.AttribName (AST.NSimple clockId) 
+                                                   (AST.NSimple eventId)
+                                                   Nothing          ) `AST.And` 
+                 (AST.PrimName (AST.NSimple clockId) AST.:=: AST.PrimLit "'1'")
+       writeOuts :: [AST.VHDLId] -> [AST.SeqSm]
+       writeOuts []  = []
+       writeOuts [i] = [writeOut i (AST.PrimLit "LF")]
+       writeOuts (i:is) = writeOut i (AST.PrimLit "HT") : writeOuts is
+       writeOut outSig suffix = 
+         genExprPCall2 writeId
+                        (AST.PrimName $ AST.NSimple outputId)
+                        ((genExprFCall showId (AST.PrimName $ AST.NSimple outSig)) AST.:&: suffix)
diff --git a/clash/CLasH/VHDL/VHDLTools.hs b/clash/CLasH/VHDL/VHDLTools.hs
new file mode 100644 (file)
index 0000000..165b1ef
--- /dev/null
@@ -0,0 +1,704 @@
+{-# LANGUAGE RelaxedPolyRec #-} -- Needed for vhdl_ty_either', for some reason...
+module CLasH.VHDL.VHDLTools where
+
+-- Standard modules
+import qualified Maybe
+import qualified Data.Either as Either
+import qualified Data.List as List
+import qualified Data.Char as Char
+import qualified Data.Map as Map
+import qualified Control.Monad as Monad
+import qualified Data.Accessor.Monad.Trans.State as MonadState
+
+-- VHDL Imports
+import qualified Language.VHDL.AST as AST
+
+-- GHC API
+import qualified CoreSyn
+import qualified Name
+import qualified OccName
+import qualified Var
+import qualified Id
+import qualified TyCon
+import qualified Type
+import qualified DataCon
+import qualified CoreSubst
+import qualified Outputable
+
+-- Local imports
+import CLasH.VHDL.VHDLTypes
+import CLasH.Translator.TranslatorTypes
+import CLasH.Utils.Core.CoreTools
+import CLasH.Utils
+import CLasH.Utils.Pretty
+import CLasH.VHDL.Constants
+
+-----------------------------------------------------------------------------
+-- Functions to generate concurrent statements
+-----------------------------------------------------------------------------
+
+-- Create an unconditional assignment statement
+mkUncondAssign ::
+  Either CoreSyn.CoreBndr AST.VHDLName -- ^ The signal to assign to
+  -> AST.Expr -- ^ The expression to assign
+  -> AST.ConcSm -- ^ The resulting concurrent statement
+mkUncondAssign dst expr = mkAssign dst Nothing expr
+
+-- Create a conditional assignment statement
+mkCondAssign ::
+  Either CoreSyn.CoreBndr AST.VHDLName -- ^ The signal to assign to
+  -> AST.Expr -- ^ The condition
+  -> AST.Expr -- ^ The value when true
+  -> AST.Expr -- ^ The value when false
+  -> AST.ConcSm -- ^ The resulting concurrent statement
+mkCondAssign dst cond true false = mkAssign dst (Just (cond, true)) false
+
+-- Create a conditional or unconditional assignment statement
+mkAssign ::
+  Either CoreSyn.CoreBndr AST.VHDLName -- ^ The signal to assign to
+  -> Maybe (AST.Expr , AST.Expr) -- ^ Optionally, the condition to test for
+                                 -- and the value to assign when true.
+  -> AST.Expr -- ^ The value to assign when false or no condition
+  -> AST.ConcSm -- ^ The resulting concurrent statement
+mkAssign dst cond false_expr =
+  let
+    -- I'm not 100% how this assignment AST works, but this gets us what we
+    -- want...
+    whenelse = case cond of
+      Just (cond_expr, true_expr) -> 
+        let 
+          true_wform = AST.Wform [AST.WformElem true_expr Nothing]
+        in
+          [AST.WhenElse true_wform cond_expr]
+      Nothing -> []
+    false_wform = AST.Wform [AST.WformElem false_expr Nothing]
+    dst_name  = case dst of
+      Left bndr -> AST.NSimple (varToVHDLId bndr)
+      Right name -> name
+    assign    = dst_name AST.:<==: (AST.ConWforms whenelse false_wform Nothing)
+  in
+    AST.CSSASm assign
+
+mkAltsAssign ::
+  Either CoreSyn.CoreBndr AST.VHDLName            -- ^ The signal to assign to
+  -> [AST.Expr]       -- ^ The conditions
+  -> [AST.Expr]       -- ^ The expressions
+  -> AST.ConcSm   -- ^ The Alt assigns
+mkAltsAssign dst conds exprs
+        | (length conds) /= ((length exprs) - 1) = error "\nVHDLTools.mkAltsAssign: conditions expression mismatch"
+        | otherwise =
+  let
+    whenelses   = zipWith mkWhenElse conds exprs
+    false_wform = AST.Wform [AST.WformElem (last exprs) Nothing]
+    dst_name  = case dst of
+      Left bndr -> AST.NSimple (varToVHDLId bndr)
+      Right name -> name
+    assign    = dst_name AST.:<==: (AST.ConWforms whenelses false_wform Nothing)
+  in
+    AST.CSSASm assign
+  where
+    mkWhenElse :: AST.Expr -> AST.Expr -> AST.WhenElse
+    mkWhenElse cond true_expr =
+      let
+        true_wform = AST.Wform [AST.WformElem true_expr Nothing]
+      in
+        AST.WhenElse true_wform cond
+
+mkAssocElems :: 
+  [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 =
+    arg_maps ++ (Maybe.maybeToList res_map_maybe)
+  where
+    arg_ports = ent_args entity
+    res_port_maybe = ent_res entity
+    -- Create an expression of res to map against the output port
+    res_expr = vhdlNameToVHDLExpr res
+    -- Map each of the input ports
+    arg_maps = zipWith mkAssocElem (map fst arg_ports) args
+    -- Map the output port, if present
+    res_map_maybe = fmap (\port -> mkAssocElem (fst port) res_expr) res_port_maybe
+
+-- | Create an VHDL port -> signal association
+mkAssocElem :: AST.VHDLId -> AST.Expr -> AST.AssocElem
+mkAssocElem port signal = Just port AST.:=>: (AST.ADExpr signal) 
+
+-- | Create an aggregate signal
+mkAggregateSignal :: [AST.Expr] -> AST.Expr
+mkAggregateSignal x = AST.Aggregate (map (\z -> AST.ElemAssoc Nothing z) x)
+
+mkComponentInst ::
+  String -- ^ The portmap label
+  -> AST.VHDLId -- ^ The entity name
+  -> [AST.AssocElem] -- ^ The port assignments
+  -> AST.ConcSm
+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 = mkAssocElem clockId (idToVHDLExpr clockId)
+    resetn_port = mkAssocElem resetId (idToVHDLExpr resetId)
+    compins = AST.CompInsSm (mkVHDLExtId label) (AST.IUEntity (AST.NSimple entity_id)) (AST.PMapAspect (portassigns ++ [clk_port,resetn_port]))
+
+-----------------------------------------------------------------------------
+-- Functions to generate VHDL Exprs
+-----------------------------------------------------------------------------
+
+varToVHDLExpr :: Var.Var -> TypeSession AST.Expr
+varToVHDLExpr var =
+  case Id.isDataConWorkId_maybe var of
+    -- This is a dataconstructor.
+    Just dc -> dataconToVHDLExpr dc
+    -- Not a datacon, just another signal.
+    Nothing -> return $ 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 core = varToVHDLExpr (exprToVar core)
+
+-- 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.
+altconToVHDLExpr :: CoreSyn.AltCon -> TypeSession AST.Expr
+altconToVHDLExpr (CoreSyn.DataAlt dc) = dataconToVHDLExpr dc
+
+altconToVHDLExpr (CoreSyn.LitAlt _) = error "\nVHDL.conToVHDLExpr: Literals not support in case alternatives yet"
+altconToVHDLExpr CoreSyn.DEFAULT = error "\nVHDL.conToVHDLExpr: DEFAULT alternative should not occur here!"
+
+-- Turn a datacon (without arguments!) into a VHDL expression.
+dataconToVHDLExpr :: DataCon.DataCon -> TypeSession AST.Expr
+dataconToVHDLExpr dc = do
+  typemap <- MonadState.get tsTypes
+  htype_either <- mkHTypeEither (DataCon.dataConRepType dc)
+  case htype_either of
+    -- No errors
+    Right htype -> do
+      let dcname = DataCon.dataConName dc
+      case htype of
+        (BuiltinType "Bit") -> return $ AST.PrimLit $ case Name.getOccString dcname of "High" -> "'1'"; "Low" -> "'0'"
+        (BuiltinType "Bool") -> return $ AST.PrimLit $ case Name.getOccString dcname of "True" -> "true"; "False" -> "false"
+        otherwise -> do
+          let existing_ty = Monad.liftM (fmap fst) $ Map.lookup htype typemap
+          case existing_ty of
+            Just ty -> do
+              let lit    = idToVHDLExpr $ mkVHDLExtId $ Name.getOccString dcname
+              return lit
+            Nothing -> error $ "\nVHDLTools.dataconToVHDLExpr: Trying to make value for non-representable DataCon: " ++ pprString dc
+    -- Error when constructing htype
+    Left err -> error err
+
+-----------------------------------------------------------------------------
+-- Functions dealing with names, variables and ids
+-----------------------------------------------------------------------------
+
+-- Creates a VHDL Id from a binder
+varToVHDLId ::
+  CoreSyn.CoreBndr
+  -> AST.VHDLId
+varToVHDLId var = mkVHDLExtId (varToString var ++ varToStringUniq var ++ show (lowers $ varToStringUniq var))
+  where
+    lowers :: String -> Int
+    lowers xs = length [x | x <- xs, Char.isLower x]
+
+-- Creates a VHDL Name from a binder
+varToVHDLName ::
+  CoreSyn.CoreBndr
+  -> AST.VHDLName
+varToVHDLName = AST.NSimple . varToVHDLId
+
+-- Extracts the binder name as a String
+varToString ::
+  CoreSyn.CoreBndr
+  -> String
+varToString = OccName.occNameString . Name.nameOccName . Var.varName
+
+-- Get the string version a Var's unique
+varToStringUniq :: Var.Var -> String
+varToStringUniq = show . Var.varUnique
+
+-- Extracts the string version of the name
+nameToString :: Name.Name -> String
+nameToString = OccName.occNameString . Name.nameOccName
+
+-- Shortcut for Basic VHDL Ids.
+-- Can only contain alphanumerics and underscores. The supplied string must be
+-- a valid basic id, otherwise an error value is returned. This function is
+-- not meant to be passed identifiers from a source file, use mkVHDLExtId for
+-- that.
+mkVHDLBasicId :: String -> AST.VHDLId
+mkVHDLBasicId s = 
+  AST.unsafeVHDLBasicId $ (strip_multiscore . strip_leading . strip_invalid) s
+  where
+    -- Strip invalid characters.
+    strip_invalid = filter (`elem` ['A'..'Z'] ++ ['a'..'z'] ++ ['0'..'9'] ++ "_.")
+    -- Strip leading numbers and underscores
+    strip_leading = dropWhile (`elem` ['0'..'9'] ++ "_")
+    -- Strip multiple adjacent underscores
+    strip_multiscore = concatMap (\cs -> 
+        case cs of 
+          ('_':_) -> "_"
+          _ -> cs
+      ) . List.group
+
+-- Shortcut for Extended VHDL Id's. These Id's can contain a lot more
+-- different characters than basic ids, but can never be used to refer to
+-- basic ids.
+-- Use extended Ids for any values that are taken from the source file.
+mkVHDLExtId :: String -> AST.VHDLId
+mkVHDLExtId s = 
+  AST.unsafeVHDLExtId $ strip_invalid s
+  where 
+    -- Allowed characters, taken from ForSyde's mkVHDLExtId
+    allowed = ['A'..'Z'] ++ ['a'..'z'] ++ ['0'..'9'] ++ " \"#&'()*+,./:;<=>_|!$%@?[]^`{}~-"
+    strip_invalid = filter (`elem` allowed)
+
+-- Create a record field selector that selects the given label from the record
+-- stored in the given binder.
+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
+-----------------------------------------------------------------------------
+builtin_types :: TypeMap
+builtin_types = 
+  Map.fromList [
+    (BuiltinType "Bit", Just (std_logicTM, Nothing)),
+    (BuiltinType "Bool", Just (booleanTM, Nothing)) -- TysWiredIn.boolTy
+  ]
+
+-- Is the given type representable at runtime?
+isReprType :: Type.Type -> TypeSession Bool
+isReprType ty = do
+  ty_either <- mkHTypeEither ty
+  return $ case ty_either of
+    Left _ -> False
+    Right _ -> True
+
+-- | Turn a Core type into a HType, returning an error using the given
+-- error string if the type was not representable.
+mkHType :: (TypedThing t, Outputable.Outputable t) => 
+  String -> t -> TypeSession HType
+mkHType msg ty = do
+  htype_either <- mkHTypeEither ty
+  case htype_either of
+    Right htype -> return htype
+    Left err -> error $ msg ++ err  
+
+-- | Turn a Core type into a HType. Returns either an error message if
+-- the type was not representable, or the HType generated.
+mkHTypeEither :: (TypedThing t, Outputable.Outputable t) => 
+  t -> TypeSession (Either String HType)
+mkHTypeEither tything =
+  case getType tything of
+    Nothing -> return $ Left $ "\nVHDLTools.mkHTypeEither: Typed thing without a type: " ++ pprString tything
+    Just ty -> mkHTypeEither' ty
+
+mkHTypeEither' :: Type.Type -> TypeSession (Either String HType)
+mkHTypeEither' ty | ty_has_free_tyvars ty = return $ Left $ "\nVHDLTools.mkHTypeEither': Cannot create type: type has free type variables: " ++ pprString ty
+                  | isStateType ty = return $ Right StateType
+                  | otherwise =
+  case Type.splitTyConApp_maybe ty of
+    Just (tycon, args) -> do
+      typemap <- MonadState.get tsTypes
+      let name = Name.getOccString (TyCon.tyConName tycon)
+      let builtinTyMaybe = Map.lookup (BuiltinType name) typemap  
+      case builtinTyMaybe of
+        (Just x) -> return $ Right $ BuiltinType name
+        Nothing ->
+          case name of
+                "Vector" -> do
+                  let el_ty = tfvec_elem ty
+                  elem_htype_either <- mkHTypeEither el_ty
+                  case elem_htype_either of
+                    -- Could create element type
+                    Right elem_htype -> do
+                      len <- tfp_to_int (tfvec_len_ty ty)
+                      return $ Right $ VecType len elem_htype
+                    -- Could not create element type
+                    Left err -> return $ Left $ 
+                      "\nVHDLTools.mkHTypeEither': Can not construct vectortype for elementtype: " ++ pprString el_ty ++ err
+                "Unsigned" -> do
+                  len <- tfp_to_int (sized_word_len_ty ty)
+                  return $ Right $ SizedWType len
+                "Signed" -> do
+                  len <- tfp_to_int (sized_word_len_ty ty)
+                  return $ Right $ SizedIType len
+                "Index" -> do
+                  bound <- tfp_to_int (ranged_word_bound_ty ty)
+                  return $ Right $ RangedWType bound
+                otherwise ->
+                  mkTyConHType tycon args
+    Nothing -> return $ Left $ "\nVHDLTools.mkHTypeEither': Do not know what to do with type: " ++ pprString ty
+
+mkTyConHType :: TyCon.TyCon -> [Type.Type] -> TypeSession (Either String HType)
+mkTyConHType tycon args =
+  case TyCon.tyConDataCons tycon of
+    -- Not an algebraic type
+    [] -> return $ Left $ "VHDLTools.mkTyConHType: Only custom algebraic types are supported: " ++ pprString tycon
+    [dc] -> do
+      let arg_tys = DataCon.dataConRepArgTys dc
+      let real_arg_tys = map (CoreSubst.substTy subst) arg_tys
+      let real_arg_tys_nostate = filter (\x -> not (isStateType x)) real_arg_tys
+      elem_htys_either <- mapM mkHTypeEither real_arg_tys_nostate
+      case Either.partitionEithers elem_htys_either of
+        ([], [elem_hty]) ->
+          return $ Right elem_hty
+        -- No errors in element types
+        ([], elem_htys) ->
+          return $ Right $ AggrType (nameToString (TyCon.tyConName tycon)) elem_htys
+        -- There were errors in element types
+        (errors, _) -> return $ Left $
+          "\nVHDLTools.mkTyConHType: Can not construct type for: " ++ pprString tycon ++ "\n because no type can be construced for some of the arguments.\n"
+          ++ (concat errors)
+    dcs -> do
+      let arg_tys = concatMap DataCon.dataConRepArgTys dcs
+      let real_arg_tys = map (CoreSubst.substTy subst) arg_tys
+      case real_arg_tys of
+        [] ->
+          return $ Right $ EnumType (nameToString (TyCon.tyConName tycon)) (map (nameToString . DataCon.dataConName) dcs)
+        xs -> return $ Left $
+          "VHDLTools.mkTyConHType: Only enum-like constructor datatypes supported: " ++ pprString dcs ++ "\n"
+  where
+    tyvars = TyCon.tyConTyVars tycon
+    subst = CoreSubst.extendTvSubstList CoreSubst.emptySubst (zip tyvars args)
+
+-- Translate a Haskell type to a VHDL type, generating a new type if needed.
+-- Returns an error value, using the given message, when no type could be
+-- created. Returns Nothing when the type is valid, but empty.
+vhdlTy :: (TypedThing t, Outputable.Outputable t) => 
+  String -> t -> TypeSession (Maybe AST.TypeMark)
+vhdlTy msg ty = do
+  htype <- mkHType msg ty
+  vhdlTyMaybe htype
+
+vhdlTyMaybe :: HType -> TypeSession (Maybe AST.TypeMark)
+vhdlTyMaybe htype = do
+  typemap <- MonadState.get tsTypes
+  -- If not a builtin type, try the custom types
+  let existing_ty = Map.lookup htype typemap
+  case existing_ty of
+    -- Found a type, return it
+    Just (Just (t, _)) -> return $ Just t
+    Just (Nothing) -> return Nothing
+    -- No type yet, try to construct it
+    Nothing -> do
+      newty <- (construct_vhdl_ty htype)
+      MonadState.modify tsTypes (Map.insert htype newty)
+      case newty of
+        Just (ty_id, ty_def) -> do
+          MonadState.modify tsTypeDecls (\typedefs -> typedefs ++ [mktydecl (ty_id, ty_def)])
+          return $ Just ty_id
+        Nothing -> return Nothing
+
+-- Construct a new VHDL type for the given Haskell type. Returns an error
+-- message or the resulting typemark and typedef.
+construct_vhdl_ty :: HType -> TypeSession TypeMapRec
+-- State types don't generate VHDL
+construct_vhdl_ty htype =
+    case htype of
+      StateType -> return  Nothing
+      (SizedWType w) -> mkUnsignedTy w
+      (SizedIType i) -> mkSignedTy i
+      (RangedWType u) -> mkNaturalTy 0 u
+      (VecType n e) -> mkVectorTy (VecType n e)
+      -- Create a custom type from this tycon
+      otherwise -> mkTyconTy htype
+
+-- | Create VHDL type for a custom tycon
+mkTyconTy :: HType -> TypeSession TypeMapRec
+mkTyconTy htype =
+  case htype of
+    (AggrType tycon args) -> do
+      elemTysMaybe <- mapM vhdlTyMaybe args
+      case Maybe.catMaybes elemTysMaybe of
+        [] -> -- No non-empty members
+          return Nothing
+        elem_tys -> do
+          let elems = zipWith AST.ElementDec recordlabels elem_tys  
+          let elem_names = concatMap prettyShow elem_tys
+          let ty_id = mkVHDLExtId $ tycon ++ elem_names
+          let ty_def = AST.TDR $ AST.RecordTypeDef elems
+          let tupshow = mkTupleShow elem_tys ty_id
+          MonadState.modify tsTypeFuns $ Map.insert (htype, showIdString) (showId, tupshow)
+          return $ Just (ty_id, Just $ Left ty_def)
+    (EnumType tycon dcs) -> do
+      let elems = map mkVHDLExtId dcs
+      let ty_id = mkVHDLExtId tycon
+      let ty_def = AST.TDE $ AST.EnumTypeDef elems
+      let enumShow = mkEnumShow elems ty_id
+      MonadState.modify tsTypeFuns $ Map.insert (htype, showIdString) (showId, enumShow)
+      return $ Just (ty_id, Just $ Left ty_def)
+    otherwise -> error $ "\nVHDLTools.mkTyconTy: Called for HType that is neiter a AggrType or EnumType: " ++ show htype
+  where
+    -- Generate a bunch of labels for fields of a record
+    recordlabels = map (\c -> mkVHDLBasicId [c]) ['A'..'Z']
+
+-- | Create a VHDL vector type
+mkVectorTy ::
+  HType -- ^ The Haskell type of the Vector
+  -> TypeSession TypeMapRec
+      -- ^ An error message or The typemark created.
+
+mkVectorTy (VecType len elHType) = do
+  typesMap <- MonadState.get tsTypes
+  elTyTmMaybe <- vhdlTyMaybe elHType
+  case elTyTmMaybe of
+    (Just elTyTm) -> do
+      let ty_id = mkVHDLExtId $ "vector-"++ (AST.fromVHDLId elTyTm) ++ "-0_to_" ++ (show len)
+      let range = AST.ConstraintIndex $ AST.IndexConstraint [AST.ToRange (AST.PrimLit "0") (AST.PrimLit $ show (len - 1))]
+      let existing_uvec_ty = fmap (fmap fst) $ Map.lookup (UVecType elHType) typesMap
+      case existing_uvec_ty of
+        Just (Just t) -> do
+          let ty_def = AST.SubtypeIn t (Just range)
+          return (Just (ty_id, Just $ Right ty_def))
+        Nothing -> do
+          let vec_id  = mkVHDLExtId $ "vector_" ++ (AST.fromVHDLId elTyTm)
+          let vec_def = AST.TDA $ AST.UnconsArrayDef [tfvec_indexTM] elTyTm
+          MonadState.modify tsTypes (Map.insert (UVecType elHType) (Just (vec_id, (Just $ Left vec_def))))
+          MonadState.modify tsTypeDecls (\typedefs -> typedefs ++ [mktydecl (vec_id, (Just $ Left vec_def))])
+          let vecShowFuns = mkVectorShow elTyTm vec_id
+          mapM_ (\(id, subprog) -> MonadState.modify tsTypeFuns $ Map.insert (UVecType elHType, id) ((mkVHDLExtId id), subprog)) vecShowFuns
+          let ty_def = AST.SubtypeIn vec_id (Just range)
+          return (Just (ty_id, Just $ Right ty_def))
+    -- Vector of empty elements becomes empty itself.
+    Nothing -> return Nothing
+mkVectorTy htype = error $ "\nVHDLTools.mkVectorTy: Called for HType that is not a VecType: " ++ show htype
+
+mkNaturalTy ::
+  Int -- ^ The minimum bound (> 0)
+  -> Int -- ^ The maximum bound (> minimum bound)
+  -> TypeSession TypeMapRec
+      -- ^ An error message or The typemark created.
+mkNaturalTy min_bound max_bound = do
+  let bitsize = floor (logBase 2 (fromInteger (toInteger max_bound)))
+  let ty_id = mkVHDLExtId $ "natural_" ++ (show min_bound) ++ "_to_" ++ (show max_bound)
+  let range = AST.ConstraintIndex $ AST.IndexConstraint [AST.ToRange (AST.PrimLit $ show min_bound) (AST.PrimLit $ show bitsize)]
+  let ty_def = AST.SubtypeIn unsignedTM (Just range)
+  return (Just (ty_id, Just $ Right ty_def))
+
+mkUnsignedTy ::
+  Int -- ^ Haskell type of the unsigned integer
+  -> TypeSession TypeMapRec
+mkUnsignedTy size = do
+  let ty_id = mkVHDLExtId $ "unsigned_" ++ show (size - 1)
+  let range = AST.ConstraintIndex $ AST.IndexConstraint [AST.ToRange (AST.PrimLit "0") (AST.PrimLit $ show (size - 1))]
+  let ty_def = AST.SubtypeIn unsignedTM (Just range)
+  return (Just (ty_id, Just $ Right ty_def))
+  
+mkSignedTy ::
+  Int -- ^ Haskell type of the signed integer
+  -> TypeSession TypeMapRec
+mkSignedTy size = do
+  let ty_id = mkVHDLExtId $ "signed_" ++ show (size - 1)
+  let range = AST.ConstraintIndex $ AST.IndexConstraint [AST.ToRange (AST.PrimLit "0") (AST.PrimLit $ show (size - 1))]
+  let ty_def = AST.SubtypeIn signedTM (Just range)
+  return (Just (ty_id, Just $ Right ty_def))
+
+-- Finds the field labels for VHDL type generated for the given Core type,
+-- which must result in a record type.
+getFieldLabels :: Type.Type -> TypeSession [AST.VHDLId]
+getFieldLabels ty = do
+  -- Ensure that the type is generated (but throw away it's VHDLId)
+  let error_msg = "\nVHDLTools.getFieldLabels: Can not get field labels, because: " ++ pprString ty ++ "can not be generated." 
+  vhdlTy error_msg ty
+  -- Get the types map, lookup and unpack the VHDL TypeDef
+  types <- MonadState.get tsTypes
+  -- Assume the type for which we want labels is really translatable
+  htype <- mkHType error_msg ty
+  case Map.lookup htype types of
+    Nothing -> error $ "\nVHDLTools.getFieldLabels: Type not found? This should not happen!\nLooking for type: " ++ (pprString ty) ++ "\nhtype: " ++ (show htype) 
+    Just Nothing -> return [] -- The type is empty
+    Just (Just (_, Just (Left (AST.TDR (AST.RecordTypeDef elems))))) -> return $ map (\(AST.ElementDec id _) -> id) elems
+    Just (Just (_, Just vty)) -> error $ "\nVHDLTools.getFieldLabels: Type not a record type? This should not happen!\nLooking for type: " ++ pprString (ty) ++ "\nhtype: " ++ (show htype) ++ "\nFound type: " ++ (show vty)
+    
+mktydecl :: (AST.VHDLId, Maybe (Either AST.TypeDef AST.SubtypeIn)) -> Maybe AST.PackageDecItem
+mytydecl (_, Nothing) = Nothing
+mktydecl (ty_id, Just (Left ty_def)) = Just $ AST.PDITD $ AST.TypeDec ty_id ty_def
+mktydecl (ty_id, Just (Right ty_def)) = Just $ AST.PDISD $ AST.SubtypeDec ty_id ty_def
+
+mkTupleShow :: 
+  [AST.TypeMark] -- ^ type of each tuple element
+  -> AST.TypeMark -- ^ type of the tuple
+  -> AST.SubProgBody
+mkTupleShow elemTMs tupleTM = AST.SubProgBody showSpec [] [showExpr]
+  where
+    tupPar    = AST.unsafeVHDLBasicId "tup"
+    showSpec  = AST.Function showId [AST.IfaceVarDec tupPar tupleTM] stringTM
+    showExpr  = AST.ReturnSm (Just $
+                  AST.PrimLit "'('" AST.:&: showMiddle AST.:&: AST.PrimLit "')'")
+      where
+        showMiddle = if null elemTMs then
+            AST.PrimLit "''"
+          else
+            foldr1 (\e1 e2 -> e1 AST.:&: AST.PrimLit "','" AST.:&: e2) $
+              map ((genExprFCall showId).
+                    AST.PrimName .
+                    AST.NSelected .
+                    (AST.NSimple tupPar AST.:.:).
+                    tupVHDLSuffix)
+                  (take tupSize recordlabels)
+    recordlabels = map (\c -> mkVHDLBasicId [c]) ['A'..'Z']
+    tupSize = length elemTMs
+
+mkEnumShow ::
+  [AST.VHDLId]
+  -> AST.TypeMark
+  -> AST.SubProgBody
+mkEnumShow elemIds enumTM = AST.SubProgBody showSpec [] [showExpr]
+  where
+    enumPar    = AST.unsafeVHDLBasicId "enum"
+    showSpec  = AST.Function showId [AST.IfaceVarDec enumPar enumTM] stringTM
+    showExpr  = AST.ReturnSm (Just $
+                  AST.PrimLit (show $ tail $ init $ AST.fromVHDLId enumTM))
+
+mkVectorShow ::
+  AST.TypeMark -- ^ elemtype
+  -> AST.TypeMark -- ^ vectype
+  -> [(String,AST.SubProgBody)]
+mkVectorShow elemTM vectorTM = 
+  [ (headId, AST.SubProgBody headSpec []                   [headExpr])
+  , (tailId, AST.SubProgBody tailSpec [AST.SPVD tailVar]   [tailExpr, tailRet])
+  , (showIdString, AST.SubProgBody showSpec [AST.SPSB doShowDef] [showRet])
+  ]
+  where
+    vecPar  = AST.unsafeVHDLBasicId "vec"
+    resId   = AST.unsafeVHDLBasicId "res"
+    headSpec = AST.Function (mkVHDLExtId headId) [AST.IfaceVarDec vecPar vectorTM] elemTM
+    -- return vec(0);
+    headExpr = AST.ReturnSm (Just (AST.PrimName $ AST.NIndexed (AST.IndexedName 
+                    (AST.NSimple vecPar) [AST.PrimLit "0"])))
+    vecSlice init last =  AST.PrimName (AST.NSlice 
+                                      (AST.SliceName 
+                                            (AST.NSimple vecPar) 
+                                            (AST.ToRange init last)))
+    tailSpec = AST.Function (mkVHDLExtId tailId) [AST.IfaceVarDec vecPar vectorTM] vectorTM
+       -- variable res : fsvec_x (0 to vec'length-2); 
+    tailVar = 
+         AST.VarDec resId 
+                (AST.SubtypeIn vectorTM
+                  (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
+                   [AST.ToRange (AST.PrimLit "0")
+                            (AST.PrimName (AST.NAttribute $ 
+                              AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:-:
+                                (AST.PrimLit "2"))   ]))
+                Nothing       
+       -- res AST.:= vec(1 to vec'length-1)
+    tailExpr = AST.NSimple resId AST.:= (vecSlice 
+                               (AST.PrimLit "1") 
+                               (AST.PrimName (AST.NAttribute $ 
+                                  AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) 
+                                                             AST.:-: AST.PrimLit "1"))
+    tailRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
+    showSpec  = AST.Function showId [AST.IfaceVarDec vecPar vectorTM] stringTM
+    doShowId  = AST.unsafeVHDLExtId "doshow"
+    doShowDef = AST.SubProgBody doShowSpec [] [doShowRet]
+      where doShowSpec = AST.Function doShowId [AST.IfaceVarDec vecPar vectorTM] 
+                                           stringTM
+            -- case vec'len is
+            --  when  0 => return "";
+            --  when  1 => return head(vec);
+            --  when others => return show(head(vec)) & ',' &
+            --                        doshow (tail(vec));
+            -- end case;
+            doShowRet = 
+              AST.CaseSm (AST.PrimName (AST.NAttribute $ 
+                          AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing))
+              [AST.CaseSmAlt [AST.ChoiceE $ AST.PrimLit "0"] 
+                         [AST.ReturnSm (Just $ AST.PrimLit "\"\"")],
+               AST.CaseSmAlt [AST.ChoiceE $ AST.PrimLit "1"] 
+                         [AST.ReturnSm (Just $ 
+                          genExprFCall showId 
+                               (genExprFCall (mkVHDLExtId headId) (AST.PrimName $ AST.NSimple vecPar)) )],
+               AST.CaseSmAlt [AST.Others] 
+                         [AST.ReturnSm (Just $ 
+                           genExprFCall showId 
+                             (genExprFCall (mkVHDLExtId headId) (AST.PrimName $ AST.NSimple vecPar)) AST.:&:
+                           AST.PrimLit "','" AST.:&:
+                           genExprFCall doShowId 
+                             (genExprFCall (mkVHDLExtId tailId) (AST.PrimName $ AST.NSimple vecPar)) ) ]]
+    -- return '<' & doshow(vec) & '>';
+    showRet =  AST.ReturnSm (Just $ AST.PrimLit "'<'" AST.:&:
+                               genExprFCall doShowId (AST.PrimName $ AST.NSimple vecPar) AST.:&:
+                               AST.PrimLit "'>'" )
+
+mkBuiltInShow :: [AST.SubProgBody]
+mkBuiltInShow = [ AST.SubProgBody showBitSpec [] [showBitExpr]
+                , AST.SubProgBody showBoolSpec [] [showBoolExpr]
+                , AST.SubProgBody showSingedSpec [] [showSignedExpr]
+                , AST.SubProgBody showUnsignedSpec [] [showUnsignedExpr]
+                -- , AST.SubProgBody showNaturalSpec [] [showNaturalExpr]
+                ]
+  where
+    bitPar      = AST.unsafeVHDLBasicId "s"
+    boolPar     = AST.unsafeVHDLBasicId "b"
+    signedPar   = AST.unsafeVHDLBasicId "sint"
+    unsignedPar = AST.unsafeVHDLBasicId "uint"
+    -- naturalPar  = AST.unsafeVHDLBasicId "nat"
+    showBitSpec = AST.Function showId [AST.IfaceVarDec bitPar std_logicTM] stringTM
+    -- if s = '1' then return "'1'" else return "'0'"
+    showBitExpr = AST.IfSm (AST.PrimName (AST.NSimple bitPar) AST.:=: AST.PrimLit "'1'")
+                        [AST.ReturnSm (Just $ AST.PrimLit "\"High\"")]
+                        []
+                        (Just $ AST.Else [AST.ReturnSm (Just $ AST.PrimLit "\"Low\"")])
+    showBoolSpec = AST.Function showId [AST.IfaceVarDec boolPar booleanTM] stringTM
+    -- if b then return "True" else return "False"
+    showBoolExpr = AST.IfSm (AST.PrimName (AST.NSimple boolPar))
+                        [AST.ReturnSm (Just $ AST.PrimLit "\"True\"")]
+                        []
+                        (Just $ AST.Else [AST.ReturnSm (Just $ AST.PrimLit "\"False\"")])
+    showSingedSpec = AST.Function showId [AST.IfaceVarDec signedPar signedTM] stringTM
+    showSignedExpr =  AST.ReturnSm (Just $
+                        AST.PrimName $ AST.NAttribute $ AST.AttribName (AST.NSimple integerId) 
+                        (AST.NIndexed $ AST.IndexedName (AST.NSimple imageId) [signToInt]) Nothing )
+                      where
+                        signToInt = genExprFCall (mkVHDLBasicId toIntegerId) (AST.PrimName $ AST.NSimple signedPar)
+    showUnsignedSpec =  AST.Function showId [AST.IfaceVarDec unsignedPar unsignedTM] stringTM
+    showUnsignedExpr =  AST.ReturnSm (Just $
+                          AST.PrimName $ AST.NAttribute $ AST.AttribName (AST.NSimple integerId) 
+                          (AST.NIndexed $ AST.IndexedName (AST.NSimple imageId) [unsignToInt]) Nothing )
+                        where
+                          unsignToInt = genExprFCall (mkVHDLBasicId toIntegerId) (AST.PrimName $ AST.NSimple unsignedPar)
+    -- showNaturalSpec = AST.Function showId [AST.IfaceVarDec naturalPar naturalTM] stringTM
+    -- showNaturalExpr = AST.ReturnSm (Just $
+    --                     AST.PrimName $ AST.NAttribute $ AST.AttribName (AST.NSimple integerId)
+    --                     (AST.NIndexed $ AST.IndexedName (AST.NSimple imageId) [AST.PrimName $ AST.NSimple $ naturalPar]) Nothing )
+                      
+  
+genExprFCall :: AST.VHDLId -> AST.Expr -> AST.Expr
+genExprFCall fName args = 
+   AST.PrimFCall $ AST.FCall (AST.NSimple fName)  $
+             map (\exp -> Nothing AST.:=>: AST.ADExpr exp) [args] 
+
+genExprPCall2 :: AST.VHDLId -> AST.Expr -> AST.Expr -> AST.SeqSm             
+genExprPCall2 entid arg1 arg2 =
+        AST.ProcCall (AST.NSimple entid) $
+         map (\exp -> Nothing AST.:=>: AST.ADExpr exp) [arg1,arg2]
+
+mkSigDec :: CoreSyn.CoreBndr -> TranslatorSession (Maybe AST.SigDec)
+mkSigDec bndr = do
+  let error_msg = "\nVHDL.mkSigDec: Can not make signal declaration for type: \n" ++ pprString bndr 
+  type_mark_maybe <- MonadState.lift tsType $ vhdlTy error_msg (Var.varType bndr)
+  case type_mark_maybe of
+    Just type_mark -> return $ Just (AST.SigDec (varToVHDLId bndr) type_mark Nothing)
+    Nothing -> return Nothing
+
+-- | Does the given thing have a non-empty type?
+hasNonEmptyType :: (TypedThing t, Outputable.Outputable t) => 
+  t -> TranslatorSession Bool
+hasNonEmptyType thing = MonadState.lift tsType $ isJustM (vhdlTy "hasNonEmptyType: Non representable type?" thing)
diff --git a/clash/CLasH/VHDL/VHDLTypes.hs b/clash/CLasH/VHDL/VHDLTypes.hs
new file mode 100644 (file)
index 0000000..38ccc97
--- /dev/null
@@ -0,0 +1,24 @@
+--
+-- Some types used by the VHDL module.
+--
+module CLasH.VHDL.VHDLTypes where
+
+-- VHDL imports
+import qualified Language.VHDL.AST as AST
+
+-- 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   :: [Port], -- ^ A port for each non-empty function argument
+  ent_res    :: Maybe Port, -- ^ The output port
+  ent_dec    :: AST.EntityDec -- ^ The complete entity declaration
+} deriving (Show);
+
+type Architecture = AST.ArchBody
+
+-- vim: set ts=8 sw=2 sts=2 expandtab:
diff --git a/clash/Data/Param/Index.hs b/clash/Data/Param/Index.hs
new file mode 100644 (file)
index 0000000..f31b1f8
--- /dev/null
@@ -0,0 +1,104 @@
+{-# LANGUAGE  TypeFamilies, TypeOperators, ScopedTypeVariables, FlexibleInstances, TemplateHaskell, Rank2Types, FlexibleContexts #-}
+module Data.Param.Index
+  ( Index
+  , fromNaturalT
+  , fromUnsigned
+  , rangeT
+  ) where
+
+import Language.Haskell.TH
+import Language.Haskell.TH.Syntax (Lift(..))    
+import Data.Bits
+import Types
+import Types.Data.Num.Decimal.Literals.TH
+
+import Data.Param.Integer
+
+instance NaturalT nT => Lift (Index nT) where
+  lift (Index i) = sigE [| (Index i) |] (decIndexT (fromIntegerT (undefined :: nT)))
+
+decIndexT :: Integer -> Q Type
+decIndexT n = appT (conT (''Index)) (decLiteralT n)
+
+fromNaturalT :: ( NaturalT n
+                , NaturalT upper
+                , (n :<=: upper) ~ True ) => n -> Index upper
+fromNaturalT x = Index (fromIntegerT x)
+
+fromUnsigned ::
+  ( NaturalT nT
+  , Integral (Unsigned nT)
+  ) => Unsigned nT -> Index ((Pow2 nT) :-: D1)
+fromUnsigned unsigned = Index (toInteger unsigned)
+
+rangeT :: Index nT -> nT
+rangeT _ = undefined
+
+instance NaturalT nT => Eq (Index nT) where
+    (Index x) == (Index y) = x == y
+    (Index x) /= (Index y) = x /= y
+    
+instance NaturalT nT => Show (Index nT) where
+    showsPrec prec n =
+        showsPrec prec $ toInteger n
+instance NaturalT nT => Ord (Index nT) where
+    a `compare` b = toInteger a `compare` toInteger b 
+        
+instance NaturalT nT => Bounded (Index nT) where
+    minBound = 0
+    maxBound = Index (fromIntegerT (undefined :: nT))
+        
+instance NaturalT nT => Enum (Index nT) where
+    succ x
+       | x == maxBound  = error $ "Enum.succ{Index " ++ show (fromIntegerT (undefined :: nT)) ++ "}: tried to take `succ' of maxBound"
+       | otherwise      = x + 1
+    pred x
+       | x == minBound  = error $ "Enum.succ{Index " ++ show (fromIntegerT (undefined :: nT)) ++ "}: tried to take `pred' of minBound"
+       | otherwise      = x - 1
+    
+    fromEnum (Index x)
+        | x > toInteger (maxBound :: Int) =
+            error $ "Enum.fromEnum{Index " ++ show (fromIntegerT (undefined :: nT)) ++ "}: tried to take `fromEnum' on Index greater than maxBound :: Int"
+        | x < toInteger (minBound :: Int) =
+            error $ "Enum.fromEnum{Index " ++ show (fromIntegerT (undefined :: nT)) ++ "}: tried to take `fromEnum' on Index smaller than minBound :: Int"
+        | otherwise =
+            fromInteger x
+    toEnum x
+        | x > fromIntegral (maxBound :: Index nT) =
+            error $ "Enum.fromEnum{Index " ++ show (fromIntegerT (undefined :: nT)) ++ "}: tried to take `fromEnum' on Index greater than maxBound :: Index " ++ show (fromIntegerT (undefined :: nT))
+        | x < fromIntegral (minBound :: Index nT) =
+            error $ "Enum.fromEnum{Index " ++ show (fromIntegerT (undefined :: nT)) ++ "}: tried to take `fromEnum' on Index smaller than minBound :: Index " ++ show (fromIntegerT (undefined :: nT))
+        | otherwise =
+            fromInteger $ toInteger x
+    
+instance NaturalT nT => Num (Index nT) where
+    (Index a) + (Index b) =
+        fromInteger $ a + b
+    (Index a) * (Index b) =
+        fromInteger $ a * b 
+    (Index a) - (Index b) =
+        fromInteger $ a - b
+    fromInteger n
+      | n > fromIntegerT (undefined :: nT) =
+        error $ "Num.fromInteger{Index " ++ show (fromIntegerT (undefined :: nT)) ++ "}: tried to make Index larger than " ++ show (fromIntegerT (undefined :: nT)) ++ ", n: " ++ show n
+    fromInteger n
+      | n < 0 =
+        error $ "Num.fromInteger{Index " ++ show (fromIntegerT (undefined :: nT)) ++ "}: tried to make Index smaller than 0, n: " ++ show n
+    fromInteger n =
+        Index n
+    abs s = s
+    signum s
+      | s == 0 =
+          0
+      | otherwise =
+          1
+
+instance NaturalT nT => Real (Index nT) where
+    toRational n = toRational $ toInteger n
+
+instance NaturalT nT => Integral (Index nT) where
+    a `quotRem` b =
+        let (quot, rem) = toInteger a `quotRem` toInteger b
+        in (fromInteger quot, fromInteger rem)
+    toInteger s@(Index x) = x
diff --git a/clash/Data/Param/Integer.hs b/clash/Data/Param/Integer.hs
new file mode 100644 (file)
index 0000000..b4b1ec8
--- /dev/null
@@ -0,0 +1,13 @@
+module Data.Param.Integer
+  ( Signed(..)
+  , Unsigned(..)
+  , Index (..)
+  ) where
+
+import Types
+
+newtype (NaturalT nT) => Signed nT = Signed Integer
+
+newtype (NaturalT nT) => Unsigned nT = Unsigned Integer
+
+newtype (NaturalT upper) => Index upper = Index Integer
\ No newline at end of file
diff --git a/clash/Data/Param/Signed.hs b/clash/Data/Param/Signed.hs
new file mode 100644 (file)
index 0000000..26ac677
--- /dev/null
@@ -0,0 +1,172 @@
+{-# LANGUAGE  TypeFamilies, TypeOperators, ScopedTypeVariables, FlexibleInstances, TemplateHaskell, Rank2Types, FlexibleContexts #-}
+module Data.Param.Signed
+  ( Signed
+  , resize
+  ) where
+
+import Language.Haskell.TH
+import Language.Haskell.TH.Syntax (Lift(..))
+import Data.Bits
+import Types
+import Types.Data.Num.Decimal.Literals.TH
+
+import Data.Param.Integer
+
+instance NaturalT nT => Lift (Signed nT) where
+  lift (Signed i) = sigE [| (Signed i) |] (decSignedT (fromIntegerT (undefined :: nT)))
+
+decSignedT :: Integer -> Q Type
+decSignedT n = appT (conT (''Signed)) (decLiteralT n)
+
+resize :: (NaturalT nT, NaturalT nT') => Signed nT -> Signed nT'
+resize a = fromInteger (toInteger a)
+
+sizeT :: Signed nT
+      -> nT
+sizeT _ = undefined
+
+mask :: forall nT . NaturalT nT
+     => nT
+     -> Integer
+mask _ = bit (fromIntegerT (undefined :: nT)) - 1
+
+signBit :: forall nT . NaturalT nT
+        => nT
+        -> Int
+signBit _ = fromIntegerT (undefined :: nT) - 1
+
+isNegative :: forall nT . NaturalT nT
+           => Signed nT
+           -> Bool
+isNegative (Signed x) =
+    testBit x $ signBit (undefined :: nT)
+
+instance NaturalT nT => Eq (Signed nT) where
+    (Signed x) == (Signed y) = x == y
+    (Signed x) /= (Signed y) = x /= y
+
+instance NaturalT nT => Show (Signed nT) where
+    showsPrec prec n =
+        showsPrec prec $ toInteger n
+
+instance NaturalT nT => Read (Signed nT) where
+    readsPrec prec str =
+        [ (fromInteger n, str)
+        | (n, str) <- readsPrec prec str ]
+
+instance NaturalT nT => Ord (Signed nT) where
+    a `compare` b = toInteger a `compare` toInteger b
+
+instance NaturalT nT => Bounded (Signed nT) where
+    minBound = Signed $ negate $ 1 `shiftL` (fromIntegerT (undefined :: nT) - 1)
+    maxBound = Signed $ (1 `shiftL` (fromIntegerT (undefined :: nT) - 1)) - 1
+
+instance NaturalT nT => Enum (Signed nT) where
+    succ x
+       | x == maxBound  = error $ "Enum.succ{Signed " ++ show (fromIntegerT (undefined :: nT)) ++ "}: tried to take `succ' of maxBound"
+       | otherwise      = x + 1
+    pred x
+       | x == minBound  = error $ "Enum.succ{Signed " ++ show (fromIntegerT (undefined :: nT)) ++ "}: tried to take `pred' of minBound"
+       | otherwise      = x - 1
+    
+    fromEnum (Signed x)
+        | x > toInteger (maxBound :: Int) =
+            error $ "Enum.fromEnum{Signed " ++ show (fromIntegerT (undefined :: nT)) ++ "}: tried to take `fromEnum' on Signed greater than maxBound :: Int"
+        | x < toInteger (minBound :: Int) =
+            error $ "Enum.fromEnum{Signed " ++ show (fromIntegerT (undefined :: nT)) ++ "}: tried to take `fromEnum' on Signed smaller than minBound :: Int"
+        | otherwise =
+            fromInteger x
+    toEnum x
+        | x' > toInteger (maxBound :: Signed nT) =
+            error $ "Enum.fromEnum{Signed " ++ show (fromIntegerT (undefined :: nT)) ++ "}: tried to take `fromEnum' on Signed greater than maxBound :: Signed " ++ show (fromIntegerT (undefined :: nT))
+        | x' < toInteger (minBound :: Signed nT) =
+            error $ "Enum.fromEnum{Signed " ++ show (fromIntegerT (undefined :: nT)) ++ "}: tried to take `fromEnum' on Signed smaller than minBound :: Signed " ++ show (fromIntegerT (undefined :: nT))
+        | otherwise =
+            fromInteger x'
+            where x' = toInteger x
+
+instance NaturalT nT => Num (Signed nT) where
+    (Signed a) + (Signed b) =
+        fromInteger $ a + b
+    (Signed a) * (Signed b) =
+        fromInteger $ a * b
+    negate (Signed n) =
+        fromInteger $ (n `xor` mask (undefined :: nT)) + 1
+    a - b =
+        a + (negate b)
+    
+    fromInteger n
+      | n > 0 =
+        Signed $ n .&. mask (undefined :: nT)
+    fromInteger n
+      | n < 0 =
+        negate $ fromInteger $ negate n
+    fromInteger _ =
+        Signed 0
+    
+    abs s
+      | isNegative s =
+          negate s
+      | otherwise =
+          s
+    signum s
+      | isNegative s =
+          -1
+      | s == 0 =
+          0
+      | otherwise =
+          1
+
+instance NaturalT nT => Real (Signed nT) where
+    toRational n = toRational $ toInteger n
+
+instance NaturalT nT => Integral (Signed nT) where
+    a `quot` b =
+        fromInteger $ toInteger a `quot` toInteger b
+    a `rem` b =
+        fromInteger $ toInteger a `rem` toInteger b
+    a `div` b =
+        fromInteger $ toInteger a `div` toInteger b
+    a `mod` b =
+        fromInteger $ toInteger a `mod` toInteger b
+    a `quotRem` b =
+        let (quot, rem) = toInteger a `quotRem` toInteger b
+        in (fromInteger quot, fromInteger rem)
+    a `divMod` b =
+        let (div, mod) = toInteger a `divMod` toInteger b
+        in (fromInteger div, fromInteger mod)
+    toInteger s@(Signed x) =
+        if isNegative s
+           then let Signed x' = negate s in negate x'
+           else x
+
+instance NaturalT nT => Bits (Signed nT) where
+    (Signed a) .&. (Signed b) = Signed $ a .&. b
+    (Signed a) .|. (Signed b) = Signed $ a .|. b
+    (Signed a) `xor` Signed b = Signed $ a `xor` b
+    complement (Signed x) = Signed $ x `xor` mask (undefined :: nT)
+    (Signed x) `shiftL` b
+      | b < 0 = error $ "Bits.shiftL{Signed " ++ show (fromIntegerT (undefined :: nT)) ++ "}: tried to shift by negative amount"
+      | otherwise =
+        Signed $ mask (undefined :: nT) .&. (x `shiftL` b)
+    s@(Signed x) `shiftR` b
+      | b < 0 = error $ "Bits.shiftR{Signed " ++ show (fromIntegerT (undefined :: nT)) ++ "}: tried to shift by negative amount"
+      | isNegative s =
+        Signed $ mask (undefined :: nT) .&.
+            ((x `shiftR` b) .|. (mask (undefined :: nT) `shiftL` (fromIntegerT (undefined :: nT) - b)))
+      | otherwise =
+        Signed $ (mask (undefined :: nT)) .&. (x `shiftR` b)
+    (Signed a) `rotateL` b
+      | b < 0 =
+        error $ "Bits.rotateL{Signed " ++ show (fromIntegerT (undefined :: nT)) ++ "}: tried to rotate by negative amount"
+      | otherwise =
+        Signed $ mask (undefined :: nT) .&.
+            ((a `shiftL` b) .|. (a `shiftR` (fromIntegerT (undefined :: nT) - b)))
+    (Signed a) `rotateR` b
+      | b < 0 =
+        error $ "Bits.rotateR{Signed " ++ show (fromIntegerT (undefined :: nT)) ++ "}: tried to rotate by negative amount"
+      | otherwise =
+        Signed $ mask (undefined :: nT) .&.
+            ((a `shiftR` b) .|. (a `shiftL` (fromIntegerT (undefined :: nT) - b)))
+    bitSize _ = fromIntegerT (undefined :: nT)
+    isSigned _ = True
diff --git a/clash/Data/Param/Unsigned.hs b/clash/Data/Param/Unsigned.hs
new file mode 100644 (file)
index 0000000..aae032d
--- /dev/null
@@ -0,0 +1,157 @@
+{-# LANGUAGE  TypeFamilies, TypeOperators, ScopedTypeVariables, FlexibleInstances, TemplateHaskell, Rank2Types, FlexibleContexts #-}
+module Data.Param.Unsigned
+    ( Unsigned
+    , resize
+    , fromIndex
+    ) where
+
+import Language.Haskell.TH
+import Language.Haskell.TH.Syntax (Lift(..))
+import Data.Bits
+import Types
+import Types.Data.Num.Decimal.Literals.TH
+
+import Data.Param.Integer
+
+instance NaturalT nT => Lift (Unsigned nT) where
+  lift (Unsigned i) = sigE [| (Unsigned i) |] (decUnsignedT (fromIntegerT (undefined :: nT)))
+
+decUnsignedT :: Integer -> Q Type
+decUnsignedT n = appT (conT (''Unsigned)) (decLiteralT n)
+
+fromIndex ::
+  ( NaturalT nT
+  , NaturalT nT'
+  , ((Pow2 nT') :>: nT) ~ True
+  , Integral (Index nT)
+  ) => Index nT -> Unsigned nT'
+fromIndex index = Unsigned (toInteger index)
+
+resize :: (NaturalT nT, NaturalT nT') => Unsigned nT -> Unsigned nT'
+resize a = fromInteger (toInteger a)
+
+sizeT :: Unsigned nT
+      -> nT
+sizeT _ = undefined
+
+mask :: forall nT . NaturalT nT
+     => nT
+     -> Integer
+mask _ = bit (fromIntegerT (undefined :: nT)) - 1
+
+instance NaturalT nT => Eq (Unsigned nT) where
+    (Unsigned x) == (Unsigned y) = x == y
+    (Unsigned x) /= (Unsigned y) = x /= y
+
+instance NaturalT nT => Show (Unsigned nT) where
+    showsPrec prec n =
+        showsPrec prec $ toInteger n
+
+instance NaturalT nT => Read (Unsigned nT) where
+    readsPrec prec str =
+        [ (fromInteger n, str)
+        | (n, str) <- readsPrec prec str ]
+
+instance NaturalT nT => Ord (Unsigned nT) where
+    a `compare` b = toInteger a `compare` toInteger b
+
+instance NaturalT nT => Bounded (Unsigned nT) where
+    minBound = 0
+    maxBound = Unsigned $ (1 `shiftL` (fromIntegerT (undefined :: nT))) - 1
+
+instance NaturalT nT => Enum (Unsigned nT) where
+    succ x
+       | x == maxBound  = error $ "Enum.succ{Unsigned " ++ show (fromIntegerT (undefined :: nT)) ++ "}: tried to take `succ' of maxBound"
+       | otherwise      = x + 1
+    pred x
+       | x == minBound  = error $ "Enum.succ{Unsigned " ++ show (fromIntegerT (undefined :: nT)) ++ "}: tried to take `pred' of minBound"
+       | otherwise      = x - 1
+    
+    fromEnum (Unsigned x)
+        | x > toInteger (maxBound :: Int) =
+            error $ "Enum.fromEnum{Unsigned " ++ show (fromIntegerT (undefined :: nT)) ++ "}: tried to take `fromEnum' on Unsigned greater than maxBound :: Int"
+        | x < toInteger (minBound :: Int) =
+            error $ "Enum.fromEnum{Unsigned " ++ show (fromIntegerT (undefined :: nT)) ++ "}: tried to take `fromEnum' on Unsigned smaller than minBound :: Int"
+        | otherwise =
+            fromInteger x
+    toEnum x
+        | x > fromIntegral (maxBound :: Unsigned nT) =
+            error $ "Enum.fromEnum{Unsigned " ++ show (fromIntegerT (undefined :: nT)) ++ "}: tried to take `fromEnum' on Unsigned greater than maxBound :: Unsigned " ++ show (fromIntegerT (undefined :: nT))
+        | x < fromIntegral (minBound :: Unsigned nT) =
+            error $ "Enum.fromEnum{Unsigned " ++ show (fromIntegerT (undefined :: nT)) ++ "}: tried to take `fromEnum' on Unsigned smaller than minBound :: Unsigned " ++ show (fromIntegerT (undefined :: nT))
+        | otherwise =
+            fromInteger $ toInteger x
+
+instance NaturalT nT => Num (Unsigned nT) where
+    (Unsigned a) + (Unsigned b) =
+        fromInteger $ a + b
+    (Unsigned a) * (Unsigned b) =
+        fromInteger $ a * b
+    negate s@(Unsigned n) =
+        fromInteger $ (n `xor` mask (sizeT s)) + 1
+    a - b =
+        a + (negate b)
+
+    fromInteger n
+      | n > 0 =
+        Unsigned $ n .&. mask (undefined :: nT)
+    fromInteger n
+      | n < 0 =
+        negate $ fromInteger $ negate n
+    fromInteger _ =
+        Unsigned 0
+
+    abs s = s
+    signum s
+      | s == 0 =
+          0
+      | otherwise =
+          1
+
+instance NaturalT nT => Real (Unsigned nT) where
+    toRational n = toRational $ toInteger n
+
+instance NaturalT nT => Integral (Unsigned nT) where
+    a `quot` b =
+        fromInteger $ toInteger a `quot` toInteger b
+    a `rem` b =
+        fromInteger $ toInteger a `rem` toInteger b
+    a `div` b =
+        fromInteger $ toInteger a `div` toInteger b
+    a `mod` b =
+        fromInteger $ toInteger a `mod` toInteger b
+    a `quotRem` b =
+        let (quot, rem) = toInteger a `quotRem` toInteger b
+        in (fromInteger quot, fromInteger rem)
+    a `divMod` b =
+        let (div, mod) = toInteger a `divMod` toInteger b
+        in (fromInteger div, fromInteger mod)
+    toInteger s@(Unsigned x) = x
+
+instance NaturalT nT => Bits (Unsigned nT) where
+    (Unsigned a) .&. (Unsigned b) = Unsigned $ a .&. b
+    (Unsigned a) .|. (Unsigned b) = Unsigned $ a .|. b
+    (Unsigned a) `xor` Unsigned b = Unsigned $ a `xor` b
+    complement (Unsigned x) = Unsigned $ x `xor` mask (undefined :: nT)
+    s@(Unsigned x) `shiftL` b
+      | b < 0 = error $ "Bits.shiftL{Unsigned " ++ show (bitSize s) ++ "}: tried to shift by negative amount"
+      | otherwise =
+        Unsigned $ mask (undefined :: nT) .&. (x `shiftL` b)
+    s@(Unsigned x) `shiftR` b
+      | b < 0 = error $ "Bits.shiftR{Unsigned " ++ show (bitSize s) ++ "}: tried to shift by negative amount"
+      | otherwise =
+        Unsigned $ (x `shiftR` b)
+    s@(Unsigned x) `rotateL` b
+      | b < 0 =
+        error $ "Bits.rotateL{Unsigned " ++ show (bitSize s) ++ "}: tried to rotate by negative amount"
+      | otherwise =
+        Unsigned $ mask (undefined :: nT) .&.
+            ((x `shiftL` b) .|. (x `shiftR` (bitSize s - b)))
+    s@(Unsigned x) `rotateR` b
+      | b < 0 =
+        error $ "Bits.rotateR{Unsigned " ++ show (bitSize s) ++ "}: tried to rotate by negative amount"
+      | otherwise =
+        Unsigned $ mask (undefined :: nT) .&.
+            ((x `shiftR` b) .|. (x `shiftL` (bitSize s - b)))
+    bitSize _ = fromIntegerT (undefined :: nT)
+    isSigned _ = False
diff --git a/clash/Data/Param/Vector.hs b/clash/Data/Param/Vector.hs
new file mode 100644 (file)
index 0000000..32218be
--- /dev/null
@@ -0,0 +1,316 @@
+{-# LANGUAGE StandaloneDeriving, ExistentialQuantification, ScopedTypeVariables, TemplateHaskell, TypeOperators, TypeFamilies #-}
+module Data.Param.Vector
+  ( Vector
+  , empty
+  , (+>)
+  , singleton
+  , vectorTH
+  , unsafeVector
+  , readVector
+  , length
+  , lengthT
+  , fromVector
+  , null
+  , (!)
+  , replace
+  , head
+  , last
+  , init
+  , tail
+  , take
+  , drop
+  , select
+  , (<+)
+  , (++)
+  , map
+  , zipWith
+  , foldl
+  , foldr
+  , zip
+  , unzip
+  , shiftl
+  , shiftr
+  , rotl
+  , rotr
+  , concat
+  , reverse
+  , iterate
+  , iteraten
+  , generate
+  , generaten
+  , copy
+  , copyn
+  , split
+  ) where
+    
+import Types
+import Types.Data.Num
+import Types.Data.Num.Decimal.Literals.TH
+import Data.Param.Index
+
+import Data.Typeable
+import qualified Prelude as P
+import Prelude hiding (
+  null, length, head, tail, last, init, take, drop, (++), map, foldl, foldr,
+  zipWith, zip, unzip, concat, reverse, iterate )
+import qualified Data.Foldable as DF (Foldable, foldr)
+import qualified Data.Traversable as DT (Traversable(traverse))
+import Language.Haskell.TH hiding (Pred)
+import Language.Haskell.TH.Syntax (Lift(..))
+
+newtype (NaturalT s) => Vector s a = Vector {unVec :: [a]}
+  deriving Eq
+
+-- deriving instance (NaturalT s, Typeable s, Data s, Typeable a, Data a) => Data (TFVec s a)
+
+-- ==========================
+-- = Constructing functions =
+-- ==========================
+                                                  
+empty :: Vector D0 a
+empty = Vector []
+
+(+>) :: a -> Vector s a -> Vector (Succ s) a
+x +> (Vector xs) = Vector (x:xs)
+
+infix 5 +>
+
+singleton :: a -> Vector D1 a
+singleton x = x +> empty
+
+-- FIXME: Not the most elegant solution... but it works for now in clash
+vectorTH :: (Lift a) => [a] -> ExpQ
+-- vectorTH xs = sigE [| (TFVec xs) |] (decTFVecT (toInteger (P.length xs)) xs)
+vectorTH [] = [| empty |]
+vectorTH [x] = [| singleton x |]
+vectorTH (x:xs) = [| x +> $(vectorTH xs) |]
+
+unsafeVector :: NaturalT s => s -> [a] -> Vector s a
+unsafeVector l xs
+  | fromIntegerT l /= P.length xs =
+    error (show 'unsafeVector P.++ ": dynamic/static lenght mismatch")
+  | otherwise = Vector xs
+
+readVector :: (Read a, NaturalT s) => String -> Vector s a
+readVector = read
+        
+-- =======================
+-- = Observing functions =
+-- =======================
+length :: forall s a . NaturalT s => Vector s a -> Int
+length _ = fromIntegerT (undefined :: s)
+
+lengthT :: NaturalT s => Vector s a -> s
+lengthT = undefined
+
+fromVector :: NaturalT s => Vector s a -> [a]
+fromVector (Vector xs) = xs
+
+null :: Vector D0 a -> Bool
+null _ = True
+
+(!) ::  ( PositiveT s
+        , NaturalT u
+        , (s :>: u) ~ True) => Vector s a -> Index u -> a
+(Vector xs) ! i = xs !! (fromInteger (toInteger i))
+
+-- ==========================
+-- = Transforming functions =
+-- ==========================
+replace :: (PositiveT s, NaturalT u, (s :>: u) ~ True) =>
+  Vector s a -> Index u -> a -> Vector s a
+replace (Vector xs) i y = Vector $ replace' xs (toInteger i) y
+  where replace' []     _ _ = []
+        replace' (_:xs) 0 y = (y:xs)
+        replace' (x:xs) n y = x : (replace' xs (n-1) y)
+  
+head :: PositiveT s => Vector s a -> a
+head = P.head . unVec
+
+tail :: PositiveT s => Vector s a -> Vector (Pred s) a
+tail = liftV P.tail
+
+last :: PositiveT s => Vector s a -> a
+last = P.last . unVec
+
+init :: PositiveT s => Vector s a -> Vector (Pred s) a
+init = liftV P.init
+
+take :: NaturalT i => i -> Vector s a -> Vector (Min s i) a
+take i = liftV $ P.take (fromIntegerT i)
+
+drop :: NaturalT i => i -> Vector s a -> Vector (s :-: (Min s i)) a
+drop i = liftV $ P.drop (fromIntegerT i)
+
+select :: (NaturalT f, NaturalT s, NaturalT n, (f :<: i) ~ True, 
+          (((s :*: n) :+: f) :<=: i) ~ True) => 
+          f -> s -> n -> Vector i a -> Vector n a
+select f s n = liftV (select' f' s' n')
+  where (f', s', n') = (fromIntegerT f, fromIntegerT s, fromIntegerT n)
+        select' f s n = ((selectFirst0 s n).(P.drop f))
+        selectFirst0 :: Int -> Int -> [a] -> [a]
+        selectFirst0 s n l@(x:_)
+          | n > 0 = x : selectFirst0 s (n-1) (P.drop s l)
+          | otherwise = []
+        selectFirst0 _ 0 [] = []
+
+(<+) :: Vector s a -> a -> Vector (Succ s) a
+(<+) (Vector xs) x = Vector (xs P.++ [x])
+
+(++) :: Vector s a -> Vector s2 a -> Vector (s :+: s2) a
+(++) = liftV2 (P.++)
+
+infixl 5 <+
+infixr 5 ++
+
+map :: (a -> b) -> Vector s a -> Vector s b
+map f = liftV (P.map f)
+
+zipWith :: (a -> b -> c) -> Vector s a -> Vector s b -> Vector s c
+zipWith f = liftV2 (P.zipWith f)
+
+foldl :: (a -> b -> a) -> a -> Vector s b -> a
+foldl f e = (P.foldl f e) . unVec
+
+foldr :: (b -> a -> a) -> a -> Vector s b -> a
+foldr f e = (P.foldr f e) . unVec
+
+zip :: Vector s a -> Vector s b -> Vector s (a, b)
+zip = liftV2 P.zip
+
+unzip :: Vector s (a, b) -> (Vector s a, Vector s b)
+unzip (Vector xs) = let (a,b) = P.unzip xs in (Vector a, Vector b)
+
+shiftl :: (PositiveT s, NaturalT n, n ~ Pred s, s ~ Succ n) => 
+          Vector s a -> a -> Vector s a
+shiftl xs x = x +> init xs
+
+shiftr :: (PositiveT s, NaturalT n, n ~ Pred s, s ~ Succ n) => 
+          Vector s a -> a -> Vector s a
+shiftr xs x = tail xs <+ x
+  
+rotl :: forall s a . NaturalT s => Vector s a -> Vector s a
+rotl = liftV rotl'
+  where vlen = fromIntegerT (undefined :: s)
+        rotl' [] = []
+        rotl' xs = let (i,[l]) = splitAt (vlen - 1) xs
+                   in l : i 
+
+rotr :: NaturalT s => Vector s a -> Vector s a
+rotr = liftV rotr'
+  where
+    rotr' [] = []
+    rotr' (x:xs) = xs P.++ [x] 
+
+concat :: Vector s1 (Vector s2 a) -> Vector (s1 :*: s2) a
+concat = liftV (P.foldr ((P.++).unVec) [])
+
+reverse :: Vector s a -> Vector s a
+reverse = liftV P.reverse
+
+iterate :: NaturalT s => (a -> a) -> a -> Vector s a
+iterate = iteraten (undefined :: s)
+
+iteraten :: NaturalT s => s -> (a -> a) -> a -> Vector s a
+iteraten s f x = let s' = fromIntegerT s in Vector (P.take s' $ P.iterate f x)
+
+generate :: NaturalT s => (a -> a) -> a -> Vector s a
+generate = generaten (undefined :: s)
+
+generaten :: NaturalT s => s -> (a -> a) -> a -> Vector s a
+generaten s f x = let s' = fromIntegerT s in Vector (P.take s' $ P.tail $ P.iterate f x)
+
+copy :: NaturalT s => a -> Vector s a
+copy x = copyn (undefined :: s) x
+
+copyn :: NaturalT s => s -> a -> Vector s a
+copyn s x = iteraten s id x
+
+split :: ( NaturalT s
+         -- , IsEven s ~ True
+         ) => Vector s a -> (Vector (Div2 s) a, Vector (Div2 s) a)
+split (Vector xs) = (Vector (P.take vlen xs), Vector (P.drop vlen xs))
+  where
+    vlen = round ((fromIntegral (P.length xs)) / 2)
+
+-- =============
+-- = Instances =
+-- =============
+instance Show a => Show (Vector s a) where
+  showsPrec _ = showV.unVec
+    where showV []      = showString "<>"
+          showV (x:xs)  = showChar '<' . shows x . showl xs
+                            where showl []      = showChar '>'
+                                  showl (x:xs)  = showChar ',' . shows x .
+                                                  showl xs
+
+instance (Read a, NaturalT nT) => Read (Vector nT a) where
+  readsPrec _ str
+    | all fitsLength possibilities = P.map toReadS possibilities
+    | otherwise = error (fName P.++ ": string/dynamic length mismatch")
+    where 
+      fName = "Data.Param.TFVec.read"
+      expectedL = fromIntegerT (undefined :: nT)
+      possibilities = readVectorList str
+      fitsLength (_, l, _) = l == expectedL
+      toReadS (xs, _, rest) = (Vector xs, rest)
+      
+instance NaturalT s => DF.Foldable (Vector s) where
+ foldr = foldr
+instance NaturalT s => Functor (Vector s) where
+ fmap = map
+
+instance NaturalT s => DT.Traversable (Vector s) where 
+  traverse f = (fmap Vector).(DT.traverse f).unVec
+
+instance (Lift a, NaturalT nT) => Lift (Vector nT a) where
+  lift (Vector xs) = [|  unsafeVectorCoerse
+                         $(decLiteralV (fromIntegerT (undefined :: nT)))
+                          (Vector xs) |]
+
+-- ======================
+-- = Internal Functions =
+-- ======================
+liftV :: ([a] -> [b]) -> Vector nT a -> Vector nT' b
+liftV f = Vector . f . unVec
+
+liftV2 :: ([a] -> [b] -> [c]) -> Vector s a -> Vector s2 b -> Vector s3 c
+liftV2 f a b = Vector (f (unVec a) (unVec b))
+
+splitAtM :: Int -> [a] -> Maybe ([a],[a])
+splitAtM n xs = splitAtM' n [] xs
+  where splitAtM' 0 xs ys = Just (xs, ys)
+        splitAtM' n xs (y:ys) | n > 0 = do
+          (ls, rs) <- splitAtM' (n-1) xs ys
+          return (y:ls,rs)
+        splitAtM' _ _ _ = Nothing
+
+unsafeVectorCoerse :: nT' -> Vector nT a -> Vector nT' a
+unsafeVectorCoerse _ (Vector v) = (Vector v)
+
+readVectorList :: Read a => String -> [([a], Int, String)]
+readVectorList = readParen' False (\r -> [pr | ("<",s) <- lexVector r,
+                                              pr <- readl s])
+  where
+    readl   s = [([],0,t) | (">",t) <- lexVector s] P.++
+                            [(x:xs,1+n,u) | (x,t)       <- reads s,
+                                            (xs, n, u)  <- readl' t]
+    readl'  s = [([],0,t) | (">",t) <- lexVector s] P.++
+                            [(x:xs,1+n,v) | (",",t)   <- lex s,
+                                            (x,u)     <- reads t,
+                                            (xs,n,v)  <- readl' u]
+    readParen' b g  = if b then mandatory else optional
+      where optional r  = g r P.++ mandatory r
+            mandatory r = [(x,n,u) | ("(",s)  <- lexVector r,
+                                      (x,n,t) <- optional s,
+                                      (")",u) <- lexVector t]
+
+-- Custom lexer for FSVecs, we cannot use lex directly because it considers
+-- sequences of < and > as unique lexemes, and that breaks nested FSVecs, e.g.
+-- <<1,2><3,4>>
+lexVector :: ReadS String
+lexVector ('>':rest) = [(">",rest)]
+lexVector ('<':rest) = [("<",rest)]
+lexVector str = lex str
+                                           
diff --git a/clash/LICENSE b/clash/LICENSE
new file mode 100644 (file)
index 0000000..23ebcfd
--- /dev/null
@@ -0,0 +1,25 @@
+Copyright (c) 2009 Christiaan Baaij & Matthijs Kooijman
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the copyright holder nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
diff --git a/clash/Setup.lhs b/clash/Setup.lhs
new file mode 100644 (file)
index 0000000..5bde0de
--- /dev/null
@@ -0,0 +1,3 @@
+#!/usr/bin/env runhaskell
+> import Distribution.Simple
+> main = defaultMain
diff --git a/clash/clash.cabal b/clash/clash.cabal
new file mode 100644 (file)
index 0000000..db16c33
--- /dev/null
@@ -0,0 +1,55 @@
+name:               clash
+version:            0.1.0.1
+build-type:         Simple
+synopsis:           CAES Language for Synchronous Hardware (CLaSH)
+description:        CLaSH is a tool-chain/language to translate subsets of
+                    Haskell to synthesizable VHDL. It does this by translating
+                    the intermediate System Fc (GHC Core) representation to a
+                    VHDL AST, which is then written to file.
+category:           Language, Hardware
+license:            BSD3
+license-file:       LICENSE
+homepage:           http://clash.ewi.utwente.nl/
+package-url:        http://github.com/christiaanb/clash/tree/master/cλash
+copyright:          Copyright (c) 2009-2010 Christiaan Baaij & 
+                    Matthijs Kooijman
+author:             Christiaan Baaij & Matthijs Kooijman
+stability:          alpha
+maintainer:         christiaan.baaij@gmail.com & matthijs@stdin.nl
+Cabal-Version:      >= 1.2
+
+Library
+  build-depends:    ghc >= 6.12 && < 6.13, pretty, vhdl > 0.1, haskell98, syb,
+                    data-accessor >= 0.2.1.3, containers, base >= 4 && < 5, 
+                    transformers >= 0.2, filepath, template-haskell, 
+                    data-accessor-template, data-accessor-transformers, 
+                    prettyclass, directory, tfp, th-lift, time
+                    
+  exposed-modules:  CLasH.HardwareTypes
+                    CLasH.Translator
+                    CLasH.Translator.Annotations
+                    
+  other-modules:    Data.Param.Integer
+                    Data.Param.Signed
+                    Data.Param.Unsigned
+                    Data.Param.Index
+                    Data.Param.Vector
+                    CLasH.Translator.TranslatorTypes
+                    CLasH.Normalize
+                    CLasH.Normalize.NormalizeTypes
+                    CLasH.Normalize.NormalizeTools
+                    CLasH.VHDL
+                    CLasH.VHDL.Constants
+                    CLasH.VHDL.Generate
+                    CLasH.VHDL.Testbench
+                    CLasH.VHDL.VHDLTools
+                    CLasH.VHDL.VHDLTypes
+                    CLasH.Utils
+                    CLasH.Utils.GhcTools
+                    CLasH.Utils.HsTools
+                    CLasH.Utils.Pretty
+                    CLasH.Utils.Core.BinderTools
+                    CLasH.Utils.Core.CoreShow
+                    CLasH.Utils.Core.CoreTools
+                    
+  
diff --git a/clash/ghc-stage b/clash/ghc-stage
new file mode 100644 (file)
index 0000000..9a7456b
--- /dev/null
@@ -0,0 +1,2 @@
+2
+
diff --git a/cλash/CLasH/HardwareTypes.hs b/cλash/CLasH/HardwareTypes.hs
deleted file mode 100644 (file)
index 3b746aa..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-{-# LANGUAGE TemplateHaskell, DeriveDataTypeable, FlexibleContexts, TypeFamilies, TypeOperators #-}
-
-module CLasH.HardwareTypes
-  ( module Types
-  , module Data.Param.TFVec
-  , module Data.RangedWord
-  , module Data.SizedInt
-  , module Data.SizedWord
-  , module Prelude
-  , Bit(..)
-  , State(..)
-  , Vector
-  , resizeInt
-  , resizeWord
-  , hwand
-  , hwor
-  , hwxor
-  , hwnot
-  , RAM
-  , MemState
-  , blockRAM
-  ) where
-
-import qualified Prelude as P
-import Prelude hiding (
-  null, length, head, tail, last, init, take, drop, (++), map, foldl, foldr,
-  zipWith, zip, unzip, concat, reverse, iterate )
-import Types
-import qualified Data.Param.TFVec as TFVec
-import Data.Param.TFVec hiding (TFVec)
-import Data.RangedWord
-import qualified Data.SizedInt as SizedInt
-import Data.SizedInt hiding (resize)
-import qualified Data.SizedWord as SizedWord
-import Data.SizedWord hiding (resize) 
-
-import Language.Haskell.TH.Lift
-import Data.Typeable
-
-newtype State s = State s deriving (P.Show)
-
-type Vector = TFVec.TFVec
-
-resizeInt :: (NaturalT nT, NaturalT nT') => SizedInt nT -> SizedInt nT'
-resizeInt = SizedInt.resize
-
-resizeWord :: (NaturalT nT, NaturalT nT') => SizedWord nT -> SizedWord nT'
-resizeWord = SizedWord.resize
-
--- The plain Bit type
-data Bit = High | Low
-  deriving (P.Show, P.Eq, P.Read, Typeable)
-
-deriveLift1 ''Bit
-
-hwand :: Bit -> Bit -> Bit
-hwor  :: Bit -> Bit -> Bit
-hwxor :: Bit -> Bit -> Bit
-hwnot :: Bit -> Bit
-
-High `hwand` High = High
-_ `hwand` _ = Low
-
-High `hwor` _  = High
-_ `hwor` High  = High
-Low `hwor` Low = Low
-
-High `hwxor` Low = High
-Low `hwxor` High = High
-_ `hwxor` _      = Low
-
-hwnot High = Low
-hwnot Low  = High
-
-type RAM s a          = Vector (s :+: D1) a
-
-type MemState s a      = State (RAM s a)
-
-blockRAM :: 
-  (NaturalT s
-  ,PositiveT (s :+: D1)
-  ,((s :+: D1) :>: s) ~ True ) =>
-  (MemState s a) -> 
-  a ->
-  RangedWord s ->
-  RangedWord s ->
-  Bool -> 
-  ((MemState s a), a )
-blockRAM (State mem) data_in rdaddr wraddr wrenable = 
-  ((State mem'), data_out)
-  where
-    data_out  = mem!rdaddr
-    -- Only write data_in to memory if write is enabled
-    mem' =  if wrenable then
-              replace mem wraddr data_in
-            else
-              mem
diff --git a/cλash/CLasH/Normalize.hs b/cλash/CLasH/Normalize.hs
deleted file mode 100644 (file)
index e97e425..0000000
+++ /dev/null
@@ -1,1047 +0,0 @@
-{-# LANGUAGE PackageImports #-}
---
--- Functions to bring a Core expression in normal form. This module provides a
--- top level function "normalize", and defines the actual transformation passes that
--- are performed.
---
-module CLasH.Normalize (getNormalized, normalizeExpr, splitNormalized) where
-
--- Standard modules
-import Debug.Trace
-import qualified Maybe
-import qualified List
-import qualified "transformers" Control.Monad.Trans as Trans
-import qualified Control.Monad as Monad
-import qualified Control.Monad.Trans.Writer as Writer
-import qualified Data.Accessor.Monad.Trans.State as MonadState
-import qualified Data.Monoid as Monoid
-import qualified Data.Map as Map
-
--- GHC API
-import CoreSyn
-import qualified CoreUtils
-import qualified BasicTypes
-import qualified Type
-import qualified TysWiredIn
-import qualified Id
-import qualified Var
-import qualified Name
-import qualified DataCon
-import qualified VarSet
-import qualified CoreFVs
-import qualified Class
-import qualified MkCore
-import Outputable ( showSDoc, ppr, nest )
-
--- Local imports
-import CLasH.Normalize.NormalizeTypes
-import CLasH.Translator.TranslatorTypes
-import CLasH.Normalize.NormalizeTools
-import CLasH.VHDL.Constants (builtinIds)
-import qualified CLasH.Utils as Utils
-import CLasH.Utils.Core.CoreTools
-import CLasH.Utils.Core.BinderTools
-import CLasH.Utils.Pretty
-
-----------------------------------------------------------------
--- Cleanup transformations
-----------------------------------------------------------------
-
---------------------------------
--- β-reduction
---------------------------------
-beta :: Transform
--- Substitute arg for x in expr. For value lambda's, also clone before
--- substitution.
-beta c (App (Lam x expr) arg) | CoreSyn.isTyVar x = setChanged >> substitute x arg c expr
-                              | otherwise         = setChanged >> substitute_clone x arg c expr
--- Leave all other expressions unchanged
-beta c expr = return expr
-
---------------------------------
--- Unused let binding removal
---------------------------------
-letremoveunused :: Transform
-letremoveunused c expr@(Let (NonRec b bound) res) = do
-  let used = expr_uses_binders [b] res
-  if used
-    then return expr
-    else change res
-letremoveunused c expr@(Let (Rec binds) res) = do
-  -- Filter out all unused binds.
-  let binds' = filter dobind binds
-  -- Only set the changed flag if binds got removed
-  changeif (length binds' /= length binds) (Let (Rec binds') res)
-    where
-      bound_exprs = map snd binds
-      -- For each bind check if the bind is used by res or any of the bound
-      -- expressions
-      dobind (bndr, _) = any (expr_uses_binders [bndr]) (res:bound_exprs)
--- Leave all other expressions unchanged
-letremoveunused c expr = return expr
-
---------------------------------
--- empty let removal
---------------------------------
--- Remove empty (recursive) lets
-letremove :: Transform
-letremove c (Let (Rec []) res) = change res
--- Leave all other expressions unchanged
-letremove c expr = return expr
-
---------------------------------
--- Simple let binding removal
---------------------------------
--- Remove a = b bindings from let expressions everywhere
-letremovesimple :: Transform
-letremovesimple = inlinebind (\(b, e) -> Trans.lift $ is_local_var e)
-
---------------------------------
--- Cast propagation
---------------------------------
--- Try to move casts as much downward as possible.
-castprop :: Transform
-castprop c (Cast (Let binds expr) ty) = change $ Let binds (Cast expr ty)
-castprop c expr@(Cast (Case scrut b _ alts) ty) = change (Case scrut b ty alts')
-  where
-    alts' = map (\(con, bndrs, expr) -> (con, bndrs, (Cast expr ty))) alts
--- Leave all other expressions unchanged
-castprop c expr = return expr
-
---------------------------------
--- Cast simplification. Mostly useful for state packing and unpacking, but
--- perhaps for others as well.
---------------------------------
-castsimpl :: Transform
-castsimpl c expr@(Cast val ty) = do
-  -- Don't extract values that are already simpl
-  local_var <- Trans.lift $ is_local_var val
-  -- Don't extract values that are not representable, to prevent loops with
-  -- inlinenonrep
-  repr <- isRepr val
-  if (not local_var) && repr
-    then do
-      -- Generate a binder for the expression
-      id <- Trans.lift $ mkBinderFor val "castval"
-      -- Extract the expression
-      change $ Let (NonRec id val) (Cast (Var id) ty)
-    else
-      return expr
--- Leave all other expressions unchanged
-castsimpl c expr = return expr
-
---------------------------------
--- Top level function inlining
---------------------------------
--- This transformation inlines simple top level bindings. Simple
--- currently means that the body is only a single application (though
--- the complexity of the arguments is not currently checked) or that the
--- normalized form only contains a single binding. This should catch most of the
--- cases where a top level function is created that simply calls a type class
--- method with a type and dictionary argument, e.g.
---   fromInteger = GHC.Num.fromInteger (SizedWord D8) $dNum
--- which is later called using simply
---   fromInteger (smallInteger 10)
---
--- These useless wrappers are created by GHC automatically. If we don't
--- inline them, we get loads of useless components cluttering the
--- generated VHDL.
---
--- Note that the inlining could also inline simple functions defined by
--- the user, not just GHC generated functions. It turns out to be near
--- impossible to reliably determine what functions are generated and
--- what functions are user-defined. Instead of guessing (which will
--- inline less than we want) we will just inline all simple functions.
---
--- Only functions that are actually completely applied and bound by a
--- variable in a let expression are inlined. These are the expressions
--- that will eventually generate instantiations of trivial components.
--- By not inlining any other reference, we also prevent looping problems
--- with funextract and inlinedict.
-inlinetoplevel :: Transform
-inlinetoplevel (LetBinding:_) expr | not (is_fun expr) =
-  case collectArgs expr of
-       (Var f, args) -> do
-         body_maybe <- needsInline f
-         case body_maybe of
-               Just body -> do
-                       -- Regenerate all uniques in the to-be-inlined expression
-                       body_uniqued <- Trans.lift $ genUniques body
-                       -- And replace the variable reference with the unique'd body.
-                       change (mkApps body_uniqued args)
-                       -- No need to inline
-               Nothing -> return expr
-       -- This is not an application of a binder, leave it unchanged.
-       _ -> return expr
-
--- Leave all other expressions unchanged
-inlinetoplevel c expr = return expr
-
--- | Does the given binder need to be inlined? If so, return the body to
--- be used for inlining.
-needsInline :: CoreBndr -> TransformMonad (Maybe CoreExpr)
-needsInline f = do
-  body_maybe <- Trans.lift $ getGlobalBind f
-  case body_maybe of
-    -- No body available?
-    Nothing -> return Nothing
-    Just body -> case CoreSyn.collectArgs body of
-      -- The body is some (top level) binder applied to 0 or more
-      -- arguments. That should be simple enough to inline.
-      (Var f, args) -> return $ Just body
-      -- Body is more complicated, try normalizing it
-      _ -> do
-        norm_maybe <- Trans.lift $ getNormalized_maybe False f
-        case norm_maybe of
-          -- Noth normalizeable
-          Nothing -> return Nothing 
-          Just norm -> case splitNormalizedNonRep norm of
-            -- The function has just a single binding, so that's simple
-            -- enough to inline.
-            (args, [bind], Var res) -> return $ Just norm
-            -- More complicated function, don't inline
-            _ -> return Nothing
-
-
-----------------------------------------------------------------
--- Program structure transformations
-----------------------------------------------------------------
-
---------------------------------
--- η expansion
---------------------------------
--- Make sure all parameters to the normalized functions are named by top
--- level lambda expressions. For this we apply η expansion to the
--- function body (possibly enclosed in some lambda abstractions) while
--- it has a function type. Eventually this will result in a function
--- body consisting of a bunch of nested lambdas containing a
--- non-function value (e.g., a complete application).
-eta :: Transform
-eta c expr | is_fun expr && not (is_lam expr) && all (== LambdaBody) c = do
-  let arg_ty = (fst . Type.splitFunTy . CoreUtils.exprType) expr
-  id <- Trans.lift $ mkInternalVar "param" arg_ty
-  change (Lam id (App expr (Var id)))
--- Leave all other expressions unchanged
-eta c e = return e
-
---------------------------------
--- Application propagation
---------------------------------
--- Move applications into let and case expressions.
-appprop :: Transform
--- Propagate the application into the let
-appprop c (App (Let binds expr) arg) = change $ Let binds (App expr arg)
--- Propagate the application into each of the alternatives
-appprop c (App (Case scrut b ty alts) arg) = change $ Case scrut b ty' alts'
-  where 
-    alts' = map (\(con, bndrs, expr) -> (con, bndrs, (App expr arg))) alts
-    ty' = CoreUtils.applyTypeToArg ty arg
--- Leave all other expressions unchanged
-appprop c expr = return expr
-
---------------------------------
--- Let recursification
---------------------------------
--- Make all lets recursive, so other transformations don't need to
--- handle non-recursive lets
-letrec :: Transform
-letrec c expr@(Let (NonRec bndr val) res) = 
-  change $ Let (Rec [(bndr, val)]) res
-
--- Leave all other expressions unchanged
-letrec c expr = return expr
-
---------------------------------
--- let flattening
---------------------------------
--- Takes a let that binds another let, and turns that into two nested lets.
--- e.g., from:
--- let b = (let b' = expr' in res') in res
--- to:
--- let b' = expr' in (let b = res' in res)
-letflat :: Transform
--- Turn a nonrec let that binds a let into two nested lets.
-letflat c (Let (NonRec b (Let binds  res')) res) = 
-  change $ Let binds (Let (NonRec b res') res)
-letflat c (Let (Rec binds) expr) = do
-  -- Flatten each binding.
-  binds' <- Utils.concatM $ Monad.mapM flatbind binds
-  -- Return the new let. We don't use change here, since possibly nothing has
-  -- changed. If anything has changed, flatbind has already flagged that
-  -- change.
-  return $ Let (Rec binds') expr
-  where
-    -- Turns a binding of a let into a multiple bindings, or any other binding
-    -- into a list with just that binding
-    flatbind :: (CoreBndr, CoreExpr) -> TransformMonad [(CoreBndr, CoreExpr)]
-    flatbind (b, Let (Rec binds) expr) = change ((b, expr):binds)
-    flatbind (b, Let (NonRec b' expr') expr) = change [(b, expr), (b', expr')]
-    flatbind (b, expr) = return [(b, expr)]
--- Leave all other expressions unchanged
-letflat c expr = return expr
-
---------------------------------
--- Return value simplification
---------------------------------
--- Ensure the return value of a function follows proper normal form. eta
--- expansion ensures the body starts with lambda abstractions, this
--- transformation ensures that the lambda abstractions always contain a
--- recursive let and that, when the return value is representable, the
--- let contains a local variable reference in its body.
-
--- Extract the return value from the body of the top level lambdas (of
--- which ther could be zero), unless it is a let expression (in which
--- case the next clause applies).
-retvalsimpl c expr | all (== LambdaBody) c && not (is_lam expr) && not (is_let expr) = do
-  local_var <- Trans.lift $ is_local_var expr
-  repr <- isRepr expr
-  if not local_var && repr
-    then do
-      id <- Trans.lift $ mkBinderFor expr "res" 
-      change $ Let (Rec [(id, expr)]) (Var id)
-    else
-      return expr
--- Extract the return value from the body of a let expression, which is
--- itself the body of the top level lambdas (of which there could be
--- zero).
-retvalsimpl c expr@(Let (Rec binds) body) | all (== LambdaBody) c = do
-  -- Don't extract values that are already a local variable, to prevent
-  -- loops with ourselves.
-  local_var <- Trans.lift $ is_local_var body
-  -- Don't extract values that are not representable, to prevent loops with
-  -- inlinenonrep
-  repr <- isRepr body
-  if not local_var && repr
-    then do
-      id <- Trans.lift $ mkBinderFor body "res" 
-      change $ Let (Rec ((id, body):binds)) (Var id)
-    else
-      return expr
--- Leave all other expressions unchanged
-retvalsimpl c expr = return expr
-
---------------------------------
--- Representable arguments simplification
---------------------------------
--- Make sure that all arguments of a representable type are simple variables.
-appsimpl :: Transform
--- Simplify all representable arguments. Do this by introducing a new Let
--- that binds the argument and passing the new binder in the application.
-appsimpl c expr@(App f arg) = do
-  -- Check runtime representability
-  repr <- isRepr arg
-  local_var <- Trans.lift $ is_local_var arg
-  if repr && not local_var
-    then do -- Extract representable arguments
-      id <- Trans.lift $ mkBinderFor arg "arg"
-      change $ Let (NonRec id arg) (App f (Var id))
-    else -- Leave non-representable arguments unchanged
-      return expr
--- Leave all other expressions unchanged
-appsimpl c expr = return expr
-
-----------------------------------------------------------------
--- Built-in function transformations
-----------------------------------------------------------------
-
---------------------------------
--- Function-typed argument extraction
---------------------------------
--- This transform takes any function-typed argument that cannot be propagated
--- (because the function that is applied to it is a builtin function), and
--- puts it in a brand new top level binder. This allows us to for example
--- apply map to a lambda expression This will not conflict with inlinenonrep,
--- since that only inlines local let bindings, not top level bindings.
-funextract :: Transform
-funextract c expr@(App _ _) | is_var fexpr = do
-  body_maybe <- Trans.lift $ getGlobalBind f
-  case body_maybe of
-    -- We don't have a function body for f, so we can perform this transform.
-    Nothing -> do
-      -- Find the new arguments
-      args' <- mapM doarg args
-      -- And update the arguments. We use return instead of changed, so the
-      -- changed flag doesn't get set if none of the args got changed.
-      return $ MkCore.mkCoreApps fexpr args'
-    -- We have a function body for f, leave this application to funprop
-    Just _ -> return expr
-  where
-    -- Find the function called and the arguments
-    (fexpr, args) = collectArgs expr
-    Var f = fexpr
-    -- Change any arguments that have a function type, but are not simple yet
-    -- (ie, a variable or application). This means to create a new function
-    -- for map (\f -> ...) b, but not for map (foo a) b.
-    --
-    -- We could use is_applicable here instead of is_fun, but I think
-    -- arguments to functions could only have forall typing when existential
-    -- typing is enabled. Not sure, though.
-    doarg arg | not (is_simple arg) && is_fun arg = do
-      -- Create a new top level binding that binds the argument. Its body will
-      -- be extended with lambda expressions, to take any free variables used
-      -- by the argument expression.
-      let free_vars = VarSet.varSetElems $ CoreFVs.exprFreeVars arg
-      let body = MkCore.mkCoreLams free_vars arg
-      id <- Trans.lift $ mkBinderFor body "fun"
-      Trans.lift $ addGlobalBind id body
-      -- Replace the argument with a reference to the new function, applied to
-      -- all vars it uses.
-      change $ MkCore.mkCoreApps (Var id) (map Var free_vars)
-    -- Leave all other arguments untouched
-    doarg arg = return arg
-
--- Leave all other expressions unchanged
-funextract c expr = return expr
-
-
-
-
-----------------------------------------------------------------
--- Case normalization transformations
-----------------------------------------------------------------
-
---------------------------------
--- Scrutinee simplification
---------------------------------
--- Make sure the scrutinee of a case expression is a local variable
--- reference.
-scrutsimpl :: Transform
--- Replace a case expression with a let that binds the scrutinee and a new
--- simple scrutinee, but only when the scrutinee is representable (to prevent
--- loops with inlinenonrep, though I don't think a non-representable scrutinee
--- will be supported anyway...) and is not a local variable already.
-scrutsimpl c expr@(Case scrut b ty alts) = do
-  repr <- isRepr scrut
-  local_var <- Trans.lift $ is_local_var scrut
-  if repr && not local_var
-    then do
-      id <- Trans.lift $ mkBinderFor scrut "scrut"
-      change $ Let (NonRec id scrut) (Case (Var id) b ty alts)
-    else
-      return expr
--- Leave all other expressions unchanged
-scrutsimpl c expr = return expr
-
---------------------------------
--- Scrutinee binder removal
---------------------------------
--- A case expression can have an extra binder, to which the scrutinee is bound
--- after bringing it to WHNF. This is used for forcing evaluation of strict
--- arguments. Since strictness does not matter for us (rather, everything is
--- sort of strict), this binder is ignored when generating VHDL, and must thus
--- be wild in the normal form.
-scrutbndrremove :: Transform
--- If the scrutinee is already simple, and the bndr is not wild yet, replace
--- all occurences of the binder with the scrutinee variable.
-scrutbndrremove c (Case (Var scrut) bndr ty alts) | bndr_used = do
-    alts' <- mapM subs_bndr alts
-    change $ Case (Var scrut) wild ty alts'
-  where
-    is_used (_, _, expr) = expr_uses_binders [bndr] expr
-    bndr_used = or $ map is_used alts
-    subs_bndr (con, bndrs, expr) = do
-      expr' <- substitute bndr (Var scrut) c expr
-      return (con, bndrs, expr')
-    wild = MkCore.mkWildBinder (Id.idType bndr)
--- Leave all other expressions unchanged
-scrutbndrremove c expr = return expr
-
---------------------------------
--- Case normalization
---------------------------------
--- Turn a case expression with any number of alternatives with any
--- number of non-wild binders into as set of case and let expressions,
--- all of which are in normal form (e.g., a bunch of extractor case
--- expressions to extract all fields from the scrutinee, a number of let
--- bindings to bind each alternative and a single selector case to
--- select the right value.
-casesimpl :: Transform
--- This is already a selector case (or, if x does not appear in bndrs, a very
--- simple case statement that will be removed by caseremove below). Just leave
--- it be.
-casesimpl c expr@(Case scrut b ty [(con, bndrs, Var x)]) = return expr
--- Make sure that all case alternatives have only wild binders and simple
--- expressions.
--- This is done by creating a new let binding for each non-wild binder, which
--- is bound to a new simple selector case statement and for each complex
--- expression. We do this only for representable types, to prevent loops with
--- inlinenonrep.
-casesimpl c expr@(Case scrut bndr ty alts) | not bndr_used = do
-  (bindingss, alts') <- (Monad.liftM unzip) $ mapM doalt alts
-  let bindings = concat bindingss
-  -- Replace the case with a let with bindings and a case
-  let newlet = mkNonRecLets bindings (Case scrut bndr ty alts')
-  -- If there are no non-wild binders, or this case is already a simple
-  -- selector (i.e., a single alt with exactly one binding), already a simple
-  -- selector altan no bindings (i.e., no wild binders in the original case),
-  -- don't change anything, otherwise, replace the case.
-  if null bindings then return expr else change newlet 
-  where
-  -- Check if the scrutinee binder is used
-  is_used (_, _, expr) = expr_uses_binders [bndr] expr
-  bndr_used = or $ map is_used alts
-  -- Generate a single wild binder, since they are all the same
-  wild = MkCore.mkWildBinder
-  -- Wilden the binders of one alt, producing a list of bindings as a
-  -- sideeffect.
-  doalt :: CoreAlt -> TransformMonad ([(CoreBndr, CoreExpr)], CoreAlt)
-  doalt (con, bndrs, expr) = do
-    -- Make each binder wild, if possible
-    bndrs_res <- Monad.zipWithM dobndr bndrs [0..]
-    let (newbndrs, bindings_maybe) = unzip bndrs_res
-    -- Extract a complex expression, if possible. For this we check if any of
-    -- the new list of bndrs are used by expr. We can't use free_vars here,
-    -- since that looks at the old bndrs.
-    let uses_bndrs = not $ VarSet.isEmptyVarSet $ CoreFVs.exprSomeFreeVars (`elem` newbndrs) expr
-    (exprbinding_maybe, expr') <- doexpr expr uses_bndrs
-    -- Create a new alternative
-    let newalt = (con, newbndrs, expr')
-    let bindings = Maybe.catMaybes (bindings_maybe ++ [exprbinding_maybe])
-    return (bindings, newalt)
-    where
-      -- Make wild alternatives for each binder
-      wildbndrs = map (\bndr -> MkCore.mkWildBinder (Id.idType bndr)) bndrs
-      -- A set of all the binders that are used by the expression
-      free_vars = CoreFVs.exprSomeFreeVars (`elem` bndrs) expr
-      -- Look at the ith binder in the case alternative. Return a new binder
-      -- for it (either the same one, or a wild one) and optionally a let
-      -- binding containing a case expression.
-      dobndr :: CoreBndr -> Int -> TransformMonad (CoreBndr, Maybe (CoreBndr, CoreExpr))
-      dobndr b i = do
-        repr <- isRepr b
-        -- Is b wild (e.g., not a free var of expr. Since b is only in scope
-        -- in expr, this means that b is unused if expr does not use it.)
-        let wild = not (VarSet.elemVarSet b free_vars)
-        -- Create a new binding for any representable binder that is not
-        -- already wild and is representable (to prevent loops with
-        -- inlinenonrep).
-        if (not wild) && repr
-          then do
-            caseexpr <- Trans.lift $ mkSelCase scrut i
-            -- Create a new binder that will actually capture a value in this
-            -- case statement, and return it.
-            return (wildbndrs!!i, Just (b, caseexpr))
-          else 
-            -- Just leave the original binder in place, and don't generate an
-            -- extra selector case.
-            return (b, Nothing)
-      -- Process the expression of a case alternative. Accepts an expression
-      -- and whether this expression uses any of the binders in the
-      -- alternative. Returns an optional new binding and a new expression.
-      doexpr :: CoreExpr -> Bool -> TransformMonad (Maybe (CoreBndr, CoreExpr), CoreExpr)
-      doexpr expr uses_bndrs = do
-        local_var <- Trans.lift $ is_local_var expr
-        repr <- isRepr expr
-        -- Extract any expressions that do not use any binders from this
-        -- alternative, is not a local var already and is representable (to
-        -- prevent loops with inlinenonrep).
-        if (not uses_bndrs) && (not local_var) && repr
-          then do
-            id <- Trans.lift $ mkBinderFor expr "caseval"
-            -- We don't flag a change here, since casevalsimpl will do that above
-            -- based on Just we return here.
-            return (Just (id, expr), Var id)
-          else
-            -- Don't simplify anything else
-            return (Nothing, expr)
--- Leave all other expressions unchanged
-casesimpl c expr = return expr
-
---------------------------------
--- Case removal
---------------------------------
--- Remove case statements that have only a single alternative and only wild
--- binders.
-caseremove :: Transform
--- Replace a useless case by the value of its single alternative
-caseremove c (Case scrut b ty [(con, bndrs, expr)]) | not usesvars = change expr
-    -- Find if any of the binders are used by expr
-    where usesvars = (not . VarSet.isEmptyVarSet . (CoreFVs.exprSomeFreeVars (`elem` b:bndrs))) expr
--- Leave all other expressions unchanged
-caseremove c expr = return expr
-
---------------------------------
--- Case of known constructor simplification
---------------------------------
--- If a case expressions scrutinizes a datacon application, we can
--- determine which alternative to use and remove the case alltogether.
--- We replace it with a let expression the binds every binder in the
--- alternative bound to the corresponding argument of the datacon. We do
--- this instead of substituting the binders, to prevent duplication of
--- work and preserve sharing wherever appropriate.
-knowncase :: Transform
-knowncase context expr@(Case scrut@(App _ _) bndr ty alts) | not bndr_used = do
-    case collectArgs scrut of
-      (Var f, args) -> case Id.isDataConId_maybe f of
-        -- Not a dataconstructor? Don't change anything (probably a
-        -- function, then)
-        Nothing -> return expr
-        Just dc -> do
-          let (altcon, bndrs, res) =  case List.find (\(altcon, bndrs, res) -> altcon == (DataAlt dc)) alts of
-                Just alt -> alt -- Return the alternative found
-                Nothing -> head alts -- If the datacon is not present, the first must be the default alternative
-          -- Double check if we have either the correct alternative, or
-          -- the default.
-          if altcon /= (DataAlt dc) && altcon /= DEFAULT then error ("Normalize.knowncase: Invalid core, datacon not found in alternatives and DEFAULT alternative is not first? " ++ pprString expr) else return ()
-          -- Find out how many arguments to drop (type variables and
-          -- predicates like dictionaries).
-          let (tvs, preds, _, _) = DataCon.dataConSig dc
-          let count = length tvs + length preds
-          -- Create a let expression that binds each of the binders in
-          -- this alternative to the corresponding argument of the data
-          -- constructor.
-          let binds = zip bndrs (drop count args)
-          change $ Let (Rec binds) res
-      _ -> return expr -- Scrutinee is not an application of a var
-  where
-    is_used (_, _, expr) = expr_uses_binders [bndr] expr
-    bndr_used = or $ map is_used alts
-
--- Leave all other expressions unchanged
-knowncase c expr = return expr
-
-
-
-
-----------------------------------------------------------------
--- Unrepresentable value removal transformations
-----------------------------------------------------------------
-
---------------------------------
--- Non-representable binding inlining
---------------------------------
--- Remove a = B bindings, with B of a non-representable type, from let
--- expressions everywhere. This means that any value that we can't generate a
--- signal for, will be inlined and hopefully turned into something we can
--- represent.
---
--- This is a tricky function, which is prone to create loops in the
--- transformations. To fix this, we make sure that no transformation will
--- create a new let binding with a non-representable type. These other
--- transformations will just not work on those function-typed values at first,
--- but the other transformations (in particular β-reduction) should make sure
--- that the type of those values eventually becomes representable.
-inlinenonrep :: Transform
-inlinenonrep = inlinebind ((Monad.liftM not) . isRepr . snd)
-
---------------------------------
--- Function specialization
---------------------------------
--- Remove all applications to non-representable arguments, by duplicating the
--- function called with the non-representable parameter replaced by the free
--- variables of the argument passed in.
-argprop :: Transform
--- Transform any application of a named function (i.e., skip applications of
--- lambda's). Also skip applications that have arguments with free type
--- variables, since we can't inline those.
-argprop c expr@(App _ _) | is_var fexpr = do
-  -- Find the body of the function called
-  body_maybe <- Trans.lift $ getGlobalBind f
-  case body_maybe of
-    Just body -> do
-      -- Process each of the arguments in turn
-      (args', changed) <- Writer.listen $ mapM doarg args
-      -- See if any of the arguments changed
-      case Monoid.getAny changed of
-        True -> do
-          let (newargs', newparams', oldargs) = unzip3 args'
-          let newargs = concat newargs'
-          let newparams = concat newparams'
-          -- Create a new body that consists of a lambda for all new arguments and
-          -- the old body applied to some arguments.
-          let newbody = MkCore.mkCoreLams newparams (MkCore.mkCoreApps body oldargs)
-          -- Create a new function with the same name but a new body
-          newf <- Trans.lift $ mkFunction f newbody
-
-          Trans.lift $ MonadState.modify tsInitStates (\ismap ->
-            let init_state_maybe = Map.lookup f ismap in
-            case init_state_maybe of
-              Nothing -> ismap
-              Just init_state -> Map.insert newf init_state ismap)
-          -- Replace the original application with one of the new function to the
-          -- new arguments.
-          change $ MkCore.mkCoreApps (Var newf) newargs
-        False ->
-          -- Don't change the expression if none of the arguments changed
-          return expr
-      
-    -- If we don't have a body for the function called, leave it unchanged (it
-    -- should be a primitive function then).
-    Nothing -> return expr
-  where
-    -- Find the function called and the arguments
-    (fexpr, args) = collectArgs expr
-    Var f = fexpr
-
-    -- Process a single argument and return (args, bndrs, arg), where args are
-    -- the arguments to replace the given argument in the original
-    -- application, bndrs are the binders to include in the top-level lambda
-    -- in the new function body, and arg is the argument to apply to the old
-    -- function body.
-    doarg :: CoreExpr -> TransformMonad ([CoreExpr], [CoreBndr], CoreExpr)
-    doarg arg = do
-      repr <- isRepr arg
-      bndrs <- Trans.lift getGlobalBinders
-      let interesting var = Var.isLocalVar var && (var `notElem` bndrs)
-      if not repr && not (is_var arg && interesting (exprToVar arg)) && not (has_free_tyvars arg) 
-        then do
-          -- Propagate all complex arguments that are not representable, but not
-          -- arguments with free type variables (since those would require types
-          -- not known yet, which will always be known eventually).
-          -- Find interesting free variables, each of which should be passed to
-          -- the new function instead of the original function argument.
-          -- 
-          -- Interesting vars are those that are local, but not available from the
-          -- top level scope (functions from this module are defined as local, but
-          -- they're not local to this function, so we can freely move references
-          -- to them into another function).
-          let free_vars = VarSet.varSetElems $ CoreFVs.exprSomeFreeVars interesting arg
-          -- Mark the current expression as changed
-          setChanged
-          -- TODO: Clone the free_vars (and update references in arg), since
-          -- this might cause conflicts if two arguments that are propagated
-          -- share a free variable. Also, we are now introducing new variables
-          -- into a function that are not fresh, which violates the binder
-          -- uniqueness invariant.
-          return (map Var free_vars, free_vars, arg)
-        else do
-          -- Representable types will not be propagated, and arguments with free
-          -- type variables will be propagated later.
-          -- Note that we implicitly remove any type variables in the type of
-          -- the original argument by using the type of the actual argument
-          -- for the new formal parameter.
-          -- TODO: preserve original naming?
-          id <- Trans.lift $ mkBinderFor arg "param"
-          -- Just pass the original argument to the new function, which binds it
-          -- to a new id and just pass that new id to the old function body.
-          return ([arg], [id], mkReferenceTo id) 
--- Leave all other expressions unchanged
-argprop c expr = return expr
-
---------------------------------
--- Non-representable result inlining
---------------------------------
--- This transformation takes a function (top level binding) that has a
--- non-representable result (e.g., a tuple containing a function, or an
--- Integer. The latter can occur in some cases as the result of the
--- fromIntegerT function) and inlines enough of the function to make the
--- result representable again.
---
--- This is done by first normalizing the function and then "inlining"
--- the result. Since no unrepresentable let bindings are allowed in
--- normal form, we can be sure that all free variables of the result
--- expression will be representable (Note that we probably can't
--- guarantee that all representable parts of the expression will be free
--- variables, so we might inline more than strictly needed).
---
--- The new function result will be a tuple containing all free variables
--- of the old result, so the old result can be rebuild at the caller.
---
--- We take care not to inline dictionary id's, which are top level
--- bindings with a non-representable result type as well, since those
--- will never become VHDL signals directly. There is a separate
--- transformation (inlinedict) that specifically inlines dictionaries
--- only when it is useful.
-inlinenonrepresult :: Transform
-
--- Apply to any (application of) a reference to a top level function
--- that is fully applied (i.e., dos not have a function type) but is not
--- representable. We apply in any context, since non-representable
--- expressions are generally left alone and can occur anywhere.
-inlinenonrepresult context expr | not (is_fun expr) =
-  case collectArgs expr of
-    (Var f, args) | not (Id.isDictId f) -> do
-      repr <- isRepr expr
-      if not repr
-        then do
-          body_maybe <- Trans.lift $ getNormalized_maybe True f
-          case body_maybe of
-            Just body -> do
-              let (bndrs, binds, res) = splitNormalizedNonRep body
-              if has_free_tyvars res 
-                then
-                  -- Don't touch anything with free type variables, since
-                  -- we can't return those. We'll wait until argprop
-                  -- removed those variables.
-                  return expr
-                else do
-                  -- Get the free local variables of res
-                  global_bndrs <- Trans.lift getGlobalBinders
-                  let interesting var = Var.isLocalVar var && (var `notElem` global_bndrs)
-                  let free_vars = VarSet.varSetElems $ CoreFVs.exprSomeFreeVars interesting res
-                  let free_var_types = map Id.idType free_vars
-                  let n_free_vars = length free_vars
-                  -- Get a tuple datacon to wrap around the free variables
-                  let fvs_datacon = TysWiredIn.tupleCon BasicTypes.Boxed n_free_vars
-                  let fvs_datacon_id = DataCon.dataConWorkId fvs_datacon
-                  -- Let the function now return a tuple with references to
-                  -- all free variables of the old return value. First pass
-                  -- all the types of the variables, since tuple
-                  -- constructors are polymorphic.
-                  let newres = mkApps (Var fvs_datacon_id) (map Type free_var_types ++  map Var free_vars)
-                  -- Recreate the function body with the changed return value
-                  let newbody = mkLams bndrs (Let (Rec binds) newres) 
-                  -- Create the new function
-                  f' <- Trans.lift $ mkFunction f newbody
-
-                  -- Call the new function
-                  let newapp = mkApps (Var f') args
-                  res_bndr <- Trans.lift $ mkBinderFor newapp "res"
-                  -- Create extractor case expressions to extract each of the
-                  -- free variables from the tuple.
-                  sel_cases <- Trans.lift $ mapM (mkSelCase (Var res_bndr)) [0..n_free_vars-1]
-
-                  -- Bind the res_bndr to the result of the new application
-                  -- and each of the free variables to the corresponding
-                  -- selector case. Replace the let body with the original
-                  -- body of the called function (which can still access all
-                  -- of its free variables, from the let).
-                  let binds = (res_bndr, newapp):(zip free_vars sel_cases)
-                  let letexpr = Let (Rec binds) res
-
-                  -- Finally, regenarate all uniques in the new expression,
-                  -- since the free variables could otherwise become
-                  -- duplicated. It is not strictly necessary to regenerate
-                  -- res, since we're moving that expression, but it won't
-                  -- hurt.
-                  letexpr_uniqued <- Trans.lift $ genUniques letexpr
-                  change letexpr_uniqued
-            Nothing -> return expr
-        else
-          -- Don't touch representable expressions or (applications of)
-          -- dictionary ids.
-          return expr
-    -- Not a reference to or application of a top level function
-    _ -> return expr
--- Leave all other expressions unchanged
-inlinenonrepresult c expr = return expr
-
-----------------------------------------------------------------
--- Type-class transformations
-----------------------------------------------------------------
-
---------------------------------
--- ClassOp resolution
---------------------------------
--- Resolves any class operation to the actual operation whenever
--- possible. Class methods (as well as parent dictionary selectors) are
--- special "functions" that take a type and a dictionary and evaluate to
--- the corresponding method. A dictionary is nothing more than a
--- special dataconstructor applied to the type the dictionary is for,
--- each of the superclasses and all of the class method definitions for
--- that particular type. Since dictionaries all always inlined (top
--- levels dictionaries are inlined by inlinedict, local dictionaries are
--- inlined by inlinenonrep), we will eventually have something like:
---
---   baz
---     @ CLasH.HardwareTypes.Bit
---     (D:Baz @ CLasH.HardwareTypes.Bit bitbaz)
---
--- Here, baz is the method selector for the baz method, while
--- D:Baz is the dictionary constructor for the Baz and bitbaz is the baz
--- method defined in the Baz Bit instance declaration.
---
--- To resolve this, we can look at the ClassOp IdInfo from the baz Id,
--- which contains the Class it is defined for. From the Class, we can
--- get a list of all selectors (both parent class selectors as well as
--- method selectors). Since the arguments to D:Baz (after the type
--- argument) correspond exactly to this list, we then look up baz in
--- that list and replace the entire expression by the corresponding 
--- argument to D:Baz.
---
--- We don't resolve methods that have a builtin translation (such as
--- ==), since the actual implementation is not always (easily)
--- translateable. For example, when deriving ==, GHC generates code
--- using $con2tag functions to translate a datacon to an int and compare
--- that with GHC.Prim.==# . Better to avoid that for now.
-classopresolution :: Transform
-classopresolution c expr@(App (App (Var sel) ty) dict) | not is_builtin =
-  case Id.isClassOpId_maybe sel of
-    -- Not a class op selector
-    Nothing -> return expr
-    Just cls -> case collectArgs dict of
-      (_, []) -> return expr -- Dict is not an application (e.g., not inlined yet)
-      (Var dictdc, (ty':selectors)) | not (Maybe.isJust (Id.isDataConId_maybe dictdc)) -> return expr -- Dictionary is not a datacon yet (but e.g., a top level binder)
-                                | tyargs_neq ty ty' -> error $ "Normalize.classopresolution: Applying class selector to dictionary without matching type?\n" ++ pprString expr
-                                | otherwise ->
-        let selector_ids = Class.classSelIds cls in
-        -- Find the selector used in the class' list of selectors
-        case List.elemIndex sel selector_ids of
-          Nothing -> error $ "Normalize.classopresolution: Selector not found in class' selector list? This should not happen!\nExpression: " ++ pprString expr ++ "\nClass: " ++ show cls ++ "\nSelectors: " ++ show selector_ids
-          -- Get the corresponding argument from the dictionary
-          Just n -> change (selectors!!n)
-      (_, _) -> return expr -- Not applying a variable? Don't touch
-  where
-    -- Compare two type arguments, returning True if they are _not_
-    -- equal
-    tyargs_neq (Type ty1) (Type ty2) = not $ Type.coreEqType ty1 ty2
-    tyargs_neq _ _ = True
-    -- Is this a builtin function / method?
-    is_builtin = elem (Name.getOccString sel) builtinIds
-
--- Leave all other expressions unchanged
-classopresolution c expr = return expr
-
---------------------------------
--- Dictionary inlining
---------------------------------
--- Inline all top level dictionaries, that are in a position where
--- classopresolution can actually resolve them. This makes this
--- transformation look similar to classoperesolution below, but we'll
--- keep them separated for clarity. By not inlining other dictionaries,
--- we prevent expression sizes exploding when huge type level integer
--- dictionaries are inlined which can never be expanded (in casts, for
--- example).
-inlinedict c expr@(App (App (Var sel) ty) (Var dict)) | not is_builtin && is_classop = do
-  body_maybe <- Trans.lift $ getGlobalBind dict
-  case body_maybe of
-    -- No body available (no source available, or a local variable /
-    -- argument)
-    Nothing -> return expr
-    Just body -> change (App (App (Var sel) ty) body)
-  where
-    -- Is this a builtin function / method?
-    is_builtin = elem (Name.getOccString sel) builtinIds
-    -- Are we dealing with a class operation selector?
-    is_classop = Maybe.isJust (Id.isClassOpId_maybe sel)
-
--- Leave all other expressions unchanged
-inlinedict c expr = return expr
-
-
-{-
---------------------------------
--- Identical let binding merging
---------------------------------
--- Merge two bindings in a let if they are identical 
--- TODO: We would very much like to use GHC's CSE module for this, but that
--- doesn't track if something changed or not, so we can't use it properly.
-letmerge :: Transform
-letmerge c expr@(Let _ _) = do
-  let (binds, res) = flattenLets expr
-  binds' <- domerge binds
-  return $ mkNonRecLets binds' res
-  where
-    domerge :: [(CoreBndr, CoreExpr)] -> TransformMonad [(CoreBndr, CoreExpr)]
-    domerge [] = return []
-    domerge (e:es) = do 
-      es' <- mapM (mergebinds e) es
-      es'' <- domerge es'
-      return (e:es'')
-
-    -- Uses the second bind to simplify the second bind, if applicable.
-    mergebinds :: (CoreBndr, CoreExpr) -> (CoreBndr, CoreExpr) -> TransformMonad (CoreBndr, CoreExpr)
-    mergebinds (b1, e1) (b2, e2)
-      -- Identical expressions? Replace the second binding with a reference to
-      -- the first binder.
-      | CoreUtils.cheapEqExpr e1 e2 = change $ (b2, Var b1)
-      -- Different expressions? Don't change
-      | otherwise = return (b2, e2)
--- Leave all other expressions unchanged
-letmerge c expr = return expr
--}
-
---------------------------------
--- End of transformations
---------------------------------
-
-
-
-
--- What transforms to run?
-transforms = [ ("inlinedict", inlinedict)
-             , ("inlinetoplevel", inlinetoplevel)
-             , ("inlinenonrepresult", inlinenonrepresult)
-             , ("knowncase", knowncase)
-             , ("classopresolution", classopresolution)
-             , ("argprop", argprop)
-             , ("funextract", funextract)
-             , ("eta", eta)
-             , ("beta", beta)
-             , ("appprop", appprop)
-             , ("castprop", castprop)
-             , ("letremovesimple", letremovesimple)
-             , ("letrec", letrec)
-             , ("letremove", letremove)
-             , ("retvalsimpl", retvalsimpl)
-             , ("letflat", letflat)
-             , ("scrutsimpl", scrutsimpl)
-             , ("scrutbndrremove", scrutbndrremove)
-             , ("casesimpl", casesimpl)
-             , ("caseremove", caseremove)
-             , ("inlinenonrep", inlinenonrep)
-             , ("appsimpl", appsimpl)
-             , ("letremoveunused", letremoveunused)
-             , ("castsimpl", castsimpl)
-             ]
-
--- | Returns the normalized version of the given function, or an error
--- if it is not a known global binder.
-getNormalized ::
-  Bool -- ^ Allow the result to be unrepresentable?
-  -> CoreBndr -- ^ The function to get
-  -> TranslatorSession CoreExpr -- The normalized function body
-getNormalized result_nonrep bndr = do
-  norm <- getNormalized_maybe result_nonrep bndr
-  return $ Maybe.fromMaybe
-    (error $ "Normalize.getNormalized: Unknown or non-representable function requested: " ++ show bndr)
-    norm
-
--- | Returns the normalized version of the given function, or Nothing
--- when the binder is not a known global binder or is not normalizeable.
-getNormalized_maybe ::
-  Bool -- ^ Allow the result to be unrepresentable?
-  -> CoreBndr -- ^ The function to get
-  -> TranslatorSession (Maybe CoreExpr) -- The normalized function body
-
-getNormalized_maybe result_nonrep bndr = do
-    expr_maybe <- getGlobalBind bndr
-    normalizeable <- isNormalizeable result_nonrep bndr
-    if not normalizeable || Maybe.isNothing expr_maybe
-      then
-        -- Binder not normalizeable or not found
-        return Nothing
-      else do
-        -- Binder found and is monomorphic. Normalize the expression
-        -- and cache the result.
-        normalized <- Utils.makeCached bndr tsNormalized $ 
-          normalizeExpr (show bndr) (Maybe.fromJust expr_maybe)
-        return (Just normalized)
-
--- | Normalize an expression
-normalizeExpr ::
-  String -- ^ What are we normalizing? For debug output only.
-  -> CoreSyn.CoreExpr -- ^ The expression to normalize 
-  -> TranslatorSession CoreSyn.CoreExpr -- ^ The normalized expression
-
-normalizeExpr what expr = do
-      startcount <- MonadState.get tsTransformCounter 
-      expr_uniqued <- genUniques expr
-      -- Do a debug print, if requested
-      let expr_uniqued' = Utils.traceIf (normalize_debug >= NormDbgFinal) (what ++ " before normalization:\n\n" ++ showSDoc ( ppr expr_uniqued ) ++ "\n") expr_uniqued
-      -- Normalize this expression
-      expr' <- dotransforms transforms expr_uniqued'
-      endcount <- MonadState.get tsTransformCounter 
-      -- Do a debug print, if requested
-      Utils.traceIf (normalize_debug >= NormDbgFinal)  (what ++ " after normalization:\n\n" ++ showSDoc ( ppr expr') ++ "\nNeeded " ++ show (endcount - startcount) ++ " transformations to normalize " ++ what) $
-        return expr'
-
--- | Split a normalized expression into the argument binders, top level
---   bindings and the result binder. This function returns an error if
---   the type of the expression is not representable.
-splitNormalized ::
-  CoreExpr -- ^ The normalized expression
-  -> ([CoreBndr], [Binding], CoreBndr)
-splitNormalized expr = 
-  case splitNormalizedNonRep expr of
-    (args, binds, Var res) -> (args, binds, res)
-    _ -> error $ "Normalize.splitNormalized: Not in normal form: " ++ pprString expr ++ "\n"
-
--- Split a normalized expression, whose type can be unrepresentable.
-splitNormalizedNonRep::
-  CoreExpr -- ^ The normalized expression
-  -> ([CoreBndr], [Binding], CoreExpr)
-splitNormalizedNonRep expr = (args, binds, resexpr)
-  where
-    (args, letexpr) = CoreSyn.collectBinders expr
-    (binds, resexpr) = flattenLets letexpr
diff --git a/cλash/CLasH/Normalize/NormalizeTools.hs b/cλash/CLasH/Normalize/NormalizeTools.hs
deleted file mode 100644 (file)
index f6c254e..0000000
+++ /dev/null
@@ -1,246 +0,0 @@
-{-# LANGUAGE PackageImports #-}
--- 
--- This module provides functions for program transformations.
---
-module CLasH.Normalize.NormalizeTools where
-
--- Standard modules
-import qualified Data.Monoid as Monoid
-import qualified Data.Either as Either
-import qualified Control.Monad as Monad
-import qualified Control.Monad.Trans.Writer as Writer
-import qualified "transformers" Control.Monad.Trans as Trans
-import qualified Data.Accessor.Monad.Trans.State as MonadState
-
--- GHC API
-import CoreSyn
-import qualified Name
-import qualified Id
-import qualified CoreSubst
-import qualified Type
-import qualified CoreUtils
-import Outputable ( showSDoc, ppr, nest )
-
--- Local imports
-import CLasH.Normalize.NormalizeTypes
-import CLasH.Translator.TranslatorTypes
-import CLasH.VHDL.Constants (builtinIds)
-import CLasH.Utils
-import qualified CLasH.Utils.Core.CoreTools as CoreTools
-import qualified CLasH.VHDL.VHDLTools as VHDLTools
-
--- Apply the given transformation to all expressions in the given expression,
--- including the expression itself.
-everywhere :: Transform -> Transform
-everywhere trans = applyboth (subeverywhere (everywhere trans)) trans
-
-data NormDbgLevel = 
-    NormDbgNone         -- ^ No debugging
-  | NormDbgFinal        -- ^ Print functions before / after normalization
-  | NormDbgApplied      -- ^ Print expressions before / after applying transformations
-  | NormDbgAll          -- ^ Print expressions when a transformation does not apply
-  deriving (Eq, Ord)
-normalize_debug = NormDbgFinal
-
--- Applies a transform, optionally showing some debug output.
-apply :: (String, Transform) -> Transform
-apply (name, trans) ctx expr =  do
-    -- Apply the transformation and find out if it changed anything
-    (expr', any_changed) <- Writer.listen $ trans ctx expr
-    let changed = Monoid.getAny any_changed
-    -- If it changed, increase the transformation counter 
-    Monad.when changed $ Trans.lift (MonadState.modify tsTransformCounter (+1))
-    -- Prepare some debug strings
-    let before = showSDoc (nest 4 $ ppr expr) ++ "\nType: \n" ++ (showSDoc $ nest 4 $ ppr $ CoreUtils.exprType expr) ++ "\n"
-    let context = "Context: " ++ show ctx ++ "\n"
-    let after  = showSDoc (nest 4 $ ppr expr') ++ "\nType: \n" ++ (showSDoc $ nest 4 $ ppr $ CoreUtils.exprType expr') ++ "\n"
-    traceIf (normalize_debug >= NormDbgApplied && changed) ("Changes when applying transform " ++ name ++ " to:\n" ++ before ++ context ++ "Result:\n" ++ after) $ 
-     traceIf (normalize_debug >= NormDbgAll && not changed) ("No changes when applying transform " ++ name ++ " to:\n" ++ before  ++ context) $
-     return expr'
-
--- Apply the first transformation, followed by the second transformation, and
--- keep applying both for as long as expression still changes.
-applyboth :: Transform -> Transform -> Transform
-applyboth first second context expr = do
-  -- Apply the first
-  expr' <- first context expr
-  -- Apply the second
-  (expr'', changed) <- Writer.listen $ second context expr'
-  if Monoid.getAny $ changed
-    then
-      applyboth first second context expr'' 
-    else 
-      return expr''
-
--- Apply the given transformation to all direct subexpressions (only), not the
--- expression itself.
-subeverywhere :: Transform -> Transform
-subeverywhere trans c (App a b) = do
-  a' <- trans (AppFirst:c) a
-  b' <- trans (AppSecond:c) b
-  return $ App a' b'
-
-subeverywhere trans c (Let (NonRec b bexpr) expr) = do
-  bexpr' <- trans (LetBinding:c) bexpr
-  expr' <- trans (LetBody:c) expr
-  return $ Let (NonRec b bexpr') expr'
-
-subeverywhere trans c (Let (Rec binds) expr) = do
-  expr' <- trans (LetBody:c) expr
-  binds' <- mapM transbind binds
-  return $ Let (Rec binds') expr'
-  where
-    transbind :: (CoreBndr, CoreExpr) -> TransformMonad (CoreBndr, CoreExpr)
-    transbind (b, e) = do
-      e' <- trans (LetBinding:c) e
-      return (b, e')
-
-subeverywhere trans c (Lam x expr) = do
-  expr' <- trans (LambdaBody:c) expr
-  return $ Lam x expr'
-
-subeverywhere trans c (Case scrut b t alts) = do
-  scrut' <- trans (Other:c) scrut
-  alts' <- mapM transalt alts
-  return $ Case scrut' b t alts'
-  where
-    transalt :: CoreAlt -> TransformMonad CoreAlt
-    transalt (con, binders, expr) = do
-      expr' <- trans (Other:c) expr
-      return (con, binders, expr')
-
-subeverywhere trans c (Var x) = return $ Var x
-subeverywhere trans c (Lit x) = return $ Lit x
-subeverywhere trans c (Type x) = return $ Type x
-
-subeverywhere trans c (Cast expr ty) = do
-  expr' <- trans (Other:c) expr
-  return $ Cast expr' ty
-
-subeverywhere trans c expr = error $ "\nNormalizeTools.subeverywhere: Unsupported expression: " ++ show expr
-
--- Runs each of the transforms repeatedly inside the State monad.
-dotransforms :: [(String, Transform)] -> CoreExpr -> TranslatorSession CoreExpr
-dotransforms transs expr = do
-  (expr', changed) <- Writer.runWriterT $ Monad.foldM (\e trans -> everywhere (apply trans) [] e) expr transs
-  if Monoid.getAny changed then dotransforms transs expr' else return expr'
-
--- Inline all let bindings that satisfy the given condition
-inlinebind :: ((CoreBndr, CoreExpr) -> TransformMonad Bool) -> Transform
-inlinebind condition context expr@(Let (Rec binds) res) = do
-    -- Find all bindings that adhere to the condition
-    res_eithers <- mapM docond binds
-    case Either.partitionEithers res_eithers of
-      -- No replaces? No change
-      ([], _) -> return expr
-      (replace, others) -> do
-        -- Substitute the to be replaced binders with their expression
-        newexpr <- do_substitute replace (Let (Rec others) res)
-        change newexpr
-  where 
-    -- Apply the condition to a let binding and return an Either
-    -- depending on whether it needs to be inlined or not.
-    docond :: (CoreBndr, CoreExpr) -> TransformMonad (Either (CoreBndr, CoreExpr) (CoreBndr, CoreExpr))
-    docond b = do
-      res <- condition b
-      return $ case res of True -> Left b; False -> Right b
-
-    -- Apply the given list of substitutions to the the given expression
-    do_substitute :: [(CoreBndr, CoreExpr)] -> CoreExpr -> TransformMonad CoreExpr
-    do_substitute [] expr = return expr
-    do_substitute ((bndr, val):reps) expr = do
-      -- Perform this substitution in the expression
-      expr' <- substitute_clone bndr val context expr
-      -- And in the substitution values we will be using next
-      reps' <- mapM (subs_bind bndr val) reps
-      -- And then perform the remaining substitutions
-      do_substitute reps' expr'
-   
-    -- Replace the given binder with the given expression in the
-    -- expression oft the given let binding
-    subs_bind :: CoreBndr -> CoreExpr -> (CoreBndr, CoreExpr) -> TransformMonad (CoreBndr, CoreExpr)
-    subs_bind bndr expr (b, v) = do
-      v' <- substitute_clone  bndr expr (LetBinding:context) v
-      return (b, v')
-
-
--- Leave all other expressions unchanged
-inlinebind _ context expr = return expr
-
--- Sets the changed flag in the TransformMonad, to signify that some
--- transform has changed the result
-setChanged :: TransformMonad ()
-setChanged = Writer.tell (Monoid.Any True)
-
--- Sets the changed flag and returns the given value.
-change :: a -> TransformMonad a
-change val = do
-  setChanged
-  return val
-
--- Returns the given value and sets the changed flag if the bool given is
--- True. Note that this will not unset the changed flag if the bool is False.
-changeif :: Bool -> a -> TransformMonad a
-changeif True val = change val
-changeif False val = return val
-
--- | Creates a transformation that substitutes the given binder with the given
--- expression (This can be a type variable, replace by a Type expression).
--- Does not set the changed flag.
-substitute :: CoreBndr -> CoreExpr -> Transform
--- Use CoreSubst to subst a type var in an expression
-substitute find repl context expr = do
-  let subst = CoreSubst.extendSubst CoreSubst.emptySubst find repl
-  return $ CoreSubst.substExpr subst expr 
-
--- | Creates a transformation that substitutes the given binder with the given
--- expression. This does only work for value expressions! All binders in the
--- expression are cloned before the replacement, to guarantee uniqueness.
-substitute_clone :: CoreBndr -> CoreExpr -> Transform
--- If we see the var to find, replace it by a uniqued version of repl
-substitute_clone find repl context (Var var) | find == var = do
-  repl' <- Trans.lift $ CoreTools.genUniques repl
-  change repl'
-
--- For all other expressions, just look in subexpressions
-substitute_clone find repl context expr = subeverywhere (substitute_clone find repl) context expr
-
--- Is the given expression representable at runtime, based on the type?
-isRepr :: (CoreTools.TypedThing t) => t -> TransformMonad Bool
-isRepr tything = Trans.lift (isRepr' tything)
-
-isRepr' :: (CoreTools.TypedThing t) => t -> TranslatorSession Bool
-isRepr' tything = case CoreTools.getType tything of
-  Nothing -> return False
-  Just ty -> MonadState.lift tsType $ VHDLTools.isReprType ty 
-
-is_local_var :: CoreSyn.CoreExpr -> TranslatorSession Bool
-is_local_var (CoreSyn.Var v) = do
-  bndrs <- getGlobalBinders
-  return $ v `notElem` bndrs
-is_local_var _ = return False
-
--- Is the given binder defined by the user?
-isUserDefined :: CoreSyn.CoreBndr -> Bool
--- System names are certain to not be user defined
-isUserDefined bndr | Name.isSystemName (Id.idName bndr) = False
--- Builtin functions are usually not user-defined either (and would
--- break currently if they are...)
-isUserDefined bndr = str `notElem` builtinIds
-  where
-    str = Name.getOccString bndr
-
--- | Is the given binder normalizable? This means that its type signature can be
--- represented in hardware, which should (?) guarantee that it can be made
--- into hardware. This checks whether all the arguments and (optionally)
--- the return value are
--- representable.
-isNormalizeable :: 
-  Bool -- ^ Allow the result to be unrepresentable?
-  -> CoreBndr  -- ^ The binder to check
-  -> TranslatorSession Bool  -- ^ Is it normalizeable?
-isNormalizeable result_nonrep bndr = do
-  let ty = Id.idType bndr
-  let (arg_tys, res_ty) = Type.splitFunTys ty
-  let check_tys = if result_nonrep then arg_tys else (res_ty:arg_tys) 
-  andM $ mapM isRepr' check_tys
diff --git a/cλash/CLasH/Normalize/NormalizeTypes.hs b/cλash/CLasH/Normalize/NormalizeTypes.hs
deleted file mode 100644 (file)
index 4e98709..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-module CLasH.Normalize.NormalizeTypes where
-
--- Standard modules
-import qualified Control.Monad.Trans.Writer as Writer
-import qualified Data.Monoid as Monoid
-
--- GHC API
-import qualified CoreSyn
-
--- Local imports
-import CLasH.Translator.TranslatorTypes
-
--- Wrap a writer around a TranslatorSession, to run a single transformation
--- over a single expression and track if the expression was changed.
-type TransformMonad = Writer.WriterT Monoid.Any TranslatorSession
-
--- | In what context does a core expression occur?
-data CoreContext = AppFirst        -- ^ The expression is the first
-                                   -- argument of an application (i.e.,
-                                   -- it is applied)
-                 | AppSecond       -- ^ The expression is the second
-                                   --   argument of an application
-                                   --   (i.e., something is applied to it)
-                 | LetBinding      -- ^ The expression is bound in a
-                                   --   (recursive or non-recursive) let
-                                   --   expression.
-                 | LetBody         -- ^ The expression is the body of a
-                                   --   let expression
-                 | LambdaBody      -- ^ The expression is the body of a
-                                   --   lambda abstraction
-                 | Other           -- ^ Another context
-  deriving (Eq, Show)
--- | Transforms a CoreExpr and keeps track if it has changed.
-type Transform = [CoreContext] -> CoreSyn.CoreExpr -> TransformMonad CoreSyn.CoreExpr
diff --git a/cλash/CLasH/Translator.hs b/cλash/CLasH/Translator.hs
deleted file mode 100644 (file)
index a9bb9fa..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-module CLasH.Translator 
-  (
-   makeVHDLAnnotations
-  ) where
-
--- Standard Modules
-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.Monad.Trans.State
-import qualified Data.Map as Map
-import qualified Data.Time.Clock as Clock
-import Debug.Trace
-
--- GHC API
-import qualified CoreSyn
-import qualified HscTypes
-import qualified UniqSupply
-
--- VHDL Imports
-import qualified Language.VHDL.AST as AST
-import qualified Language.VHDL.FileIO as FileIO
-import qualified Language.VHDL.Ppr as Ppr
-
--- Local Imports
-import CLasH.Translator.TranslatorTypes
-import CLasH.Translator.Annotations
-import CLasH.Utils
-import CLasH.Utils.GhcTools
-import CLasH.VHDL
-import CLasH.VHDL.VHDLTools
-import CLasH.VHDL.Testbench
-
--- | Turn Haskell to VHDL, Usings Strings to indicate the Top Entity, Initial
---   State and Test Inputs.
--- makeVHDLStrings :: 
---   FilePath      -- ^ The GHC Library Dir
---   -> [FilePath] -- ^ The FileNames
---   -> String     -- ^ The TopEntity
---   -> String     -- ^ The InitState
---   -> String     -- ^ The TestInput
---   -> IO ()
--- makeVHDLStrings libdir filenames topentity initstate testinput = do
---   makeVHDL libdir filenames finder
---     where
---       finder = findSpec (hasVarName topentity)
---                         (hasVarName initstate)
---                         (isCLasHAnnotation isInitState)
---                         (hasVarName testinput)
-
--- | Turn Haskell to VHDL, Using the Annotations for Top Entity, Initial State
---   and Test Inputs found in the Files. 
-makeVHDLAnnotations :: 
-  FilePath      -- ^ The GHC Library Dir
-  -> [FilePath] -- ^ The FileNames
-  -> IO ()
-makeVHDLAnnotations libdir filenames =
-  makeVHDL libdir filenames finder
-    where
-      finder = findSpec (hasCLasHAnnotation isTopEntity)
-                        (hasCLasHAnnotation isInitState)
-                        (isCLasHAnnotation isInitState)
-                        (hasCLasHAnnotation isTestInput)
-
--- | Turn Haskell to VHDL, using the given finder functions to find the Top
---   Entity, Initial State and Test Inputs in the Haskell Files.
-makeVHDL ::
-  FilePath      -- ^ The GHC Library Dir
-  -> [FilePath] -- ^ The Filenames
-  -> Finder
-  -> IO ()
-makeVHDL libdir filenames finder = do
-  start <- Clock.getCurrentTime
-  -- Load the modules
-  (cores, env, specs) <- loadModules libdir filenames (Just finder)
-  -- Translate to VHDL
-  vhdl <- moduleToVHDL env cores specs
-  -- Write VHDL to file. Just use the first entity for the name
-  let top_entity = head $ Maybe.catMaybes $ map (\(t, _, _) -> t) specs
-  let dir = "./vhdl/" ++ (show top_entity) ++ "/"
-  prepareDir dir
-  mapM_ (writeVHDL dir) vhdl
-  end <- Clock.getCurrentTime
-  trace ("\nTotal compilation took " ++ show (Clock.diffUTCTime end start)) $
-    return ()
-
--- | Translate the specified entities in the given modules to VHDL.
-moduleToVHDL ::
-  HscTypes.HscEnv             -- ^ The GHC Environment
-  -> [HscTypes.CoreModule]    -- ^ The Core Modules
-  -> [EntitySpec]             -- ^ The entities to generate
-  -> IO [(AST.VHDLId, AST.DesignFile)]
-moduleToVHDL env cores specs = do
-  (vhdl, count) <- runTranslatorSession env $ do
-    let all_bindings = concatMap (\x -> CoreSyn.flattenBinds (HscTypes.cm_binds x)) cores
-    -- Store the bindings we loaded
-    tsBindings %= Map.fromList all_bindings
-    let all_initstates = concatMap (\x -> case x of (_, Nothing, _) -> []; (_, Just inits, _) -> inits) specs 
-    tsInitStates %= Map.fromList all_initstates
-    test_binds <- catMaybesM $ Monad.mapM mkTest specs
-    let topbinds = Maybe.catMaybes $ map (\(top, _, _) -> top) specs
-    vhdl <- case topbinds of
-      []  -> error "Could not find top entity requested"
-      tops -> createDesignFiles (tops ++ test_binds)
-    count <- get tsTransformCounter 
-    return (vhdl, count)
-  mapM_ (putStr . render . Ppr.ppr . snd) vhdl
-  putStr $ "Total number of transformations applied: " ++ (show count) ++ "\n"
-  return vhdl
-  where
-    mkTest :: EntitySpec -> TranslatorSession (Maybe CoreSyn.CoreBndr)
-    -- Create a testbench for any entry that has test input
-    mkTest (_, _, Nothing) = return Nothing
-    mkTest (Nothing, _, _) = return Nothing
-    mkTest (Just top, _, Just input) = do
-      bndr <- createTestbench Nothing cores input top
-      return $ Just bndr
-
--- 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 builtin_types [] Map.empty Map.empty env
-  let init_state = TranslatorState uniqSupply init_typestate Map.empty Map.empty 0 Map.empty Map.empty Map.empty 0
-  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.
-prepareDir :: String -> IO()
-prepareDir dir = do
-  -- Create the dir if needed
-  Directory.createDirectoryIfMissing True dir
-  -- Find all .vhdl files in the directory
-  files <- Directory.getDirectoryContents dir
-  let to_remove = filter ((==".vhdl") . FilePath.takeExtension) files
-  -- Prepend the dirname to the filenames
-  let abs_to_remove = map (FilePath.combine dir) to_remove
-  -- Remove the files
-  mapM_ Directory.removeFile abs_to_remove
-
--- | Write the given design file to a file with the given name inside the
---   given dir
-writeVHDL :: String -> (AST.VHDLId, AST.DesignFile) -> IO ()
-writeVHDL dir (name, vhdl) = do
-  -- Find the filename
-  let fname = dir ++ (AST.fromVHDLId name) ++ ".vhdl"
-  -- Write the file
-  FileIO.writeDesignFile vhdl fname
-
--- vim: set ts=8 sw=2 sts=2 expandtab:
diff --git a/cλash/CLasH/Translator/Annotations.hs b/cλash/CLasH/Translator/Annotations.hs
deleted file mode 100644 (file)
index 2c87550..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-{-# LANGUAGE DeriveDataTypeable #-}
-module CLasH.Translator.Annotations where
-  
-import qualified Language.Haskell.TH as TH
-import Data.Data
-
-data CLasHAnn = TopEntity | InitState TH.Name | TestInput | TestCycles
-  deriving (Show, Data, Typeable)
-  
-isTopEntity :: CLasHAnn -> Bool
-isTopEntity TopEntity = True
-isTopEntity _         = False
-
-isInitState :: CLasHAnn -> Bool
-isInitState (InitState _) = True
-isInitState _             = False
-
-isTestInput :: CLasHAnn -> Bool
-isTestInput TestInput = True
-isTestInput _         = False
-
-isTestCycles :: CLasHAnn -> Bool
-isTestCycles TestCycles = True
-isTestCycles _          = False
\ No newline at end of file
diff --git a/cλash/CLasH/Translator/TranslatorTypes.hs b/cλash/CLasH/Translator/TranslatorTypes.hs
deleted file mode 100644 (file)
index eabb004..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-{-# LANGUAGE TemplateHaskell #-}
---
--- Simple module providing some types used by Translator. These are in a
--- separate module to prevent circular dependencies in Pretty for example.
---
-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 qualified Data.Accessor.Monad.Trans.State as MonadState
-
--- GHC API
-import qualified GHC
-import qualified CoreSyn
-import qualified Type
-import qualified HscTypes
-import qualified UniqSupply
-
--- VHDL Imports
-import qualified Language.VHDL.AST as AST
-
--- Local imports
-import CLasH.VHDL.VHDLTypes
-
--- | A specification of an entity we can generate VHDL for. Consists of the
---   binder of the top level entity, an optional initial state and an optional
---   test input.
-type EntitySpec = (Maybe CoreSyn.CoreBndr, Maybe [(CoreSyn.CoreBndr, CoreSyn.CoreBndr)], Maybe CoreSyn.CoreExpr)
-
--- | A function that knows which parts of a module to compile
-type Finder =
-  HscTypes.CoreModule -- ^ The module to look at
-  -> GHC.Ghc [EntitySpec]
-
------------------------------------------------------------------------------
--- The TranslatorSession
------------------------------------------------------------------------------
-
--- A orderable equivalent of CoreSyn's Type for use as a map key
-newtype OrdType = OrdType 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 = AggrType String [HType] |
-             EnumType String [String] |
-             VecType Int HType |
-             UVecType HType |
-             SizedWType Int |
-             RangedWType Int |
-             SizedIType Int |
-             BuiltinType String |
-             StateType
-  deriving (Eq, Ord, Show)
-
--- A map of a Core type to the corresponding type name, or Nothing when the
--- type would be empty.
-type TypeMapRec   = Maybe (AST.VHDLId, Maybe (Either AST.TypeDef AST.SubtypeIn))
-type TypeMap      = Map.Map HType TypeMapRec
-
--- 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 (HType, 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_  :: [Maybe 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
-
--- 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
-  , tsEntityCounter_ :: Integer
-  , tsEntities_ :: Map.Map CoreSyn.CoreBndr Entity
-  , tsArchitectures_ :: Map.Map CoreSyn.CoreBndr (Architecture, [CoreSyn.CoreBndr])
-  , tsInitStates_ :: Map.Map CoreSyn.CoreBndr CoreSyn.CoreBndr
-  , tsTransformCounter_ :: Int -- ^ How many transformations were applied?
-}
-
--- Derive accessors
-Data.Accessor.Template.deriveAccessors ''TranslatorState
-
-type TranslatorSession = State.State TranslatorState
-
------------------------------------------------------------------------------
--- Some accessors
------------------------------------------------------------------------------
-
--- Does the given binder reference a top level binder in the current
--- module(s)?
-isTopLevelBinder :: CoreSyn.CoreBndr -> TranslatorSession Bool
-isTopLevelBinder bndr = do
-  bindings <- MonadState.get tsBindings
-  return $ Map.member bndr bindings
-
--- Finds the value of a global binding, if available
-getGlobalBind :: CoreSyn.CoreBndr -> TranslatorSession (Maybe CoreSyn.CoreExpr)
-getGlobalBind bndr = do
-  bindings <- MonadState.get tsBindings
-  return $ Map.lookup bndr bindings 
-
--- Adds a new global binding with the given value
-addGlobalBind :: CoreSyn.CoreBndr -> CoreSyn.CoreExpr -> TranslatorSession ()
-addGlobalBind bndr expr = MonadState.modify tsBindings (Map.insert bndr expr)
-
--- Returns a list of all global binders
-getGlobalBinders :: TranslatorSession [CoreSyn.CoreBndr]
-getGlobalBinders = do
-  bindings <- MonadState.get tsBindings
-  return $ Map.keys bindings
-
--- vim: set ts=8 sw=2 sts=2 expandtab:
diff --git a/cλash/CLasH/Utils.hs b/cλash/CLasH/Utils.hs
deleted file mode 100644 (file)
index d85b25b..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-module CLasH.Utils where
-
--- Standard Imports
-import qualified Maybe
-import Data.Accessor
-import qualified Data.Accessor.Monad.Trans.State as MonadState
-import qualified Data.Map as Map
-import qualified Control.Monad as Monad
-import qualified Control.Monad.Trans.State as State
-import qualified Debug.Trace as Trace
-  
--- 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 <- MonadState.get 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
-      MonadState.modify accessor (Map.insert key value)
-      return value
-
-unzipM :: (Monad m) =>
-  m [(a, b)]
-  -> m ([a], [b])
-unzipM = Monad.liftM unzip
-
-catMaybesM :: (Monad m) =>
-  m [Maybe a]
-  -> m [a]
-catMaybesM = Monad.liftM Maybe.catMaybes
-
-concatM :: (Monad m) =>
-  m [[a]]
-  -> m [a]
-concatM = Monad.liftM concat
-
-isJustM :: (Monad m) => m (Maybe a) -> m Bool
-isJustM = Monad.liftM Maybe.isJust
-
-andM, orM :: (Monad m) => m [Bool] -> m Bool
-andM = Monad.liftM and
-orM = Monad.liftM or
-
--- | Monadic versions of any and all. We reimplement them, since there
--- is no ready-made lifting function for them.
-allM, anyM :: (Monad m) => (a -> m Bool) -> [a] -> m Bool
-allM f = andM . (mapM f)
-anyM f = orM . (mapM f)
-
-mapAccumLM :: (Monad m) => (acc -> x -> m (acc, y)) -> acc -> [x] -> m (acc, [y])
-mapAccumLM _ s []        =  return (s, [])
-mapAccumLM f s (x:xs)    =  do
-  (s',  y ) <- f s x
-  (s'', ys) <- mapAccumLM f s' xs
-  return (s'', y:ys)
-
--- Trace the given string if the given bool is True, do nothing
--- otherwise.
-traceIf :: Bool -> String -> a -> a
-traceIf True = Trace.trace
-traceIf False = flip const
diff --git a/cλash/CLasH/Utils/Core/BinderTools.hs b/cλash/CLasH/Utils/Core/BinderTools.hs
deleted file mode 100644 (file)
index cd01675..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
---
--- This module contains functions that manipulate binders in various ways.
---
-module CLasH.Utils.Core.BinderTools where
-
--- Standard modules
-import qualified Data.Accessor.Monad.Trans.State as MonadState
-
--- GHC API
-import qualified CoreSyn
-import qualified Type
-import qualified UniqSupply
-import qualified Unique
-import qualified OccName
-import qualified Name
-import qualified Module
-import qualified Var
-import qualified SrcLoc
-import qualified IdInfo
-import qualified CoreUtils
-
--- Local imports
-import CLasH.Translator.TranslatorTypes
-
--- Create a new Unique
-mkUnique :: TranslatorSession Unique.Unique    
-mkUnique = do
-  us <- MonadState.get tsUniqSupply 
-  let (us', us'') = UniqSupply.splitUniqSupply us
-  MonadState.set tsUniqSupply us'
-  return $ UniqSupply.uniqFromSupply us''
-
--- Create a new internal var with the given name and type. A Unique is
--- appended to the given name, to ensure uniqueness (not strictly neccesary,
--- since the Unique is also stored in the name, but this ensures variable
--- names are unique in the output).
-mkInternalVar :: String -> Type.Type -> TranslatorSession Var.Var
-mkInternalVar str ty = do
-  uniq <- mkUnique
-  let occname = OccName.mkVarOcc (str ++ show uniq)
-  let name = Name.mkInternalName uniq occname SrcLoc.noSrcSpan
-  return $ Var.mkLocalVar IdInfo.VanillaId name ty IdInfo.vanillaIdInfo
-
--- Create a new type variable with the given name and kind. A Unique is
--- appended to the given name, to ensure uniqueness (not strictly neccesary,
--- since the Unique is also stored in the name, but this ensures variable
--- names are unique in the output).
-mkTypeVar :: String -> Type.Kind -> TranslatorSession Var.Var
-mkTypeVar str kind = do
-  uniq <- mkUnique
-  let occname = OccName.mkVarOcc (str ++ show uniq)
-  let name = Name.mkInternalName uniq occname SrcLoc.noSrcSpan
-  return $ Var.mkTyVar name kind
-
--- Creates a binder for the given expression with the given name. This
--- works for both value and type level expressions, so it can return a Var or
--- TyVar (which is just an alias for Var).
-mkBinderFor :: CoreSyn.CoreExpr -> String -> TranslatorSession Var.Var
-mkBinderFor (CoreSyn.Type ty) string = mkTypeVar string (Type.typeKind ty)
-mkBinderFor expr string = mkInternalVar string (CoreUtils.exprType expr)
-
--- Creates a reference to the given variable. This works for both a normal
--- variable as well as a type variable
-mkReferenceTo :: Var.Var -> CoreSyn.CoreExpr
-mkReferenceTo var | Var.isTyVar var = (CoreSyn.Type $ Type.mkTyVarTy var)
-                  | otherwise       = (CoreSyn.Var var)
-
-cloneVar :: Var.Var -> TranslatorSession Var.Var
-cloneVar v = do
-  uniq <- mkUnique
-  -- Swap out the unique, and reset the IdInfo (I'm not 100% sure what it
-  -- contains, but vannillaIdInfo is always correct, since it means "no info").
-  return $ Var.lazySetIdInfo (Var.setVarUnique v uniq) IdInfo.vanillaIdInfo
-
--- Creates a new function with the same name as the given binder (but with a
--- new unique) and with the given function body. Returns the new binder for
--- this function.
-mkFunction :: CoreSyn.CoreBndr -> CoreSyn.CoreExpr -> TranslatorSession CoreSyn.CoreBndr
-mkFunction bndr body = do
-  let ty = CoreUtils.exprType body
-  id <- cloneVar bndr
-  let newid = Var.setVarType id ty
-  addGlobalBind newid body
-  return newid
-
--- Returns the full name of a NamedThing, in the forum
--- modulename.occname
-getFullString :: Name.NamedThing a => a -> String
-getFullString thing = modstr ++ occstr
-  where
-    name    = Name.getName thing
-    modstr  = case Name.nameModule_maybe name of
-      Nothing -> ""
-      Just mod -> Module.moduleNameString (Module.moduleName mod) ++ "."
-    occstr  = Name.getOccString name
diff --git a/cλash/CLasH/Utils/Core/CoreShow.hs b/cλash/CLasH/Utils/Core/CoreShow.hs
deleted file mode 100644 (file)
index ca2a7fb..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-{-# LANGUAGE StandaloneDeriving,FlexibleInstances, UndecidableInstances, OverlappingInstances #-}
---
--- This module derives Show instances for CoreSyn types.
---
-module CLasH.Utils.Core.CoreShow where
-
--- GHC API
-import qualified BasicTypes
-import qualified CoreSyn
-import qualified TypeRep
-import qualified TyCon
-import qualified HsTypes
-import qualified HsExpr
-import qualified HsBinds
-import qualified SrcLoc
-import qualified RdrName
-import Outputable ( Outputable, OutputableBndr, showSDoc, ppr)
-
--- Derive Show for core expressions and binders, so we can see the actual
--- structure.
-deriving instance (Show b) => Show (CoreSyn.Expr b)
-deriving instance (Show b) => Show (CoreSyn.Bind b)
-deriving instance Show TypeRep.Type
-deriving instance (Show n, OutputableBndr n) => Show (HsTypes.HsType n)
-deriving instance (Show n, OutputableBndr n) => Show (HsTypes.ConDeclField n)
-deriving instance (Show x) => Show (SrcLoc.Located x)
-deriving instance (Show x, OutputableBndr x) => Show (HsExpr.StmtLR x x)
-deriving instance (Show x, OutputableBndr x) => Show (HsExpr.HsTupArg x)
-deriving instance (Show x, OutputableBndr x) => Show (HsExpr.HsExpr x)
-deriving instance Show (RdrName.RdrName)
-deriving instance (Show idL, Show idR, OutputableBndr idL, OutputableBndr idR) => Show (HsBinds.HsBindLR idL idR)
-deriving instance Show CoreSyn.Note
-deriving instance Show TyCon.SynTyConRhs
-
-
--- Implement dummy shows, since deriving them will need loads of other shows
--- as well.
-instance Show TypeRep.PredType where
-  show t = "_PredType:(" ++ showSDoc (ppr t) ++ ")"
-instance Show TyCon.TyCon where
-  show t | TyCon.isAlgTyCon t && not (TyCon.isTupleTyCon t) =
-           showtc "AlgTyCon" ""
-         | TyCon.isCoercionTyCon t =
-           showtc "CoercionTyCon" ""
-         | TyCon.isSynTyCon t =
-           showtc "SynTyCon" (", synTcRhs = " ++ synrhs)
-         | TyCon.isTupleTyCon t =
-           showtc "TupleTyCon" ""
-         | TyCon.isFunTyCon t =
-           showtc "FunTyCon" ""
-         | TyCon.isPrimTyCon t =
-           showtc "PrimTyCon" ""
-         | TyCon.isSuperKindTyCon t =
-           showtc "SuperKindTyCon" ""
-         | otherwise = 
-           "_Nonexistant tycon?:(" ++ showSDoc (ppr t) ++ ")_"
-      where
-        showtc con extra = "(" ++ con ++ " {tyConName = " ++ name ++ extra ++ ", ...})"
-        name = show (TyCon.tyConName t)
-        synrhs = show (TyCon.synTyConRhs t)
-instance Show BasicTypes.Boxity where
-  show b = "_Boxity"
-instance Show HsTypes.HsExplicitForAll where
-  show b = "_HsExplicitForAll"
-instance Show HsExpr.HsArrAppType where
-  show b = "_HsArrAppType"
-instance Show (HsExpr.MatchGroup x) where
-  show b = "_HsMatchGroup"
-instance Show (HsExpr.GroupByClause x) where
-  show b = "_GroupByClause"
-instance Show (HsExpr.HsStmtContext x) where
-  show b = "_HsStmtContext"
-instance Show (HsBinds.Prag) where
-  show b = "_Prag"
-instance Show (HsExpr.GRHSs id) where
-  show b = "_GRHSs"
-
-
-instance (Outputable x) => Show x where
-  show x = "__" ++ showSDoc (ppr x) ++ "__"
diff --git a/cλash/CLasH/Utils/Core/CoreTools.hs b/cλash/CLasH/Utils/Core/CoreTools.hs
deleted file mode 100644 (file)
index 2bb688b..0000000
+++ /dev/null
@@ -1,463 +0,0 @@
-{-# LANGUAGE PatternGuards, TypeSynonymInstances #-}
--- | This module provides a number of functions to find out things about Core
--- programs. This module does not provide the actual plumbing to work with
--- Core and Haskell (it uses HsTools for this), but only the functions that
--- know about various libraries and know which functions to call.
-module CLasH.Utils.Core.CoreTools where
-
---Standard modules
-import qualified Maybe
-import qualified System.IO.Unsafe
-import qualified Data.Map as Map
-import qualified Data.Accessor.Monad.Trans.State as MonadState
-
--- GHC API
-import qualified GHC
-import qualified Type
-import qualified TcType
-import qualified HsExpr
-import qualified HsTypes
-import qualified HscTypes
-import qualified Name
-import qualified Id
-import qualified TyCon
-import qualified DataCon
-import qualified TysWiredIn
-import qualified DynFlags
-import qualified SrcLoc
-import qualified CoreSyn
-import qualified Var
-import qualified IdInfo
-import qualified VarSet
-import qualified CoreUtils
-import qualified CoreFVs
-import qualified Literal
-import qualified MkCore
-import qualified VarEnv
-
--- Local imports
-import CLasH.Translator.TranslatorTypes
-import CLasH.Utils.GhcTools
-import CLasH.Utils.Core.BinderTools
-import CLasH.Utils.HsTools
-import CLasH.Utils.Pretty
-import CLasH.Utils
-import qualified CLasH.Utils.Core.BinderTools as BinderTools
-
--- | A single binding, used as a shortcut to simplify type signatures.
-type Binding = (CoreSyn.CoreBndr, CoreSyn.CoreExpr)
-
--- | Evaluate a core Type representing type level int from the tfp
--- library to a real int. Checks if the type really is a Dec type and
--- caches the results.
-tfp_to_int :: Type.Type -> TypeSession Int
-tfp_to_int ty = do
-  hscenv <- MonadState.get tsHscEnv
-  let norm_ty = normalize_tfp_int hscenv ty
-  case Type.splitTyConApp_maybe norm_ty of
-    Just (tycon, args) -> do
-      let name = Name.getOccString (TyCon.tyConName tycon)
-      case name of
-        "Dec" ->
-          tfp_to_int' ty
-        otherwise -> do
-          return $ error ("Callin tfp_to_int on non-dec:" ++ (show ty))
-    Nothing -> return $ error ("Callin tfp_to_int on non-dec:" ++ (show ty))
-
--- | Evaluate a core Type representing type level int from the tfp
--- library to a real int. Caches the results. Do not use directly, use
--- tfp_to_int instead.
-tfp_to_int' :: Type.Type -> TypeSession Int
-tfp_to_int' ty = do
-  lens <- MonadState.get tsTfpInts
-  hscenv <- MonadState.get tsHscEnv
-  let norm_ty = normalize_tfp_int hscenv ty
-  let existing_len = Map.lookup (OrdType norm_ty) lens
-  case existing_len of
-    Just len -> return len
-    Nothing -> do
-      let new_len = eval_tfp_int hscenv ty
-      MonadState.modify tsTfpInts (Map.insert (OrdType norm_ty) (new_len))
-      return new_len
-      
--- | Evaluate a core Type representing type level int from the tfp
--- library to a real int. Do not use directly, use tfp_to_int instead.
-eval_tfp_int :: HscTypes.HscEnv -> Type.Type -> Int
-eval_tfp_int env ty =
-  unsafeRunGhc libdir $ do
-    GHC.setSession env
-    -- Automatically import modules for any fully qualified identifiers
-    setDynFlag DynFlags.Opt_ImplicitImportQualified
-
-    let from_int_t_name = mkRdrName "Types.Data.Num.Ops" "fromIntegerT"
-    let from_int_t = SrcLoc.noLoc $ HsExpr.HsVar from_int_t_name
-    let undef = hsTypedUndef $ coreToHsType ty
-    let app = SrcLoc.noLoc $ HsExpr.HsApp (from_int_t) (undef)
-    let int_ty = SrcLoc.noLoc $ HsTypes.HsTyVar TysWiredIn.intTyCon_RDR
-    let expr = HsExpr.ExprWithTySig app int_ty
-    core <- toCore expr
-    execCore core
-  where
-    libdir = DynFlags.topDir dynflags
-    dynflags = HscTypes.hsc_dflags env
-
-normalize_tfp_int :: HscTypes.HscEnv -> Type.Type -> Type.Type
-normalize_tfp_int env ty =
-   System.IO.Unsafe.unsafePerformIO $
-     normalizeType env ty
-
-sized_word_len_ty :: Type.Type -> Type.Type
-sized_word_len_ty ty = len
-  where
-    args = case Type.splitTyConApp_maybe ty of
-      Just (tycon, args) -> args
-      Nothing -> error $ "\nCoreTools.sized_word_len_ty: Not a sized word type: " ++ (pprString ty)
-    [len]         = args
-
-sized_int_len_ty :: Type.Type -> Type.Type
-sized_int_len_ty ty = len
-  where
-    args = case Type.splitTyConApp_maybe ty of
-      Just (tycon, args) -> args
-      Nothing -> error $ "\nCoreTools.sized_int_len_ty: Not a sized int type: " ++ (pprString ty)
-    [len]         = args
-    
-ranged_word_bound_ty :: Type.Type -> Type.Type
-ranged_word_bound_ty ty = len
-  where
-    args = case Type.splitTyConApp_maybe ty of
-      Just (tycon, args) -> args
-      Nothing -> error $ "\nCoreTools.ranged_word_bound_ty: Not a sized word type: " ++ (pprString ty)
-    [len]         = args
-
-tfvec_len_ty :: Type.Type -> Type.Type
-tfvec_len_ty ty = len
-  where  
-    args = case Type.splitTyConApp_maybe ty of
-      Just (tycon, args) -> args
-      Nothing -> error $ "\nCoreTools.tfvec_len_ty: Not a vector type: " ++ (pprString ty)
-    [len, el_ty] = args
-    
--- | Get the element type of a TFVec type
-tfvec_elem :: Type.Type -> Type.Type
-tfvec_elem ty = el_ty
-  where
-    args = case Type.splitTyConApp_maybe ty of
-      Just (tycon, args) -> args
-      Nothing -> error $ "\nCoreTools.tfvec_len: Not a vector type: " ++ (pprString ty)
-    [len, el_ty] = args
-
--- Is the given core expression a lambda abstraction?
-is_lam :: CoreSyn.CoreExpr -> Bool
-is_lam (CoreSyn.Lam _ _) = True
-is_lam _ = False
-
--- Is the given core expression a let expression?
-is_let :: CoreSyn.CoreExpr -> Bool
-is_let (CoreSyn.Let _ _) = True
-is_let _ = False
-
--- Is the given core expression of a function type?
-is_fun :: CoreSyn.CoreExpr -> Bool
--- Treat Type arguments differently, because exprType is not defined for them.
-is_fun (CoreSyn.Type _) = False
-is_fun expr = (Type.isFunTy . CoreUtils.exprType) expr
-
--- Is the given core expression polymorphic (i.e., does it accept type
--- arguments?).
-is_poly :: CoreSyn.CoreExpr -> Bool
--- Treat Type arguments differently, because exprType is not defined for them.
-is_poly (CoreSyn.Type _) = False
-is_poly expr = (Maybe.isJust . Type.splitForAllTy_maybe . CoreUtils.exprType) expr
-
--- Is the given core expression a variable reference?
-is_var :: CoreSyn.CoreExpr -> Bool
-is_var (CoreSyn.Var _) = True
-is_var _ = False
-
-is_lit :: CoreSyn.CoreExpr -> Bool
-is_lit (CoreSyn.Lit _) = True
-is_lit _ = False
-
--- Can the given core expression be applied to something? This is true for
--- applying to a value as well as a type.
-is_applicable :: CoreSyn.CoreExpr -> Bool
-is_applicable expr = is_fun expr || is_poly expr
-
--- Is the given core expression a variable or an application?
-is_simple :: CoreSyn.CoreExpr -> Bool
-is_simple (CoreSyn.App _ _) = True
-is_simple (CoreSyn.Var _) = True
-is_simple (CoreSyn.Cast expr _) = is_simple expr
-is_simple _ = False
-
--- Does the given CoreExpr have any free type vars?
-has_free_tyvars :: CoreSyn.CoreExpr -> Bool
-has_free_tyvars = not . VarSet.isEmptyVarSet . (CoreFVs.exprSomeFreeVars Var.isTyVar)
-
--- Does the given type have any free type vars?
-ty_has_free_tyvars :: Type.Type -> Bool
-ty_has_free_tyvars = not . VarSet.isEmptyVarSet . Type.tyVarsOfType
-
--- Does the given CoreExpr have any free local vars?
-has_free_vars :: CoreSyn.CoreExpr -> Bool
-has_free_vars = not . VarSet.isEmptyVarSet . CoreFVs.exprFreeVars
-
--- Does the given expression use any of the given binders?
-expr_uses_binders :: [CoreSyn.CoreBndr] -> CoreSyn.CoreExpr -> Bool
-expr_uses_binders bndrs = not . VarSet.isEmptyVarSet . (CoreFVs.exprSomeFreeVars (`elem` bndrs))
-
--- Turns a Var CoreExpr into the Id inside it. Will of course only work for
--- simple Var CoreExprs, not complexer ones.
-exprToVar :: CoreSyn.CoreExpr -> Var.Id
-exprToVar (CoreSyn.Var id) = id
-exprToVar expr = error $ "\nCoreTools.exprToVar: Not a var: " ++ show expr
-
--- Turns a Lit CoreExpr into the Literal inside it.
-exprToLit :: CoreSyn.CoreExpr -> Literal.Literal
-exprToLit (CoreSyn.Lit lit) = lit
-exprToLit expr = error $ "\nCoreTools.exprToLit: Not a lit: " ++ show expr
-
--- Removes all the type and dictionary arguments from the given argument list,
--- leaving only the normal value arguments. The type given is the type of the
--- expression applied to this argument list.
-get_val_args :: Type.Type -> [CoreSyn.CoreExpr] -> [CoreSyn.CoreExpr]
-get_val_args ty args = drop n args
-  where
-    (tyvars, predtypes, _) = TcType.tcSplitSigmaTy ty
-    -- The first (length tyvars) arguments should be types, the next 
-    -- (length predtypes) arguments should be dictionaries. We drop this many
-    -- arguments, to get at the value arguments.
-    n = length tyvars + length predtypes
-
--- Finds out what literal Integer this expression represents.
-getIntegerLiteral :: CoreSyn.CoreExpr -> TranslatorSession Integer
-getIntegerLiteral expr =
-  case CoreSyn.collectArgs expr of
-    (CoreSyn.Var f, [CoreSyn.Lit (Literal.MachInt integer)]) 
-      | getFullString f == "GHC.Integer.smallInteger" -> return integer
-    (CoreSyn.Var f, [CoreSyn.Lit (Literal.MachInt64 integer)]) 
-      | getFullString f == "GHC.Integer.int64ToInteger" -> return integer
-    (CoreSyn.Var f, [CoreSyn.Lit (Literal.MachWord integer)]) 
-      | getFullString f == "GHC.Integer.wordToInteger" -> return integer
-    (CoreSyn.Var f, [CoreSyn.Lit (Literal.MachWord64 integer)]) 
-      | getFullString f == "GHC.Integer.word64ToInteger" -> return integer
-    -- fromIntegerT returns the integer corresponding to the type of its
-    -- (third) argument. Since it is polymorphic, the type of that
-    -- argument is passed as the first argument, so we can just use that
-    -- one.
-    (CoreSyn.Var f, [CoreSyn.Type dec_ty, dec_dict, CoreSyn.Type num_ty, num_dict, arg]) 
-      | getFullString f == "Types.Data.Num.Ops.fromIntegerT" -> do
-          int <- MonadState.lift tsType $ tfp_to_int dec_ty
-          return $ toInteger int
-    _ -> error $ "CoreTools.getIntegerLiteral: Unsupported Integer literal: " ++ pprString expr
-
-reduceCoreListToHsList :: 
-  [HscTypes.CoreModule] -- ^ The modules where parts of the list are hidden
-  -> CoreSyn.CoreExpr   -- ^ The refence to atleast one of the nodes
-  -> TranslatorSession [CoreSyn.CoreExpr]
-reduceCoreListToHsList cores app@(CoreSyn.App _ _) = do {
-  ; let { (fun, args) = CoreSyn.collectArgs app
-        ; len         = length args 
-        } ;
-  ; case len of
-      3 -> do {
-        ; let topelem = args!!1
-        ; case (args!!2) of
-            (varz@(CoreSyn.Var id)) -> do {
-              ; binds <- mapM (findExpr (isVarName id)) cores
-              ; otherelems <- reduceCoreListToHsList cores (head (Maybe.catMaybes binds))
-              ; return (topelem:otherelems)
-              }
-            (appz@(CoreSyn.App _ _)) -> do {
-              ; otherelems <- reduceCoreListToHsList cores appz
-              ; return (topelem:otherelems)
-              }
-            otherwise -> return [topelem]
-        }
-      otherwise -> return []
-  }
-  where
-    isVarName :: Monad m => Var.Var -> Var.Var -> m Bool
-    isVarName lookfor bind = return $ (Var.varName lookfor) == (Var.varName bind)
-
-reduceCoreListToHsList _ _ = return []
-
--- Is the given var the State data constructor?
-isStateCon :: Var.Var -> Bool
-isStateCon var =
-  -- See if it is a DataConWrapId (not DataConWorkId, since State is a
-  -- newtype).
-  case Id.idDetails var of
-    IdInfo.DataConWrapId dc -> 
-      -- See if the datacon is the State datacon from the State type.
-      let tycon = DataCon.dataConTyCon dc
-          tyname = Name.getOccString tycon
-          dcname = Name.getOccString dc
-      in case (tyname, dcname) of
-        ("State", "State") -> True
-        _ -> False
-    _ -> False
-
--- | Is the given type a State type?
-isStateType :: Type.Type -> Bool
--- Resolve any type synonyms remaining
-isStateType ty | Just ty' <- Type.tcView ty = isStateType ty'
-isStateType ty  = Maybe.isJust $ do
-  -- Split the type. Don't use normal splitAppTy, since that looks through
-  -- newtypes, and we want to see the State newtype.
-  (typef, _) <- Type.repSplitAppTy_maybe ty
-  -- See if the applied type is a type constructor
-  (tycon, _) <- Type.splitTyConApp_maybe typef
-  if TyCon.isNewTyCon tycon && Name.getOccString tycon == "State"
-    then
-      Just ()
-    else
-      Nothing
-
--- | Does the given TypedThing have a State type?
-hasStateType :: (TypedThing t) => t -> Bool
-hasStateType expr = case getType expr of
-  Nothing -> False
-  Just ty -> isStateType ty
-
-
--- | Flattens nested lets into a single list of bindings. The expression
---   passed does not have to be a let expression, if it isn't an empty list of
---   bindings is returned.
-flattenLets ::
-  CoreSyn.CoreExpr -- ^ The expression to flatten.
-  -> ([Binding], CoreSyn.CoreExpr) -- ^ The bindings and resulting expression.
-flattenLets (CoreSyn.Let binds expr) = 
-  (bindings ++ bindings', expr')
-  where
-    -- Recursively flatten the contained expression
-    (bindings', expr') =flattenLets expr
-    -- Flatten our own bindings to remove the Rec / NonRec constructors
-    bindings = CoreSyn.flattenBinds [binds]
-flattenLets expr = ([], expr)
-
--- | Create bunch of nested non-recursive let expressions from the given
--- bindings. The first binding is bound at the highest level (and thus
--- available in all other bindings).
-mkNonRecLets :: [Binding] -> CoreSyn.CoreExpr -> CoreSyn.CoreExpr
-mkNonRecLets bindings expr = MkCore.mkCoreLets binds expr
-  where
-    binds = map (uncurry CoreSyn.NonRec) bindings
-
--- | A class of things that (optionally) have a core Type. The type is
--- optional, since Type expressions don't have a type themselves.
-class TypedThing t where
-  getType :: t -> Maybe Type.Type
-
-instance TypedThing CoreSyn.CoreExpr where
-  getType (CoreSyn.Type _) = Nothing
-  getType expr = Just $ CoreUtils.exprType expr
-
-instance TypedThing CoreSyn.CoreBndr where
-  getType = return . Id.idType
-
-instance TypedThing Type.Type where
-  getType = return . id
-
--- | Generate new uniques for all binders in the given expression.
--- Does not support making type variables unique, though this could be
--- supported if required (by passing a CoreSubst.Subst instead of VarEnv to
--- genUniques' below).
-genUniques :: CoreSyn.CoreExpr -> TranslatorSession CoreSyn.CoreExpr
-genUniques = genUniques' VarEnv.emptyVarEnv
-
--- | A helper function to generate uniques, that takes a VarEnv containing the
---   substitutions already performed.
-genUniques' :: VarEnv.VarEnv CoreSyn.CoreBndr -> CoreSyn.CoreExpr -> TranslatorSession CoreSyn.CoreExpr
-genUniques' subst (CoreSyn.Var f) = do
-  -- Replace the binder with its new value, if applicable.
-  let f' = VarEnv.lookupWithDefaultVarEnv subst f f
-  return (CoreSyn.Var f')
--- Leave literals untouched
-genUniques' subst (CoreSyn.Lit l) = return $ CoreSyn.Lit l
-genUniques' subst (CoreSyn.App f arg) = do
-  -- Only work on subexpressions
-  f' <- genUniques' subst f
-  arg' <- genUniques' subst arg
-  return (CoreSyn.App f' arg')
--- Don't change type abstractions
-genUniques' subst expr@(CoreSyn.Lam bndr res) | CoreSyn.isTyVar bndr = return expr
-genUniques' subst (CoreSyn.Lam bndr res) = do
-  -- Generate a new unique for the bound variable
-  (subst', bndr') <- genUnique subst bndr
-  res' <- genUniques' subst' res
-  return (CoreSyn.Lam bndr' res')
-genUniques' subst (CoreSyn.Let (CoreSyn.NonRec bndr bound) res) = do
-  -- Make the binders unique
-  (subst', bndr') <- genUnique subst bndr
-  bound' <- genUniques' subst' bound
-  res' <- genUniques' subst' res
-  return $ CoreSyn.Let (CoreSyn.NonRec bndr' bound') res'
-genUniques' subst (CoreSyn.Let (CoreSyn.Rec binds) res) = do
-  -- Make each of the binders unique
-  (subst', bndrs') <- mapAccumLM genUnique subst (map fst binds)
-  bounds' <- mapM (genUniques' subst' . snd) binds
-  res' <- genUniques' subst' res
-  let binds' = zip bndrs' bounds'
-  return $ CoreSyn.Let (CoreSyn.Rec binds') res'
-genUniques' subst (CoreSyn.Case scrut bndr ty alts) = do
-  -- Process the scrutinee with the original substitution, since non of the
-  -- binders bound in the Case statement is in scope in the scrutinee.
-  scrut' <- genUniques' subst scrut
-  -- Generate a new binder for the scrutinee
-  (subst', bndr') <- genUnique subst bndr
-  -- Process each of the alts
-  alts' <- mapM (doalt subst') alts
-  return $ CoreSyn.Case scrut' bndr' ty alts'
-  where
-    doalt subst (con, bndrs, expr) = do
-      (subst', bndrs') <- mapAccumLM genUnique subst bndrs
-      expr' <- genUniques' subst' expr
-      -- Note that we don't return subst', since bndrs are only in scope in
-      -- expr.
-      return (con, bndrs', expr')
-genUniques' subst (CoreSyn.Cast expr coercion) = do
-  expr' <- genUniques' subst expr
-  -- Just process the casted expression
-  return $ CoreSyn.Cast expr' coercion
-genUniques' subst (CoreSyn.Note note expr) = do
-  expr' <- genUniques' subst expr
-  -- Just process the annotated expression
-  return $ CoreSyn.Note note expr'
--- Leave types untouched
-genUniques' subst expr@(CoreSyn.Type _) = return expr
-
--- Generate a new unique for the given binder, and extend the given
--- substitution to reflect this.
-genUnique :: VarEnv.VarEnv CoreSyn.CoreBndr -> CoreSyn.CoreBndr -> TranslatorSession (VarEnv.VarEnv CoreSyn.CoreBndr, CoreSyn.CoreBndr)
-genUnique subst bndr = do
-  bndr' <- BinderTools.cloneVar bndr
-  -- Replace all occurences of the old binder with a reference to the new
-  -- binder.
-  let subst' = VarEnv.extendVarEnv subst bndr bndr'
-  return (subst', bndr')
-
--- Create a "selector" case that selects the ith field from a datacon
-mkSelCase :: CoreSyn.CoreExpr -> Int -> TranslatorSession CoreSyn.CoreExpr
-mkSelCase scrut i = do
-  let scrut_ty = CoreUtils.exprType scrut
-  case Type.splitTyConApp_maybe scrut_ty of
-    -- The scrutinee should have a type constructor. We keep the type
-    -- arguments around so we can instantiate the field types below
-    Just (tycon, tyargs) -> case TyCon.tyConDataCons tycon of
-      -- The scrutinee type should have a single dataconstructor,
-      -- otherwise we can't construct a valid selector case.
-      [datacon] -> do
-        let field_tys = DataCon.dataConInstOrigArgTys datacon tyargs
-        -- Create a list of wild binders for the fields we don't want
-        let wildbndrs = map MkCore.mkWildBinder field_tys
-        -- Create a single binder for the field we want
-        sel_bndr <- mkInternalVar "sel" (field_tys!!i)
-        -- Create a wild binder for the scrutinee
-        let scrut_bndr = MkCore.mkWildBinder scrut_ty
-        -- Create the case expression
-        let binders = take i wildbndrs ++ [sel_bndr] ++ drop (i+1) wildbndrs
-        return $ CoreSyn.Case scrut scrut_bndr scrut_ty [(CoreSyn.DataAlt datacon, binders, CoreSyn.Var sel_bndr)]
-      dcs -> error $ "CoreTools.mkSelCase: Scrutinee type must have exactly one datacon. Extracting element " ++ (show i) ++ " from '" ++ pprString scrut ++ "' Datacons: " ++ (show dcs) ++ " Type: " ++ (pprString scrut_ty)
-    Nothing -> error $ "CoreTools.mkSelCase: Creating extractor case, but scrutinee has no tycon? Extracting element " ++ (show i) ++ " from '" ++ pprString scrut ++ "'" ++ " Type: " ++ (pprString scrut_ty)
diff --git a/cλash/CLasH/Utils/GhcTools.hs b/cλash/CLasH/Utils/GhcTools.hs
deleted file mode 100644 (file)
index 022a997..0000000
+++ /dev/null
@@ -1,256 +0,0 @@
-{-# LANGUAGE ScopedTypeVariables #-}
-
-module CLasH.Utils.GhcTools where
-  
--- Standard modules
-import qualified Monad
-import qualified System.IO.Unsafe
-import qualified Language.Haskell.TH as TH
-import qualified Maybe
-
--- GHC API
-import qualified Annotations
-import qualified CoreSyn
-import qualified CoreUtils
-import qualified DynFlags
-import qualified HscTypes
-import qualified GHC
-import qualified Name
-import qualified Serialized
-import qualified Var
-import qualified Outputable
-import Outputable(($+$), (<+>), nest, empty, text, vcat)
-import qualified Class
-
--- Local Imports
-import CLasH.Utils.Pretty
-import CLasH.Translator.TranslatorTypes
-import CLasH.Translator.Annotations
-import CLasH.Utils
-
--- How far to indent the values after a Foo: header
-align = 20
--- How far to indent all lines after the first
-indent = 5
-
-listBindings :: FilePath -> [FilePath] -> IO ()
-listBindings libdir filenames = do
-  (cores,_,_) <- loadModules libdir filenames Nothing
-  let binds = concatMap (CoreSyn.flattenBinds . HscTypes.cm_binds) cores
-  mapM listBinding binds
-  putStr "\n=========================\n"
-  let classes = concatMap (HscTypes.typeEnvClasses . HscTypes.cm_types) cores
-  mapM listClass classes
-  return ()
-
--- Slightly different version of hang, that always uses vcat instead of
--- sep, so the first line of d2 preserves its nesting.
-hang' d1 n d2 = vcat [d1, nest n d2]
-
-listBinding :: (CoreSyn.CoreBndr, CoreSyn.CoreExpr) -> IO ()
-listBinding (b, e) = putStr $ Outputable.showSDoc $
-  (text "Binder:") <+> (text $ show b ++ "[" ++ show (Var.varUnique b) ++ "]")
-  $+$ nest indent (
-    hang' (text "Type of Binder:") align (Outputable.ppr $ Var.varType b)
-    $+$ hang' (text "Expression:") align (text $ prettyShow e)
-    $+$ nest align (Outputable.ppr e)
-    $+$ hang' (text "Type of Expression:") align (Outputable.ppr $ CoreUtils.exprType e)
-  )
-  $+$ (text "\n") -- Add an empty line
-
-listClass :: Class.Class -> IO ()
-listClass c = putStr $ Outputable.showSDoc $
-  (text "Class:") <+> (text $ show (Class.className c))
-  $+$ nest indent (
-    hang' (text "Selectors:") align (text $ show (Class.classSelIds c))
-  )
-  $+$ (text "\n") -- Add an empty line
-  
--- | Show the core structure of the given binds in the given file.
-listBind :: FilePath -> [FilePath] -> String -> IO ()
-listBind libdir filenames name = do
-  (cores,_,_) <- loadModules libdir filenames Nothing
-  bindings <- concatM $ mapM (findBinder (hasVarName name)) cores
-  mapM_ listBinding bindings
-  return ()
-
--- Change a DynFlag from within the Ghc monad. Strangely enough there seems to
--- be no standard function to do exactly this.
-setDynFlag :: DynFlags.DynFlag -> GHC.Ghc ()
-setDynFlag dflag = do
-  dflags <- GHC.getSessionDynFlags
-  let dflags' = DynFlags.dopt_set dflags dflag
-  GHC.setSessionDynFlags dflags'
-  return ()
-
--- We don't want the IO monad sprinkled around everywhere, so we hide it.
--- This should be safe as long as we only do simple things in the GhcMonad
--- such as interface lookups and evaluating simple expressions that
--- don't have side effects themselves (Or rather, that don't use
--- unsafePerformIO themselves, since normal side effectful function would
--- just return an IO monad when they are evaluated).
-unsafeRunGhc :: FilePath -> GHC.Ghc a -> a
-unsafeRunGhc libDir m =
-  System.IO.Unsafe.unsafePerformIO $
-      GHC.runGhc (Just libDir) $ do
-        dflags <- GHC.getSessionDynFlags
-        GHC.setSessionDynFlags dflags
-        m
-  
--- | Loads the given files and turns it into a core module
-loadModules ::
-  FilePath      -- ^ The GHC Library directory 
-  -> [String]   -- ^ The files that need to be loaded
-  -> Maybe Finder -- ^ What entities to build?
-  -> IO ( [HscTypes.CoreModule]
-        , HscTypes.HscEnv
-        , [EntitySpec]
-        ) -- ^ ( The loaded modules, the resulting ghc environment, the entities to build)
-loadModules libdir filenames finder =
-  GHC.defaultErrorHandler DynFlags.defaultDynFlags $
-    GHC.runGhc (Just libdir) $ do
-      dflags <- GHC.getSessionDynFlags
-      GHC.setSessionDynFlags dflags
-      cores <- mapM GHC.compileToCoreModule filenames
-      env <- GHC.getSession
-      specs <- case finder of
-        Nothing -> return []
-        Just f -> concatM $ mapM f cores
-      return (cores, env, specs)
-
-findBinds ::
-  Monad m =>
-  (Var.Var -> m Bool)
-  -> HscTypes.CoreModule
-  -> m (Maybe [CoreSyn.CoreBndr])
-findBinds criteria core = do
-  binders <- findBinder criteria core
-  case binders of
-    [] -> return Nothing
-    bndrs -> return $ Just $ map fst bndrs
-
-findBind ::
-  Monad m =>
-  (Var.Var -> m Bool)
-  -> HscTypes.CoreModule
-  -> m (Maybe CoreSyn.CoreBndr)
-findBind criteria core = do
-  binders <- findBinds criteria core
-  case binders of
-    Nothing -> return Nothing
-    (Just bndrs) -> return $ Just $ head bndrs
-
-findExprs ::
-  Monad m =>
-  (Var.Var -> m Bool)
-  -> HscTypes.CoreModule
-  -> m (Maybe [CoreSyn.CoreExpr])
-findExprs criteria core = do
-  binders <- findBinder criteria core
-  case binders of
-    [] -> return Nothing
-    bndrs -> return $ Just (map snd bndrs)
-
-findExpr ::
-  Monad m =>
-  (Var.Var -> m Bool)
-  -> HscTypes.CoreModule
-  -> m (Maybe CoreSyn.CoreExpr)
-findExpr criteria core = do
-  exprs <- findExprs criteria core
-  case exprs of
-    Nothing -> return Nothing
-    (Just exprs) -> return $ Just $ head exprs
-
-findAnns ::
-  Monad m =>
-  (Var.Var -> m [CLasHAnn])
-  -> HscTypes.CoreModule
-  -> m [CLasHAnn]
-findAnns criteria core = do
-  let binds = CoreSyn.flattenBinds $ HscTypes.cm_binds core
-  anns <- Monad.mapM (criteria . fst) binds
-  case anns of
-    [] -> return []
-    xs -> return $ concat xs
-
--- | Find a binder in module according to a certain criteria
-findBinder :: 
-  Monad m =>
-  (Var.Var -> m Bool)     -- ^ The criteria to filter the binders on
-  -> HscTypes.CoreModule  -- ^ The module to be inspected
-  -> m [(CoreSyn.CoreBndr, CoreSyn.CoreExpr)] -- ^ The binders to meet the criteria
-findBinder criteria core = do
-  let binds = CoreSyn.flattenBinds $ HscTypes.cm_binds core
-  Monad.filterM (criteria . fst) binds
-
--- | Determine if a binder has an Annotation meeting a certain criteria
-isCLasHAnnotation ::
-  GHC.GhcMonad m =>
-  (CLasHAnn -> Bool)  -- ^ The criteria the Annotation has to meet
-  -> Var.Var          -- ^ The Binder
-  -> m [CLasHAnn]           -- ^ Indicates if binder has the Annotation
-isCLasHAnnotation clashAnn var = do
-  let deserializer = Serialized.deserializeWithData
-  let target = Annotations.NamedTarget (Var.varName var)
-  (anns :: [CLasHAnn]) <- GHC.findGlobalAnns deserializer target
-  let annEnts = filter clashAnn anns
-  return annEnts
-
--- | Determine if a binder has an Annotation meeting a certain criteria
-hasCLasHAnnotation ::
-  GHC.GhcMonad m =>
-  (CLasHAnn -> Bool)  -- ^ The criteria the Annotation has to meet
-  -> Var.Var          -- ^ The Binder
-  -> m Bool           -- ^ Indicates if binder has the Annotation
-hasCLasHAnnotation clashAnn var = do
-  anns <- isCLasHAnnotation clashAnn var
-  case anns of
-    [] -> return False
-    xs -> return True
-
--- | Determine if a binder has a certain name
-hasVarName ::   
-  Monad m =>
-  String        -- ^ The name the binder has to have
-  -> Var.Var    -- ^ The Binder
-  -> m Bool     -- ^ Indicate if the binder has the name
-hasVarName lookfor bind = return $ lookfor == Name.occNameString (Name.nameOccName $ Name.getName bind)
-
-
-findInitStates ::
-  (Var.Var -> GHC.Ghc Bool) -> 
-  (Var.Var -> GHC.Ghc [CLasHAnn]) -> 
-  HscTypes.CoreModule -> 
-  GHC.Ghc (Maybe [(CoreSyn.CoreBndr, CoreSyn.CoreBndr)])
-findInitStates statec annsc mod = do
-  states <- findBinds statec mod
-  anns  <- findAnns annsc mod
-  let funs = Maybe.catMaybes (map extractInits anns)
-  exprs' <- mapM (\x -> findBind (hasVarName (TH.nameBase x)) mod) funs
-  let exprs = Maybe.catMaybes exprs'
-  let inits = zipMWith (\a b -> (a,b)) states exprs
-  return inits
-  where
-    extractInits :: CLasHAnn -> Maybe TH.Name
-    extractInits (InitState x)  = Just x
-    extractInits _              = Nothing
-    zipMWith :: (a -> b -> c) -> (Maybe [a]) -> [b] -> (Maybe [c])
-    zipMWith _ Nothing   _  = Nothing
-    zipMWith f (Just as) bs = Just $ zipWith f as bs
-
--- | Make a complete spec out of a three conditions
-findSpec ::
-  (Var.Var -> GHC.Ghc Bool) -> (Var.Var -> GHC.Ghc Bool) -> (Var.Var -> GHC.Ghc [CLasHAnn]) -> (Var.Var -> GHC.Ghc Bool)
-  -> Finder
-
-findSpec topc statec annsc testc mod = do
-  top <- findBind topc mod
-  state <- findExprs statec mod
-  anns <- findAnns annsc mod
-  test <- findExpr testc mod
-  inits <- findInitStates statec annsc mod
-  return [(top, inits, test)]
-  -- case top of
-  --   Just t -> return [(t, state, test)]
-  --   Nothing -> return error $ "Could not find top entity requested"
diff --git a/cλash/CLasH/Utils/HsTools.hs b/cλash/CLasH/Utils/HsTools.hs
deleted file mode 100644 (file)
index 22b1382..0000000
+++ /dev/null
@@ -1,212 +0,0 @@
-module CLasH.Utils.HsTools where
-
--- Standard modules
-import qualified Unsafe.Coerce
-import qualified Maybe
-
--- GHC API
-import qualified GHC
-import qualified HscMain
-import qualified HscTypes
-import qualified DynFlags
-import qualified FastString
-import qualified StringBuffer
-import qualified MonadUtils
-import Outputable ( showSDoc, ppr )
-import qualified Outputable
--- Lexer & Parser, i.e. up to HsExpr
-import qualified Lexer
-import qualified Parser
--- HsExpr representation, renaming, typechecking and desugaring
--- (i.e., everything up to Core).
-import qualified HsSyn
-import qualified HsExpr
-import qualified HsTypes
-import qualified HsBinds
-import qualified TcRnMonad
-import qualified TcRnTypes
-import qualified RnExpr
-import qualified RnEnv
-import qualified TcExpr
-import qualified TcEnv
-import qualified TcSimplify
-import qualified TcTyFuns
-import qualified Desugar
-import qualified PrelNames
-import qualified Module
-import qualified OccName
-import qualified RdrName
-import qualified Name
-import qualified SrcLoc
-import qualified LoadIface
-import qualified BasicTypes
--- Core representation and handling
-import qualified CoreSyn
-import qualified Id
-import qualified Type
-import qualified TyCon
-
--- | Translate a HsExpr to a Core expression. This does renaming, type
--- checking, simplification of class instances and desugaring. The result is
--- a let expression that holds the given expression and a number of binds that
--- are needed for any type classes used to work. For example, the HsExpr:
---  \x = x == (1 :: Int)
--- will result in the CoreExpr
---  let 
---    $dInt = ...
---    (==) = Prelude.(==) Int $dInt 
---  in 
---    \x = (==) x 1
-toCore ::
-  HsSyn.HsExpr RdrName.RdrName -- ^ The expression to translate to Core.
-  -> GHC.Ghc CoreSyn.CoreExpr -- ^ The resulting core expression.
-toCore expr = do
-  env <- GHC.getSession
-  let icontext = HscTypes.hsc_IC env
-  
-  (binds, tc_expr) <- HscTypes.ioMsgMaybe $ MonadUtils.liftIO $ 
-    -- Translage the TcRn (typecheck-rename) monad into an IO monad
-    TcRnMonad.initTcPrintErrors env PrelNames.iNTERACTIVE $ do
-      (tc_expr, insts) <- TcRnMonad.getLIE $ do
-        -- Rename the expression, resulting in a HsExpr Name
-        (rn_expr, freevars) <- RnExpr.rnExpr expr
-        -- Typecheck the expression, resulting in a HsExpr Id and a list of
-        -- Insts
-        (res, _) <- TcExpr.tcInferRho (SrcLoc.noLoc rn_expr)
-        return res
-      -- Translate the instances into bindings
-      --(insts', binds) <- TcSimplify.tcSimplifyRuleLhs insts
-      binds <- TcSimplify.tcSimplifyTop insts
-      return (binds, tc_expr)
-  
-  -- Create a let expression with the extra binds (for polymorphism etc.) and
-  -- the resulting expression.
-  let letexpr = SrcLoc.noLoc $ HsExpr.HsLet 
-        (HsBinds.HsValBinds $ HsBinds.ValBindsOut [(BasicTypes.NonRecursive, binds)] [])
-        tc_expr
-  -- Desugar the expression, resulting in core.
-  let rdr_env  = HscTypes.ic_rn_gbl_env icontext
-  HscTypes.ioMsgMaybe $ Desugar.deSugarExpr env PrelNames.iNTERACTIVE rdr_env HscTypes.emptyTypeEnv letexpr
-
-
--- | Create an Id from a RdrName. Might not work for DataCons...
-mkId :: RdrName.RdrName -> GHC.Ghc Id.Id
-mkId rdr_name = do
-  env <- GHC.getSession
-  HscTypes.ioMsgMaybe $ MonadUtils.liftIO $ 
-    -- Translage the TcRn (typecheck-rename) monad in an IO monad
-    TcRnMonad.initTcPrintErrors env PrelNames.iNTERACTIVE $ 
-      -- Automatically import all available modules, so fully qualified names
-      -- always work
-      TcRnMonad.setOptM DynFlags.Opt_ImplicitImportQualified $ do
-        -- Lookup a Name for the RdrName. This finds the package (version) in
-        -- which the name resides.
-        name <- RnEnv.lookupGlobalOccRn rdr_name
-        -- Lookup an Id for the Name. This finds out the the type of the thing
-        -- we're looking for.
-        --
-        -- Note that tcLookupId doesn't seem to work for DataCons. See source for
-        -- tcLookupId to find out.
-        TcEnv.tcLookupId name 
-
-normalizeType ::
-  HscTypes.HscEnv
-  -> Type.Type
-  -> IO Type.Type
-normalizeType env ty = do
-   (err, nty) <- MonadUtils.liftIO $
-     -- Initialize the typechecker monad
-     TcRnMonad.initTcPrintErrors env PrelNames.iNTERACTIVE $ do
-       -- Normalize the type
-       (_, nty) <- TcTyFuns.tcNormaliseFamInst ty
-       return nty
-   let normalized_ty = Maybe.fromJust nty
-   return normalized_ty
-
--- | Translate a core Type to an HsType. Far from complete so far.
-coreToHsType :: Type.Type -> HsTypes.LHsType RdrName.RdrName
---  Translate TyConApps
-coreToHsType ty = case Type.splitTyConApp_maybe ty of
-  Just (tycon, tys) ->
-    foldl (\t a -> SrcLoc.noLoc $ HsTypes.HsAppTy t a) tycon_ty (map coreToHsType tys)
-    where
-      tycon_name = TyCon.tyConName tycon
-      mod_name = Module.moduleName $ Name.nameModule tycon_name
-      occ_name = Name.nameOccName tycon_name
-      tycon_rdrname = RdrName.mkRdrQual mod_name occ_name
-      tycon_ty = SrcLoc.noLoc $ HsTypes.HsTyVar tycon_rdrname
-  Nothing -> error "HsTools.coreToHsType Cannot translate non-tycon type"
-
--- | Evaluate a CoreExpr and return its value. For this to work, the caller
---   should already know the result type for sure, since the result value is
---   unsafely coerced into this type.
-execCore :: CoreSyn.CoreExpr -> GHC.Ghc a
-execCore expr = do
-        -- Setup session flags (yeah, this seems like a noop, but
-        -- setSessionDynFlags really does some extra work...)
-        dflags <- GHC.getSessionDynFlags
-        GHC.setSessionDynFlags dflags
-        -- Compile the expressions. This runs in the IO monad, but really wants
-        -- to run an IO-monad-inside-a-GHC-monad for some reason. I don't really
-        -- understand what it means, but it works.
-        env <- GHC.getSession
-        let srcspan = SrcLoc.noSrcSpan
-        hval <- MonadUtils.liftIO $ HscMain.compileExpr env srcspan expr
-        let res = Unsafe.Coerce.unsafeCoerce hval :: Int
-        return $ Unsafe.Coerce.unsafeCoerce hval
-
--- These functions build (parts of) a LHSExpr RdrName.
-
--- | A reference to the Prelude.undefined function.
-hsUndef :: HsExpr.LHsExpr RdrName.RdrName
-hsUndef = SrcLoc.noLoc $ HsExpr.HsVar PrelNames.undefined_RDR
-
--- | A typed reference to the Prelude.undefined function.
-hsTypedUndef :: HsTypes.LHsType RdrName.RdrName -> HsExpr.LHsExpr RdrName.RdrName
-hsTypedUndef ty = SrcLoc.noLoc $ HsExpr.ExprWithTySig hsUndef ty
-
--- | Create a qualified RdrName from a module name and a variable name
-mkRdrName :: String -> String -> RdrName.RdrName
-mkRdrName mod var =
-    RdrName.mkRdrQual (Module.mkModuleName mod) (OccName.mkVarOcc var)
-
--- These three functions are simplified copies of those in HscMain, because
--- those functions are not exported. These versions have all error handling
--- removed.
-hscParseType = hscParseThing Parser.parseType
-hscParseStmt = hscParseThing Parser.parseStmt
-
-hscParseThing :: Lexer.P thing -> DynFlags.DynFlags -> String -> GHC.Ghc thing
-hscParseThing parser dflags str = do
-    buf <- MonadUtils.liftIO $ StringBuffer.stringToStringBuffer str
-    let loc  = SrcLoc.mkSrcLoc (FastString.fsLit "<interactive>") 1 0
-    let Lexer.POk _ thing = Lexer.unP parser (Lexer.mkPState buf loc dflags)
-    return thing
-
--- | This function imports the module with the given name, for the renamer /
--- typechecker to use. It also imports any "orphans" and "family instances"
--- from modules included by this module, but not the actual modules
--- themselves. I'm not 100% sure how this works, but it seems that any
--- functions defined in included modules are available just by loading the
--- original module, and by doing this orphan stuff, any (type family or class)
--- instances are available as well.
---
--- Most of the code is based on tcRnImports and rnImportDecl, but those
--- functions do a lot more (which I hope we won't need...).
-importModule :: Module.ModuleName -> TcRnTypes.RnM ()
-importModule mod = do
-  let reason = Outputable.text "Hardcoded import" -- Used for trace output
-  let pkg = Nothing
-  -- Load the interface.
-  iface <- LoadIface.loadSrcInterface reason mod False pkg
-  -- Load orphan an familiy instance dependencies as well. I think these
-  -- dependencies are needed for the type checker to know all instances. Any
-  -- other instances (on other packages) are only useful to the
-  -- linker, so we can probably safely ignore them here. Dependencies within
-  -- the same package are also listed in deps, but I'm not so sure what to do
-  -- with them.
-  let deps = HscTypes.mi_deps iface
-  let orphs = HscTypes.dep_orphs deps
-  let finsts = HscTypes.dep_finsts deps
-  LoadIface.loadOrphanModules orphs False
-  LoadIface.loadOrphanModules finsts True
diff --git a/cλash/CLasH/Utils/Pretty.hs b/cλash/CLasH/Utils/Pretty.hs
deleted file mode 100644 (file)
index df78ad9..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-module CLasH.Utils.Pretty (prettyShow, pprString, pprStringDebug) where
-
--- Standard imports
-import qualified Data.Map as Map
-import Text.PrettyPrint.HughesPJClass
-
--- GHC API
-import qualified CoreSyn
-import Outputable ( showSDoc, showSDocDebug, ppr, Outputable, OutputableBndr)
-
--- VHDL Imports 
-import qualified Language.VHDL.Ppr as Ppr
-import qualified Language.VHDL.AST as AST
-import qualified Language.VHDL.AST.Ppr
-
--- Local imports
-import CLasH.VHDL.VHDLTypes
-import CLasH.Utils.Core.CoreShow
-
--- | A version of the default pPrintList method, which uses a custom function
---   f instead of pPrint to print elements.
-printList :: (a -> Doc) -> [a] -> Doc
-printList f = brackets . fsep . punctuate comma . map f
-
-{-
-instance Pretty FuncData where
-  pPrint (FuncData flatfunc entity arch) =
-    text "Flattened: " $$ nest 15 (ppffunc flatfunc)
-    $+$ text "Entity" $$ nest 15 (ppent entity)
-    $+$ pparch arch
-    where
-      ppffunc (Just f) = pPrint f
-      ppffunc Nothing  = text "Nothing"
-      ppent (Just e)   = pPrint e
-      ppent Nothing    = text "Nothing"
-      pparch Nothing = text "VHDL architecture not present"
-      pparch (Just _) = text "VHDL architecture present"
--}
-
-instance Pretty Entity where
-  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) =
-    text "NonRec: " $$ nest 10 (prettyBind (b, expr))
-  pPrint (CoreSyn.Rec binds) =
-    text "Rec: " $$ nest 10 (vcat $ map (prettyBind) binds)
-
-instance (OutputableBndr b, Show b) => Pretty (CoreSyn.Expr b) where
-  pPrint = text . show
-
-instance Pretty AST.VHDLId where
-  pPrint id = Ppr.ppr id
-  
-instance Pretty AST.VHDLName where
-  pPrint name = Ppr.ppr name
-
-prettyBind :: (Show b, Show e) => (b, e) -> Doc
-prettyBind (b, expr) =
-  text b' <> text " = " <> text expr'
-  where
-    b' = show b
-    expr' = show expr
-
-instance (Pretty k, Pretty v) => Pretty (Map.Map k v) where
-  pPrint = 
-    vcat . map ppentry . Map.toList
-    where
-      ppentry (k, v) =
-        pPrint k <> text " : " $$ nest 15 (pPrint v)
-
--- Convenience method for turning an Outputable into a string
-pprString :: (Outputable x) => x -> String
-pprString = showSDoc . ppr
-
-pprStringDebug :: (Outputable x) => x -> String
-pprStringDebug = showSDocDebug . ppr
diff --git a/cλash/CLasH/VHDL.hs b/cλash/CLasH/VHDL.hs
deleted file mode 100644 (file)
index 56342fc..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
---
--- Functions to generate VHDL from FlatFunctions
---
-module CLasH.VHDL where
-
--- Standard modules
-import qualified Data.Map as Map
-import qualified Maybe
-import qualified Control.Arrow as Arrow
-import Data.Accessor
-import qualified Data.Accessor.Monad.Trans.State as MonadState
-
--- VHDL Imports
-import qualified Language.VHDL.AST as AST
-
--- GHC API
-import qualified CoreSyn
-
--- Local imports
-import CLasH.Translator.TranslatorTypes
-import CLasH.VHDL.VHDLTypes
-import CLasH.VHDL.VHDLTools
-import CLasH.VHDL.Constants
-import CLasH.VHDL.Generate
-
-createDesignFiles ::
-  [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
-    full_context =
-      mkUseAll ["work", "types"]
-      : (mkUseAll ["work"]
-      : ieee_context)
-
-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 <- MonadState.get (tsType .> tsTypeFuns)
-  let tyfun_decls = mkBuiltInShow ++ map snd (Map.elems tyfuns)
-  ty_decls_maybes <- MonadState.get (tsType .> tsTypeDecls)
-  let ty_decls = Maybe.catMaybes ty_decls_maybes
-  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
-mkUseAll :: [String] -> AST.ContextItem
-mkUseAll ss = 
-  AST.Use $ from AST.:.: AST.All
-  where
-    base_prefix = (AST.NSimple $ mkVHDLBasicId $ head ss)
-    from = foldl select base_prefix (tail ss)
-    select prefix s = AST.NSelected $ prefix AST.:.: (AST.SSimple $ mkVHDLBasicId s)
-      
-createLibraryUnit ::
-  CoreSyn.CoreBndr
-  -> TranslatorSession (AST.VHDLId, [AST.LibraryUnit])
-
-createLibraryUnit bndr = do
-  entity <- getEntity bndr
-  (arch, _) <- getArchitecture bndr
-  return (ent_id entity, [AST.LUEntity (ent_dec entity), AST.LUArch arch])
diff --git a/cλash/CLasH/VHDL/Constants.hs b/cλash/CLasH/VHDL/Constants.hs
deleted file mode 100644 (file)
index 6051d9b..0000000
+++ /dev/null
@@ -1,399 +0,0 @@
-module CLasH.VHDL.Constants where
-
--- VHDL Imports  
-import qualified Language.VHDL.AST as AST
-
--- | A list of all builtin functions. Partly duplicates the name table
--- in VHDL.Generate, but we can't use that map everywhere due to
--- circular dependencie.
-builtinIds = [ exId, replaceId, headId, lastId, tailId, initId, takeId, dropId
-             , selId, plusgtId, ltplusId, plusplusId, mapId, zipWithId, foldlId
-             , foldrId, zipId, unzipId, shiftlId, shiftrId, rotlId, rotrId
-             , concatId, reverseId, iteratenId, iterateId, generatenId, generateId
-             , emptyId, singletonId, copynId, copyId, lengthTId, nullId
-             , hwxorId, hwandId, hworId, hwnotId, equalityId, inEqualityId, ltId
-             , lteqId, gtId, gteqId, boolOrId, boolAndId, plusId, timesId
-             , negateId, minusId, fromSizedWordId, fromIntegerId, resizeWordId
-             , resizeIntId, sizedIntId, smallIntegerId, fstId, sndId, blockRAMId
-             , splitId, minimumId, fromRangedWordId 
-             ]
---------------
--- Identifiers
---------------
-
--- | reset and clock signal identifiers in String form
-resetStr, clockStr :: String
-resetStr = "resetn"
-clockStr = "clock"
-
--- | reset and clock signal identifiers in basic AST.VHDLId form
-resetId, clockId :: AST.VHDLId
-resetId = AST.unsafeVHDLBasicId resetStr
-clockId = AST.unsafeVHDLBasicId clockStr
-
-integerId :: AST.VHDLId
-integerId = AST.unsafeVHDLBasicId "integer"
-
--- | \"types\" identifier
-typesId :: AST.VHDLId
-typesId = AST.unsafeVHDLBasicId "types"
-
--- | work identifier
-workId :: AST.VHDLId
-workId = AST.unsafeVHDLBasicId "work"
-
--- | std identifier
-stdId :: AST.VHDLId
-stdId = AST.unsafeVHDLBasicId "std"
-
-
--- | textio identifier
-textioId :: AST.VHDLId
-textioId = AST.unsafeVHDLBasicId "textio"
-
--- | range attribute identifier
-rangeId :: AST.VHDLId
-rangeId = AST.unsafeVHDLBasicId "range"
-
-
--- | high attribute identifier
-highId :: AST.VHDLId
-highId = AST.unsafeVHDLBasicId "high"
-
--- | range attribute identifier
-imageId :: AST.VHDLId
-imageId = AST.unsafeVHDLBasicId "image"
-
--- | event attribute identifie
-eventId :: AST.VHDLId
-eventId = AST.unsafeVHDLBasicId "event"
-
-
--- | default function identifier
-defaultId :: AST.VHDLId
-defaultId = AST.unsafeVHDLBasicId "default"
-
--- FSVec function identifiers
-
--- | ex (operator ! in original Haskell source) function identifier
-exId :: String
-exId = "!"
-
--- | sel (function select in original Haskell source) function identifier
-selId :: String
-selId = "select"
-
-
--- | ltplus (function (<+) in original Haskell source) function identifier
-ltplusId :: String
-ltplusId = "<+"
-
-
--- | plusplus (function (++) in original Haskell source) function identifier
-plusplusId :: String
-plusplusId = "++"
-
-
--- | empty function identifier
-emptyId :: String
-emptyId = "empty"
-
--- | plusgt (function (+>) in original Haskell source) function identifier
-plusgtId :: String
-plusgtId = "+>"
-
--- | singleton function identifier
-singletonId :: String
-singletonId = "singleton"
-
--- | length function identifier
-lengthId :: String
-lengthId = "length"
-
-
--- | isnull (function null in original Haskell source) function identifier
-nullId :: String
-nullId = "null"
-
-
--- | replace function identifier
-replaceId :: String
-replaceId = "replace"
-
-
--- | head function identifier
-headId :: String
-headId = "head"
-
-
--- | last function identifier
-lastId :: String
-lastId = "last"
-
-
--- | init function identifier
-initId :: String
-initId = "init"
-
-
--- | tail function identifier
-tailId :: String
-tailId = "tail"
-
--- | minimum ftp function identifier
-minimumId :: String
-minimumId = "minimum"
-
--- | take function identifier
-takeId :: String
-takeId = "take"
-
-
--- | drop function identifier
-dropId :: String
-dropId = "drop"
-
--- | shiftl function identifier
-shiftlId :: String
-shiftlId = "shiftl"
-
--- | shiftr function identifier
-shiftrId :: String
-shiftrId = "shiftr"
-
--- | rotl function identifier
-rotlId :: String
-rotlId = "rotl"
-
--- | reverse function identifier
-rotrId :: String
-rotrId = "rotr"
-
--- | concatenate the vectors in a vector
-concatId :: String
-concatId = "concat"
-
--- | reverse function identifier
-reverseId :: String
-reverseId = "reverse"
-
--- | iterate function identifier
-iterateId :: String
-iterateId = "iterate"
-
--- | iteraten function identifier
-iteratenId :: String
-iteratenId = "iteraten"
-
--- | iterate function identifier
-generateId :: String
-generateId = "generate"
-
--- | iteraten function identifier
-generatenId :: String
-generatenId = "generaten"
-
--- | copy function identifier
-copyId :: String
-copyId = "copy"
-
--- | copyn function identifier
-copynId :: String
-copynId = "copyn"
-
--- | map function identifier
-mapId :: String
-mapId = "map"
-
--- | zipwith function identifier
-zipWithId :: String
-zipWithId = "zipWith"
-
--- | foldl function identifier
-foldlId :: String
-foldlId = "foldl"
-
--- | foldr function identifier
-foldrId :: String
-foldrId = "foldr"
-
--- | zip function identifier
-zipId :: String
-zipId = "zip"
-
--- | unzip function identifier
-unzipId :: String
-unzipId = "unzip"
-
--- | hwxor function identifier
-hwxorId :: String
-hwxorId = "hwxor"
-
--- | hwor function identifier
-hworId :: String
-hworId = "hwor"
-
--- | hwnot function identifier
-hwnotId :: String
-hwnotId = "hwnot"
-
--- | hwand function identifier
-hwandId :: String
-hwandId = "hwand"
-
-lengthTId :: String
-lengthTId = "lengthT"
-
-fstId :: String
-fstId = "fst"
-
-sndId :: String
-sndId = "snd"
-
-splitId :: String
-splitId = "split"
-
--- Equality Operations
-equalityId :: String
-equalityId = "=="
-
-inEqualityId :: String
-inEqualityId = "/="
-
-gtId :: String
-gtId = ">"
-
-ltId :: String
-ltId = "<"
-
-gteqId :: String
-gteqId = ">="
-
-lteqId :: String
-lteqId = "<="
-
-boolOrId :: String
-boolOrId = "||"
-
-boolAndId :: String
-boolAndId = "&&"
-
-boolNot :: String
-boolNot = "not"
-
--- Numeric Operations
-
--- | plus operation identifier
-plusId :: String
-plusId = "+"
-
--- | times operation identifier
-timesId :: String
-timesId = "*"
-
--- | negate operation identifier
-negateId :: String
-negateId = "negate"
-
--- | minus operation identifier
-minusId :: String
-minusId = "-"
-
--- | convert sizedword to ranged
-fromSizedWordId :: String
-fromSizedWordId = "fromSizedWord"
-
-fromRangedWordId :: String
-fromRangedWordId = "fromRangedWord"
-
-toIntegerId :: String
-toIntegerId = "to_integer"
-
-fromIntegerId :: String
-fromIntegerId = "fromInteger"
-
-toSignedId :: String
-toSignedId = "to_signed"
-
-toUnsignedId :: String
-toUnsignedId = "to_unsigned"
-
-resizeId :: String
-resizeId = "resize"
-
-resizeWordId :: String
-resizeWordId = "resizeWord"
-
-resizeIntId :: String
-resizeIntId = "resizeInt"
-
-smallIntegerId :: String
-smallIntegerId = "smallInteger"
-
-sizedIntId :: String
-sizedIntId = "SizedInt"
-
-tfvecId :: String
-tfvecId = "TFVec"
-
-blockRAMId :: String
-blockRAMId = "blockRAM"
-
--- | output file identifier (from std.textio)
-showIdString :: String
-showIdString = "show"
-
-showId :: AST.VHDLId
-showId = AST.unsafeVHDLExtId showIdString
-
--- | write function identifier (from std.textio)
-writeId :: AST.VHDLId
-writeId = AST.unsafeVHDLBasicId "write"
-
--- | output file identifier (from std.textio)
-outputId :: AST.VHDLId
-outputId = AST.unsafeVHDLBasicId "output"
-
-------------------
--- VHDL type marks
-------------------
-
--- | The Bit type mark
-bitTM :: AST.TypeMark
-bitTM = AST.unsafeVHDLBasicId "Bit"
-
--- | Stardard logic type mark
-std_logicTM :: AST.TypeMark
-std_logicTM = AST.unsafeVHDLBasicId "std_logic"
-
--- | boolean type mark
-booleanTM :: AST.TypeMark
-booleanTM = AST.unsafeVHDLBasicId "boolean"
-
--- | fsvec_index AST. TypeMark
-tfvec_indexTM :: AST.TypeMark
-tfvec_indexTM = AST.unsafeVHDLBasicId "tfvec_index"
-
--- | natural AST. TypeMark
-naturalTM :: AST.TypeMark
-naturalTM = AST.unsafeVHDLBasicId "natural"
-
--- | integer TypeMark
-integerTM :: AST.TypeMark
-integerTM = AST.unsafeVHDLBasicId "integer"
-
--- | signed TypeMark
-signedTM :: AST.TypeMark
-signedTM = AST.unsafeVHDLBasicId "signed"
-
--- | unsigned TypeMark
-unsignedTM :: AST.TypeMark
-unsignedTM = AST.unsafeVHDLBasicId "unsigned"
-
--- | string TypeMark
-stringTM :: AST.TypeMark
-stringTM = AST.unsafeVHDLBasicId "string"
-
--- | tup VHDLName suffix
-tupVHDLSuffix :: AST.VHDLId -> AST.Suffix
-tupVHDLSuffix id = AST.SSimple id
diff --git a/cλash/CLasH/VHDL/Generate.hs b/cλash/CLasH/VHDL/Generate.hs
deleted file mode 100644 (file)
index 8340433..0000000
+++ /dev/null
@@ -1,1634 +0,0 @@
-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 qualified Data.Accessor.Monad.Trans.State as MonadState
-
--- VHDL Imports
-import qualified Language.VHDL.AST as AST
-
--- GHC API
-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 CLasH.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
-  -> TranslatorSession Entity -- ^ The resulting entity
-
-getEntity fname = makeCached fname tsEntities $ do
-      expr <- Normalize.getNormalized False fname
-      -- Split the normalized expression
-      let (args, binds, res) = Normalize.splitNormalized expr
-      -- Generate ports for all non-empty types
-      args' <- catMaybesM $ mapM mkMap args
-      -- TODO: Handle Nothing
-      res' <- mkMap res
-      count <- MonadState.get tsEntityCounter 
-      let vhdl_id = mkVHDLBasicId $ varToString fname ++ "Component_" ++ show count
-      MonadState.set tsEntityCounter (count + 1)
-      let ent_decl = createEntityAST vhdl_id args' res'
-      let signature = Entity vhdl_id args' res' ent_decl
-      return signature
-  where
-    mkMap ::
-      --[(SignalId, SignalInfo)] 
-      CoreSyn.CoreBndr 
-      -> TranslatorSession (Maybe Port)
-    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_maybe <- MonadState.lift tsType $ vhdlTy error_msg ty
-        case type_mark_maybe of 
-          Just type_mark -> return $ Just (id, type_mark)
-          Nothing -> return Nothing
-     )
-
--- | Create the VHDL AST for an entity
-createEntityAST ::
-  AST.VHDLId                   -- ^ The name of the function
-  -> [Port]                    -- ^ The entity's arguments
-  -> Maybe 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
-              ++ (Maybe.maybeToList res_port)
-              ++ [clk_port,resetn_port]
-    -- Add a clk port if we have state
-    clk_port = AST.IfaceSigDec clockId AST.In std_logicTM
-    resetn_port = AST.IfaceSigDec resetId AST.In std_logicTM
-    res_port = fmap (mkIfaceSigDec AST.Out) res
-
--- | Create a port declaration
-mkIfaceSigDec ::
-  AST.Mode                         -- ^ The mode for the port (In / Out)
-  -> Port                          -- ^ 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
-  -> TranslatorSession (Architecture, [CoreSyn.CoreBndr])
-  -- ^ The architecture for this function
-
-getArchitecture fname = makeCached fname tsArchitectures $ do
-  expr <- Normalize.getNormalized False fname
-  -- Split the normalized expression
-  let (args, binds, res) = Normalize.splitNormalized expr
-  
-  -- Get the entity for this function
-  signature <- getEntity fname
-  let entity_id = ent_id signature
-
-  -- 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
-  -- Process each bind, resulting in info about state variables and concurrent
-  -- statements.
-  (state_vars, sms) <- Monad.mapAndUnzipM dobind binds
-  let (in_state_maybes, out_state_maybes) = unzip state_vars
-  let (statementss, used_entitiess) = unzip sms
-  -- Get initial state, if it's there
-  initSmap <- MonadState.get tsInitStates
-  let init_state = Map.lookup fname initSmap
-  -- Create a state proc, if needed
-  (state_proc, resbndr) <- case (Maybe.catMaybes in_state_maybes, Maybe.catMaybes out_state_maybes, init_state) of
-        ([in_state], [out_state], Nothing) -> do 
-          nonEmpty <- hasNonEmptyType in_state
-          if nonEmpty 
-            then error ("No initial state defined for: " ++ show fname) 
-            else return ([],[])
-        ([in_state], [out_state], Just resetval) -> do
-          nonEmpty <- hasNonEmptyType in_state
-          if nonEmpty 
-            then mkStateProcSm (in_state, out_state, resetval)
-            else error ("Initial state defined for function with only substate: " ++ show fname)
-        ([], [], Just _) -> error $ "Initial state defined for state-less function: " ++ show fname
-        ([], [], Nothing) -> return ([],[])
-        (ins, outs, res) -> error $ "Weird use of state in " ++ show fname ++ ". In: " ++ show ins ++ " Out: " ++ show outs
-  -- Join the create statements and the (optional) state_proc
-  let statements = concat statementss ++ state_proc
-  -- Create the architecture
-  let arch = AST.ArchBody (mkVHDLBasicId "structural") (AST.NSimple entity_id) (map AST.BDISD sig_decs) statements
-  let used_entities = (concat used_entitiess) ++ resbndr
-  return (arch, used_entities)
-  where
-    dobind :: (CoreSyn.CoreBndr, CoreSyn.CoreExpr) -- ^ The bind to process
-              -> TranslatorSession ((Maybe CoreSyn.CoreBndr, Maybe CoreSyn.CoreBndr), ([AST.ConcSm], [CoreSyn.CoreBndr]))
-              -- ^ ((Input state variable, output state variable), (statements, used entities))
-    -- newtype unpacking is just a cast
-    dobind (bndr, unpacked@(CoreSyn.Cast packed coercion)) 
-      | hasStateType packed && not (hasStateType unpacked)
-      = return ((Just bndr, Nothing), ([], []))
-    -- With simplCore, newtype packing is just a cast
-    dobind (bndr, packed@(CoreSyn.Cast unpacked@(CoreSyn.Var state) coercion)) 
-      | hasStateType packed && not (hasStateType unpacked)
-      = return ((Nothing, Just state), ([], []))
-    -- Without simplCore, newtype packing uses a data constructor
-    dobind (bndr, (CoreSyn.App (CoreSyn.App (CoreSyn.Var con) (CoreSyn.Type _)) (CoreSyn.Var state))) 
-      | isStateCon con
-      = return ((Nothing, Just state), ([], []))
-    -- Anything else is handled by mkConcSm
-    dobind bind = do
-      sms <- mkConcSm bind
-      return ((Nothing, Nothing), sms)
-
-mkStateProcSm :: 
-  (CoreSyn.CoreBndr, CoreSyn.CoreBndr, CoreSyn.CoreBndr) -- ^ The current state, new state and reset variables
-  -> TranslatorSession ([AST.ConcSm], [CoreSyn.CoreBndr]) -- ^ The resulting statements
-mkStateProcSm (old, new, res) = do
-  let error_msg = "\nVHDL.mkSigDec: Can not make signal declaration for type: \n" ++ pprString res 
-  type_mark_old_maybe <- MonadState.lift tsType $ vhdlTy error_msg (Var.varType old)
-  let type_mark_old = Maybe.fromMaybe 
-                        (error $ "\nGenerate.mkStateProcSm: empty type for state? Type: " ++ pprString (Var.varType old))
-                        type_mark_old_maybe
-  type_mark_res_maybe <- MonadState.lift tsType $ vhdlTy error_msg (Var.varType res)
-  let type_mark_res' = Maybe.fromMaybe 
-                        (error $ "\nGenerate.mkStateProcSm: empty type for initial state? Type: " ++ pprString (Var.varType res))
-                        type_mark_res_maybe
-  let type_mark_res = if type_mark_old == type_mark_res' then
-                        type_mark_res'
-                      else 
-                        error $ "Initial state has different type than state type, state type: " ++ show type_mark_old ++ ", init type: "  ++ show type_mark_res'    
-  let resvalid  = mkVHDLExtId $ varToString res ++ "val"
-  let resvaldec = AST.BDISD $ AST.SigDec resvalid type_mark_res Nothing
-  let reswform  = AST.Wform [AST.WformElem (AST.PrimName $ AST.NSimple resvalid) Nothing]
-  let res_assign = AST.SigAssign (varToVHDLName old) reswform
-  let blocklabel       = mkVHDLBasicId "state"
-  let statelabel  = mkVHDLBasicId "stateupdate"
-  let rising_edge = AST.NSimple $ mkVHDLBasicId "rising_edge"
-  let wform       = AST.Wform [AST.WformElem (AST.PrimName $ varToVHDLName new) Nothing]
-  let clk_assign      = AST.SigAssign (varToVHDLName old) wform
-  let rising_edge_clk = AST.PrimFCall $ AST.FCall rising_edge [Nothing AST.:=>: (AST.ADName $ AST.NSimple clockId)]
-  let resetn_is_low  = (AST.PrimName $ AST.NSimple resetId) AST.:=: (AST.PrimLit "'0'")
-  signature <- getEntity res
-  let entity_id = ent_id signature
-  let reslabel = "resetval_" ++ ((prettyShow . varToVHDLName) res)
-  let portmaps = mkAssocElems [] (AST.NSimple resvalid) signature
-  let reset_statement = mkComponentInst reslabel entity_id portmaps
-  let clk_statement = [AST.ElseIf rising_edge_clk [clk_assign]]
-  let statement   = AST.IfSm resetn_is_low [res_assign] clk_statement Nothing
-  let stateupdate = AST.CSPSm $ AST.ProcSm statelabel [clockId,resetId,resvalid] [statement]
-  let block = AST.CSBSm $ AST.BlockSm blocklabel [] (AST.PMapAspect []) [resvaldec] [reset_statement,stateupdate]
-  return ([block],[res])
-
--- | 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. Throw away state repacking
-mkConcSm (bndr, to@(CoreSyn.Cast from ty))
-  | hasStateType to && hasStateType from
-  = return ([],[])
-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) =
-  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 the 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])) 
-                -- Don't generate VHDL for substate extraction
-                | hasStateType bndr = return ([], [])
-                | otherwise =
-  case alt of
-    (CoreSyn.DataAlt dc, bndrs, (CoreSyn.Var sel_bndr)) -> do
-      nonemptysel <- hasNonEmptyType sel_bndr 
-      if nonemptysel 
-        then do
-          bndrs' <- Monad.filterM hasNonEmptyType bndrs
-          case List.elemIndex sel_bndr bndrs' of
-            Just i -> do
-              htypeScrt <- MonadState.lift tsType $ mkHTypeEither (Var.varType scrut)
-              htypeBndr <- MonadState.lift tsType $ mkHTypeEither (Var.varType bndr)
-              case htypeScrt == htypeBndr of
-                True -> do
-                  let sel_name = varToVHDLName scrut
-                  let sel_expr = AST.PrimName sel_name
-                  return ([mkUncondAssign (Left bndr) sel_expr], [])
-                otherwise ->
-                  case htypeScrt of
-                    Right (AggrType _ _) -> do
-                      labels <- MonadState.lift tsType $ 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], [])
-                    _ -> do -- error $ "DIE!"
-                      let sel_name = varToVHDLName scrut
-                      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: result is not one of the binders\n" ++ (pprString expr)
-          else
-            -- A selector case that selects a state value, ignore it.
-            return ([], [])
-      
-    _ -> error $ "\nVHDL.mkConcSM: Not in normal form: Not a selector case:\n" ++ (pprString expr)
-
--- Multiple case alt become 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) _ _ (alt:alts))) = do
-  scrut' <- MonadState.lift tsType $ varToVHDLExpr scrut
-  -- Omit first condition, which is the default
-  altcons <- MonadState.lift tsType $ mapM (altconToVHDLExpr . (\(con,_,_) -> con)) alts
-  let cond_exprs = map (\x -> scrut' AST.:=: x) altcons
-  -- Rotate expressions to the left, so that the expression related to the default case is the last
-  exprs <- MonadState.lift tsType $ mapM (varToVHDLExpr . (\(_,_,CoreSyn.Var expr) -> expr)) (alts ++ [alt])
-  return ([mkAltsAssign (Left bndr) cond_exprs exprs], [])
-
-mkConcSm (_, CoreSyn.Case _ _ _ _) = error "\nVHDL.mkConcSm: Not in normal form: Case statement 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
------------------------------------------------------------------------------
-
--- | A function to wrap a builder-like function that expects its arguments to
--- be expressions.
-genExprArgs wrap dst func args = do
-  args' <- argsToVHDLExprs args
-  wrap dst func args'
-
--- | Turn the all lefts into VHDL Expressions.
-argsToVHDLExprs :: [Either CoreSyn.CoreExpr AST.Expr] -> TranslatorSession [AST.Expr]
-argsToVHDLExprs = catMaybesM . (mapM argToVHDLExpr)
-
-argToVHDLExpr :: Either CoreSyn.CoreExpr AST.Expr -> TranslatorSession (Maybe AST.Expr)
-argToVHDLExpr (Left expr) = MonadState.lift tsType $ do
-  let errmsg = "Generate.argToVHDLExpr: Using non-representable type? Should not happen!"
-  ty_maybe <- vhdlTy errmsg expr
-  case ty_maybe of
-    Just _ -> do
-      vhdl_expr <- varToVHDLExpr $ exprToVar expr
-      return $ Just vhdl_expr
-    Nothing -> return Nothing
-
-argToVHDLExpr (Right expr) = return $ Just expr
-
--- 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 ::
-  (dst -> func -> [Var.Var] -> res)
-  -> (dst -> func -> [Either CoreSyn.CoreExpr AST.Expr] -> res)
-genVarArgs wrap = genCoreArgs $ \dst func args -> let
-    args' = map exprToVar args
-  in
-    wrap dst func args'
-
--- | A function to wrap a builder-like function that expects its arguments to
--- be core expressions.
-genCoreArgs ::
-  (dst -> func -> [CoreSyn.CoreExpr] -> res)
-  -> (dst -> func -> [Either CoreSyn.CoreExpr AST.Expr] -> res)
-genCoreArgs wrap dst func args = wrap dst func args'
-  where
-    -- Check (rather crudely) that all arguments are CoreExprs
-    args' = case Either.partitionEithers args of 
-      (exprargs, []) -> exprargs
-      (exprsargs, rest) -> error $ "\nGenerate.genCoreArgs: expect core expression arguments but found ast exprs:" ++ (show rest)
-
--- | A function to wrap a builder-like function that produces an expression
--- and expects it to be assigned to the destination.
-genExprRes ::
-  ((Either CoreSyn.CoreBndr AST.VHDLName) -> func -> [arg] -> TranslatorSession AST.Expr)
-  -> ((Either CoreSyn.CoreBndr AST.VHDLName) -> func -> [arg] -> TranslatorSession [AST.ConcSm])
-genExprRes wrap dst func args = do
-  expr <- wrap dst func args
-  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 = genNoInsts $ genExprArgs $ genExprRes (genOperator2' op)
-genOperator2' :: (AST.Expr -> AST.Expr -> AST.Expr) -> dst -> CoreSyn.CoreBndr -> [AST.Expr] -> TranslatorSession AST.Expr
-genOperator2' op _ f [arg1, arg2] = return $ op arg1 arg2
-
--- | Generate a unary operator application
-genOperator1 :: (AST.Expr -> AST.Expr) -> BuiltinBuilder 
-genOperator1 op = genNoInsts $ genExprArgs $ genExprRes (genOperator1' op)
-genOperator1' :: (AST.Expr -> AST.Expr) -> dst -> CoreSyn.CoreBndr -> [AST.Expr] -> TranslatorSession AST.Expr
-genOperator1' op _ f [arg] = return $ op arg
-
--- | Generate a unary operator application
-genNegation :: BuiltinBuilder 
-genNegation = genNoInsts $ genVarArgs $ genExprRes genNegation'
-genNegation' :: dst -> CoreSyn.CoreBndr -> [Var.Var] -> TranslatorSession AST.Expr
-genNegation' _ f [arg] = do
-  arg1 <- MonadState.lift tsType $ varToVHDLExpr arg
-  let ty = Var.varType arg
-  let (tycon, args) = Type.splitTyConApp ty
-  let name = Name.getOccString (TyCon.tyConName tycon)
-  case name of
-    "SizedInt" -> return $ AST.Neg arg1
-    otherwise -> error $ "\nGenerate.genNegation': Negation not allowed for type: " ++ show name 
-
--- | Generate a function call from the destination binder, function name and a
--- list of expressions (its arguments)
-genFCall :: Bool -> BuiltinBuilder 
-genFCall switch = genNoInsts $ genExprArgs $ genExprRes (genFCall' switch)
-genFCall' :: Bool -> Either CoreSyn.CoreBndr AST.VHDLName -> CoreSyn.CoreBndr -> [AST.Expr] -> TranslatorSession AST.Expr
-genFCall' switch (Left res) f args = do
-  let fname = varToString f
-  let el_ty = if switch then (Var.varType res) else ((tfvec_elem . Var.varType) res)
-  id <- MonadState.lift tsType $ vectorFunId el_ty fname
-  return $ AST.PrimFCall $ AST.FCall (AST.NSimple id)  $
-             map (\exp -> Nothing AST.:=>: AST.ADExpr exp) args
-genFCall' _ (Right name) _ _ = error $ "\nGenerate.genFCall': Cannot generate builtin function call assigned to a VHDLName: " ++ show name
-
-genFromSizedWord :: BuiltinBuilder
-genFromSizedWord = genNoInsts $ genExprArgs genFromSizedWord'
-genFromSizedWord' :: Either CoreSyn.CoreBndr AST.VHDLName -> CoreSyn.CoreBndr -> [AST.Expr] -> TranslatorSession [AST.ConcSm]
-genFromSizedWord' (Left res) f args@[arg] =
-  return [mkUncondAssign (Left res) arg]
-  -- let fname = varToString f
-  -- return $ AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLBasicId toIntegerId))  $
-  --            map (\exp -> Nothing AST.:=>: AST.ADExpr exp) args
-genFromSizedWord' (Right name) _ _ = error $ "\nGenerate.genFromSizedWord': Cannot generate builtin function call assigned to a VHDLName: " ++ show name
-
-genFromRangedWord :: BuiltinBuilder
-genFromRangedWord = genNoInsts $ genExprArgs $ genExprRes genFromRangedWord'
-genFromRangedWord' :: Either CoreSyn.CoreBndr AST.VHDLName -> CoreSyn.CoreBndr -> [AST.Expr] -> TranslatorSession AST.Expr
-genFromRangedWord' (Left res) f [arg] = do {
-  ; let { ty = Var.varType res
-        ; (tycon, args) = Type.splitTyConApp ty
-        ; name = Name.getOccString (TyCon.tyConName tycon)
-        } ;
-  ; len <- MonadState.lift tsType $ tfp_to_int (sized_word_len_ty ty)
-  ; return $ AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLBasicId resizeId))
-             [Nothing AST.:=>: AST.ADExpr arg, Nothing AST.:=>: AST.ADExpr( AST.PrimLit (show len))]
-  }
-genFromRangedWord' (Right name) _ _ = error $ "\nGenerate.genFromRangedWord': Cannot generate builtin function call assigned to a VHDLName: " ++ show name
-
-genResize :: BuiltinBuilder
-genResize = genNoInsts $ genExprArgs $ genExprRes genResize'
-genResize' :: Either CoreSyn.CoreBndr AST.VHDLName -> CoreSyn.CoreBndr -> [AST.Expr] -> TranslatorSession AST.Expr
-genResize' (Left res) f [arg] = do {
-  ; let { ty = Var.varType res
-        ; (tycon, args) = Type.splitTyConApp ty
-        ; name = Name.getOccString (TyCon.tyConName tycon)
-        } ;
-  ; len <- case name of
-      "SizedInt" -> MonadState.lift tsType $ tfp_to_int (sized_int_len_ty ty)
-      "SizedWord" -> MonadState.lift tsType $ tfp_to_int (sized_word_len_ty ty)
-  ; return $ AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLBasicId resizeId))
-             [Nothing AST.:=>: AST.ADExpr arg, Nothing AST.:=>: AST.ADExpr( AST.PrimLit (show len))]
-  }
-genResize' (Right name) _ _ = error $ "\nGenerate.genFromSizedWord': Cannot generate builtin function call assigned to a VHDLName: " ++ show name
-
-genTimes :: BuiltinBuilder
-genTimes = genNoInsts $ genExprArgs $ genExprRes genTimes'
-genTimes' :: Either CoreSyn.CoreBndr AST.VHDLName -> CoreSyn.CoreBndr -> [AST.Expr] -> TranslatorSession AST.Expr
-genTimes' (Left res) f [arg1,arg2] = do {
-  ; let { ty = Var.varType res
-        ; (tycon, args) = Type.splitTyConApp ty
-        ; name = Name.getOccString (TyCon.tyConName tycon)
-        } ;
-  ; len <- case name of
-      "SizedInt" -> MonadState.lift tsType $ tfp_to_int (sized_int_len_ty ty)
-      "SizedWord" -> MonadState.lift tsType $ tfp_to_int (sized_word_len_ty ty)
-      "RangedWord" -> do {  ubound <- MonadState.lift tsType $ tfp_to_int (ranged_word_bound_ty ty)
-                         ;  let bitsize = floor (logBase 2 (fromInteger (toInteger ubound)))
-                         ;  return bitsize
-                         }
-  ; return $ AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLBasicId resizeId))
-             [Nothing AST.:=>: AST.ADExpr (arg1 AST.:*: arg2), Nothing AST.:=>: AST.ADExpr( AST.PrimLit (show len))]
-  }
-genTimes' (Right name) _ _ = error $ "\nGenerate.genTimes': Cannot generate builtin function call assigned to a VHDLName: " ++ show name
-
--- fromInteger turns an Integer into a Num instance. Since Integer is
--- not representable and is only allowed for literals, the actual
--- Integer should be inlined entirely into the fromInteger argument.
-genFromInteger :: BuiltinBuilder
-genFromInteger = genNoInsts $ genCoreArgs $ genExprRes genFromInteger'
-genFromInteger' :: Either CoreSyn.CoreBndr AST.VHDLName -> CoreSyn.CoreBndr -> [CoreSyn.CoreExpr] -> TranslatorSession AST.Expr
-genFromInteger' (Left res) f args = do
-  let ty = Var.varType res
-  let (tycon, tyargs) = Type.splitTyConApp ty
-  let name = Name.getOccString (TyCon.tyConName tycon)
-  len <- case name of
-    "SizedInt" -> MonadState.lift tsType $ tfp_to_int (sized_int_len_ty ty)
-    "SizedWord" -> MonadState.lift tsType $ tfp_to_int (sized_word_len_ty ty)
-    "RangedWord" -> do
-      bound <- MonadState.lift tsType $ tfp_to_int (ranged_word_bound_ty ty)
-      return $ floor (logBase 2 (fromInteger (toInteger (bound)))) + 1
-  let fname = case name of "SizedInt" -> toSignedId ; "SizedWord" -> toUnsignedId ; "RangedWord" -> toUnsignedId
-  case args of
-    [integer] -> do -- The type and dictionary arguments are removed by genApplication
-      literal <- getIntegerLiteral integer
-      return $ AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLBasicId fname))
-              [Nothing AST.:=>: AST.ADExpr (AST.PrimLit (show literal)), Nothing AST.:=>: AST.ADExpr( AST.PrimLit (show len))]
-    _ -> error $ "\nGenerate.genFromInteger': Wrong number of arguments to genInteger. Applying " ++ pprString f ++ " to " ++ pprString args
-
-genFromInteger' (Right name) _ _ = error $ "\nGenerate.genFromInteger': Cannot generate builtin function call assigned to a VHDLName: " ++ show name
-
-genSizedInt :: BuiltinBuilder
-genSizedInt = genFromInteger
-
-{-
--- This function is useful for use with vectorTH, since that generates
--- explicit references to the TFVec constructor (which is normally
--- hidden). Below implementation is probably not current anymore, but
--- kept here in case we start using vectorTH again.
--- | Generate a Builder for the builtin datacon TFVec
-genTFVec :: BuiltinBuilder
-genTFVec (Left res) f [Left (CoreSyn.Let (CoreSyn.Rec letBinders) letRes)] = do {
-  -- Generate Assignments for all the binders
-  ; letAssigns <- mapM genBinderAssign letBinders
-  -- Generate assignments for the result (which might be another let binding)
-  ; (resBinders,resAssignments) <- genResAssign letRes
-  -- Get all the Assigned binders
-  ; let assignedBinders = Maybe.catMaybes (map fst letAssigns)
-  -- Make signal names for all the assigned binders
-  ; sigs <- mapM (\x -> MonadState.lift tsType $ varToVHDLExpr x) (assignedBinders ++ resBinders)
-  -- Assign all the signals to the resulting vector
-  ; let { vecsigns = mkAggregateSignal sigs
-        ; vecassign = mkUncondAssign (Left res) vecsigns
-        } ;
-  -- Generate all the signal declaration for the assigned binders
-  ; sig_dec_maybes <- mapM mkSigDec (assignedBinders ++ resBinders)
-  ; let { sig_decs = map (AST.BDISD) (Maybe.catMaybes $ sig_dec_maybes)
-  -- Setup the VHDL Block
-        ; block_label = mkVHDLExtId ("TFVec_" ++ show (varToString res))
-        ; block = AST.BlockSm block_label [] (AST.PMapAspect []) sig_decs ((concat (map snd letAssigns)) ++ resAssignments ++ [vecassign])
-        } ;
-  -- Return the block statement coressponding to the TFVec literal
-  ; return $ [AST.CSBSm block]
-  }
-  where
-    genBinderAssign :: (CoreSyn.CoreBndr, CoreSyn.CoreExpr) -> TranslatorSession (Maybe CoreSyn.CoreBndr, [AST.ConcSm])
-    -- For now we only translate applications
-    genBinderAssign (bndr, app@(CoreSyn.App _ _)) = do
-      let (CoreSyn.Var f, args) = CoreSyn.collectArgs app
-      let valargs = get_val_args (Var.varType f) args
-      apps <- genApplication (Left bndr) f (map Left valargs)
-      return (Just bndr, apps)
-    genBinderAssign _ = return (Nothing,[])
-    genResAssign :: CoreSyn.CoreExpr -> TranslatorSession ([CoreSyn.CoreBndr], [AST.ConcSm])
-    genResAssign app@(CoreSyn.App _ letexpr) = do
-      case letexpr of
-        (CoreSyn.Let (CoreSyn.Rec letbndrs) letres) -> do
-          letapps <- mapM genBinderAssign letbndrs
-          let bndrs = Maybe.catMaybes (map fst letapps)
-          let app = (map snd letapps)
-          (vars, apps) <- genResAssign letres
-          return ((bndrs ++ vars),((concat app) ++ apps))
-        otherwise -> return ([],[])
-    genResAssign _ = return ([],[])
-
-genTFVec (Left res) f [Left app@(CoreSyn.App _ _)] = do {
-  ; let { elems = reduceCoreListToHsList app
-  -- Make signal names for all the binders
-        ; binders = map (\expr -> case expr of 
-                          (CoreSyn.Var b) -> b
-                          otherwise -> error $ "\nGenerate.genTFVec: Cannot generate TFVec: " 
-                            ++ show res ++ ", with elems:\n" ++ show elems ++ "\n" ++ pprString elems) elems
-        } ;
-  ; sigs <- mapM (\x -> MonadState.lift tsType $ varToVHDLExpr x) binders
-  -- Assign all the signals to the resulting vector
-  ; let { vecsigns = mkAggregateSignal sigs
-        ; vecassign = mkUncondAssign (Left res) vecsigns
-  -- Setup the VHDL Block
-        ; block_label = mkVHDLExtId ("TFVec_" ++ show (varToString res))
-        ; block = AST.BlockSm block_label [] (AST.PMapAspect []) [] [vecassign]
-        } ;
-  -- Return the block statement coressponding to the TFVec literal
-  ; return $ [AST.CSBSm block]
-  }
-  
-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 {
-  -- mapped_f must be a CoreExpr (since we can't represent functions as VHDL
-  -- expressions). arg must be a CoreExpr (and should be a CoreSyn.Var), since
-  -- we must index it (which we couldn't if it was a VHDL Expr, since only
-  -- VHDLNames can be indexed).
-  -- Setup the generate scheme
-  ; len <- MonadState.lift tsType $ tfp_to_int $ (tfvec_len_ty . Var.varType) res
-          -- TODO: Use something better than varToString
-  ; let { label       = mkVHDLExtId ("mapVector" ++ (varToString res))
-        ; n_id        = mkVHDLBasicId "n"
-        ; n_expr      = idToVHDLExpr n_id
-        ; range       = AST.ToRange (AST.PrimLit "0") (AST.PrimLit $ show (len-1))
-        ; 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
-        ; (CoreSyn.Var real_f, already_mapped_args) = CoreSyn.collectArgs mapped_f
-        ; valargs = get_val_args (Var.varType real_f) already_mapped_args
-        } ;
-  ; (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], used)
-  }
-
-genMap' (Right name) _ _ = error $ "\nGenerate.genMap': Cannot generate map function call assigned to a VHDLName: " ++ show name
-    
-genZipWith :: BuiltinBuilder
-genZipWith (Left res) f args@[Left zipped_f, Left (CoreSyn.Var arg1), Left (CoreSyn.Var arg2)] = do {
-  -- Setup the generate scheme
-  ; len <- MonadState.lift tsType $ tfp_to_int $ (tfvec_len_ty . Var.varType) res
-          -- TODO: Use something better than varToString
-  ; let { label       = mkVHDLExtId ("zipWithVector" ++ (varToString res))
-        ; n_id        = mkVHDLBasicId "n"
-        ; n_expr      = idToVHDLExpr n_id
-        ; range       = AST.ToRange (AST.PrimLit "0") (AST.PrimLit $ show (len-1))
-        ; 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
-        ; (CoreSyn.Var real_f, already_mapped_args) = CoreSyn.collectArgs zipped_f
-        ; valargs     = get_val_args (Var.varType real_f) already_mapped_args
-        ; argexpr1    = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName arg1) n_expr
-        ; argexpr2    = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName arg2) n_expr
-        } ;
-  ; (app_concsms, used) <- genApplication (Right resname) real_f (map Left valargs ++ [Right argexpr1, Right argexpr2])
-    -- Return the generate functions
-  ; return ([AST.CSGSm $ AST.GenerateSm label genScheme [] app_concsms], used)
-  }
-
-genFoldl :: BuiltinBuilder
-genFoldl = genFold True
-
-genFoldr :: BuiltinBuilder
-genFoldr = genFold False
-
-genFold :: Bool -> BuiltinBuilder
-genFold left = genVarArgs (genFold' left)
-
-genFold' :: Bool -> (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> TranslatorSession ([AST.ConcSm], [CoreSyn.CoreBndr])
-genFold' left res f args@[folded_f , start ,vec]= do
-  len <- MonadState.lift tsType $ 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] -> TranslatorSession ([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 tsType $ varToVHDLExpr start
-  return ([mkUncondAssign (Left res) arg], [])
-    
-genFold'' len left (Left res) f [folded_f, start, vec] = do
-  -- The vector length
-  --len <- MonadState.lift tsType $ tfp_to_int $ (tfvec_len_ty . Var.varType) vec
-  -- An expression for len-1
-  let len_min_expr = (AST.PrimLit $ show (len-1))
-  -- evec is (TFVec n), so it still needs an element type
-  let (nvec, _) = Type.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)
-  let error_msg = "\nGenerate.genFold': Can not construct temp vector for element type: " ++ pprString tmp_ty 
-  -- TODO: Handle Nothing
-  Just tmp_vhdl_ty <- MonadState.lift tsType $ vhdlTy error_msg tmp_ty
-  -- Setup the generate scheme
-  let gen_label = mkVHDLExtId ("foldlVector" ++ (varToString vec))
-  let block_label = mkVHDLExtId ("foldlVector" ++ (varToString res))
-  let gen_range = if left then AST.ToRange (AST.PrimLit "0") len_min_expr
-                  else AST.DownRange len_min_expr (AST.PrimLit "0")
-  let gen_scheme   = AST.ForGn n_id gen_range
-  -- 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]
-  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], concat useds)
-  where
-    -- An id for the counter
-    n_id = mkVHDLBasicId "n"
-    n_cur = idToVHDLExpr n_id
-    -- An expression for previous n
-    n_prev = if left then (n_cur AST.:-: (AST.PrimLit "1"))
-                     else (n_cur AST.:+: (AST.PrimLit "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 :: TranslatorSession (AST.GenerateSm, [CoreSyn.CoreBndr])
-    genFirstCell = do
-      len <- MonadState.lift tsType $ tfp_to_int $ (tfvec_len_ty . Var.varType) vec
-      let cond_label = mkVHDLExtId "firstcell"
-      -- if n == 0 or n == len-1
-      let cond_scheme = AST.IfGn $ n_cur AST.:=: (if left then (AST.PrimLit "0")
-                                                  else (AST.PrimLit $ show (len-1)))
-      -- Output to tmp[current n]
-      let resname = mkIndexedName tmp_name n_cur
-      -- Input from start
-      argexpr1 <- MonadState.lift tsType $ varToVHDLExpr start
-      -- Input from vec[current n]
-      let argexpr2 = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName vec) n_cur
-      (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, used)
-
-    genOtherCell = do
-      len <- MonadState.lift tsType $ tfp_to_int $ (tfvec_len_ty . Var.varType) vec
-      let cond_label = mkVHDLExtId "othercell"
-      -- if n > 0 or n < len-1
-      let cond_scheme = AST.IfGn $ n_cur AST.:/=: (if left then (AST.PrimLit "0")
-                                                   else (AST.PrimLit $ show (len-1)))
-      -- Output to tmp[current n]
-      let resname = mkIndexedName tmp_name n_cur
-      -- Input from tmp[previous n]
-      let argexpr1 = vhdlNameToVHDLExpr $ mkIndexedName tmp_name n_prev
-      -- Input from vec[current n]
-      let argexpr2 = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName vec) n_cur
-      (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, used)
-
--- | Generate a generate statement for the builtin function "zip"
-genZip :: BuiltinBuilder
-genZip = genNoInsts $ genVarArgs genZip'
-genZip' :: (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> TranslatorSession [AST.ConcSm]
-genZip' (Left res) f args@[arg1, arg2] = do {
-    -- Setup the generate scheme
-  ; len <- MonadState.lift tsType $ tfp_to_int $ (tfvec_len_ty . Var.varType) res
-          -- TODO: Use something better than varToString
-  ; let { label           = mkVHDLExtId ("zipVector" ++ (varToString res))
-        ; n_id            = mkVHDLBasicId "n"
-        ; n_expr          = idToVHDLExpr n_id
-        ; range           = AST.ToRange (AST.PrimLit "0") (AST.PrimLit $ show (len-1))
-        ; genScheme       = AST.ForGn n_id range
-        ; resname'        = mkIndexedName (varToVHDLName res) n_expr
-        ; argexpr1        = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName arg1) n_expr
-        ; argexpr2        = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName arg2) n_expr
-        } ; 
-  ; labels <- MonadState.lift tsType $ getFieldLabels (tfvec_elem (Var.varType res))
-  ; let { resnameA    = mkSelectedName resname' (labels!!0)
-        ; resnameB    = mkSelectedName resname' (labels!!1)
-        ; resA_assign = mkUncondAssign (Right resnameA) argexpr1
-        ; resB_assign = mkUncondAssign (Right resnameB) argexpr2
-        } ;
-    -- Return the generate functions
-  ; return [AST.CSGSm $ AST.GenerateSm label genScheme [] [resA_assign,resB_assign]]
-  }
-  
--- | Generate a generate statement for the builtin function "fst"
-genFst :: BuiltinBuilder
-genFst = genNoInsts $ genVarArgs genFst'
-genFst' :: (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> TranslatorSession [AST.ConcSm]
-genFst' (Left res) f args@[arg] = do {
-  ; labels <- MonadState.lift tsType $ getFieldLabels (Var.varType arg)
-  ; let { argexpr'    = varToVHDLName arg
-        ; argexprA    = vhdlNameToVHDLExpr $ mkSelectedName argexpr' (labels!!0)
-        ; assign      = mkUncondAssign (Left res) argexprA
-        } ;
-    -- Return the generate functions
-  ; return [assign]
-  }
-  
--- | Generate a generate statement for the builtin function "snd"
-genSnd :: BuiltinBuilder
-genSnd = genNoInsts $ genVarArgs genSnd'
-genSnd' :: (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> TranslatorSession [AST.ConcSm]
-genSnd' (Left res) f args@[arg] = do {
-  ; labels <- MonadState.lift tsType $ getFieldLabels (Var.varType arg)
-  ; let { argexpr'    = varToVHDLName arg
-        ; argexprB    = vhdlNameToVHDLExpr $ mkSelectedName argexpr' (labels!!1)
-        ; assign      = mkUncondAssign (Left res) argexprB
-        } ;
-    -- Return the generate functions
-  ; return [assign]
-  }
-    
--- | Generate a generate statement for the builtin function "unzip"
-genUnzip :: BuiltinBuilder
-genUnzip = genNoInsts $ genVarArgs genUnzip'
-genUnzip' :: (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> TranslatorSession [AST.ConcSm]
-genUnzip' (Left res) f args@[arg] = do
-  let error_msg = "\nGenerate.genUnzip: Cannot generate unzip call: " ++ pprString res ++ " = " ++ pprString f ++ " " ++ pprString arg
-  htype <- MonadState.lift tsType $ mkHType error_msg (Var.varType arg)
-  -- Prepare a unconditional assignment, for the case when either part
-  -- of the unzip is a state variable, which will disappear in the
-  -- resulting VHDL, making the the unzip no longer required.
-  case htype of
-    -- A normal vector containing two-tuples
-    VecType _ (AggrType _ [_, _]) -> do {
-        -- Setup the generate scheme
-      ; len <- MonadState.lift tsType $ tfp_to_int $ (tfvec_len_ty . Var.varType) arg
-        -- TODO: Use something better than varToString
-      ; let { label           = mkVHDLExtId ("unzipVector" ++ (varToString res))
-            ; n_id            = mkVHDLBasicId "n"
-            ; n_expr          = idToVHDLExpr n_id
-            ; range           = AST.ToRange (AST.PrimLit "0") (AST.PrimLit $ show (len-1))
-            ; genScheme       = AST.ForGn n_id range
-            ; resname'        = varToVHDLName res
-            ; argexpr'        = mkIndexedName (varToVHDLName arg) n_expr
-            } ;
-      ; reslabels <- MonadState.lift tsType $ getFieldLabels (Var.varType res)
-      ; arglabels <- MonadState.lift tsType $ getFieldLabels (tfvec_elem (Var.varType arg))
-      ; let { resnameA    = mkIndexedName (mkSelectedName resname' (reslabels!!0)) n_expr
-            ; resnameB    = mkIndexedName (mkSelectedName resname' (reslabels!!1)) n_expr
-            ; argexprA    = vhdlNameToVHDLExpr $ mkSelectedName argexpr' (arglabels!!0)
-            ; argexprB    = vhdlNameToVHDLExpr $ mkSelectedName argexpr' (arglabels!!1)
-            ; resA_assign = mkUncondAssign (Right resnameA) argexprA
-            ; resB_assign = mkUncondAssign (Right resnameB) argexprB
-            } ;
-        -- Return the generate functions
-      ; return [AST.CSGSm $ AST.GenerateSm label genScheme [] [resA_assign,resB_assign]]
-      }
-    -- Both elements of the tuple were state, so they've disappeared. No
-    -- need to do anything
-    VecType _ (AggrType _ []) -> return []
-    -- A vector containing aggregates with more than two elements?
-    VecType _ (AggrType _ _) -> error $ "Unzipping a value that is not a vector of two-tuples? Value: " ++ pprString arg ++ "\nType: " ++ pprString (Var.varType arg)
-    -- One of the elements of the tuple was state, so there won't be a
-    -- tuple (record) in the VHDL output. We can just do a plain
-    -- assignment, then.
-    VecType _ _ -> do
-      argexpr <- MonadState.lift tsType $ varToVHDLExpr arg
-      return [mkUncondAssign (Left res) argexpr]
-    _ -> error $ "Unzipping a value that is not a vector? Value: " ++ pprString arg ++ "\nType: " ++ pprString (Var.varType arg) ++ "\nhtype: " ++ show htype
-
-genCopy :: BuiltinBuilder 
-genCopy = genNoInsts genCopy'
-genCopy' :: (Either CoreSyn.CoreBndr AST.VHDLName ) -> CoreSyn.CoreBndr -> [Either CoreSyn.CoreExpr AST.Expr] -> TranslatorSession [AST.ConcSm]
-genCopy' (Left res) f [arg] = do {
-  ; [arg'] <- argsToVHDLExprs [arg]
-  ; let { resExpr = AST.Aggregate [AST.ElemAssoc (Just AST.Others) arg']
-        ; out_assign = mkUncondAssign (Left res) resExpr
-        }
-  ; return [out_assign]
-  }
-    
-genConcat :: BuiltinBuilder
-genConcat = genNoInsts $ genVarArgs genConcat'
-genConcat' :: (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> TranslatorSession [AST.ConcSm]
-genConcat' (Left res) f args@[arg] = do {
-    -- Setup the generate scheme
-  ; len1 <- MonadState.lift tsType $ tfp_to_int $ (tfvec_len_ty . Var.varType) arg
-  ; let (_, nvec) = Type.splitAppTy (Var.varType arg)
-  ; len2 <- MonadState.lift tsType $ tfp_to_int $ tfvec_len_ty nvec
-          -- TODO: Use something better than varToString
-  ; let { label       = mkVHDLExtId ("concatVector" ++ (varToString res))
-        ; n_id        = mkVHDLBasicId "n"
-        ; n_expr      = idToVHDLExpr n_id
-        ; fromRange   = n_expr AST.:*: (AST.PrimLit $ show len2)
-        ; 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
-        ; toRange     = (n_expr AST.:*: (AST.PrimLit $ show len2)) AST.:+: (AST.PrimLit $ show (len2-1))
-        ; range       = AST.ToRange (AST.PrimLit "0") (AST.PrimLit $ show (len1-1))
-        ; resname     = vecSlice fromRange toRange
-        ; argexpr     = vhdlNameToVHDLExpr $ mkIndexedName (varToVHDLName arg) n_expr
-        ; out_assign  = mkUncondAssign (Right resname) argexpr
-        } ;
-    -- Return the generate statement
-  ; return [AST.CSGSm $ AST.GenerateSm label genScheme [] [out_assign]]
-  }
-  where
-    vecSlice init last =  AST.NSlice (AST.SliceName (varToVHDLName res) 
-                            (AST.ToRange init last))
-
-genIteraten :: BuiltinBuilder
-genIteraten dst f args = genIterate dst f (tail args)
-
-genIterate :: BuiltinBuilder
-genIterate = genIterateOrGenerate True
-
-genGeneraten :: BuiltinBuilder
-genGeneraten dst f args = genGenerate dst f (tail args)
-
-genGenerate :: BuiltinBuilder
-genGenerate = genIterateOrGenerate False
-
-genIterateOrGenerate :: Bool -> BuiltinBuilder
-genIterateOrGenerate iter = genVarArgs (genIterateOrGenerate' iter)
-
-genIterateOrGenerate' :: Bool -> (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> TranslatorSession ([AST.ConcSm], [CoreSyn.CoreBndr])
-genIterateOrGenerate' iter (Left res) f args = do
-  len <- MonadState.lift tsType $ 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] -> TranslatorSession ([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) f [app_f, start] = do
-  -- The vector length
-  -- len <- MonadState.lift tsType $ tfp_to_int ((tfvec_len_ty . Var.varType) res)
-  -- An expression for len-1
-  let len_min_expr = (AST.PrimLit $ show (len-1))
-  -- -- 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 = Var.varType res
-  let error_msg = "\nGenerate.genFold': Can not construct temp vector for element type: " ++ pprString tmp_ty 
-  -- TODO: Handle Nothing
-  Just tmp_vhdl_ty <- MonadState.lift tsType $ vhdlTy error_msg tmp_ty
-  -- Setup the generate scheme
-  let gen_label = mkVHDLExtId ("iterateVector" ++ (varToString start))
-  let block_label = mkVHDLExtId ("iterateVector" ++ (varToString res))
-  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  tmp_dec     = AST.BDISD $ AST.SigDec tmp_id tmp_vhdl_ty Nothing
-  -- Create the generate statement
-  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], concat useds)
-  where
-    -- An id for the counter
-    n_id = mkVHDLBasicId "n"
-    n_cur = idToVHDLExpr n_id
-    -- An expression for previous n
-    n_prev = n_cur AST.:-: (AST.PrimLit "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 :: TranslatorSession (AST.GenerateSm, [CoreSyn.CoreBndr])
-    genFirstCell = do
-      let cond_label = mkVHDLExtId "firstcell"
-      -- if n == 0 or n == len-1
-      let cond_scheme = AST.IfGn $ n_cur AST.:=: (AST.PrimLit "0")
-      -- Output to tmp[current n]
-      let resname = mkIndexedName tmp_name n_cur
-      -- Input from start
-      argexpr <- MonadState.lift tsType $ varToVHDLExpr start
-      let startassign = mkUncondAssign (Right resname) argexpr
-      (app_concsms, used) <- genApplication (Right resname) app_f  [Right argexpr]
-      -- Return the conditional generate part
-      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"
-      -- if n > 0 or n < len-1
-      let cond_scheme = AST.IfGn $ n_cur AST.:/=: (AST.PrimLit "0")
-      -- Output to tmp[current n]
-      let resname = mkIndexedName tmp_name n_cur
-      -- Input from tmp[previous n]
-      let argexpr = vhdlNameToVHDLExpr $ mkIndexedName tmp_name n_prev
-      (app_concsms, used) <- genApplication (Right resname) app_f [Right argexpr]
-      -- Return the conditional generate part
-      return (AST.GenerateSm cond_label cond_scheme [] app_concsms, used)
-
-genBlockRAM :: BuiltinBuilder
-genBlockRAM = genNoInsts $ genExprArgs genBlockRAM'
-
-genBlockRAM' :: (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [AST.Expr] -> TranslatorSession [AST.ConcSm]
-genBlockRAM' (Left res) f args@[data_in,rdaddr,wraddr,wrenable] = do
-  -- Get the ram type
-  let (tup,data_out) = Type.splitAppTy (Var.varType res)
-  let (tup',ramvec) = Type.splitAppTy tup
-  let Just realram = Type.coreView ramvec
-  let Just (tycon, types) = Type.splitTyConApp_maybe realram
-  Just ram_vhdl_ty <- MonadState.lift tsType $ vhdlTy "wtf" (head types)
-  -- Make the intermediate vector
-  let ram_dec = AST.BDISD $ AST.SigDec ram_id ram_vhdl_ty Nothing
-  -- Get the data_out name
-  -- reslabels <- MonadState.lift tsType $ getFieldLabels (Var.varType res)
-  let resname = varToVHDLName res
-  -- let resname = mkSelectedName resname' (reslabels!!0)
-  let rdaddr_int = genExprFCall (mkVHDLBasicId toIntegerId) rdaddr
-  let argexpr = vhdlNameToVHDLExpr $ mkIndexedName (AST.NSimple ram_id) rdaddr_int
-  let assign = mkUncondAssign (Right resname) argexpr
-  let block_label = mkVHDLExtId ("blockRAM" ++ (varToString res))
-  let block = AST.BlockSm block_label [] (AST.PMapAspect []) [ram_dec] [assign, mkUpdateProcSm]
-  return [AST.CSBSm block]
-  where
-    ram_id = mkVHDLBasicId "ram"
-    mkUpdateProcSm :: AST.ConcSm
-    mkUpdateProcSm = AST.CSPSm $ AST.ProcSm proclabel [clockId] [statement]
-      where
-        proclabel   = mkVHDLBasicId "updateRAM"
-        rising_edge = mkVHDLBasicId "rising_edge"
-        wraddr_int  = genExprFCall (mkVHDLBasicId toIntegerId) wraddr
-        ramloc      = mkIndexedName (AST.NSimple ram_id) wraddr_int
-        wform       = AST.Wform [AST.WformElem data_in Nothing]
-        ramassign      = AST.SigAssign ramloc wform
-        rising_edge_clk = genExprFCall rising_edge (AST.PrimName $ AST.NSimple clockId)
-        statement   = AST.IfSm (AST.And rising_edge_clk wrenable) [ramassign] [] Nothing
-        
-genSplit :: BuiltinBuilder
-genSplit = genNoInsts $ genVarArgs genSplit'
-
-genSplit' :: (Either CoreSyn.CoreBndr AST.VHDLName) -> CoreSyn.CoreBndr -> [Var.Var] -> TranslatorSession [AST.ConcSm]
-genSplit' (Left res) f args@[vecIn] = do {
-  ; labels <- MonadState.lift tsType $ getFieldLabels (Var.varType res)
-  ; len <- MonadState.lift tsType $ tfp_to_int $ (tfvec_len_ty . Var.varType) vecIn
-  ; let { block_label = mkVHDLExtId ("split" ++ (varToString vecIn))
-        ; halflen   = round ((fromIntegral len) / 2)
-        ; rangeL    = vecSlice (AST.PrimLit "0") (AST.PrimLit $ show (halflen - 1))
-        ; rangeR    = vecSlice (AST.PrimLit $ show halflen) (AST.PrimLit $ show (len - 1))
-        ; resname   = varToVHDLName res
-        ; resnameL  = mkSelectedName resname (labels!!0)
-        ; resnameR  = mkSelectedName resname (labels!!1)
-        ; argexprL  = vhdlNameToVHDLExpr rangeL
-        ; argexprR  = vhdlNameToVHDLExpr rangeR
-        ; out_assignL = mkUncondAssign (Right resnameL) argexprL
-        ; out_assignR = mkUncondAssign (Right resnameR) argexprR
-        ; block = AST.BlockSm block_label [] (AST.PMapAspect []) [] [out_assignL, out_assignR]
-        }
-  ; return [AST.CSBSm block]
-  }
-  where
-    vecSlice init last =  AST.NSlice (AST.SliceName (varToVHDLName res) 
-                            (AST.ToRange init last))
------------------------------------------------------------------------------
--- 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
-  -> TranslatorSession ([AST.ConcSm], [CoreSyn.CoreBndr]) 
-  -- ^ The corresponding VHDL concurrent statements and entities
-  --   instantiated.
-genApplication dst f args = do
-  nonemptydst <- case dst of
-    Left bndr -> hasNonEmptyType bndr 
-    Right _ -> return True
-  if nonemptydst
-    then
-      if Var.isGlobalId f then
-        case Var.idDetails 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
-              htype <- MonadState.lift tsType $ mkHTypeEither (Var.varType bndr)
-              let argsNostate = filter (\x -> not (either hasStateType (\x -> False) x)) args
-              case argsNostate of
-                [arg] -> do
-                  [arg'] <- argsToVHDLExprs [arg]
-                  return ([mkUncondAssign dst arg'], [])
-                otherwise ->
-                  case htype of
-                    Right (AggrType _ _) -> do
-                      labels <- MonadState.lift tsType $ getFieldLabels (Var.varType bndr)
-                      args' <- argsToVHDLExprs argsNostate
-                      return (zipWith mkassign labels 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
-                    _ -> do -- error $ "DIE!"
-                      args' <- argsToVHDLExprs argsNostate
-                      return ([mkUncondAssign dst (head args')], [])            
-            Right _ -> error "\nGenerate.genApplication(DataConWorkId): Can't generate dataconstructor application without an original binder"
-          IdInfo.DataConWrapId dc -> case dst of
-            -- It's a datacon. Create a record from its arguments.
-            Left bndr ->
-              case (Map.lookup (varToString f) globalNameTable) of
-               Just (arg_count, builder) ->
-                if length args == arg_count then
-                  builder dst f args
-                else
-                  error $ "\nGenerate.genApplication(DataConWrapId): Incorrect number of arguments to builtin function: " ++ pprString f ++ " Args: " ++ show args
-               Nothing -> error $ "\nGenerate.genApplication(DataConWrapId): Can't generate dataconwrapper: " ++ (show dc)
-            Right _ -> error "\nGenerate.genApplication(DataConWrapId): Can't generate dataconwrapper application without an original binder"
-          IdInfo.VanillaId ->
-            -- 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 $ "\nGenerate.genApplication(VanillaId): Incorrect number of arguments to builtin function: " ++ pprString f ++ " Args: " ++ show args
-              Nothing -> do
-                top <- isTopLevelBinder f
-                if top then
-                  do
-                    -- Local binder that references a top level binding.  Generate a
-                    -- component instantiation.
-                    signature <- getEntity f
-                    args' <- argsToVHDLExprs 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], [f])
-                  else
-                    -- 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.
-                    -- FIXME : I DONT KNOW IF THE ABOVE COMMENT HOLDS HERE, SO FOR NOW JUST ERROR!
-                    -- f' <- MonadState.lift tsType $ varToVHDLExpr f
-                    --                   return $ ([mkUncondAssign dst f'], [])
-                  do errtype <- case dst of 
-                        Left bndr -> do 
-                          htype <- MonadState.lift tsType $ mkHTypeEither (Var.varType bndr)
-                          return (show htype)
-                        Right vhd -> return $ show vhd
-                     error ("\nGenerate.genApplication(VanillaId): Using function from another module that is not a known builtin: " ++ (pprString f) ++ "::" ++ errtype) 
-          IdInfo.ClassOpId cls ->
-            -- FIXME: Not looking for what instance this class op is called for
-            -- Is quite stupid of course.
-            case (Map.lookup (varToString f) globalNameTable) of
-              Just (arg_count, builder) ->
-                if length args == arg_count then
-                  builder dst f args
-                else
-                  error $ "\nGenerate.genApplication(ClassOpId): Incorrect number of arguments to builtin function: " ++ pprString f ++ " Args: " ++ show args
-              Nothing -> error $ "\nGenerate.genApplication(ClassOpId): Using function from another module that is not a known builtin: " ++ pprString f
-          details -> error $ "\nGenerate.genApplication: Calling unsupported function " ++ pprString f ++ " with GlobalIdDetails " ++ pprString details
-        else do
-          top <- isTopLevelBinder f
-          if top then
-            do
-               -- Local binder that references a top level binding.  Generate a
-               -- component instantiation.
-               signature <- getEntity f
-               args' <- argsToVHDLExprs 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 (prettyShow . varToVHDLName) prettyShow) dst
-               let portmaps = mkAssocElems args' ((either varToVHDLName id) dst) signature
-               return ([mkComponentInst label entity_id portmaps], [f])
-            else
-              -- 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.
-            do f' <- MonadState.lift tsType $ varToVHDLExpr f
-               return ([mkUncondAssign dst f'], [])
-    else -- Destination has empty type, don't generate anything
-      return ([], [])
------------------------------------------------------------------------------
--- 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 -> TypeSession AST.VHDLId
-vectorFunId el_ty fname = do
-  let error_msg = "\nGenerate.vectorFunId: Can not construct vector function for element: " ++ pprString el_ty
-  -- TODO: Handle the Nothing case?
-  elemTM_maybe <- vhdlTy error_msg el_ty
-  let elemTM = Maybe.fromMaybe
-                 (error $ "\nGenerate.vectorFunId: Cannot generate vector function \"" ++ fname ++ "\" for the empty type \"" ++ (pprString el_ty) ++ "\"")
-                 elemTM_maybe
-  -- TODO: This should not be duplicated from mk_vector_ty. Probably but it in
-  -- the VHDLState or something.
-  let vectorTM = mkVHDLExtId $ "vector_" ++ (AST.fromVHDLId elemTM)
-  typefuns <- MonadState.get tsTypeFuns
-  el_htype <- mkHType error_msg el_ty
-  case Map.lookup (UVecType el_htype, fname) typefuns of
-    -- Function already generated, just return it
-    Just (id, _) -> return id
-    -- Function not generated yet, generate it
-    Nothing -> do
-      let functions = genUnconsVectorFuns elemTM vectorTM
-      case lookup fname functions of
-        Just body -> do
-          MonadState.modify tsTypeFuns $ Map.insert (UVecType el_htype, fname) (function_id, (fst body))
-          mapM_ (vectorFunId el_ty) (snd body)
-          return function_id
-        Nothing -> error $ "\nGenerate.vectorFunId: I don't know how to generate vector function " ++ fname
-  where
-    function_id = mkVHDLExtId fname
-
-genUnconsVectorFuns :: AST.TypeMark -- ^ type of the vector elements
-                    -> AST.TypeMark -- ^ type of the vector
-                    -> [(String, (AST.SubProgBody, [String]))]
-genUnconsVectorFuns elemTM vectorTM  = 
-  [ (exId, (AST.SubProgBody exSpec      []                  [exExpr],[]))
-  , (replaceId, (AST.SubProgBody replaceSpec [AST.SPVD replaceVar] [replaceExpr1,replaceExpr2,replaceRet],[]))
-  , (lastId, (AST.SubProgBody lastSpec    []                  [lastExpr],[]))
-  , (initId, (AST.SubProgBody initSpec    [AST.SPVD initVar]  [initExpr, initRet],[]))
-  , (minimumId, (AST.SubProgBody minimumSpec [] [minimumExpr],[]))
-  , (takeId, (AST.SubProgBody takeSpec    [AST.SPVD takeVar]  [takeExpr, takeRet],[minimumId]))
-  , (dropId, (AST.SubProgBody dropSpec    [AST.SPVD dropVar]  [dropExpr, dropRet],[]))
-  , (plusgtId, (AST.SubProgBody plusgtSpec  [AST.SPVD plusgtVar] [plusgtExpr, plusgtRet],[]))
-  , (emptyId, (AST.SubProgBody emptySpec   [AST.SPVD emptyVar] [emptyExpr],[]))
-  , (singletonId, (AST.SubProgBody singletonSpec [AST.SPVD singletonVar] [singletonRet],[]))
-  , (copynId, (AST.SubProgBody copynSpec    [AST.SPVD copynVar]      [copynExpr],[]))
-  , (selId, (AST.SubProgBody selSpec  [AST.SPVD selVar] [selFor, selRet],[]))
-  , (ltplusId, (AST.SubProgBody ltplusSpec [AST.SPVD ltplusVar] [ltplusExpr, ltplusRet],[]))  
-  , (plusplusId, (AST.SubProgBody plusplusSpec [AST.SPVD plusplusVar] [plusplusExpr, plusplusRet],[]))
-  , (lengthTId, (AST.SubProgBody lengthTSpec [] [lengthTExpr],[]))
-  , (shiftlId, (AST.SubProgBody shiftlSpec [AST.SPVD shiftlVar] [shiftlExpr, shiftlRet], [initId]))
-  , (shiftrId, (AST.SubProgBody shiftrSpec [AST.SPVD shiftrVar] [shiftrExpr, shiftrRet], [tailId]))
-  , (nullId, (AST.SubProgBody nullSpec [] [nullExpr], []))
-  , (rotlId, (AST.SubProgBody rotlSpec [AST.SPVD rotlVar] [rotlExpr, rotlRet], [nullId, lastId, initId]))
-  , (rotrId, (AST.SubProgBody rotrSpec [AST.SPVD rotrVar] [rotrExpr, rotrRet], [nullId, tailId, headId]))
-  , (reverseId, (AST.SubProgBody reverseSpec [AST.SPVD reverseVar] [reverseFor, reverseRet], []))
-  ]
-  where 
-    ixPar   = AST.unsafeVHDLBasicId "ix"
-    vecPar  = AST.unsafeVHDLBasicId "vec"
-    vec1Par = AST.unsafeVHDLBasicId "vec1"
-    vec2Par = AST.unsafeVHDLBasicId "vec2"
-    nPar    = AST.unsafeVHDLBasicId "n"
-    leftPar = AST.unsafeVHDLBasicId "nLeft"
-    rightPar = AST.unsafeVHDLBasicId "nRight"
-    iId     = AST.unsafeVHDLBasicId "i"
-    iPar    = iId
-    aPar    = AST.unsafeVHDLBasicId "a"
-    fPar = AST.unsafeVHDLBasicId "f"
-    sPar = AST.unsafeVHDLBasicId "s"
-    resId   = AST.unsafeVHDLBasicId "res"    
-    exSpec = AST.Function (mkVHDLExtId exId) [AST.IfaceVarDec vecPar vectorTM,
-                               AST.IfaceVarDec ixPar  unsignedTM] elemTM
-    exExpr = AST.ReturnSm (Just $ AST.PrimName $ AST.NIndexed 
-              (AST.IndexedName (AST.NSimple vecPar) [genExprFCall (mkVHDLBasicId toIntegerId) (AST.PrimName $ AST.NSimple ixPar)]))
-    replaceSpec = AST.Function (mkVHDLExtId replaceId)  [ AST.IfaceVarDec vecPar vectorTM
-                                          , AST.IfaceVarDec iPar   unsignedTM
-                                          , AST.IfaceVarDec aPar   elemTM
-                                          ] vectorTM 
-       -- variable res : fsvec_x (0 to vec'length-1);
-    replaceVar =
-         AST.VarDec resId 
-                (AST.SubtypeIn vectorTM
-                  (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
-                   [AST.ToRange (AST.PrimLit "0")
-                            (AST.PrimName (AST.NAttribute $ 
-                              AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:-:
-                                (AST.PrimLit "1"))   ]))
-                Nothing
-       --  res AST.:= vec(0 to i-1) & a & vec(i+1 to length'vec-1)
-    replaceExpr1 = AST.NSimple resId AST.:= AST.PrimName (AST.NSimple vecPar)
-    replaceExpr2 = AST.NIndexed (AST.IndexedName (AST.NSimple resId) [genExprFCall (mkVHDLBasicId toIntegerId) (AST.PrimName $ AST.NSimple iPar)]) AST.:= AST.PrimName (AST.NSimple aPar)
-    replaceRet =  AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
-    vecSlice init last =  AST.PrimName (AST.NSlice 
-                                        (AST.SliceName 
-                                              (AST.NSimple vecPar) 
-                                              (AST.ToRange init last)))
-    lastSpec = AST.Function (mkVHDLExtId lastId) [AST.IfaceVarDec vecPar vectorTM] elemTM
-       -- return vec(vec'length-1);
-    lastExpr = AST.ReturnSm (Just (AST.PrimName $ AST.NIndexed (AST.IndexedName 
-                    (AST.NSimple vecPar) 
-                    [AST.PrimName (AST.NAttribute $ 
-                                AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) 
-                                                             AST.:-: AST.PrimLit "1"])))
-    initSpec = AST.Function (mkVHDLExtId initId) [AST.IfaceVarDec vecPar vectorTM] vectorTM 
-       -- variable res : fsvec_x (0 to vec'length-2);
-    initVar = 
-         AST.VarDec resId 
-                (AST.SubtypeIn vectorTM
-                  (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
-                   [AST.ToRange (AST.PrimLit "0")
-                            (AST.PrimName (AST.NAttribute $ 
-                              AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:-:
-                                (AST.PrimLit "2"))   ]))
-                Nothing
-       -- resAST.:= vec(0 to vec'length-2)
-    initExpr = AST.NSimple resId AST.:= (vecSlice 
-                               (AST.PrimLit "0") 
-                               (AST.PrimName (AST.NAttribute $ 
-                                  AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) 
-                                                             AST.:-: AST.PrimLit "2"))
-    initRet =  AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
-    minimumSpec = AST.Function (mkVHDLExtId minimumId) [AST.IfaceVarDec leftPar   naturalTM,
-                                   AST.IfaceVarDec rightPar naturalTM ] naturalTM
-    minimumExpr = AST.IfSm ((AST.PrimName $ AST.NSimple leftPar) AST.:<: (AST.PrimName $ AST.NSimple rightPar))
-                        [AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple leftPar)]
-                        []
-                        (Just $ AST.Else [minimumExprRet])
-      where minimumExprRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple rightPar)
-    takeSpec = AST.Function (mkVHDLExtId takeId) [AST.IfaceVarDec nPar   naturalTM,
-                                   AST.IfaceVarDec vecPar vectorTM ] vectorTM
-       -- variable res : fsvec_x (0 to (minimum (n,vec'length))-1);
-    minLength = AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLExtId minimumId))  
-                              [Nothing AST.:=>: AST.ADExpr (AST.PrimName $ AST.NSimple nPar)
-                              ,Nothing AST.:=>: AST.ADExpr (AST.PrimName (AST.NAttribute $ 
-                                AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing))]
-    takeVar = 
-         AST.VarDec resId 
-                (AST.SubtypeIn vectorTM
-                  (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
-                   [AST.ToRange (AST.PrimLit "0")
-                               (minLength AST.:-:
-                                (AST.PrimLit "1"))   ]))
-                Nothing
-       -- res AST.:= vec(0 to n-1)
-    takeExpr = AST.NSimple resId AST.:= 
-                    (vecSlice (AST.PrimLit "0") 
-                              (minLength AST.:-: AST.PrimLit "1"))
-    takeRet =  AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
-    dropSpec = AST.Function (mkVHDLExtId dropId) [AST.IfaceVarDec nPar   naturalTM,
-                                   AST.IfaceVarDec vecPar vectorTM ] vectorTM 
-       -- variable res : fsvec_x (0 to vec'length-n-1);
-    dropVar = 
-         AST.VarDec resId 
-                (AST.SubtypeIn vectorTM
-                  (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
-                   [AST.ToRange (AST.PrimLit "0")
-                            (AST.PrimName (AST.NAttribute $ 
-                              AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:-:
-                               (AST.PrimName $ AST.NSimple nPar)AST.:-: (AST.PrimLit "1")) ]))
-               Nothing
-       -- res AST.:= vec(n to vec'length-1)
-    dropExpr = AST.NSimple resId AST.:= (vecSlice 
-                               (AST.PrimName $ AST.NSimple nPar) 
-                               (AST.PrimName (AST.NAttribute $ 
-                                  AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) 
-                                                             AST.:-: AST.PrimLit "1"))
-    dropRet =  AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
-    plusgtSpec = AST.Function (mkVHDLExtId plusgtId) [AST.IfaceVarDec aPar   elemTM,
-                                       AST.IfaceVarDec vecPar vectorTM] vectorTM 
-    -- variable res : fsvec_x (0 to vec'length);
-    plusgtVar = 
-      AST.VarDec resId 
-             (AST.SubtypeIn vectorTM
-               (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
-                [AST.ToRange (AST.PrimLit "0")
-                        (AST.PrimName (AST.NAttribute $ 
-                          AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing))]))
-             Nothing
-    plusgtExpr = AST.NSimple resId AST.:= 
-                   ((AST.PrimName $ AST.NSimple aPar) AST.:&: 
-                    (AST.PrimName $ AST.NSimple vecPar))
-    plusgtRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
-    emptySpec = AST.Function (mkVHDLExtId emptyId) [] vectorTM
-    emptyVar = 
-          AST.VarDec resId
-            (AST.SubtypeIn vectorTM
-              (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
-                [AST.ToRange (AST.PrimLit "0") (AST.PrimLit "-1")]))
-             Nothing
-    emptyExpr = AST.ReturnSm (Just $ AST.PrimName (AST.NSimple resId))
-    singletonSpec = AST.Function (mkVHDLExtId singletonId) [AST.IfaceVarDec aPar elemTM ] 
-                                         vectorTM
-    -- variable res : fsvec_x (0 to 0) := (others => a);
-    singletonVar = 
-      AST.VarDec resId 
-             (AST.SubtypeIn vectorTM
-               (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
-                [AST.ToRange (AST.PrimLit "0") (AST.PrimLit "0")]))
-             (Just $ AST.Aggregate [AST.ElemAssoc (Just AST.Others) 
-                                          (AST.PrimName $ AST.NSimple aPar)])
-    singletonRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
-    copynSpec = AST.Function (mkVHDLExtId copynId) [AST.IfaceVarDec nPar   naturalTM,
-                                   AST.IfaceVarDec aPar   elemTM   ] vectorTM 
-    -- variable res : fsvec_x (0 to n-1) := (others => a);
-    copynVar = 
-      AST.VarDec resId 
-             (AST.SubtypeIn vectorTM
-               (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
-                [AST.ToRange (AST.PrimLit "0")
-                            ((AST.PrimName (AST.NSimple nPar)) AST.:-:
-                             (AST.PrimLit "1"))   ]))
-             (Just $ AST.Aggregate [AST.ElemAssoc (Just AST.Others) 
-                                          (AST.PrimName $ AST.NSimple aPar)])
-    -- return res
-    copynExpr = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
-    selSpec = AST.Function (mkVHDLExtId selId) [AST.IfaceVarDec fPar   naturalTM,
-                               AST.IfaceVarDec sPar   naturalTM,
-                               AST.IfaceVarDec nPar   naturalTM,
-                               AST.IfaceVarDec vecPar vectorTM ] vectorTM
-    -- variable res : fsvec_x (0 to n-1);
-    selVar = 
-      AST.VarDec resId 
-                (AST.SubtypeIn vectorTM
-                  (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
-                    [AST.ToRange (AST.PrimLit "0")
-                      ((AST.PrimName (AST.NSimple nPar)) AST.:-:
-                      (AST.PrimLit "1"))   ])
-                )
-                Nothing
-    -- for i res'range loop
-    --   res(i) := vec(f+i*s);
-    -- end loop;
-    selFor = AST.ForSM iId (AST.AttribRange $ AST.AttribName (AST.NSimple resId) (AST.NSimple rangeId) Nothing) [selAssign]
-    -- res(i) := vec(f+i*s);
-    selAssign = let origExp = AST.PrimName (AST.NSimple fPar) AST.:+: 
-                                (AST.PrimName (AST.NSimple iId) AST.:*: 
-                                  AST.PrimName (AST.NSimple sPar)) in
-                                  AST.NIndexed (AST.IndexedName (AST.NSimple resId) [AST.PrimName (AST.NSimple iId)]) AST.:=
-                                    (AST.PrimName $ AST.NIndexed (AST.IndexedName (AST.NSimple vecPar) [origExp]))
-    -- return res;
-    selRet =  AST.ReturnSm (Just $ AST.PrimName (AST.NSimple resId))
-    ltplusSpec = AST.Function (mkVHDLExtId ltplusId) [AST.IfaceVarDec vecPar vectorTM,
-                                        AST.IfaceVarDec aPar   elemTM] vectorTM 
-     -- variable res : fsvec_x (0 to vec'length);
-    ltplusVar = 
-      AST.VarDec resId 
-        (AST.SubtypeIn vectorTM
-          (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
-            [AST.ToRange (AST.PrimLit "0")
-              (AST.PrimName (AST.NAttribute $ 
-                AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing))]))
-        Nothing
-    ltplusExpr = AST.NSimple resId AST.:= 
-                     ((AST.PrimName $ AST.NSimple vecPar) AST.:&: 
-                      (AST.PrimName $ AST.NSimple aPar))
-    ltplusRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
-    plusplusSpec = AST.Function (mkVHDLExtId plusplusId) [AST.IfaceVarDec vec1Par vectorTM,
-                                             AST.IfaceVarDec vec2Par vectorTM] 
-                                             vectorTM 
-    -- variable res : fsvec_x (0 to vec1'length + vec2'length -1);
-    plusplusVar = 
-      AST.VarDec resId 
-        (AST.SubtypeIn vectorTM
-          (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
-            [AST.ToRange (AST.PrimLit "0")
-              (AST.PrimName (AST.NAttribute $ 
-                AST.AttribName (AST.NSimple vec1Par) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:+:
-                  AST.PrimName (AST.NAttribute $ 
-                AST.AttribName (AST.NSimple vec2Par) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:-:
-                  AST.PrimLit "1")]))
-       Nothing
-    plusplusExpr = AST.NSimple resId AST.:= 
-                     ((AST.PrimName $ AST.NSimple vec1Par) AST.:&: 
-                      (AST.PrimName $ AST.NSimple vec2Par))
-    plusplusRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
-    lengthTSpec = AST.Function (mkVHDLExtId lengthTId) [AST.IfaceVarDec vecPar vectorTM] naturalTM
-    lengthTExpr = AST.ReturnSm (Just $ AST.PrimName (AST.NAttribute $ 
-                                AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing))
-    shiftlSpec = AST.Function (mkVHDLExtId shiftlId) [AST.IfaceVarDec vecPar vectorTM,
-                                   AST.IfaceVarDec aPar   elemTM  ] vectorTM 
-    -- variable res : fsvec_x (0 to vec'length-1);
-    shiftlVar = 
-     AST.VarDec resId 
-            (AST.SubtypeIn vectorTM
-              (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
-               [AST.ToRange (AST.PrimLit "0")
-                        (AST.PrimName (AST.NAttribute $ 
-                          AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:-:
-                           (AST.PrimLit "1")) ]))
-            Nothing
-    -- res := a & init(vec)
-    shiftlExpr = AST.NSimple resId AST.:=
-                    (AST.PrimName (AST.NSimple aPar) AST.:&:
-                     (AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLExtId initId))  
-                       [Nothing AST.:=>: AST.ADExpr (AST.PrimName $ AST.NSimple vecPar)]))
-    shiftlRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)       
-    shiftrSpec = AST.Function (mkVHDLExtId shiftrId) [AST.IfaceVarDec vecPar vectorTM,
-                                       AST.IfaceVarDec aPar   elemTM  ] vectorTM 
-    -- variable res : fsvec_x (0 to vec'length-1);
-    shiftrVar = 
-     AST.VarDec resId 
-            (AST.SubtypeIn vectorTM
-              (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
-               [AST.ToRange (AST.PrimLit "0")
-                        (AST.PrimName (AST.NAttribute $ 
-                          AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:-:
-                           (AST.PrimLit "1")) ]))
-            Nothing
-    -- res := tail(vec) & a
-    shiftrExpr = AST.NSimple resId AST.:=
-                  ((AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLExtId tailId))  
-                    [Nothing AST.:=>: AST.ADExpr (AST.PrimName $ AST.NSimple vecPar)]) AST.:&:
-                  (AST.PrimName (AST.NSimple aPar)))
-                
-    shiftrRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)      
-    nullSpec = AST.Function (mkVHDLExtId nullId) [AST.IfaceVarDec vecPar vectorTM] booleanTM
-    -- return vec'length = 0
-    nullExpr = AST.ReturnSm (Just $ 
-                AST.PrimName (AST.NAttribute $ 
-                  AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:=:
-                    AST.PrimLit "0")
-    rotlSpec = AST.Function (mkVHDLExtId rotlId) [AST.IfaceVarDec vecPar vectorTM] vectorTM 
-    -- variable res : fsvec_x (0 to vec'length-1);
-    rotlVar = 
-     AST.VarDec resId 
-            (AST.SubtypeIn vectorTM
-              (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
-               [AST.ToRange (AST.PrimLit "0")
-                        (AST.PrimName (AST.NAttribute $ 
-                          AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:-:
-                           (AST.PrimLit "1")) ]))
-            Nothing
-    -- if null(vec) then res := vec else res := last(vec) & init(vec)
-    rotlExpr = AST.IfSm (AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLExtId nullId))  
-                          [Nothing AST.:=>: AST.ADExpr (AST.PrimName $ AST.NSimple vecPar)])
-                        [AST.NSimple resId AST.:= (AST.PrimName $ AST.NSimple vecPar)]
-                        []
-                        (Just $ AST.Else [rotlExprRet])
-      where rotlExprRet = 
-                AST.NSimple resId AST.:= 
-                      ((AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLExtId lastId))  
-                        [Nothing AST.:=>: AST.ADExpr (AST.PrimName $ AST.NSimple vecPar)]) AST.:&:
-                      (AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLExtId initId))  
-                        [Nothing AST.:=>: AST.ADExpr (AST.PrimName $ AST.NSimple vecPar)]))
-    rotlRet =  AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)       
-    rotrSpec = AST.Function (mkVHDLExtId rotrId) [AST.IfaceVarDec vecPar vectorTM] vectorTM 
-    -- variable res : fsvec_x (0 to vec'length-1);
-    rotrVar = 
-     AST.VarDec resId 
-            (AST.SubtypeIn vectorTM
-              (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
-               [AST.ToRange (AST.PrimLit "0")
-                        (AST.PrimName (AST.NAttribute $ 
-                          AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:-:
-                           (AST.PrimLit "1")) ]))
-            Nothing
-    -- if null(vec) then res := vec else res := tail(vec) & head(vec)
-    rotrExpr = AST.IfSm (AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLExtId nullId))  
-                          [Nothing AST.:=>: AST.ADExpr (AST.PrimName $ AST.NSimple vecPar)])
-                        [AST.NSimple resId AST.:= (AST.PrimName $ AST.NSimple vecPar)]
-                        []
-                        (Just $ AST.Else [rotrExprRet])
-      where rotrExprRet = 
-                AST.NSimple resId AST.:= 
-                      ((AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLExtId tailId))  
-                        [Nothing AST.:=>: AST.ADExpr (AST.PrimName $ AST.NSimple vecPar)]) AST.:&:
-                      (AST.PrimFCall $ AST.FCall (AST.NSimple (mkVHDLExtId headId))  
-                        [Nothing AST.:=>: AST.ADExpr (AST.PrimName $ AST.NSimple vecPar)]))
-    rotrRet =  AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
-    reverseSpec = AST.Function (mkVHDLExtId reverseId) [AST.IfaceVarDec vecPar vectorTM] vectorTM
-    reverseVar = 
-      AST.VarDec resId 
-             (AST.SubtypeIn vectorTM
-               (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
-                [AST.ToRange (AST.PrimLit "0")
-                         (AST.PrimName (AST.NAttribute $ 
-                           AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:-:
-                            (AST.PrimLit "1")) ]))
-             Nothing
-    -- for i in 0 to res'range loop
-    --   res(vec'length-i-1) := vec(i);
-    -- end loop;
-    reverseFor = 
-       AST.ForSM iId (AST.AttribRange $ AST.AttribName (AST.NSimple resId) (AST.NSimple rangeId) Nothing) [reverseAssign]
-    -- res(vec'length-i-1) := vec(i);
-    reverseAssign = AST.NIndexed (AST.IndexedName (AST.NSimple resId) [destExp]) AST.:=
-      (AST.PrimName $ AST.NIndexed (AST.IndexedName (AST.NSimple vecPar) 
-                           [AST.PrimName $ AST.NSimple iId]))
-        where destExp = AST.PrimName (AST.NAttribute $ AST.AttribName (AST.NSimple vecPar) 
-                                   (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:-: 
-                        AST.PrimName (AST.NSimple iId) AST.:-: 
-                        (AST.PrimLit "1") 
-    -- return res;
-    reverseRet = AST.ReturnSm (Just $ AST.PrimName (AST.NSimple resId))
-
-    
------------------------------------------------------------------------------
--- 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. If you add a name to this map, don't forget to add
--- it to VHDL.Constants/builtinIds as well.
-globalNameTable :: NameTable
-globalNameTable = Map.fromList
-  [ (exId             , (2, genFCall True          ) )
-  , (replaceId        , (3, genFCall False          ) )
-  , (headId           , (1, genFCall True           ) )
-  , (lastId           , (1, genFCall True           ) )
-  , (tailId           , (1, genFCall False          ) )
-  , (initId           , (1, genFCall False          ) )
-  , (takeId           , (2, genFCall False          ) )
-  , (dropId           , (2, genFCall False          ) )
-  , (selId            , (4, genFCall False          ) )
-  , (plusgtId         , (2, genFCall False          ) )
-  , (ltplusId         , (2, genFCall False          ) )
-  , (plusplusId       , (2, genFCall False          ) )
-  , (mapId            , (2, genMap                  ) )
-  , (zipWithId        , (3, genZipWith              ) )
-  , (foldlId          , (3, genFoldl                ) )
-  , (foldrId          , (3, genFoldr                ) )
-  , (zipId            , (2, genZip                  ) )
-  , (unzipId          , (1, genUnzip                ) )
-  , (shiftlId         , (2, genFCall False          ) )
-  , (shiftrId         , (2, genFCall False          ) )
-  , (rotlId           , (1, genFCall False          ) )
-  , (rotrId           , (1, genFCall False          ) )
-  , (concatId         , (1, genConcat               ) )
-  , (reverseId        , (1, genFCall False          ) )
-  , (iteratenId       , (3, genIteraten             ) )
-  , (iterateId        , (2, genIterate              ) )
-  , (generatenId      , (3, genGeneraten            ) )
-  , (generateId       , (2, genGenerate             ) )
-  , (emptyId          , (0, genFCall False          ) )
-  , (singletonId      , (1, genFCall False          ) )
-  , (copynId          , (2, genFCall False          ) )
-  , (copyId           , (1, genCopy                 ) )
-  , (lengthTId        , (1, genFCall False          ) )
-  , (nullId           , (1, genFCall False          ) )
-  , (hwxorId          , (2, genOperator2 AST.Xor    ) )
-  , (hwandId          , (2, genOperator2 AST.And    ) )
-  , (hworId           , (2, genOperator2 AST.Or     ) )
-  , (hwnotId          , (1, genOperator1 AST.Not    ) )
-  , (equalityId       , (2, genOperator2 (AST.:=:)  ) )
-  , (inEqualityId     , (2, genOperator2 (AST.:/=:) ) )
-  , (ltId             , (2, genOperator2 (AST.:<:)  ) )
-  , (lteqId           , (2, genOperator2 (AST.:<=:) ) )
-  , (gtId             , (2, genOperator2 (AST.:>:)  ) )
-  , (gteqId           , (2, genOperator2 (AST.:>=:) ) )
-  , (boolOrId         , (2, genOperator2 AST.Or     ) )
-  , (boolAndId        , (2, genOperator2 AST.And    ) )
-  , (boolNot          , (1, genOperator1 AST.Not    ) )
-  , (plusId           , (2, genOperator2 (AST.:+:)  ) )
-  , (timesId          , (2, genTimes                ) )
-  , (negateId         , (1, genNegation             ) )
-  , (minusId          , (2, genOperator2 (AST.:-:)  ) )
-  , (fromSizedWordId  , (1, genFromSizedWord        ) )
-  , (fromRangedWordId , (1, genFromRangedWord       ) )
-  , (fromIntegerId    , (1, genFromInteger          ) )
-  , (resizeWordId     , (1, genResize               ) )
-  , (resizeIntId      , (1, genResize               ) )
-  , (sizedIntId       , (1, genSizedInt             ) )
-  , (smallIntegerId   , (1, genFromInteger          ) )
-  , (fstId            , (1, genFst                  ) )
-  , (sndId            , (1, genSnd                  ) )
-  , (blockRAMId       , (5, genBlockRAM             ) )
-  , (splitId          , (1, genSplit                ) )
-  --, (tfvecId          , (1, genTFVec                ) )
-  , (minimumId        , (2, error "\nFunction name: \"minimum\" is used internally, use another name"))
-  ]
diff --git a/cλash/CLasH/VHDL/Testbench.hs b/cλash/CLasH/VHDL/Testbench.hs
deleted file mode 100644 (file)
index fa2e9dc..0000000
+++ /dev/null
@@ -1,173 +0,0 @@
--- 
--- Functions to create a VHDL testbench from a list of test input.
---
-module CLasH.VHDL.Testbench where
-
--- Standard modules
-import qualified Control.Monad as Monad
-import qualified Maybe
-import qualified Data.Map as Map
-import qualified Data.Accessor.Monad.Trans.State as MonadState
-
--- VHDL Imports
-import qualified Language.VHDL.AST as AST
-
--- GHC API
-import qualified CoreSyn
-import qualified HscTypes
-import qualified Var
-import qualified TysWiredIn
-
--- Local imports
-import CLasH.Translator.TranslatorTypes
-import CLasH.VHDL.Constants
-import CLasH.VHDL.Generate
-import CLasH.VHDL.VHDLTools
-import CLasH.VHDL.VHDLTypes
-import CLasH.Normalize
-import CLasH.Utils.Core.BinderTools
-import CLasH.Utils.Core.CoreTools
-import CLasH.Utils
-
-createTestbench :: 
-  Maybe Int -- ^ Number of cycles to simulate
-  -> [HscTypes.CoreModule] -- ^ Compiled modules
-  -> CoreSyn.CoreExpr -- ^ Input stimuli
-  -> CoreSyn.CoreBndr -- ^ Top Entity
-  -> TranslatorSession CoreSyn.CoreBndr -- ^ The id of the generated archictecture
-createTestbench mCycles cores stimuli top = do
-  stimuli' <- reduceCoreListToHsList cores stimuli
-  -- Create a binder for the testbench. We use the unit type (), since the
-  -- testbench has no outputs and no inputs.
-  bndr <- mkInternalVar "testbench" TysWiredIn.unitTy
-  let entity = createTestbenchEntity bndr
-  MonadState.modify tsEntities (Map.insert bndr entity)
-  arch <- createTestbenchArch mCycles stimuli' top entity
-  MonadState.modify tsArchitectures (Map.insert bndr arch)
-  return bndr
-
-createTestbenchEntity :: 
-  CoreSyn.CoreBndr
-  -> Entity
-createTestbenchEntity bndr = entity
-  where
-    vhdl_id = mkVHDLBasicId "testbench"
-    -- Create an AST entity declaration with no ports
-    ent_decl = AST.EntityDec vhdl_id []
-    -- Create a signature with no input and no output ports
-    entity = Entity vhdl_id [] undefined ent_decl
-
-createTestbenchArch ::
-  Maybe Int -- ^ Number of cycles to simulate
-  -> [CoreSyn.CoreExpr] -- ^ Imput stimuli
-  -> CoreSyn.CoreBndr -- ^ Top Entity
-  -> Entity -- ^ The signature to create an architecture for
-  -> TranslatorSession (Architecture, [CoreSyn.CoreBndr])
-  -- ^ The architecture and any other entities used.
-createTestbenchArch mCycles stimuli top testent= do
-  signature <- getEntity top
-  let entId   = ent_id signature
-      iIface  = ent_args signature
-      oIface  = ent_res signature
-      iIds    = map fst iIface
-  let (oId, oDec, oProc) = case oIface of
-        Just (id, ty) -> ( id
-                         , [AST.SigDec id ty Nothing]
-                         , [createOutputProc [id]])
-        -- No output port? Just use undefined for the output id, since it won't be
-        -- used by mkAssocElems when there is no output port.
-        Nothing -> (undefined, [], [])
-  let iDecs   = map (\(vId, tm) -> AST.SigDec vId tm Nothing) iIface
-  let finalIDecs = iDecs ++
-                    [AST.SigDec clockId std_logicTM (Just $ AST.PrimLit "'0'"),
-                     AST.SigDec resetId std_logicTM (Just $ AST.PrimLit "'0'")]
-  let portmaps = mkAssocElems (map idToVHDLExpr iIds) (AST.NSimple oId) signature
-  let mIns    = mkComponentInst "totest" entId portmaps
-  (stimuliAssigns, stimuliDecs, cycles, used) <- createStimuliAssigns mCycles stimuli (head iIds)
-  let finalAssigns = (AST.CSSASm (AST.NSimple resetId AST.:<==:
-                      AST.ConWforms []
-                                    (AST.Wform [AST.WformElem (AST.PrimLit "'0'") (Just $ AST.PrimLit "0 ns"), AST.WformElem (AST.PrimLit "'1'") (Just $ AST.PrimLit "3 ns")])
-                                    Nothing)) : stimuliAssigns
-  let clkProc     = createClkProc
-  let arch = AST.ArchBody
-              (AST.unsafeVHDLBasicId "test")
-              (AST.NSimple $ ent_id testent)
-              (map AST.BDISD (finalIDecs ++ stimuliDecs ++ oDec))
-              (mIns :
-                ( (AST.CSPSm clkProc) : (fmap AST.CSPSm oProc) ++ finalAssigns ) )
-  return (arch, top : used)
-
-createStimuliAssigns ::
-  Maybe Int -- ^ Number of cycles to simulate
-  -> [CoreSyn.CoreExpr] -- ^ Input stimuli
-  -> AST.VHDLId -- ^ Input signal
-  -> TranslatorSession ( [AST.ConcSm]
-                       , [AST.SigDec]
-                       , Int
-                       , [CoreSyn.CoreBndr]) -- ^ (Resulting statements, Needed signals, The number of cycles to simulate, Any entities used)
-createStimuliAssigns mCycles [] _ = return ([], [], Maybe.maybe 0 id mCycles, [])
-
-createStimuliAssigns mCycles stimuli signal = do
-  let genWformElem time stim = (AST.WformElem stim (Just $ AST.PrimLit (show time ++ " ns")))
-  let inputlen = length stimuli
-  assigns <- Monad.zipWithM createStimulans stimuli [0..inputlen]
-  let (stimuli_sms, resvars, useds) = unzip3 assigns
-  sig_dec_maybes <- mapM mkSigDec resvars
-  let sig_decs = Maybe.catMaybes sig_dec_maybes
-  outps <- mapM (\x -> MonadState.lift tsType (varToVHDLExpr x)) resvars
-  let wformelems = zipWith genWformElem [0,10..] outps
-  let inassign = AST.CSSASm $ AST.NSimple signal AST.:<==: AST.ConWforms [] (AST.Wform wformelems) Nothing
-  case (concat stimuli_sms) of
-    []        -> return ([inassign], [], inputlen, concat useds)
-    stims     -> return (stims ++ [inassign], sig_decs, inputlen, concat useds)
-
-createStimulans ::
-  CoreSyn.CoreExpr -- ^ The stimulans
-  -> Int -- ^ The cycle for this stimulans
-  -> TranslatorSession ( [AST.ConcSm]
-                       , Var.Var 
-                       , [CoreSyn.CoreBndr]) -- ^ (The statement, the variable it assigns to (assumed to be available!), Any entities used by this stimulans)
-
-createStimulans expr cycl = do 
-  -- There must be a let at top level 
-  expr <- normalizeExpr ("test input #" ++ show cycl) expr
-  -- Split the normalized expression. It can't have a function type, so match
-  -- an empty list of argument binders
-  let ([], binds, res) = splitNormalized expr
-  (stimulansbindss, useds) <- unzipM $ Monad.mapM mkConcSm binds
-  sig_dec_maybes <- mapM (mkSigDec . fst) (filter ((/=res).fst) binds)
-  let sig_decs = map (AST.BDISD) (Maybe.catMaybes sig_dec_maybes)
-  let block_label = mkVHDLExtId ("testcycle_" ++ (show cycl))
-  let block = AST.BlockSm block_label [] (AST.PMapAspect []) sig_decs (concat stimulansbindss)
-  case (sig_decs,(concat stimulansbindss)) of
-    ([],[])   ->  return ([], res, concat useds)
-    otherwise ->  return ([AST.CSBSm block], res, concat useds)
--- | generates a clock process with a period of 10ns
-createClkProc :: AST.ProcSm
-createClkProc = AST.ProcSm (AST.unsafeVHDLBasicId "clkproc") [] sms
- where sms = -- wait for 5 ns -- (half a cycle)
-             [AST.WaitFor $ AST.PrimLit "5 ns",
-              -- clk <= not clk;
-              AST.NSimple clockId `AST.SigAssign` 
-                 AST.Wform [AST.WformElem (AST.Not (AST.PrimName $ AST.NSimple clockId)) Nothing]]
-
--- | generate the output process
-createOutputProc :: [AST.VHDLId] -- ^ output signal
-              -> AST.ProcSm  
-createOutputProc outs = 
-  AST.ProcSm (AST.unsafeVHDLBasicId "writeoutput") 
-         [clockId]
-         [AST.IfSm clkPred (writeOuts outs) [] Nothing]
- where clkPred = AST.PrimName (AST.NAttribute $ AST.AttribName (AST.NSimple clockId) 
-                                                   (AST.NSimple eventId)
-                                                   Nothing          ) `AST.And` 
-                 (AST.PrimName (AST.NSimple clockId) AST.:=: AST.PrimLit "'1'")
-       writeOuts :: [AST.VHDLId] -> [AST.SeqSm]
-       writeOuts []  = []
-       writeOuts [i] = [writeOut i (AST.PrimLit "LF")]
-       writeOuts (i:is) = writeOut i (AST.PrimLit "HT") : writeOuts is
-       writeOut outSig suffix = 
-         genExprPCall2 writeId
-                        (AST.PrimName $ AST.NSimple outputId)
-                        ((genExprFCall showId (AST.PrimName $ AST.NSimple outSig)) AST.:&: suffix)
diff --git a/cλash/CLasH/VHDL/VHDLTools.hs b/cλash/CLasH/VHDL/VHDLTools.hs
deleted file mode 100644 (file)
index 7166630..0000000
+++ /dev/null
@@ -1,704 +0,0 @@
-{-# LANGUAGE RelaxedPolyRec #-} -- Needed for vhdl_ty_either', for some reason...
-module CLasH.VHDL.VHDLTools where
-
--- Standard modules
-import qualified Maybe
-import qualified Data.Either as Either
-import qualified Data.List as List
-import qualified Data.Char as Char
-import qualified Data.Map as Map
-import qualified Control.Monad as Monad
-import qualified Data.Accessor.Monad.Trans.State as MonadState
-
--- VHDL Imports
-import qualified Language.VHDL.AST as AST
-
--- GHC API
-import qualified CoreSyn
-import qualified Name
-import qualified OccName
-import qualified Var
-import qualified Id
-import qualified TyCon
-import qualified Type
-import qualified DataCon
-import qualified CoreSubst
-import qualified Outputable
-
--- Local imports
-import CLasH.VHDL.VHDLTypes
-import CLasH.Translator.TranslatorTypes
-import CLasH.Utils.Core.CoreTools
-import CLasH.Utils
-import CLasH.Utils.Pretty
-import CLasH.VHDL.Constants
-
------------------------------------------------------------------------------
--- Functions to generate concurrent statements
------------------------------------------------------------------------------
-
--- Create an unconditional assignment statement
-mkUncondAssign ::
-  Either CoreSyn.CoreBndr AST.VHDLName -- ^ The signal to assign to
-  -> AST.Expr -- ^ The expression to assign
-  -> AST.ConcSm -- ^ The resulting concurrent statement
-mkUncondAssign dst expr = mkAssign dst Nothing expr
-
--- Create a conditional assignment statement
-mkCondAssign ::
-  Either CoreSyn.CoreBndr AST.VHDLName -- ^ The signal to assign to
-  -> AST.Expr -- ^ The condition
-  -> AST.Expr -- ^ The value when true
-  -> AST.Expr -- ^ The value when false
-  -> AST.ConcSm -- ^ The resulting concurrent statement
-mkCondAssign dst cond true false = mkAssign dst (Just (cond, true)) false
-
--- Create a conditional or unconditional assignment statement
-mkAssign ::
-  Either CoreSyn.CoreBndr AST.VHDLName -- ^ The signal to assign to
-  -> Maybe (AST.Expr , AST.Expr) -- ^ Optionally, the condition to test for
-                                 -- and the value to assign when true.
-  -> AST.Expr -- ^ The value to assign when false or no condition
-  -> AST.ConcSm -- ^ The resulting concurrent statement
-mkAssign dst cond false_expr =
-  let
-    -- I'm not 100% how this assignment AST works, but this gets us what we
-    -- want...
-    whenelse = case cond of
-      Just (cond_expr, true_expr) -> 
-        let 
-          true_wform = AST.Wform [AST.WformElem true_expr Nothing]
-        in
-          [AST.WhenElse true_wform cond_expr]
-      Nothing -> []
-    false_wform = AST.Wform [AST.WformElem false_expr Nothing]
-    dst_name  = case dst of
-      Left bndr -> AST.NSimple (varToVHDLId bndr)
-      Right name -> name
-    assign    = dst_name AST.:<==: (AST.ConWforms whenelse false_wform Nothing)
-  in
-    AST.CSSASm assign
-
-mkAltsAssign ::
-  Either CoreSyn.CoreBndr AST.VHDLName            -- ^ The signal to assign to
-  -> [AST.Expr]       -- ^ The conditions
-  -> [AST.Expr]       -- ^ The expressions
-  -> AST.ConcSm   -- ^ The Alt assigns
-mkAltsAssign dst conds exprs
-        | (length conds) /= ((length exprs) - 1) = error "\nVHDLTools.mkAltsAssign: conditions expression mismatch"
-        | otherwise =
-  let
-    whenelses   = zipWith mkWhenElse conds exprs
-    false_wform = AST.Wform [AST.WformElem (last exprs) Nothing]
-    dst_name  = case dst of
-      Left bndr -> AST.NSimple (varToVHDLId bndr)
-      Right name -> name
-    assign    = dst_name AST.:<==: (AST.ConWforms whenelses false_wform Nothing)
-  in
-    AST.CSSASm assign
-  where
-    mkWhenElse :: AST.Expr -> AST.Expr -> AST.WhenElse
-    mkWhenElse cond true_expr =
-      let
-        true_wform = AST.Wform [AST.WformElem true_expr Nothing]
-      in
-        AST.WhenElse true_wform cond
-
-mkAssocElems :: 
-  [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 =
-    arg_maps ++ (Maybe.maybeToList res_map_maybe)
-  where
-    arg_ports = ent_args entity
-    res_port_maybe = ent_res entity
-    -- Create an expression of res to map against the output port
-    res_expr = vhdlNameToVHDLExpr res
-    -- Map each of the input ports
-    arg_maps = zipWith mkAssocElem (map fst arg_ports) args
-    -- Map the output port, if present
-    res_map_maybe = fmap (\port -> mkAssocElem (fst port) res_expr) res_port_maybe
-
--- | Create an VHDL port -> signal association
-mkAssocElem :: AST.VHDLId -> AST.Expr -> AST.AssocElem
-mkAssocElem port signal = Just port AST.:=>: (AST.ADExpr signal) 
-
--- | Create an aggregate signal
-mkAggregateSignal :: [AST.Expr] -> AST.Expr
-mkAggregateSignal x = AST.Aggregate (map (\z -> AST.ElemAssoc Nothing z) x)
-
-mkComponentInst ::
-  String -- ^ The portmap label
-  -> AST.VHDLId -- ^ The entity name
-  -> [AST.AssocElem] -- ^ The port assignments
-  -> AST.ConcSm
-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 = mkAssocElem clockId (idToVHDLExpr clockId)
-    resetn_port = mkAssocElem resetId (idToVHDLExpr resetId)
-    compins = AST.CompInsSm (mkVHDLExtId label) (AST.IUEntity (AST.NSimple entity_id)) (AST.PMapAspect (portassigns ++ [clk_port,resetn_port]))
-
------------------------------------------------------------------------------
--- Functions to generate VHDL Exprs
------------------------------------------------------------------------------
-
-varToVHDLExpr :: Var.Var -> TypeSession AST.Expr
-varToVHDLExpr var =
-  case Id.isDataConWorkId_maybe var of
-    -- This is a dataconstructor.
-    Just dc -> dataconToVHDLExpr dc
-    -- Not a datacon, just another signal.
-    Nothing -> return $ 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 core = varToVHDLExpr (exprToVar core)
-
--- 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.
-altconToVHDLExpr :: CoreSyn.AltCon -> TypeSession AST.Expr
-altconToVHDLExpr (CoreSyn.DataAlt dc) = dataconToVHDLExpr dc
-
-altconToVHDLExpr (CoreSyn.LitAlt _) = error "\nVHDL.conToVHDLExpr: Literals not support in case alternatives yet"
-altconToVHDLExpr CoreSyn.DEFAULT = error "\nVHDL.conToVHDLExpr: DEFAULT alternative should not occur here!"
-
--- Turn a datacon (without arguments!) into a VHDL expression.
-dataconToVHDLExpr :: DataCon.DataCon -> TypeSession AST.Expr
-dataconToVHDLExpr dc = do
-  typemap <- MonadState.get tsTypes
-  htype_either <- mkHTypeEither (DataCon.dataConRepType dc)
-  case htype_either of
-    -- No errors
-    Right htype -> do
-      let dcname = DataCon.dataConName dc
-      case htype of
-        (BuiltinType "Bit") -> return $ AST.PrimLit $ case Name.getOccString dcname of "High" -> "'1'"; "Low" -> "'0'"
-        (BuiltinType "Bool") -> return $ AST.PrimLit $ case Name.getOccString dcname of "True" -> "true"; "False" -> "false"
-        otherwise -> do
-          let existing_ty = Monad.liftM (fmap fst) $ Map.lookup htype typemap
-          case existing_ty of
-            Just ty -> do
-              let lit    = idToVHDLExpr $ mkVHDLExtId $ Name.getOccString dcname
-              return lit
-            Nothing -> error $ "\nVHDLTools.dataconToVHDLExpr: Trying to make value for non-representable DataCon: " ++ pprString dc
-    -- Error when constructing htype
-    Left err -> error err
-
------------------------------------------------------------------------------
--- Functions dealing with names, variables and ids
------------------------------------------------------------------------------
-
--- Creates a VHDL Id from a binder
-varToVHDLId ::
-  CoreSyn.CoreBndr
-  -> AST.VHDLId
-varToVHDLId var = mkVHDLExtId (varToString var ++ varToStringUniq var ++ show (lowers $ varToStringUniq var))
-  where
-    lowers :: String -> Int
-    lowers xs = length [x | x <- xs, Char.isLower x]
-
--- Creates a VHDL Name from a binder
-varToVHDLName ::
-  CoreSyn.CoreBndr
-  -> AST.VHDLName
-varToVHDLName = AST.NSimple . varToVHDLId
-
--- Extracts the binder name as a String
-varToString ::
-  CoreSyn.CoreBndr
-  -> String
-varToString = OccName.occNameString . Name.nameOccName . Var.varName
-
--- Get the string version a Var's unique
-varToStringUniq :: Var.Var -> String
-varToStringUniq = show . Var.varUnique
-
--- Extracts the string version of the name
-nameToString :: Name.Name -> String
-nameToString = OccName.occNameString . Name.nameOccName
-
--- Shortcut for Basic VHDL Ids.
--- Can only contain alphanumerics and underscores. The supplied string must be
--- a valid basic id, otherwise an error value is returned. This function is
--- not meant to be passed identifiers from a source file, use mkVHDLExtId for
--- that.
-mkVHDLBasicId :: String -> AST.VHDLId
-mkVHDLBasicId s = 
-  AST.unsafeVHDLBasicId $ (strip_multiscore . strip_leading . strip_invalid) s
-  where
-    -- Strip invalid characters.
-    strip_invalid = filter (`elem` ['A'..'Z'] ++ ['a'..'z'] ++ ['0'..'9'] ++ "_.")
-    -- Strip leading numbers and underscores
-    strip_leading = dropWhile (`elem` ['0'..'9'] ++ "_")
-    -- Strip multiple adjacent underscores
-    strip_multiscore = concatMap (\cs -> 
-        case cs of 
-          ('_':_) -> "_"
-          _ -> cs
-      ) . List.group
-
--- Shortcut for Extended VHDL Id's. These Id's can contain a lot more
--- different characters than basic ids, but can never be used to refer to
--- basic ids.
--- Use extended Ids for any values that are taken from the source file.
-mkVHDLExtId :: String -> AST.VHDLId
-mkVHDLExtId s = 
-  AST.unsafeVHDLExtId $ strip_invalid s
-  where 
-    -- Allowed characters, taken from ForSyde's mkVHDLExtId
-    allowed = ['A'..'Z'] ++ ['a'..'z'] ++ ['0'..'9'] ++ " \"#&'()*+,./:;<=>_|!$%@?[]^`{}~-"
-    strip_invalid = filter (`elem` allowed)
-
--- Create a record field selector that selects the given label from the record
--- stored in the given binder.
-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
------------------------------------------------------------------------------
-builtin_types :: TypeMap
-builtin_types = 
-  Map.fromList [
-    (BuiltinType "Bit", Just (std_logicTM, Nothing)),
-    (BuiltinType "Bool", Just (booleanTM, Nothing)) -- TysWiredIn.boolTy
-  ]
-
--- Is the given type representable at runtime?
-isReprType :: Type.Type -> TypeSession Bool
-isReprType ty = do
-  ty_either <- mkHTypeEither ty
-  return $ case ty_either of
-    Left _ -> False
-    Right _ -> True
-
--- | Turn a Core type into a HType, returning an error using the given
--- error string if the type was not representable.
-mkHType :: (TypedThing t, Outputable.Outputable t) => 
-  String -> t -> TypeSession HType
-mkHType msg ty = do
-  htype_either <- mkHTypeEither ty
-  case htype_either of
-    Right htype -> return htype
-    Left err -> error $ msg ++ err  
-
--- | Turn a Core type into a HType. Returns either an error message if
--- the type was not representable, or the HType generated.
-mkHTypeEither :: (TypedThing t, Outputable.Outputable t) => 
-  t -> TypeSession (Either String HType)
-mkHTypeEither tything =
-  case getType tything of
-    Nothing -> return $ Left $ "\nVHDLTools.mkHTypeEither: Typed thing without a type: " ++ pprString tything
-    Just ty -> mkHTypeEither' ty
-
-mkHTypeEither' :: Type.Type -> TypeSession (Either String HType)
-mkHTypeEither' ty | ty_has_free_tyvars ty = return $ Left $ "\nVHDLTools.mkHTypeEither': Cannot create type: type has free type variables: " ++ pprString ty
-                  | isStateType ty = return $ Right StateType
-                  | otherwise =
-  case Type.splitTyConApp_maybe ty of
-    Just (tycon, args) -> do
-      typemap <- MonadState.get tsTypes
-      let name = Name.getOccString (TyCon.tyConName tycon)
-      let builtinTyMaybe = Map.lookup (BuiltinType name) typemap  
-      case builtinTyMaybe of
-        (Just x) -> return $ Right $ BuiltinType name
-        Nothing ->
-          case name of
-                "TFVec" -> do
-                  let el_ty = tfvec_elem ty
-                  elem_htype_either <- mkHTypeEither el_ty
-                  case elem_htype_either of
-                    -- Could create element type
-                    Right elem_htype -> do
-                      len <- tfp_to_int (tfvec_len_ty ty)
-                      return $ Right $ VecType len elem_htype
-                    -- Could not create element type
-                    Left err -> return $ Left $ 
-                      "\nVHDLTools.mkHTypeEither': Can not construct vectortype for elementtype: " ++ pprString el_ty ++ err
-                "SizedWord" -> do
-                  len <- tfp_to_int (sized_word_len_ty ty)
-                  return $ Right $ SizedWType len
-                "SizedInt" -> do
-                  len <- tfp_to_int (sized_word_len_ty ty)
-                  return $ Right $ SizedIType len
-                "RangedWord" -> do
-                  bound <- tfp_to_int (ranged_word_bound_ty ty)
-                  return $ Right $ RangedWType bound
-                otherwise ->
-                  mkTyConHType tycon args
-    Nothing -> return $ Left $ "\nVHDLTools.mkHTypeEither': Do not know what to do with type: " ++ pprString ty
-
-mkTyConHType :: TyCon.TyCon -> [Type.Type] -> TypeSession (Either String HType)
-mkTyConHType tycon args =
-  case TyCon.tyConDataCons tycon of
-    -- Not an algebraic type
-    [] -> return $ Left $ "VHDLTools.mkTyConHType: Only custom algebraic types are supported: " ++ pprString tycon
-    [dc] -> do
-      let arg_tys = DataCon.dataConRepArgTys dc
-      let real_arg_tys = map (CoreSubst.substTy subst) arg_tys
-      let real_arg_tys_nostate = filter (\x -> not (isStateType x)) real_arg_tys
-      elem_htys_either <- mapM mkHTypeEither real_arg_tys_nostate
-      case Either.partitionEithers elem_htys_either of
-        ([], [elem_hty]) ->
-          return $ Right elem_hty
-        -- No errors in element types
-        ([], elem_htys) ->
-          return $ Right $ AggrType (nameToString (TyCon.tyConName tycon)) elem_htys
-        -- There were errors in element types
-        (errors, _) -> return $ Left $
-          "\nVHDLTools.mkTyConHType: Can not construct type for: " ++ pprString tycon ++ "\n because no type can be construced for some of the arguments.\n"
-          ++ (concat errors)
-    dcs -> do
-      let arg_tys = concatMap DataCon.dataConRepArgTys dcs
-      let real_arg_tys = map (CoreSubst.substTy subst) arg_tys
-      case real_arg_tys of
-        [] ->
-          return $ Right $ EnumType (nameToString (TyCon.tyConName tycon)) (map (nameToString . DataCon.dataConName) dcs)
-        xs -> return $ Left $
-          "VHDLTools.mkTyConHType: Only enum-like constructor datatypes supported: " ++ pprString dcs ++ "\n"
-  where
-    tyvars = TyCon.tyConTyVars tycon
-    subst = CoreSubst.extendTvSubstList CoreSubst.emptySubst (zip tyvars args)
-
--- Translate a Haskell type to a VHDL type, generating a new type if needed.
--- Returns an error value, using the given message, when no type could be
--- created. Returns Nothing when the type is valid, but empty.
-vhdlTy :: (TypedThing t, Outputable.Outputable t) => 
-  String -> t -> TypeSession (Maybe AST.TypeMark)
-vhdlTy msg ty = do
-  htype <- mkHType msg ty
-  vhdlTyMaybe htype
-
-vhdlTyMaybe :: HType -> TypeSession (Maybe AST.TypeMark)
-vhdlTyMaybe htype = do
-  typemap <- MonadState.get tsTypes
-  -- If not a builtin type, try the custom types
-  let existing_ty = Map.lookup htype typemap
-  case existing_ty of
-    -- Found a type, return it
-    Just (Just (t, _)) -> return $ Just t
-    Just (Nothing) -> return Nothing
-    -- No type yet, try to construct it
-    Nothing -> do
-      newty <- (construct_vhdl_ty htype)
-      MonadState.modify tsTypes (Map.insert htype newty)
-      case newty of
-        Just (ty_id, ty_def) -> do
-          MonadState.modify tsTypeDecls (\typedefs -> typedefs ++ [mktydecl (ty_id, ty_def)])
-          return $ Just ty_id
-        Nothing -> return Nothing
-
--- Construct a new VHDL type for the given Haskell type. Returns an error
--- message or the resulting typemark and typedef.
-construct_vhdl_ty :: HType -> TypeSession TypeMapRec
--- State types don't generate VHDL
-construct_vhdl_ty htype =
-    case htype of
-      StateType -> return  Nothing
-      (SizedWType w) -> mkUnsignedTy w
-      (SizedIType i) -> mkSignedTy i
-      (RangedWType u) -> mkNaturalTy 0 u
-      (VecType n e) -> mkVectorTy (VecType n e)
-      -- Create a custom type from this tycon
-      otherwise -> mkTyconTy htype
-
--- | Create VHDL type for a custom tycon
-mkTyconTy :: HType -> TypeSession TypeMapRec
-mkTyconTy htype =
-  case htype of
-    (AggrType tycon args) -> do
-      elemTysMaybe <- mapM vhdlTyMaybe args
-      case Maybe.catMaybes elemTysMaybe of
-        [] -> -- No non-empty members
-          return Nothing
-        elem_tys -> do
-          let elems = zipWith AST.ElementDec recordlabels elem_tys  
-          let elem_names = concatMap prettyShow elem_tys
-          let ty_id = mkVHDLExtId $ tycon ++ elem_names
-          let ty_def = AST.TDR $ AST.RecordTypeDef elems
-          let tupshow = mkTupleShow elem_tys ty_id
-          MonadState.modify tsTypeFuns $ Map.insert (htype, showIdString) (showId, tupshow)
-          return $ Just (ty_id, Just $ Left ty_def)
-    (EnumType tycon dcs) -> do
-      let elems = map mkVHDLExtId dcs
-      let ty_id = mkVHDLExtId tycon
-      let ty_def = AST.TDE $ AST.EnumTypeDef elems
-      let enumShow = mkEnumShow elems ty_id
-      MonadState.modify tsTypeFuns $ Map.insert (htype, showIdString) (showId, enumShow)
-      return $ Just (ty_id, Just $ Left ty_def)
-    otherwise -> error $ "\nVHDLTools.mkTyconTy: Called for HType that is neiter a AggrType or EnumType: " ++ show htype
-  where
-    -- Generate a bunch of labels for fields of a record
-    recordlabels = map (\c -> mkVHDLBasicId [c]) ['A'..'Z']
-
--- | Create a VHDL vector type
-mkVectorTy ::
-  HType -- ^ The Haskell type of the Vector
-  -> TypeSession TypeMapRec
-      -- ^ An error message or The typemark created.
-
-mkVectorTy (VecType len elHType) = do
-  typesMap <- MonadState.get tsTypes
-  elTyTmMaybe <- vhdlTyMaybe elHType
-  case elTyTmMaybe of
-    (Just elTyTm) -> do
-      let ty_id = mkVHDLExtId $ "vector-"++ (AST.fromVHDLId elTyTm) ++ "-0_to_" ++ (show len)
-      let range = AST.ConstraintIndex $ AST.IndexConstraint [AST.ToRange (AST.PrimLit "0") (AST.PrimLit $ show (len - 1))]
-      let existing_uvec_ty = fmap (fmap fst) $ Map.lookup (UVecType elHType) typesMap
-      case existing_uvec_ty of
-        Just (Just t) -> do
-          let ty_def = AST.SubtypeIn t (Just range)
-          return (Just (ty_id, Just $ Right ty_def))
-        Nothing -> do
-          let vec_id  = mkVHDLExtId $ "vector_" ++ (AST.fromVHDLId elTyTm)
-          let vec_def = AST.TDA $ AST.UnconsArrayDef [tfvec_indexTM] elTyTm
-          MonadState.modify tsTypes (Map.insert (UVecType elHType) (Just (vec_id, (Just $ Left vec_def))))
-          MonadState.modify tsTypeDecls (\typedefs -> typedefs ++ [mktydecl (vec_id, (Just $ Left vec_def))])
-          let vecShowFuns = mkVectorShow elTyTm vec_id
-          mapM_ (\(id, subprog) -> MonadState.modify tsTypeFuns $ Map.insert (UVecType elHType, id) ((mkVHDLExtId id), subprog)) vecShowFuns
-          let ty_def = AST.SubtypeIn vec_id (Just range)
-          return (Just (ty_id, Just $ Right ty_def))
-    -- Vector of empty elements becomes empty itself.
-    Nothing -> return Nothing
-mkVectorTy htype = error $ "\nVHDLTools.mkVectorTy: Called for HType that is not a VecType: " ++ show htype
-
-mkNaturalTy ::
-  Int -- ^ The minimum bound (> 0)
-  -> Int -- ^ The maximum bound (> minimum bound)
-  -> TypeSession TypeMapRec
-      -- ^ An error message or The typemark created.
-mkNaturalTy min_bound max_bound = do
-  let bitsize = floor (logBase 2 (fromInteger (toInteger max_bound)))
-  let ty_id = mkVHDLExtId $ "natural_" ++ (show min_bound) ++ "_to_" ++ (show max_bound)
-  let range = AST.ConstraintIndex $ AST.IndexConstraint [AST.ToRange (AST.PrimLit $ show min_bound) (AST.PrimLit $ show bitsize)]
-  let ty_def = AST.SubtypeIn unsignedTM (Just range)
-  return (Just (ty_id, Just $ Right ty_def))
-
-mkUnsignedTy ::
-  Int -- ^ Haskell type of the unsigned integer
-  -> TypeSession TypeMapRec
-mkUnsignedTy size = do
-  let ty_id = mkVHDLExtId $ "unsigned_" ++ show (size - 1)
-  let range = AST.ConstraintIndex $ AST.IndexConstraint [AST.ToRange (AST.PrimLit "0") (AST.PrimLit $ show (size - 1))]
-  let ty_def = AST.SubtypeIn unsignedTM (Just range)
-  return (Just (ty_id, Just $ Right ty_def))
-  
-mkSignedTy ::
-  Int -- ^ Haskell type of the signed integer
-  -> TypeSession TypeMapRec
-mkSignedTy size = do
-  let ty_id = mkVHDLExtId $ "signed_" ++ show (size - 1)
-  let range = AST.ConstraintIndex $ AST.IndexConstraint [AST.ToRange (AST.PrimLit "0") (AST.PrimLit $ show (size - 1))]
-  let ty_def = AST.SubtypeIn signedTM (Just range)
-  return (Just (ty_id, Just $ Right ty_def))
-
--- Finds the field labels for VHDL type generated for the given Core type,
--- which must result in a record type.
-getFieldLabels :: Type.Type -> TypeSession [AST.VHDLId]
-getFieldLabels ty = do
-  -- Ensure that the type is generated (but throw away it's VHDLId)
-  let error_msg = "\nVHDLTools.getFieldLabels: Can not get field labels, because: " ++ pprString ty ++ "can not be generated." 
-  vhdlTy error_msg ty
-  -- Get the types map, lookup and unpack the VHDL TypeDef
-  types <- MonadState.get tsTypes
-  -- Assume the type for which we want labels is really translatable
-  htype <- mkHType error_msg ty
-  case Map.lookup htype types of
-    Nothing -> error $ "\nVHDLTools.getFieldLabels: Type not found? This should not happen!\nLooking for type: " ++ (pprString ty) ++ "\nhtype: " ++ (show htype) 
-    Just Nothing -> return [] -- The type is empty
-    Just (Just (_, Just (Left (AST.TDR (AST.RecordTypeDef elems))))) -> return $ map (\(AST.ElementDec id _) -> id) elems
-    Just (Just (_, Just vty)) -> error $ "\nVHDLTools.getFieldLabels: Type not a record type? This should not happen!\nLooking for type: " ++ pprString (ty) ++ "\nhtype: " ++ (show htype) ++ "\nFound type: " ++ (show vty)
-    
-mktydecl :: (AST.VHDLId, Maybe (Either AST.TypeDef AST.SubtypeIn)) -> Maybe AST.PackageDecItem
-mytydecl (_, Nothing) = Nothing
-mktydecl (ty_id, Just (Left ty_def)) = Just $ AST.PDITD $ AST.TypeDec ty_id ty_def
-mktydecl (ty_id, Just (Right ty_def)) = Just $ AST.PDISD $ AST.SubtypeDec ty_id ty_def
-
-mkTupleShow :: 
-  [AST.TypeMark] -- ^ type of each tuple element
-  -> AST.TypeMark -- ^ type of the tuple
-  -> AST.SubProgBody
-mkTupleShow elemTMs tupleTM = AST.SubProgBody showSpec [] [showExpr]
-  where
-    tupPar    = AST.unsafeVHDLBasicId "tup"
-    showSpec  = AST.Function showId [AST.IfaceVarDec tupPar tupleTM] stringTM
-    showExpr  = AST.ReturnSm (Just $
-                  AST.PrimLit "'('" AST.:&: showMiddle AST.:&: AST.PrimLit "')'")
-      where
-        showMiddle = if null elemTMs then
-            AST.PrimLit "''"
-          else
-            foldr1 (\e1 e2 -> e1 AST.:&: AST.PrimLit "','" AST.:&: e2) $
-              map ((genExprFCall showId).
-                    AST.PrimName .
-                    AST.NSelected .
-                    (AST.NSimple tupPar AST.:.:).
-                    tupVHDLSuffix)
-                  (take tupSize recordlabels)
-    recordlabels = map (\c -> mkVHDLBasicId [c]) ['A'..'Z']
-    tupSize = length elemTMs
-
-mkEnumShow ::
-  [AST.VHDLId]
-  -> AST.TypeMark
-  -> AST.SubProgBody
-mkEnumShow elemIds enumTM = AST.SubProgBody showSpec [] [showExpr]
-  where
-    enumPar    = AST.unsafeVHDLBasicId "enum"
-    showSpec  = AST.Function showId [AST.IfaceVarDec enumPar enumTM] stringTM
-    showExpr  = AST.ReturnSm (Just $
-                  AST.PrimLit (show $ tail $ init $ AST.fromVHDLId enumTM))
-
-mkVectorShow ::
-  AST.TypeMark -- ^ elemtype
-  -> AST.TypeMark -- ^ vectype
-  -> [(String,AST.SubProgBody)]
-mkVectorShow elemTM vectorTM = 
-  [ (headId, AST.SubProgBody headSpec []                   [headExpr])
-  , (tailId, AST.SubProgBody tailSpec [AST.SPVD tailVar]   [tailExpr, tailRet])
-  , (showIdString, AST.SubProgBody showSpec [AST.SPSB doShowDef] [showRet])
-  ]
-  where
-    vecPar  = AST.unsafeVHDLBasicId "vec"
-    resId   = AST.unsafeVHDLBasicId "res"
-    headSpec = AST.Function (mkVHDLExtId headId) [AST.IfaceVarDec vecPar vectorTM] elemTM
-    -- return vec(0);
-    headExpr = AST.ReturnSm (Just (AST.PrimName $ AST.NIndexed (AST.IndexedName 
-                    (AST.NSimple vecPar) [AST.PrimLit "0"])))
-    vecSlice init last =  AST.PrimName (AST.NSlice 
-                                      (AST.SliceName 
-                                            (AST.NSimple vecPar) 
-                                            (AST.ToRange init last)))
-    tailSpec = AST.Function (mkVHDLExtId tailId) [AST.IfaceVarDec vecPar vectorTM] vectorTM
-       -- variable res : fsvec_x (0 to vec'length-2); 
-    tailVar = 
-         AST.VarDec resId 
-                (AST.SubtypeIn vectorTM
-                  (Just $ AST.ConstraintIndex $ AST.IndexConstraint 
-                   [AST.ToRange (AST.PrimLit "0")
-                            (AST.PrimName (AST.NAttribute $ 
-                              AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) AST.:-:
-                                (AST.PrimLit "2"))   ]))
-                Nothing       
-       -- res AST.:= vec(1 to vec'length-1)
-    tailExpr = AST.NSimple resId AST.:= (vecSlice 
-                               (AST.PrimLit "1") 
-                               (AST.PrimName (AST.NAttribute $ 
-                                  AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing) 
-                                                             AST.:-: AST.PrimLit "1"))
-    tailRet = AST.ReturnSm (Just $ AST.PrimName $ AST.NSimple resId)
-    showSpec  = AST.Function showId [AST.IfaceVarDec vecPar vectorTM] stringTM
-    doShowId  = AST.unsafeVHDLExtId "doshow"
-    doShowDef = AST.SubProgBody doShowSpec [] [doShowRet]
-      where doShowSpec = AST.Function doShowId [AST.IfaceVarDec vecPar vectorTM] 
-                                           stringTM
-            -- case vec'len is
-            --  when  0 => return "";
-            --  when  1 => return head(vec);
-            --  when others => return show(head(vec)) & ',' &
-            --                        doshow (tail(vec));
-            -- end case;
-            doShowRet = 
-              AST.CaseSm (AST.PrimName (AST.NAttribute $ 
-                          AST.AttribName (AST.NSimple vecPar) (AST.NSimple $ mkVHDLBasicId lengthId) Nothing))
-              [AST.CaseSmAlt [AST.ChoiceE $ AST.PrimLit "0"] 
-                         [AST.ReturnSm (Just $ AST.PrimLit "\"\"")],
-               AST.CaseSmAlt [AST.ChoiceE $ AST.PrimLit "1"] 
-                         [AST.ReturnSm (Just $ 
-                          genExprFCall showId 
-                               (genExprFCall (mkVHDLExtId headId) (AST.PrimName $ AST.NSimple vecPar)) )],
-               AST.CaseSmAlt [AST.Others] 
-                         [AST.ReturnSm (Just $ 
-                           genExprFCall showId 
-                             (genExprFCall (mkVHDLExtId headId) (AST.PrimName $ AST.NSimple vecPar)) AST.:&:
-                           AST.PrimLit "','" AST.:&:
-                           genExprFCall doShowId 
-                             (genExprFCall (mkVHDLExtId tailId) (AST.PrimName $ AST.NSimple vecPar)) ) ]]
-    -- return '<' & doshow(vec) & '>';
-    showRet =  AST.ReturnSm (Just $ AST.PrimLit "'<'" AST.:&:
-                               genExprFCall doShowId (AST.PrimName $ AST.NSimple vecPar) AST.:&:
-                               AST.PrimLit "'>'" )
-
-mkBuiltInShow :: [AST.SubProgBody]
-mkBuiltInShow = [ AST.SubProgBody showBitSpec [] [showBitExpr]
-                , AST.SubProgBody showBoolSpec [] [showBoolExpr]
-                , AST.SubProgBody showSingedSpec [] [showSignedExpr]
-                , AST.SubProgBody showUnsignedSpec [] [showUnsignedExpr]
-                -- , AST.SubProgBody showNaturalSpec [] [showNaturalExpr]
-                ]
-  where
-    bitPar      = AST.unsafeVHDLBasicId "s"
-    boolPar     = AST.unsafeVHDLBasicId "b"
-    signedPar   = AST.unsafeVHDLBasicId "sint"
-    unsignedPar = AST.unsafeVHDLBasicId "uint"
-    -- naturalPar  = AST.unsafeVHDLBasicId "nat"
-    showBitSpec = AST.Function showId [AST.IfaceVarDec bitPar std_logicTM] stringTM
-    -- if s = '1' then return "'1'" else return "'0'"
-    showBitExpr = AST.IfSm (AST.PrimName (AST.NSimple bitPar) AST.:=: AST.PrimLit "'1'")
-                        [AST.ReturnSm (Just $ AST.PrimLit "\"High\"")]
-                        []
-                        (Just $ AST.Else [AST.ReturnSm (Just $ AST.PrimLit "\"Low\"")])
-    showBoolSpec = AST.Function showId [AST.IfaceVarDec boolPar booleanTM] stringTM
-    -- if b then return "True" else return "False"
-    showBoolExpr = AST.IfSm (AST.PrimName (AST.NSimple boolPar))
-                        [AST.ReturnSm (Just $ AST.PrimLit "\"True\"")]
-                        []
-                        (Just $ AST.Else [AST.ReturnSm (Just $ AST.PrimLit "\"False\"")])
-    showSingedSpec = AST.Function showId [AST.IfaceVarDec signedPar signedTM] stringTM
-    showSignedExpr =  AST.ReturnSm (Just $
-                        AST.PrimName $ AST.NAttribute $ AST.AttribName (AST.NSimple integerId) 
-                        (AST.NIndexed $ AST.IndexedName (AST.NSimple imageId) [signToInt]) Nothing )
-                      where
-                        signToInt = genExprFCall (mkVHDLBasicId toIntegerId) (AST.PrimName $ AST.NSimple signedPar)
-    showUnsignedSpec =  AST.Function showId [AST.IfaceVarDec unsignedPar unsignedTM] stringTM
-    showUnsignedExpr =  AST.ReturnSm (Just $
-                          AST.PrimName $ AST.NAttribute $ AST.AttribName (AST.NSimple integerId) 
-                          (AST.NIndexed $ AST.IndexedName (AST.NSimple imageId) [unsignToInt]) Nothing )
-                        where
-                          unsignToInt = genExprFCall (mkVHDLBasicId toIntegerId) (AST.PrimName $ AST.NSimple unsignedPar)
-    -- showNaturalSpec = AST.Function showId [AST.IfaceVarDec naturalPar naturalTM] stringTM
-    -- showNaturalExpr = AST.ReturnSm (Just $
-    --                     AST.PrimName $ AST.NAttribute $ AST.AttribName (AST.NSimple integerId)
-    --                     (AST.NIndexed $ AST.IndexedName (AST.NSimple imageId) [AST.PrimName $ AST.NSimple $ naturalPar]) Nothing )
-                      
-  
-genExprFCall :: AST.VHDLId -> AST.Expr -> AST.Expr
-genExprFCall fName args = 
-   AST.PrimFCall $ AST.FCall (AST.NSimple fName)  $
-             map (\exp -> Nothing AST.:=>: AST.ADExpr exp) [args] 
-
-genExprPCall2 :: AST.VHDLId -> AST.Expr -> AST.Expr -> AST.SeqSm             
-genExprPCall2 entid arg1 arg2 =
-        AST.ProcCall (AST.NSimple entid) $
-         map (\exp -> Nothing AST.:=>: AST.ADExpr exp) [arg1,arg2]
-
-mkSigDec :: CoreSyn.CoreBndr -> TranslatorSession (Maybe AST.SigDec)
-mkSigDec bndr = do
-  let error_msg = "\nVHDL.mkSigDec: Can not make signal declaration for type: \n" ++ pprString bndr 
-  type_mark_maybe <- MonadState.lift tsType $ vhdlTy error_msg (Var.varType bndr)
-  case type_mark_maybe of
-    Just type_mark -> return $ Just (AST.SigDec (varToVHDLId bndr) type_mark Nothing)
-    Nothing -> return Nothing
-
--- | Does the given thing have a non-empty type?
-hasNonEmptyType :: (TypedThing t, Outputable.Outputable t) => 
-  t -> TranslatorSession Bool
-hasNonEmptyType thing = MonadState.lift tsType $ isJustM (vhdlTy "hasNonEmptyType: Non representable type?" thing)
diff --git a/cλash/CLasH/VHDL/VHDLTypes.hs b/cλash/CLasH/VHDL/VHDLTypes.hs
deleted file mode 100644 (file)
index 38ccc97..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
---
--- Some types used by the VHDL module.
---
-module CLasH.VHDL.VHDLTypes where
-
--- VHDL imports
-import qualified Language.VHDL.AST as AST
-
--- 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   :: [Port], -- ^ A port for each non-empty function argument
-  ent_res    :: Maybe Port, -- ^ The output port
-  ent_dec    :: AST.EntityDec -- ^ The complete entity declaration
-} deriving (Show);
-
-type Architecture = AST.ArchBody
-
--- vim: set ts=8 sw=2 sts=2 expandtab:
diff --git a/cλash/LICENSE b/cλash/LICENSE
deleted file mode 100644 (file)
index 23ebcfd..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-Copyright (c) 2009 Christiaan Baaij & Matthijs Kooijman
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-    * Redistributions of source code must retain the above copyright
-      notice, this list of conditions and the following disclaimer.
-    * Redistributions in binary form must reproduce the above copyright
-      notice, this list of conditions and the following disclaimer in the
-      documentation and/or other materials provided with the distribution.
-    * Neither the name of the copyright holder nor the
-      names of its contributors may be used to endorse or promote products
-      derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY
-EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
diff --git a/cλash/clash.cabal b/cλash/clash.cabal
deleted file mode 100644 (file)
index d722191..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-name:               clash
-version:            0.1
-build-type:         Simple
-synopsis:           CAES Languege for Hardware Descriptions (CLasH)
-description:        CLasH is a toolchain/language to translate subsets of
-                    Haskell to synthesizable VHDL. It does this by translating
-                    the intermediate System Fc (GHC Core) representation to a
-                    VHDL AST, which is then written to file.
-category:           Development
-license:            BSD3
-license-file:       LICENSE
-package-url:        http://github.com/darchon/clash/tree/master
-copyright:          Copyright (c) 2009 Christiaan Baaij & Matthijs Kooijman
-author:             Christiaan Baaij & Matthijs Kooijman
-stability:          alpha
-maintainer:         christiaan.baaij@gmail.com & matthijs@stdin.nl
-Cabal-Version:      >= 1.2
-
-Library
-  build-depends:    ghc >= 6.11, pretty, vhdl > 0.1, haskell98, syb,
-                    data-accessor, containers, base >= 4, transformers,
-                    filepath, template-haskell, data-accessor-template,
-                    data-accessor-transformers, prettyclass, directory, 
-                    th-lift-ng, tfp, tfvec, time
-                    
-  exposed-modules:  CLasH.HardwareTypes
-                    CLasH.Translator
-                    CLasH.Translator.Annotations
-                    CLasH.Utils
-                    
-  other-modules:    CLasH.Translator.TranslatorTypes
-                    CLasH.Normalize
-                    CLasH.Normalize.NormalizeTypes
-                    CLasH.Normalize.NormalizeTools
-                    CLasH.VHDL
-                    CLasH.VHDL.Constants
-                    CLasH.VHDL.Generate
-                    CLasH.VHDL.Testbench
-                    CLasH.VHDL.VHDLTools
-                    CLasH.VHDL.VHDLTypes
-                    CLasH.Utils.GhcTools
-                    CLasH.Utils.HsTools
-                    CLasH.Utils.Pretty
-                    CLasH.Utils.Core.BinderTools
-                    CLasH.Utils.Core.CoreShow
-                    CLasH.Utils.Core.CoreTools
-  
diff --git a/cλash/ghc-stage b/cλash/ghc-stage
deleted file mode 100644 (file)
index 9a7456b..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-2
-
index a565745971366b1829b5040506bcf9868fdc15cb..ce4025e0007194a5584fb9469b4d28a5b20eaa3b 100644 (file)
@@ -6,10 +6,6 @@ import qualified Prelude as P
 import CLasH.HardwareTypes hiding ((>>))
 import CLasH.Translator.Annotations
 
-type Signed   = SizedInt
-type Unsigned = SizedWord
-type Index    = RangedWord
-
 -- =======================================
 -- = System size configuration variables =
 -- =======================================
@@ -60,7 +56,7 @@ e >> v = shiftl v e
 -- =======================
 data DiscrRecord =
   DiscrR { prev_index  ::  ArrayIndex
-         , cur_discr   ::  SizedWord DiscrSize
+         , cur_discr   ::  Unsigned DiscrSize
          }
 type DiscrState = State DiscrRecord
                             
@@ -68,7 +64,7 @@ type RippleState =
   State (Vector (AdderDepthPL :+: D1) (CellType, Discr))
 
 data BlockRecord = 
-  Block { ptrs    ::  (SizedWord D4, SizedWord D4, SizedWord D4)
+  Block { ptrs    ::  (Unsigned D4, Unsigned D4, Unsigned D4)
         , buf1    ::  MemState AdderDepthPL DataInt
         , buf2    ::  MemState AdderDepthPL DataInt
         }
@@ -124,7 +120,7 @@ discriminator (State (DiscrR {..})) index = ( State DiscrR { prev_index = index
     new_discr               = index /= prev_index
     cur_discr'  | new_discr = cur_discr + 1
                 | otherwise = cur_discr
-    discr                   = fromSizedWord cur_discr'
+    discr                   = fromUnsigned cur_discr'
 
 -- ======================================================
 -- = Input Buffer: Buffers incomming inputs when needed =
@@ -166,12 +162,12 @@ blockBuffer (State (Block {..})) (inp, shift) = ( State Block { ptrs = ptrs'
     (rd_ptr1, rd_ptr2, wr_ptr) = ptrs
     ptrs'                      = (rd_ptr1', rd_ptr2', wr_ptr')
     -- Update pointers               
-    count                      = fromRangedWord shift
+    count                      = fromIndex shift
     (rd_ptr1', rd_ptr2')       = (rd_ptr1 + count, rd_ptr2 + count)
     wr_ptr'                    = wr_ptr + 1
     -- Write & Read from RAMs
-    (buf1', out1)              = blockRAM buf1 inp (fromSizedWord rd_ptr1) (fromSizedWord wr_ptr) True
-    (buf2', out2)              = blockRAM buf2 inp (fromSizedWord rd_ptr2) (fromSizedWord wr_ptr) True
+    (buf1', out1)              = blockRAM buf1 inp (fromUnsigned rd_ptr1) (fromUnsigned wr_ptr) True
+    (buf2', out2)              = blockRAM buf2 inp (fromUnsigned rd_ptr2) (fromUnsigned wr_ptr) True
     
 -- ============================================
 -- = Simulated pipelined floating point adder =
@@ -302,7 +298,7 @@ initDiscrState = DiscrR { prev_index = 255
 initRippleState :: Vector (AdderDepthPL :+: D1) (CellType, Discr)
 initRippleState = copy (False, 0)
 
-initBlockState :: (SizedWord D4, SizedWord D4, SizedWord D4)
+initBlockState :: (Unsigned D4, Unsigned D4, Unsigned D4)
 initBlockState = (0,1,0)
                      
 initPipeState ::