X-Git-Url: https://git.stderr.nl/gitweb?a=blobdiff_plain;f=VHDL.hs;h=d177a10b934dc8004425a150552de5df83c12e4e;hb=e230d86ae7135a268a72cdffba947a9011001ec2;hp=b577110db761643e37d83fa0e7caad7a4a7f061b;hpb=707e72908a69288f3922c6e9110b802e4daaa03a;p=matthijs%2Fmaster-project%2Fc%CE%BBash.git diff --git a/VHDL.hs b/VHDL.hs index b577110..d177a10 100644 --- a/VHDL.hs +++ b/VHDL.hs @@ -15,6 +15,8 @@ import qualified Data.Traversable as Traversable import qualified Data.Monoid as Monoid import Data.Accessor import qualified Data.Accessor.MonadState as MonadState +import Text.Regex.Posix +import Debug.Trace -- ForSyDe import qualified ForSyDe.Backend.VHDL.AST as AST @@ -22,7 +24,10 @@ import qualified ForSyDe.Backend.VHDL.AST as AST -- GHC API import qualified Type import qualified Name +import qualified OccName +import qualified Var import qualified TyCon +import qualified CoreSyn import Outputable ( showSDoc, ppr ) -- Local imports @@ -32,38 +37,51 @@ import FlattenTypes import TranslatorTypes import HsValueMap import Pretty +import CoreTools +import Constants +import Generate +import GlobalNameTable createDesignFiles :: - FlatFuncMap + [(CoreSyn.CoreBndr, CoreSyn.CoreExpr)] -> [(AST.VHDLId, AST.DesignFile)] -createDesignFiles flatfuncmap = - (mkVHDLId "types", AST.DesignFile ieee_context [type_package]) : +createDesignFiles binds = + (mkVHDLBasicId "types", AST.DesignFile ieee_context [type_package]) : map (Arrow.second $ AST.DesignFile full_context) units where - init_session = VHDLSession Map.empty builtin_funcs + init_session = VHDLSession Map.empty Map.empty builtin_funcs globalNameTable (units, final_session) = - State.runState (createLibraryUnits flatfuncmap) init_session + State.runState (createLibraryUnits binds) init_session ty_decls = Map.elems (final_session ^. vsTypes) ieee_context = [ - AST.Library $ mkVHDLId "IEEE", - AST.Use $ (AST.NSimple $ mkVHDLId "IEEE.std_logic_1164") AST.:.: AST.All + AST.Library $ mkVHDLBasicId "IEEE", + mkUseAll ["IEEE", "std_logic_1164"], + mkUseAll ["IEEE", "numeric_std"] ] full_context = - (AST.Use $ (AST.NSimple $ mkVHDLId "work.types") AST.:.: AST.All) + mkUseAll ["work", "types"] : ieee_context - type_package = AST.LUPackageDec $ AST.PackageDec (mkVHDLId "types") (map (AST.PDITD . snd) ty_decls) + type_package = AST.LUPackageDec $ AST.PackageDec (mkVHDLBasicId "types") (map (AST.PDITD . snd) ty_decls) +-- 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) + createLibraryUnits :: - FlatFuncMap + [(CoreSyn.CoreBndr, CoreSyn.CoreExpr)] -> VHDLState [(AST.VHDLId, [AST.LibraryUnit])] -createLibraryUnits flatfuncmap = do - let hsfuncs = Map.keys flatfuncmap - let flatfuncs = Map.elems flatfuncmap - entities <- Monad.zipWithM createEntity hsfuncs flatfuncs - archs <- Monad.zipWithM createArchitecture hsfuncs flatfuncs +createLibraryUnits binds = do + entities <- Monad.mapM createEntity binds + archs <- Monad.mapM createArchitecture binds return $ zipWith (\ent arch -> let AST.EntityDec id _ = ent in @@ -73,68 +91,66 @@ createLibraryUnits flatfuncmap = do -- | Create an entity for a given function createEntity :: - HsFunction -- | The function signature - -> FlatFunction -- | The FlatFunction + (CoreSyn.CoreBndr, CoreSyn.CoreExpr) -- | The function -> VHDLState AST.EntityDec -- | The resulting entity -createEntity hsfunc flatfunc = do - let sigs = flat_sigs flatfunc - let args = flat_args flatfunc - let res = flat_res flatfunc - args' <- Traversable.traverse (Traversable.traverse (mkMap sigs)) args - res' <- Traversable.traverse (mkMap sigs) res - let ent_decl' = createEntityAST hsfunc args' res' +createEntity (fname, expr) = do + -- Strip off lambda's, these will be arguments + let (args, letexpr) = CoreSyn.collectBinders expr + args' <- Monad.mapM mkMap args + -- There must be a let at top level + let (CoreSyn.Let binds (CoreSyn.Var res)) = letexpr + res' <- mkMap res + let ent_decl' = createEntityAST fname args' res' let AST.EntityDec entity_id _ = ent_decl' let signature = Entity entity_id args' res' - modA vsSignatures (Map.insert hsfunc signature) + modA vsSignatures (Map.insert (bndrToString fname) signature) return ent_decl' where mkMap :: - [(SignalId, SignalInfo)] - -> SignalId + --[(SignalId, SignalInfo)] + CoreSyn.CoreBndr -> VHDLState VHDLSignalMapElement -- We only need the vsTypes element from the state - mkMap sigmap = MonadState.lift vsTypes . (\id -> + mkMap = (\bndr -> let - info = Maybe.fromMaybe - (error $ "Signal not found in the name map? This should not happen!") - (lookup id sigmap) - nm = Maybe.fromMaybe - (error $ "Signal not named? This should not happen!") - (sigName info) - ty = sigTy info + --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 = bndrToVHDLId bndr + ty = Var.varType bndr in - if isPortSigUse $ sigUse info + if True -- isPortSigUse $ sigUse info then do type_mark <- vhdl_ty ty - return $ Just (mkVHDLId nm, type_mark) + return $ Just (id, type_mark) else return $ Nothing ) -- | Create the VHDL AST for an entity createEntityAST :: - HsFunction -- | The signature of the function we're working with - -> [VHDLSignalMap] -- | The entity's arguments - -> VHDLSignalMap -- | The entity's result - -> AST.EntityDec -- | The entity with the ent_decl filled in as well + CoreSyn.CoreBndr -- | The name of the function + -> [VHDLSignalMapElement] -- | The entity's arguments + -> VHDLSignalMapElement -- | The entity's result + -> AST.EntityDec -- | The entity with the ent_decl filled in as well -createEntityAST hsfunc args res = +createEntityAST name args res = AST.EntityDec vhdl_id ports where - vhdl_id = mkEntityId hsfunc - ports = concatMap (mapToPorts AST.In) args - ++ mapToPorts AST.Out res - ++ clk_port - mapToPorts :: AST.Mode -> VHDLSignalMap -> [AST.IfaceSigDec] - mapToPorts mode m = - Maybe.catMaybes $ map (mkIfaceSigDec mode) (Foldable.toList m) + -- Create a basic Id, since VHDL doesn't grok filenames with extended Ids. + vhdl_id = mkVHDLBasicId $ bndrToString name + ports = Maybe.catMaybes $ + map (mkIfaceSigDec AST.In) args + ++ [mkIfaceSigDec AST.Out res] + ++ [clk_port] -- Add a clk port if we have state - clk_port = if hasState hsfunc + clk_port = if True -- hasState hsfunc then - [AST.IfaceSigDec (mkVHDLId "clk") AST.In VHDL.std_logic_ty] + Just $ AST.IfaceSigDec (mkVHDLExtId "clk") AST.In VHDL.std_logic_ty else - [] + Nothing -- | Create a port declaration mkIfaceSigDec :: @@ -148,35 +164,37 @@ mkIfaceSigDec _ Nothing = Nothing -- | Generate a VHDL entity name for the given hsfunc mkEntityId hsfunc = -- TODO: This doesn't work for functions with multiple signatures! - mkVHDLId $ hsFuncName hsfunc + -- Use a Basic Id, since using extended id's for entities throws off + -- precision and causes problems when generating filenames. + mkVHDLBasicId $ hsFuncName hsfunc -- | Create an architecture for a given function createArchitecture :: - HsFunction -- ^ The function signature - -> FlatFunction -- ^ The FlatFunction + (CoreSyn.CoreBndr, CoreSyn.CoreExpr) -- ^ The function -> VHDLState AST.ArchBody -- ^ The architecture for this function -createArchitecture hsfunc flatfunc = do - signaturemap <- getA vsSignatures - let signature = Maybe.fromMaybe - (error $ "Generating architecture for function " ++ (prettyShow hsfunc) ++ "without signature? This should not happen!") - (Map.lookup hsfunc signaturemap) - let entity_id = ent_id signature +createArchitecture (fname, expr) = do + --signaturemap <- getA vsSignatures + --let signature = Maybe.fromMaybe + -- (error $ "Generating architecture for function " ++ (prettyShow hsfunc) ++ "without signature? This should not happen!") + -- (Map.lookup hsfunc signaturemap) + let entity_id = mkVHDLBasicId $ bndrToString fname + -- 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) res) = letexpr + -- Create signal declarations for all internal and state signals - sig_dec_maybes <- mapM (mkSigDec' . snd) sigs + sig_dec_maybes <- mapM (mkSigDec' . fst) binds let sig_decs = Maybe.catMaybes $ sig_dec_maybes - -- Create concurrent statements for all signal definitions - let statements = zipWith (mkConcSm signaturemap sigs) defs [0..] - return $ AST.ArchBody (mkVHDLId "structural") (AST.NSimple entity_id) (map AST.BDISD sig_decs) (statements ++ procs') + + statements <- Monad.mapM mkConcSm binds + return $ AST.ArchBody (mkVHDLBasicId "structural") (AST.NSimple entity_id) (map AST.BDISD sig_decs) (statements ++ procs') where - sigs = flat_sigs flatfunc - args = flat_args flatfunc - res = flat_res flatfunc - defs = flat_defs flatfunc - procs = map mkStateProcSm (makeStatePairs flatfunc) + procs = map mkStateProcSm [] -- (makeStatePairs flatfunc) procs' = map AST.CSPSm procs -- mkSigDec only uses vsTypes from the state - mkSigDec' = MonadState.lift vsTypes . mkSigDec + mkSigDec' = mkSigDec -- | Looks up all pairs of old state, new state signals, together with -- the state id they represent. @@ -197,75 +215,83 @@ mkStateProcSm :: (StateId, SignalInfo, SignalInfo) -> AST.ProcSm mkStateProcSm (num, old, new) = AST.ProcSm label [clk] [statement] where - label = mkVHDLId $ "state_" ++ (show num) - clk = mkVHDLId "clk" - rising_edge = AST.NSimple $ mkVHDLId "rising_edge" + label = mkVHDLExtId $ "state_" ++ (show num) + clk = mkVHDLExtId "clk" + rising_edge = AST.NSimple $ mkVHDLBasicId "rising_edge" wform = AST.Wform [AST.WformElem (AST.PrimName $ AST.NSimple $ getSignalId new) Nothing] assign = AST.SigAssign (AST.NSimple $ getSignalId old) wform rising_edge_clk = AST.PrimFCall $ AST.FCall rising_edge [Nothing AST.:=>: (AST.ADName $ AST.NSimple clk)] statement = AST.IfSm rising_edge_clk [assign] [] Nothing -mkSigDec :: SignalInfo -> TypeState (Maybe AST.SigDec) -mkSigDec info = - let use = sigUse info in - if isInternalSigUse use || isStateSigUse use then do - type_mark <- vhdl_ty ty - return $ Just (AST.SigDec (getSignalId info) type_mark Nothing) +mkSigDec :: CoreSyn.CoreBndr -> VHDLState (Maybe AST.SigDec) +mkSigDec bndr = + if True then do --isInternalSigUse use || isStateSigUse use then do + type_mark <- vhdl_ty $ Var.varType bndr + return $ Just (AST.SigDec (bndrToVHDLId bndr) type_mark Nothing) else return Nothing - where - ty = sigTy info -- | Creates a VHDL Id from a named SignalInfo. Errors out if the SignalInfo -- is not named. getSignalId :: SignalInfo -> AST.VHDLId getSignalId info = - mkVHDLId $ Maybe.fromMaybe + mkVHDLExtId $ Maybe.fromMaybe (error $ "Unnamed signal? This should not happen!") (sigName info) --- | Transforms a signal definition into a VHDL concurrent statement +-- | Transforms a core binding into a VHDL concurrent statement mkConcSm :: - SignatureMap -- ^ The interfaces of functions in the session - -> [(SignalId, SignalInfo)] -- ^ The signals in the current architecture - -> SigDef -- ^ The signal definition - -> Int -- ^ A number that will be unique for all - -- concurrent statements in the architecture. - -> AST.ConcSm -- ^ The corresponding VHDL component instantiation. - -mkConcSm signatures sigs (FApp hsfunc args res) num = - let - signature = Maybe.fromMaybe - (error $ "Using function '" ++ (prettyShow hsfunc) ++ "' without signature? This should not happen!") - (Map.lookup hsfunc signatures) - entity_id = ent_id signature - label = (AST.fromVHDLId entity_id) ++ "_" ++ (show num) - -- Add a clk port if we have state - clk_port = Maybe.fromJust $ mkAssocElem (Just $ mkVHDLId "clk") "clk" - portmaps = mkAssocElems sigs args res signature ++ (if hasState hsfunc then [clk_port] else []) - in - AST.CSISm $ AST.CompInsSm (mkVHDLId label) (AST.IUEntity (AST.NSimple entity_id)) (AST.PMapAspect portmaps) + (CoreSyn.CoreBndr, CoreSyn.CoreExpr) -- ^ The binding to process + -> VHDLState AST.ConcSm -- ^ The corresponding VHDL component instantiation. -mkConcSm _ sigs (UncondDef src dst) _ = - let - src_expr = vhdl_expr src - src_wform = AST.Wform [AST.WformElem src_expr Nothing] - dst_name = AST.NSimple (getSignalId $ signalInfo sigs dst) - assign = dst_name AST.:<==: (AST.ConWforms [] src_wform Nothing) - in - AST.CSSASm assign +mkConcSm (bndr, app@(CoreSyn.App _ _))= do + signatures <- getA vsSignatures + let + (CoreSyn.Var f, args) = CoreSyn.collectArgs app + signature = Maybe.fromMaybe + (error $ "Using function '" ++ (bndrToString f) ++ "' without signature? This should not happen!") + (Map.lookup (bndrToString f) signatures) + entity_id = ent_id signature + label = bndrToString bndr + -- Add a clk port if we have state + --clk_port = Maybe.fromJust $ mkAssocElem (Just $ mkVHDLExtId "clk") "clk" + --portmaps = mkAssocElems sigs args res signature ++ (if hasState hsfunc then [clk_port] else []) + portmaps = mkAssocElems args bndr signature + in + return $ AST.CSISm $ AST.CompInsSm (mkVHDLExtId label) (AST.IUEntity (AST.NSimple entity_id)) (AST.PMapAspect portmaps) + +-- GHC generates some funny "r = r" bindings in let statements before +-- simplification. This outputs some dummy ConcSM for these, so things will at +-- least compile for now. +mkConcSm (bndr, CoreSyn.Var _) = return $ AST.CSPSm $ AST.ProcSm (mkVHDLBasicId "unused") [] [] + +{- +mkConcSm sigs (UncondDef src dst) _ = do + src_expr <- vhdl_expr src + let src_wform = AST.Wform [AST.WformElem src_expr Nothing] + let dst_name = AST.NSimple (getSignalId $ signalInfo sigs dst) + let assign = dst_name AST.:<==: (AST.ConWforms [] src_wform Nothing) + return $ AST.CSSASm assign where - vhdl_expr (Left id) = mkIdExpr sigs id + vhdl_expr (Left id) = return $ mkIdExpr sigs id vhdl_expr (Right expr) = case expr of (EqLit id lit) -> - (mkIdExpr sigs id) AST.:=: (AST.PrimLit lit) - (Literal lit) -> - AST.PrimLit lit + return $ (mkIdExpr sigs id) AST.:=: (AST.PrimLit lit) + (Literal lit Nothing) -> + return $ AST.PrimLit lit + (Literal lit (Just ty)) -> do + -- Create a cast expression, which is just a function call using the + -- type name as the function name. + let litexpr = AST.PrimLit lit + ty_id <- vhdl_ty ty + let ty_name = AST.NSimple ty_id + let args = [Nothing AST.:=>: (AST.ADExpr litexpr)] + return $ AST.PrimFCall $ AST.FCall ty_name args (Eq a b) -> - (mkIdExpr sigs a) AST.:=: (mkIdExpr sigs b) + return $ (mkIdExpr sigs a) AST.:=: (mkIdExpr sigs b) -mkConcSm _ sigs (CondDef cond true false dst) _ = +mkConcSm sigs (CondDef cond true false dst) _ = let cond_expr = mkIdExpr sigs cond true_expr = mkIdExpr sigs true @@ -276,8 +302,8 @@ mkConcSm _ sigs (CondDef cond true false dst) _ = dst_name = AST.NSimple (getSignalId $ signalInfo sigs dst) assign = dst_name AST.:<==: (AST.ConWforms [whenelse] false_wform Nothing) in - AST.CSSASm assign - + return $ AST.CSSASm assign +-} -- | Turn a SignalId into a VHDL Expr mkIdExpr :: [(SignalId, SignalInfo)] -> SignalId -> AST.Expr mkIdExpr sigs id = @@ -285,27 +311,29 @@ mkIdExpr sigs id = AST.PrimName src_name mkAssocElems :: - [(SignalId, SignalInfo)] -- | The signals in the current architecture - -> [SignalMap] -- | The signals that are applied to function - -> SignalMap -- | the signals in which to store the function result + [CoreSyn.CoreExpr] -- | The argument that are applied to function + -> CoreSyn.CoreBndr -- | The binder in which to store the result -> Entity -- | The entity to map against. -> [AST.AssocElem] -- | The resulting port maps -mkAssocElems sigmap args res entity = +mkAssocElems args res entity = -- Create the actual AssocElems Maybe.catMaybes $ zipWith mkAssocElem ports sigs where -- Turn the ports and signals from a map into a flat list. This works, -- since the maps must have an identical form by definition. TODO: Check -- the similar form? - arg_ports = concat (map Foldable.toList (ent_args entity)) - res_ports = Foldable.toList (ent_res entity) - arg_sigs = (concat (map Foldable.toList args)) - res_sigs = Foldable.toList res + arg_ports = ent_args entity + res_port = ent_res entity -- Extract the id part from the (id, type) tuple - ports = (map (fmap fst) (arg_ports ++ res_ports)) + ports = map (Monad.liftM fst) (res_port : arg_ports) -- Translate signal numbers into names - sigs = (map (lookupSigName sigmap) (arg_sigs ++ res_sigs)) + sigs = (bndrToString res : map (bndrToString.varBndr) args) + +-- Turns a Var CoreExpr into the Id inside it. Will of course only work for +-- simple Var CoreExprs, not complexer ones. +varBndr :: CoreSyn.CoreExpr -> Var.Id +varBndr (CoreSyn.Var id) = id -- | Look up a signal in the signal name map lookupSigName :: [(SignalId, SignalInfo)] -> SignalId -> String @@ -320,7 +348,7 @@ lookupSigName sigs sig = name -- | Create an VHDL port -> signal association mkAssocElem :: Maybe AST.VHDLId -> String -> Maybe AST.AssocElem -mkAssocElem (Just port) signal = Just $ Just port AST.:=>: (AST.ADName (AST.NSimple (mkVHDLId signal))) +mkAssocElem (Just port) signal = Just $ Just port AST.:=>: (AST.ADName (AST.NSimple (mkVHDLExtId signal))) mkAssocElem Nothing _ = Nothing -- | The VHDL Bit type @@ -336,9 +364,9 @@ std_logic_ty :: AST.TypeMark std_logic_ty = AST.unsafeVHDLBasicId "std_logic" -- Translate a Haskell type to a VHDL type -vhdl_ty :: Type.Type -> TypeState AST.TypeMark +vhdl_ty :: Type.Type -> VHDLState AST.TypeMark vhdl_ty ty = do - typemap <- State.get + typemap <- getA vsTypes let builtin_ty = do -- See if this is a tycon and lookup its name (tycon, args) <- Type.splitTyConApp_maybe ty let name = Name.getOccString (TyCon.tyConName tycon) @@ -355,31 +383,31 @@ vhdl_ty ty = do (tycon, args) <- Type.splitTyConApp_maybe ty let name = Name.getOccString (TyCon.tyConName tycon) case name of - "FSVec" -> Just $ mk_fsvec_ty ty args + "TFVec" -> Just $ mk_vector_ty (tfvec_len ty) ty + "SizedWord" -> Just $ mk_vector_ty (sized_word_len ty) ty otherwise -> Nothing -- Return new_ty when a new type was successfully created Maybe.fromMaybe (error $ "Unsupported Haskell type: " ++ (showSDoc $ ppr ty)) new_ty --- | Create a VHDL type belonging to a FSVec Haskell type -mk_fsvec_ty :: - Type.Type -- ^ The Haskell type to create a VHDL type for - -> [Type.Type] -- ^ Type arguments to the FSVec type constructor - -> TypeState AST.TypeMark -- The typemark created. - -mk_fsvec_ty ty args = do - -- Assume there are two type arguments - let [len, el_ty] = args - -- TODO: Find actual number - -- Construct the type id, but filter out dots (since these are not allowed). - let ty_id = mkVHDLId $ filter (/='.') ("vector_" ++ (show len)) +-- | Create a VHDL vector type +mk_vector_ty :: + Int -- ^ The length of the vector + -> Type.Type -- ^ The Haskell type to create a VHDL type for + -> VHDLState AST.TypeMark -- The typemark created. + +mk_vector_ty len ty = do + -- Assume there is a single type argument + let ty_id = mkVHDLExtId $ "vector_" ++ (show len) -- TODO: Use el_ty - let range = AST.IndexConstraint [AST.ToRange (AST.PrimLit "0") (AST.PrimLit "16")] + let range = AST.IndexConstraint [AST.ToRange (AST.PrimLit "0") (AST.PrimLit $ show (len - 1))] let ty_def = AST.TDA $ AST.ConsArrayDef range std_logic_ty let ty_dec = AST.TypeDec ty_id ty_def -- TODO: Check name uniqueness - State.modify (Map.insert (OrdType ty) (ty_id, ty_dec)) + --State.modify (Map.insert (OrdType ty) (ty_id, ty_dec)) + modA vsTypes (Map.insert (OrdType ty) (ty_id, ty_dec)) + modA vsTypeFuns (Map.insert (OrdType ty) (genUnconsVectorFuns std_logic_ty ty_id)) return ty_id @@ -389,13 +417,19 @@ builtin_types = ("Bool", bool_ty) -- TysWiredIn.boolTy ] --- Shortcut -mkVHDLId :: String -> AST.VHDLId -mkVHDLId s = - AST.unsafeVHDLBasicId $ (strip_multiscore . strip_invalid) s +-- Shortcut for +-- 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 = concat . map (\cs -> case cs of @@ -403,31 +437,55 @@ mkVHDLId s = _ -> 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) + +-- Creates a VHDL Id from a binder +bndrToVHDLId :: + CoreSyn.CoreBndr + -> AST.VHDLId + +bndrToVHDLId = mkVHDLExtId . OccName.occNameString . Name.nameOccName . Var.varName + +-- Extracts the binder name as a String +bndrToString :: + CoreSyn.CoreBndr + -> String + +bndrToString = OccName.occNameString . Name.nameOccName . Var.varName + -- | A consise representation of a (set of) ports on a builtin function -type PortMap = HsValueMap (String, AST.TypeMark) +--type PortMap = HsValueMap (String, AST.TypeMark) -- | A consise representation of a builtin function -data BuiltIn = BuiltIn String [PortMap] PortMap +data BuiltIn = BuiltIn String [(String, AST.TypeMark)] (String, AST.TypeMark) -- | Translate a list of concise representation of builtin functions to a -- SignatureMap mkBuiltins :: [BuiltIn] -> SignatureMap mkBuiltins = Map.fromList . map (\(BuiltIn name args res) -> - (HsFunction name (map useAsPort args) (useAsPort res), - Entity (VHDL.mkVHDLId name) (map toVHDLSignalMap args) (toVHDLSignalMap res)) + (name, + Entity (VHDL.mkVHDLBasicId name) (map toVHDLSignalMapElement args) (toVHDLSignalMapElement res)) ) builtin_hsfuncs = Map.keys builtin_funcs builtin_funcs = mkBuiltins [ - BuiltIn "hwxor" [(Single ("a", VHDL.bit_ty)), (Single ("b", VHDL.bit_ty))] (Single ("o", VHDL.bit_ty)), - BuiltIn "hwand" [(Single ("a", VHDL.bit_ty)), (Single ("b", VHDL.bit_ty))] (Single ("o", VHDL.bit_ty)), - BuiltIn "hwor" [(Single ("a", VHDL.bit_ty)), (Single ("b", VHDL.bit_ty))] (Single ("o", VHDL.bit_ty)), - BuiltIn "hwnot" [(Single ("a", VHDL.bit_ty))] (Single ("o", VHDL.bit_ty)) + BuiltIn "hwxor" [("a", VHDL.bit_ty), ("b", VHDL.bit_ty)] ("o", VHDL.bit_ty), + BuiltIn "hwand" [("a", VHDL.bit_ty), ("b", VHDL.bit_ty)] ("o", VHDL.bit_ty), + BuiltIn "hwor" [("a", VHDL.bit_ty), ("b", VHDL.bit_ty)] ("o", VHDL.bit_ty), + BuiltIn "hwnot" [("a", VHDL.bit_ty)] ("o", VHDL.bit_ty) ] -- | Map a port specification of a builtin function to a VHDL Signal to put in -- a VHDLSignalMap -toVHDLSignalMap :: HsValueMap (String, AST.TypeMark) -> VHDLSignalMap -toVHDLSignalMap = fmap (\(name, ty) -> Just (mkVHDLId name, ty)) - --- vim: set ts=8 sw=2 sts=2 expandtab: +toVHDLSignalMapElement :: (String, AST.TypeMark) -> VHDLSignalMapElement +toVHDLSignalMapElement (name, ty) = Just (mkVHDLBasicId name, ty)