+ Just (tycon, args) -> do
+ let name = Name.getOccString (TyCon.tyConName tycon)
+ case name of
+ "TFVec" -> do
+ res <- mk_vector_ty (tfvec_len ty) ty
+ return $ Just $ (Arrow.second Left) res
+ "SizedWord" -> do
+ res <- mk_vector_ty (sized_word_len ty) ty
+ return $ Just $ (Arrow.second Left) res
+ "RangedWord" -> do
+ res <- mk_natural_ty 0 (ranged_word_bound ty) ty
+ return $ Just $ (Arrow.second Right) res
+ -- Create a custom type from this tycon
+ otherwise -> mk_tycon_ty tycon args
+ Nothing -> return $ Nothing
+
+-- | Create VHDL type for a custom tycon
+mk_tycon_ty :: TyCon.TyCon -> [Type.Type] -> VHDLState (Maybe (AST.TypeMark, Either AST.TypeDef AST.SubtypeIn))
+mk_tycon_ty tycon args =
+ case TyCon.tyConDataCons tycon of
+ -- Not an algebraic type
+ [] -> error $ "Only custom algebraic types are supported: " ++ (showSDoc $ ppr tycon)
+ [dc] -> do
+ let arg_tys = DataCon.dataConRepArgTys dc
+ -- TODO: CoreSubst docs say each Subs can be applied only once. Is this a
+ -- violation? Or does it only mean not to apply it again to the same
+ -- subject?
+ let real_arg_tys = map (CoreSubst.substTy subst) arg_tys
+ elem_tys <- mapM vhdl_ty real_arg_tys
+ let elems = zipWith AST.ElementDec recordlabels elem_tys
+ -- For a single construct datatype, build a record with one field for
+ -- each argument.
+ -- TODO: Add argument type ids to this, to ensure uniqueness
+ -- TODO: Special handling for tuples?
+ let ty_id = mkVHDLExtId $ nameToString (TyCon.tyConName tycon)
+ let ty_def = AST.TDR $ AST.RecordTypeDef elems
+ return $ Just (ty_id, Left ty_def)
+ dcs -> error $ "Only single constructor datatypes supported: " ++ (showSDoc $ ppr tycon)
+ where
+ -- Create a subst that instantiates all types passed to the tycon
+ -- TODO: I'm not 100% sure that this is the right way to do this. It seems
+ -- to work so far, though..
+ tyvars = TyCon.tyConTyVars tycon
+ subst = CoreSubst.extendTvSubstList CoreSubst.emptySubst (zip tyvars args)
+
+-- | 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, AST.TypeDef) -- 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 $ show (len - 1))]
+ let ty_def = AST.TDA $ AST.ConsArrayDef range std_logic_ty
+ modA vsTypeFuns (Map.insert (OrdType ty) (genUnconsVectorFuns std_logic_ty ty_id))
+ return (ty_id, ty_def)
+
+mk_natural_ty ::
+ Int -- ^ The minimum bound (> 0)
+ -> Int -- ^ The maximum bound (> minimum bound)
+ -> Type.Type -- ^ The Haskell type to create a VHDL type for
+ -> VHDLState (AST.TypeMark, AST.SubtypeIn) -- The typemark created.
+mk_natural_ty min_bound max_bound ty = do
+ let ty_id = mkVHDLExtId $ "nat_" ++ (show min_bound) ++ "_to_" ++ (show max_bound)
+ let ty_def = AST.SubtypeIn naturalTM (Nothing)
+ return (ty_id, ty_def)
+
+
+builtin_types =
+ Map.fromList [
+ ("Bit", std_logic_ty),
+ ("Bool", bool_ty) -- TysWiredIn.boolTy
+ ]
+
+-- 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
+ ('_':_) -> "_"
+ _ -> 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
+
+-- Extracts the string version of the name
+nameToString :: Name.Name -> String
+nameToString = OccName.occNameString . Name.nameOccName
+
+-- | A consise representation of a (set of) ports on a builtin function
+--type PortMap = HsValueMap (String, AST.TypeMark)
+-- | A consise representation of a builtin function
+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) ->
+ (name,
+ Entity (VHDL.mkVHDLBasicId name) (map toVHDLSignalMapElement args) (toVHDLSignalMapElement res))
+ )
+
+builtin_hsfuncs = Map.keys builtin_funcs
+builtin_funcs = mkBuiltins
+ [
+ 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)
+ ]
+
+recordlabels = map (\c -> mkVHDLBasicId [c]) ['A'..'Z']
+
+-- | Map a port specification of a builtin function to a VHDL Signal to put in
+-- a VHDLSignalMap
+toVHDLSignalMapElement :: (String, AST.TypeMark) -> VHDLSignalMapElement
+toVHDLSignalMapElement (name, ty) = Just (mkVHDLBasicId name, ty)