X-Git-Url: https://git.stderr.nl/gitweb?a=blobdiff_plain;f=Translator.hs;h=93eeacd30792761438d90d92e03b78c690bad0ef;hb=f87607e43aff4cdf81c5d57f57687ea5f81dd89a;hp=690b2649a10a1ae0d46d20b53f31ef433b410a87;hpb=39ddcee174445353b8fd83385cb078d0653507ba;p=matthijs%2Fmaster-project%2Fc%CE%BBash.git diff --git a/Translator.hs b/Translator.hs index 690b264..93eeacd 100644 --- a/Translator.hs +++ b/Translator.hs @@ -108,7 +108,7 @@ getPortMapEntry :: -- Accepts a port name and an argument to map to it. -- Returns the appropriate line for in the port map -getPortMapEntry (Signal portname _) (Signal signame _) = +getPortMapEntry (Single (portname, _)) (Single (signame, _)) = (Just portname) AST.:=>: (AST.ADName (AST.NSimple signame)) expandExpr :: [(CoreBndr, SignalNameMap)] @@ -142,10 +142,10 @@ expandExpr binds lam@(Lam b expr) = do res_signal') expandExpr binds (Var id) = - return ([], [], [], Signal signal_id ty) + return ([], [], [], Single (signal_id, ty)) where -- Lookup the id in our binds map - Signal signal_id ty = Maybe.fromMaybe + Single (signal_id, ty) = Maybe.fromMaybe (error $ "Argument " ++ getOccString id ++ "is unknown") (lookup id binds) @@ -254,7 +254,7 @@ expandApplicationExpr binds ty f args = do -- Generate a unique name for the application appname <- uniqueName ("app_" ++ name) -- Lookup the hwfunction to instantiate - HWFunction vhdl_id inports outport <- getHWFunc name + HWFunction vhdl_id inports outport <- getHWFunc (appToHsFunction f args ty) -- Expand each of the args, so each of them is reduced to output signals (arg_signal_decls, arg_statements, arg_res_signals) <- expandArgs binds args -- Bind each of the input ports to the expanded arguments @@ -284,7 +284,7 @@ createAssocElems :: -> SignalNameMap -- The signals to bind to it -> [AST.AssocElem] -- The resulting port map lines -createAssocElems (Signal port_id _) (Signal signal_id _) = +createAssocElems (Single (port_id, _)) (Single (signal_id, _)) = [(Just port_id) AST.:=>: (AST.ADName (AST.NSimple signal_id))] createAssocElems (Tuple ports) (Tuple signals) = @@ -307,7 +307,7 @@ mkSignalsFromMap :: SignalNameMap -> [AST.SigDec] -mkSignalsFromMap (Signal id ty) = +mkSignalsFromMap (Single (id, ty)) = [mkSignalFromId id ty] mkSignalsFromMap (Tuple signals) = @@ -350,7 +350,7 @@ mapOutputPorts :: -- Map the output port of a component to the output port of the containing -- entity. -mapOutputPorts (Signal portname _) (Signal signalname _) = +mapOutputPorts (Single (portname, _)) (Single (signalname, _)) = [(Just portname) AST.:=>: (AST.ADName (AST.NSimple signalname))] -- Map matching output ports in the tuple @@ -365,7 +365,7 @@ getArchitecture (Rec _) = error "Recursive binders not supported" getArchitecture (NonRec var expr) = do let name = (getOccString var) - HWFunction vhdl_id inports outport <- getHWFunc name + HWFunction vhdl_id inports outport <- getHWFunc (HsFunction name [] (Tuple [])) sess <- State.get (signal_decls, statements, arg_signals, res_signal) <- expandExpr [] expr let inport_assigns = concat $ zipWith createSignalAssignments arg_signals inports @@ -390,7 +390,7 @@ mkIfaceSigDecs :: -> SignalNameMap -- The ports to generate a map for -> [AST.IfaceSigDec] -- The resulting ports -mkIfaceSigDecs mode (Signal port_id ty) = +mkIfaceSigDecs mode (Single (port_id, ty)) = [AST.IfaceSigDec port_id mode ty] mkIfaceSigDecs mode (Tuple ports) = @@ -405,7 +405,7 @@ createSignalAssignments :: -- A simple assignment of one signal to another (greatly complicated because -- signal assignments can be conditional with multiple conditions in VHDL). -createSignalAssignments (Signal dst _) (Signal src _) = +createSignalAssignments (Single (dst, _)) (Single (src, _)) = [AST.CSSASm assign] where src_name = AST.NSimple src @@ -420,10 +420,38 @@ createSignalAssignments (Tuple dsts) (Tuple srcs) = createSignalAssignments dst src = error $ "Non matching source and destination: " ++ show dst ++ "\nand\n" ++ show src -data SignalNameMap = - Tuple [SignalNameMap] - | Signal AST.VHDLId AST.TypeMark -- A signal (or port) of the given (VDHL) type - deriving (Show) +type SignalNameMap = HsValueMap (AST.VHDLId, AST.TypeMark) + +-- | A datatype that maps each of the single values in a haskell structure to +-- a mapto. The map has the same structure as the haskell type mapped, ie +-- nested tuples etc. +data HsValueMap mapto = + Tuple [HsValueMap mapto] + | Single mapto + deriving (Show, Eq) + +-- | Creates a HsValueMap with the same structure as the given type, using the +-- given function for mapping the single types. +mkHsValueMap :: + (Type -> HsValueMap mapto) -- ^ A function to map single value Types + -- (basically anything but tuples) to a + -- HsValueMap (not limited to the Single + -- constructor) + -> Type -- ^ The type to map to a HsValueMap + -> HsValueMap mapto -- ^ The resulting map + +mkHsValueMap f ty = + case Type.splitTyConApp_maybe ty of + Just (tycon, args) -> + if (TyCon.isTupleTyCon tycon) + then + -- Handle tuple construction especially + Tuple (map (mkHsValueMap f) args) + else + -- And let f handle the rest + f ty + -- And let f handle the rest + Nothing -> f ty -- Generate a port name map (or multiple for tuple types) in the given direction for -- each type given. @@ -438,7 +466,7 @@ getPortNameMapForTy name ty = -- Expand tuples we find Tuple (getPortNameMapForTys name 0 args) else -- Assume it's a type constructor application, ie simple data type - Signal (AST.unsafeVHDLBasicId name) (vhdl_ty ty) + Single ((AST.unsafeVHDLBasicId name), (vhdl_ty ty)) where (tycon, args) = Type.splitTyConApp ty @@ -453,10 +481,10 @@ data HWFunction = HWFunction { -- A function that is available in hardware -- output ports. mkHWFunction :: CoreBind -- The core binder to generate the interface for - -> VHDLState (String, HWFunction) -- The name of the function and its interface + -> VHDLState (HsFunction, HWFunction) -- The name of the function and its interface mkHWFunction (NonRec var expr) = - return (name, HWFunction (mkVHDLId name) inports outport) + return (hsfunc, HWFunction (mkVHDLId name) inports outport) where name = getOccString var ty = CoreUtils.exprType expr @@ -468,31 +496,62 @@ mkHWFunction (NonRec var expr) = [port] -> [getPortNameMapForTy "portin" port] ps -> getPortNameMapForTys "portin" 0 ps outport = getPortNameMapForTy "portout" res + hsfunc = HsFunction name [] (Tuple []) mkHWFunction (Rec _) = error "Recursive binders not supported" +-- | How is a given (single) value in a function's type (ie, argument or +-- return value) used? +data HsValueUse = + Port -- ^ Use it as a port (input or output) + deriving (Show, Eq) + +-- | 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? +} deriving (Show, Eq) + +-- | Translate a function application to a HsFunction. i.e., which function +-- do you need to translate this function application. +appToHsFunction :: + Var.Var -- ^ The function to call + -> [CoreExpr] -- ^ The function arguments + -> Type -- ^ The return type + -> HsFunction -- ^ The needed HsFunction + +appToHsFunction f args ty = + HsFunction hsname hsargs hsres + where + mkPort = \x -> Single Port + hsargs = map (mkHsValueMap mkPort . CoreUtils.exprType) args + hsres = mkHsValueMap mkPort ty + hsname = getOccString f + data VHDLSession = VHDLSession { - nameCount :: Int, -- A counter that can be used to generate unique names - funcs :: [(String, HWFunction)] -- All functions available, indexed by name + nameCount :: Int, -- A counter that can be used to generate unique names + funcs :: [(HsFunction, HWFunction)] -- All functions available } deriving (Show) type VHDLState = State.State VHDLSession -- Add the function to the session -addFunc :: String -> HWFunction -> VHDLState () -addFunc name f = do +addFunc :: HsFunction -> HWFunction -> VHDLState () +addFunc hsfunc hwfunc = do fs <- State.gets funcs -- Get the funcs element from the session - State.modify (\x -> x {funcs = (name, f) : fs }) -- Prepend name and f + State.modify (\x -> x {funcs = (hsfunc, hwfunc) : fs }) -- Prepend name and f -- Lookup the function with the given name in the current session. Errors if -- it was not found. -getHWFunc :: String -> VHDLState HWFunction -getHWFunc name = do +getHWFunc :: HsFunction -> VHDLState HWFunction +getHWFunc hsfunc = do fs <- State.gets funcs -- Get the funcs element from the session return $ Maybe.fromMaybe - (error $ "Function " ++ name ++ "is unknown? This should not happen!") - (lookup name fs) + (error $ "Function " ++ (hsName hsfunc) ++ "is unknown? This should not happen!") + (lookup hsfunc fs) -- Makes the given name unique by appending a unique number. -- This does not do any checking against existing names, so it only guarantees @@ -509,10 +568,10 @@ mkVHDLId = AST.unsafeVHDLBasicId builtin_funcs = [ - ("hwxor", HWFunction (mkVHDLId "hwxor") [Signal (mkVHDLId "a") vhdl_bit_ty, Signal (mkVHDLId "b") vhdl_bit_ty] (Signal (mkVHDLId "o") vhdl_bit_ty)), - ("hwand", HWFunction (mkVHDLId "hwand") [Signal (mkVHDLId "a") vhdl_bit_ty, Signal (mkVHDLId "b") vhdl_bit_ty] (Signal (mkVHDLId "o") vhdl_bit_ty)), - ("hwor", HWFunction (mkVHDLId "hwor") [Signal (mkVHDLId "a") vhdl_bit_ty, Signal (mkVHDLId "b") vhdl_bit_ty] (Signal (mkVHDLId "o") vhdl_bit_ty)), - ("hwnot", HWFunction (mkVHDLId "hwnot") [Signal (mkVHDLId "i") vhdl_bit_ty] (Signal (mkVHDLId "o") vhdl_bit_ty)) + (HsFunction "hwxor" [(Single Port), (Single Port)] (Single Port), HWFunction (mkVHDLId "hwxor") [Single (mkVHDLId "a", vhdl_bit_ty), Single (mkVHDLId "b", vhdl_bit_ty)] (Single (mkVHDLId "o", vhdl_bit_ty))), + (HsFunction "hwand" [(Single Port), (Single Port)] (Single Port), HWFunction (mkVHDLId "hwand") [Single (mkVHDLId "a", vhdl_bit_ty), Single (mkVHDLId "b", vhdl_bit_ty)] (Single (mkVHDLId "o", vhdl_bit_ty))), + (HsFunction "hwor" [(Single Port), (Single Port)] (Single Port), HWFunction (mkVHDLId "hwor") [Single (mkVHDLId "a", vhdl_bit_ty), Single (mkVHDLId "b", vhdl_bit_ty)] (Single (mkVHDLId "o", vhdl_bit_ty))), + (HsFunction "hwnot" [(Single Port)] (Single Port), HWFunction (mkVHDLId "hwnot") [Single (mkVHDLId "i", vhdl_bit_ty)] (Single (mkVHDLId "o", vhdl_bit_ty))) ] vhdl_bit_ty :: AST.TypeMark