let binds = Maybe.mapMaybe (findBind (cm_binds core)) ["shalf_adder"]
liftIO $ printBinds binds
-- Turn bind into VHDL
- let vhdl = State.evalState (mkVHDL binds) (VHDLSession 0 [])
+ let (vhdl, sess) = State.runState (mkVHDL binds) (VHDLSession 0 [])
liftIO $ putStr $ render $ ForSyDe.Backend.Ppr.ppr vhdl
liftIO $ ForSyDe.Backend.VHDL.FileIO.writeDesignFile vhdl "../vhdl/vhdl/output.vhdl"
+ liftIO $ putStr $ "\n\nFinal session:\n" ++ show sess
return ()
where
-- Turns the given bind into VHDL
-- Find the type of the binder
let (arg_ty, _) = Type.splitFunTy (CoreUtils.exprType lam)
-- Create signal names for the binder
- let arg_signal = getPortNameMapForTy ("xxx") arg_ty
+ -- TODO: We assume arguments are ports here
+ let arg_signal = getPortNameMapForTy ("xxx") arg_ty (useAsPort arg_ty)
-- Create the corresponding signal declarations
let signal_decls = mkSignalsFromMap arg_signal
-- Add the binder to the list of binds
-- Bind each of the input ports to the expanded arguments
let inmaps = concat $ zipWith createAssocElems inports arg_res_signals
-- Create signal names for our result
- let res_signal = getPortNameMapForTy (appname ++ "_out") ty
+ -- TODO: We assume the result is a port here
+ let res_signal = getPortNameMapForTy (appname ++ "_out") ty (useAsPort ty)
-- Create the corresponding signal declarations
let signal_decls = mkSignalsFromMap res_signal
-- Bind each of the output ports to our output signals
expandBind bind@(NonRec var expr) = do
-- Create the function signature
- hwfunc <- mkHWFunction bind
let ty = CoreUtils.exprType expr
let hsfunc = mkHsFunction var ty
+ hwfunc <- mkHWFunction bind hsfunc
-- Add it to the session
addFunc hsfunc hwfunc
arch <- getArchitecture hwfunc expr
data HsValueMap mapto =
Tuple [HsValueMap mapto]
| Single mapto
+ | Unused
deriving (Show, Eq)
-- | Creates a HsValueMap with the same structure as the given type, using the
-- Generate a port name map (or multiple for tuple types) in the given direction for
-- each type given.
-getPortNameMapForTys :: String -> Int -> [Type] -> [SignalNameMap]
-getPortNameMapForTys prefix num [] = []
-getPortNameMapForTys prefix num (t:ts) =
- (getPortNameMapForTy (prefix ++ show num) t) : getPortNameMapForTys prefix (num + 1) ts
+getPortNameMapForTys :: String -> Int -> [Type] -> [HsUseMap] -> [SignalNameMap]
+getPortNameMapForTys prefix num [] [] = []
+getPortNameMapForTys prefix num (t:ts) (u:us) =
+ (getPortNameMapForTy (prefix ++ show num) t u) : getPortNameMapForTys prefix (num + 1) ts us
-getPortNameMapForTy :: String -> Type -> SignalNameMap
-getPortNameMapForTy name ty =
+getPortNameMapForTy :: String -> Type -> HsUseMap -> SignalNameMap
+getPortNameMapForTy name _ (Single State) =
+ Unused
+
+getPortNameMapForTy name ty use =
if (TyCon.isTupleTyCon tycon) then
+ let (Tuple uses) = use in
-- Expand tuples we find
- Tuple (getPortNameMapForTys name 0 args)
+ Tuple (getPortNameMapForTys name 0 args uses)
else -- Assume it's a type constructor application, ie simple data type
Single ((AST.unsafeVHDLBasicId name), (vhdl_ty ty))
where
-- output ports.
mkHWFunction ::
CoreBind -- The core binder to generate the interface for
+ -> HsFunction -- The HsFunction describing the function
-> VHDLState HWFunction -- The function interface
-mkHWFunction (NonRec var expr) =
+mkHWFunction (NonRec var expr) hsfunc =
return $ HWFunction (mkVHDLId name) inports outport
where
name = getOccString var
ty = CoreUtils.exprType expr
- (fargs, res) = Type.splitFunTys ty
- args = if length fargs == 1 then fargs else (init fargs)
- --state = if length fargs == 1 then () else (last fargs)
+ (args, res) = Type.splitFunTys ty
inports = case args of
-- Handle a single port specially, to prevent an extra 0 in the name
- [port] -> [getPortNameMapForTy "portin" port]
- ps -> getPortNameMapForTys "portin" 0 ps
- outport = getPortNameMapForTy "portout" res
+ [port] -> [getPortNameMapForTy "portin" port (head $ hsArgs hsfunc)]
+ ps -> getPortNameMapForTys "portin" 0 ps (hsArgs hsfunc)
+ outport = getPortNameMapForTy "portout" res (hsRes hsfunc)
-mkHWFunction (Rec _) =
+mkHWFunction (Rec _) _ =
error "Recursive binders not supported"
-- | How is a given (single) value in a function's type (ie, argument or
| State --- ^ Use it as state (input or output)
deriving (Show, Eq)
+useAsPort = mkHsValueMap (\x -> Single Port)
+useAsState = mkHsValueMap (\x -> Single State)
+
+type HsUseMap = HsValueMap HsValueUse
+
-- | This type describes a particular use of a Haskell function and is used to
-- look up an appropriate hardware description.
data HsFunction = HsFunction {
hsName :: String, -- ^ What was the name of the original Haskell function?
- hsArgs :: [HsValueMap HsValueUse], -- ^ How are the arguments used?
- hsRes :: HsValueMap HsValueUse -- ^ How is the result value used?
+ hsArgs :: [HsUseMap], -- ^ How are the arguments used?
+ hsRes :: HsUseMap -- ^ How is the result value used?
} deriving (Show, Eq)
-- | Translate a function application to a HsFunction. i.e., which function
mkHsFunction f ty =
HsFunction hsname hsargs hsres
where
- mkPort = mkHsValueMap (\x -> Single Port)
- mkState = mkHsValueMap (\x -> Single State)
hsname = getOccString f
(arg_tys, res_ty) = Type.splitFunTys ty
-- The last argument must be state
state_ty = last arg_tys
- state = mkState state_ty
+ state = useAsState state_ty
-- All but the last argument are inports
- inports = map mkPort (init arg_tys)
+ inports = map useAsPort (init arg_tys)
hsargs = inports ++ [state]
hsres = case splitTupleType res_ty of
-- Result type must be a two tuple (state, ports)
Just [outstate_ty, outport_ty] -> if Type.coreEqType state_ty outstate_ty
then
- Tuple [state, mkPort outport_ty]
+ Tuple [state, useAsPort outport_ty]
else
error $ "Input state type of function " ++ hsname ++ ": " ++ (showSDoc $ ppr state_ty) ++ " does not match output state type: " ++ (showSDoc $ ppr outstate_ty)
otherwise -> error $ "Return type of top-level function " ++ hsname ++ " must be a two-tuple containing a state and output ports."