-- top level function "normalize", and defines the actual transformation passes that
-- are performed.
--
-module CLasH.Normalize (getNormalized, normalizeExpr) where
+module CLasH.Normalize (getNormalized, normalizeExpr, splitNormalized) where
-- Standard modules
import Debug.Trace
-- If the binding isn't in the "cache" (bindings map), then we can't create
-- it out of thin air, so return an error.
error $ "Normalize.getBinding: Unknown function requested: " ++ show bndr
+
+-- | Split a normalized expression into the argument binders, top level
+-- bindings and the result binder.
+splitNormalized ::
+ CoreExpr -- ^ The normalized expression
+ -> ([CoreBndr], [Binding], CoreBndr)
+splitNormalized expr =
+ case letexpr of
+ (Let (Rec binds) (Var res)) -> (args, binds, res)
+ _ -> error $ "Normalize.splitNormalized: Not in normal form: " ++ pprString expr ++ "\n"
+ where
+ (args, letexpr) = CoreSyn.collectBinders expr
import CLasH.Utils.HsTools
import CLasH.Utils.Pretty
+-- | 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.
eval_tfp_int :: HscTypes.HscEnv -> Type.Type -> Int
getEntity fname = Utils.makeCached fname tsEntities $ do
expr <- Normalize.getNormalized fname
- -- Strip off lambda's, these will be arguments
- let (args, letexpr) = CoreSyn.collectBinders expr
+ -- Split the normalized expression
+ let (args, binds, res) = Normalize.splitNormalized expr
-- Generate ports for all non-empty types
args' <- catMaybesM $ mapM mkMap args
- -- There must be a let at top level
- let (CoreSyn.Let binds (CoreSyn.Var res)) = letexpr
-- TODO: Handle Nothing
res' <- mkMap res
let vhdl_id = mkVHDLBasicId $ varToString fname ++ "_" ++ varToStringUniq fname
getArchitecture fname = Utils.makeCached fname tsArchitectures $ do
expr <- Normalize.getNormalized 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
- -- Strip off lambda's, these will be arguments
- let (args, letexpr) = CoreSyn.collectBinders expr
- -- There must be a let at top level
- let (CoreSyn.Let (CoreSyn.Rec binds) (CoreSyn.Var res)) = letexpr
-- Create signal declarations for all binders in the let expression, except
-- for the output port (that will already have an output port declared in
createStimulans expr cycl = do
-- There must be a let at top level
- (CoreSyn.Let (CoreSyn.Rec binds) (Var res)) <- normalizeExpr ("test input #" ++ show cycl) expr
+ 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)