-
--- Finds the field labels for VHDL type generated for the given Core type,
--- which must result in a record type.
-getFieldLabels :: Type.Type -> VHDLState [AST.VHDLId]
-getFieldLabels ty = do
- -- Ensure that the type is generated (but throw away it's VHDLId)
- vhdl_ty ty
- -- Get the types map, lookup and unpack the VHDL TypeDef
- types <- getA vsTypes
- case Map.lookup (OrdType ty) types of
- Just (_, Left (AST.TDR (AST.RecordTypeDef elems))) -> return $ map (\(AST.ElementDec id _) -> id) elems
- _ -> error $ "VHDL.getFieldLabels Type not found or not a record type? This should not happen! Type: " ++ (show ty)
-
-{-
-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) = return $ mkIdExpr sigs id
- vhdl_expr (Right expr) =
- case expr of
- (EqLit id 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) ->
- return $ (mkIdExpr sigs a) AST.:=: (mkIdExpr sigs b)
-
-mkConcSm sigs (CondDef cond true false dst) _ =
- let
- cond_expr = mkIdExpr sigs cond
- true_expr = mkIdExpr sigs true
- false_expr = mkIdExpr sigs false
- false_wform = AST.Wform [AST.WformElem false_expr Nothing]
- true_wform = AST.Wform [AST.WformElem true_expr Nothing]
- whenelse = AST.WhenElse true_wform cond_expr
- dst_name = AST.NSimple (getSignalId $ signalInfo sigs dst)
- assign = dst_name AST.:<==: (AST.ConWforms [whenelse] false_wform Nothing)
- in
- return $ AST.CSSASm assign
-
-| Turn a SignalId into a VHDL Expr
-mkIdExpr :: [(SignalId, SignalInfo)] -> SignalId -> AST.Expr
-mkIdExpr sigs id =
- let src_name = AST.NSimple (getSignalId $ signalInfo sigs id) in
- AST.PrimName src_name
-
--- | Look up a signal in the signal name map
-lookupSigName :: [(SignalId, SignalInfo)] -> SignalId -> String
-lookupSigName sigs sig = name
- where
- info = Maybe.fromMaybe
- (error $ "Unknown signal " ++ (show sig) ++ " used? This should not happen!")
- (lookup sig sigs)
- name = Maybe.fromMaybe
- (error $ "Unnamed signal " ++ (show sig) ++ " used? This should not happen!")
- (sigName info)
--}
-
--- Translate a Haskell type to a VHDL type
-vhdl_ty :: Type.Type -> VHDLState AST.TypeMark
-vhdl_ty ty = do
- 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)
- Map.lookup name builtin_types
- -- If not a builtin type, try the custom types
- let existing_ty = (fmap fst) $ Map.lookup (OrdType ty) typemap
- case Monoid.getFirst $ Monoid.mconcat (map Monoid.First [builtin_ty, existing_ty]) of
- -- Found a type, return it
- Just t -> return t
- -- No type yet, try to construct it
- Nothing -> do
- newty_maybe <- (construct_vhdl_ty ty)
- case newty_maybe of
- Just (ty_id, ty_def) -> do
- -- TODO: Check name uniqueness
- modA vsTypes (Map.insert (OrdType ty) (ty_id, ty_def))
- return ty_id
- Nothing -> error $ "Unsupported Haskell type: " ++ (showSDoc $ ppr ty)
-
--- Construct a new VHDL type for the given Haskell type.
-construct_vhdl_ty :: Type.Type -> VHDLState (Maybe (AST.TypeMark, Either AST.TypeDef AST.SubtypeIn))
-construct_vhdl_ty ty = do
- case Type.splitTyConApp_maybe ty of
- Just (tycon, args) -> do
- let name = Name.getOccString (TyCon.tyConName tycon)
- case name of
- "TFVec" -> do
- res <- mk_vector_ty (tfvec_len ty) (tfvec_elem ty)
- return $ Just $ (Arrow.second Right) 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)
- 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 element type of the Vector
- -> VHDLState (AST.TypeMark, AST.SubtypeIn) -- The typemark created.
-
-mk_vector_ty len el_ty = do
- elem_types_map <- getA vsElemTypes
- el_ty_tm <- vhdl_ty el_ty
- let ty_id = mkVHDLExtId $ "vector-"++ (AST.fromVHDLId el_ty_tm) ++ "-0_to_" ++ (show len)
- let range = AST.ConstraintIndex $ AST.IndexConstraint [AST.ToRange (AST.PrimLit "0") (AST.PrimLit $ show (len - 1))]
- let existing_elem_ty = (fmap fst) $ Map.lookup (OrdType el_ty) elem_types_map
- case existing_elem_ty of
- Just t -> do
- let ty_def = AST.SubtypeIn t (Just range)
- return (ty_id, ty_def)
- Nothing -> do
- let vec_id = mkVHDLExtId $ "vector_" ++ (AST.fromVHDLId el_ty_tm)
- let vec_def = AST.TDA $ AST.UnconsArrayDef [tfvec_indexTM] el_ty_tm
- modA vsElemTypes (Map.insert (OrdType el_ty) (vec_id, vec_def))
- modA vsTypeFuns (Map.insert (OrdType el_ty) (genUnconsVectorFuns el_ty_tm vec_id))
- let ty_def = AST.SubtypeIn vec_id (Just range)
- return (ty_id, ty_def)
-
-mk_natural_ty ::
- Int -- ^ The minimum bound (> 0)
- -> Int -- ^ The maximum bound (> minimum bound)
- -> VHDLState (AST.TypeMark, AST.SubtypeIn) -- The typemark created.
-mk_natural_ty min_bound max_bound = do
- let ty_id = mkVHDLExtId $ "nat_" ++ (show min_bound) ++ "_to_" ++ (show max_bound)
- let range = AST.ConstraintRange $ AST.SubTypeRange (AST.PrimLit $ (show min_bound)) (AST.PrimLit $ (show max_bound))
- let ty_def = AST.SubtypeIn naturalTM (Just range)
- return (ty_id, ty_def)
\ No newline at end of file