2021-05-29 02:27:14 +02:00
|
|
|
{-# LANGUAGE PatternSynonyms #-}
|
2020-08-13 03:47:24 +02:00
|
|
|
{- sv2v
|
|
|
|
|
- Author: Zachary Snow <zach@zachjs.com>
|
|
|
|
|
-
|
|
|
|
|
- Conversion for variable-length string parameters
|
2021-05-29 02:27:14 +02:00
|
|
|
-
|
|
|
|
|
- While implicitly variable-length string parameters are supported in
|
|
|
|
|
- Verilog-2005, some usages depend on their type information (e.g., size). In
|
|
|
|
|
- such instances, an additional parameter is added encoding the width of the
|
|
|
|
|
- parameter.
|
2020-08-13 03:47:24 +02:00
|
|
|
-}
|
|
|
|
|
|
|
|
|
|
module Convert.StringParam (convert) where
|
|
|
|
|
|
|
|
|
|
import Control.Monad.Writer.Strict
|
2021-05-29 02:27:14 +02:00
|
|
|
import Data.Maybe (mapMaybe)
|
|
|
|
|
import qualified Data.Set as Set
|
2020-08-13 03:47:24 +02:00
|
|
|
import qualified Data.Map.Strict as Map
|
|
|
|
|
|
|
|
|
|
import Convert.Traverse
|
|
|
|
|
import Language.SystemVerilog.AST
|
|
|
|
|
|
2021-05-29 02:27:14 +02:00
|
|
|
type PartStringParams = Map.Map Identifier [Identifier]
|
|
|
|
|
type Idents = Set.Set Identifier
|
2020-08-13 03:47:24 +02:00
|
|
|
|
|
|
|
|
convert :: [AST] -> [AST]
|
|
|
|
|
convert files =
|
|
|
|
|
if Map.null partStringParams
|
|
|
|
|
then files
|
|
|
|
|
else map traverseModuleItem files'
|
|
|
|
|
where
|
|
|
|
|
(files', partStringParams) = runWriter $
|
|
|
|
|
mapM (traverseDescriptionsM traverseDescriptionM) files
|
|
|
|
|
traverseModuleItem = traverseDescriptions $ traverseModuleItems $
|
|
|
|
|
mapInstance partStringParams
|
|
|
|
|
|
|
|
|
|
-- adds automatic width parameters for string parameters
|
|
|
|
|
traverseDescriptionM :: Description -> Writer PartStringParams Description
|
|
|
|
|
traverseDescriptionM (Part attrs extern kw lifetime name ports items) =
|
2021-05-29 02:27:14 +02:00
|
|
|
if null candidateStringParams || Set.null stringParamNames
|
2020-08-13 03:47:24 +02:00
|
|
|
then return $ Part attrs extern kw lifetime name ports items
|
|
|
|
|
else do
|
2021-05-29 02:27:14 +02:00
|
|
|
tell $ Map.singleton name $ Set.toList stringParamNames
|
2020-08-13 03:47:24 +02:00
|
|
|
return $ Part attrs extern kw lifetime name ports items'
|
|
|
|
|
where
|
2021-05-29 02:27:14 +02:00
|
|
|
items' = map (elaborateStringParam stringParamNames) items
|
|
|
|
|
candidateStringParams = mapMaybe candidateStringParam items
|
|
|
|
|
stringParamNames = execWriter $
|
|
|
|
|
mapM (collectNestedModuleItemsM collectModuleItemM) items
|
|
|
|
|
collectModuleItemM = collectTypesM $ collectNestedTypesM $
|
|
|
|
|
collectQueriedIdentsM $ Set.fromList candidateStringParams
|
2020-08-13 03:47:24 +02:00
|
|
|
traverseDescriptionM other = return other
|
|
|
|
|
|
2021-05-29 02:27:14 +02:00
|
|
|
-- utility pattern for candidate string parameter items
|
|
|
|
|
pattern StringParam :: Identifier -> String -> ModuleItem
|
|
|
|
|
pattern StringParam x s =
|
|
|
|
|
MIPackageItem (Decl (Param Parameter UnknownType x (String s)))
|
|
|
|
|
|
|
|
|
|
-- write down which parameters may be variable-length strings
|
|
|
|
|
candidateStringParam :: ModuleItem -> Maybe Identifier
|
|
|
|
|
candidateStringParam (MIAttr _ item) = candidateStringParam item
|
|
|
|
|
candidateStringParam (StringParam x _) = Just x
|
|
|
|
|
candidateStringParam _ = Nothing
|
|
|
|
|
|
|
|
|
|
-- write down which of the given identifiers are subject to type queries
|
|
|
|
|
collectQueriedIdentsM :: Idents -> Type -> Writer Idents ()
|
|
|
|
|
collectQueriedIdentsM idents (TypeOf (Ident x)) =
|
|
|
|
|
when (Set.member x idents) $ tell $ Set.singleton x
|
|
|
|
|
collectQueriedIdentsM _ _ = return ()
|
2020-08-13 03:47:24 +02:00
|
|
|
|
|
|
|
|
-- rewrite an existing string parameter
|
2021-05-29 02:27:14 +02:00
|
|
|
elaborateStringParam :: Idents -> ModuleItem -> ModuleItem
|
|
|
|
|
elaborateStringParam idents (MIAttr attr item) =
|
|
|
|
|
MIAttr attr $ elaborateStringParam idents item
|
|
|
|
|
elaborateStringParam idents (orig @ (StringParam x str)) =
|
|
|
|
|
if Set.member x idents
|
|
|
|
|
then Generate $ map wrap [width, param]
|
|
|
|
|
else orig
|
2020-08-13 03:47:24 +02:00
|
|
|
where
|
2021-05-29 02:27:14 +02:00
|
|
|
wrap = GenModuleItem . MIPackageItem . Decl
|
2020-08-13 03:47:24 +02:00
|
|
|
w = widthName x
|
|
|
|
|
r = (BinOp Sub (Ident w) (RawNum 1), RawNum 0)
|
|
|
|
|
t' = IntegerVector TBit Unspecified [r]
|
2021-05-29 02:27:14 +02:00
|
|
|
defaultWidth = DimsFn FnBits $ Right $ String str
|
|
|
|
|
width = Param Parameter UnknownType w defaultWidth
|
|
|
|
|
param = Param Parameter t' x (String str)
|
|
|
|
|
elaborateStringParam _ other = other
|
2020-08-13 03:47:24 +02:00
|
|
|
|
|
|
|
|
widthName :: Identifier -> Identifier
|
|
|
|
|
widthName paramName = "_sv2v_width_" ++ paramName
|
|
|
|
|
|
2021-05-29 02:27:14 +02:00
|
|
|
-- convert instances which use the converted string parameters
|
2020-08-13 03:47:24 +02:00
|
|
|
mapInstance :: PartStringParams -> ModuleItem -> ModuleItem
|
|
|
|
|
mapInstance partStringParams (Instance m params x rs ports) =
|
|
|
|
|
case Map.lookup m partStringParams of
|
|
|
|
|
Nothing -> Instance m params x rs ports
|
|
|
|
|
Just stringParams -> Instance m params' x rs ports
|
2021-05-29 02:27:14 +02:00
|
|
|
where params' = concatMap (expand stringParams) params
|
2020-08-13 03:47:24 +02:00
|
|
|
where
|
2021-05-29 02:27:14 +02:00
|
|
|
expand :: [Identifier] -> ParamBinding -> [ParamBinding]
|
|
|
|
|
expand _ (paramName, Left t) = [(paramName, Left t)]
|
|
|
|
|
expand stringParams (orig @ (paramName, Right expr)) =
|
|
|
|
|
if elem paramName stringParams
|
2020-08-13 03:47:24 +02:00
|
|
|
then [(widthName paramName, Right width), orig]
|
|
|
|
|
else [orig]
|
|
|
|
|
where width = DimsFn FnBits $ Right expr
|
|
|
|
|
mapInstance _ other = other
|