Commit 67466eaa by Zachary Snow

major interface conversion update

- module instances with modport bindings are now inlined
- support for modports in generate loops
- support for generic interfaces
- implied modport instance propagation
- add error message for interface instances missing port list
parent 5161a9e7
...@@ -6,397 +6,333 @@ ...@@ -6,397 +6,333 @@
module Convert.Interface (convert) where module Convert.Interface (convert) where
import Data.List (isPrefixOf)
import Data.Maybe (mapMaybe) import Data.Maybe (mapMaybe)
import Control.Monad.Writer import Control.Monad.Writer
import Control.Monad.State
import qualified Data.Map.Strict as Map import qualified Data.Map.Strict as Map
import qualified Data.Set as Set
import Convert.Scoper
import Convert.Traverse import Convert.Traverse
import Language.SystemVerilog.AST import Language.SystemVerilog.AST
type Idents = Set.Set Identifier data PartInfo = PartInfo
type Interface = ([Identifier], [ModuleItem]) { pKind :: PartKW
type Interfaces = Map.Map Identifier Interface , pPorts :: [Identifier]
type Module = ([Identifier], [(Identifier, Type)]) , pItems :: [ModuleItem]
type Modules = Map.Map Identifier Module } deriving Eq
type Instances = Map.Map Identifier Identifier type PartInfos = Map.Map Identifier PartInfo
type Modports = Map.Map Identifier (Identifier, Identifier)
type ModportInstances = [(Identifier, (Identifier, Identifier))]
type ModportBinding = (Identifier, (Expr, Expr))
convert :: [AST] -> [AST] convert :: [AST] -> [AST]
convert = convert =
map (filter $ not . isInterface) . traverseFiles (collectDescriptionsM collectPart)
repeatedConverter (map . convertDescription)
where where
repeatedConverter :: [AST] -> [AST] -- we can only collect/map non-extern interfaces and modules
repeatedConverter files = collectPart :: Description -> Writer PartInfos ()
if files == files' collectPart (Part _ False kw _ name ports items) =
then files tell $ Map.singleton name $ PartInfo kw ports items
else repeatedConverter files' collectPart _ = return ()
where
files' = convertDescription :: PartInfos -> Description -> Description
traverseFiles (collectDescriptionsM collectDesc) convertDescription _ (Part _ _ Interface _ name _ _) =
(map . uncurry convertDescription) PackageItem $ Decl $ CommentDecl $ "removed interface: " ++ name
files convertDescription parts (Part attrs extern Module lifetime name ports items) =
-- we can only collect/map non-extern interfaces if null $ extractModportInstances $ PartInfo Module ports items then
collectDesc :: Description -> Writer (Interfaces, Modules) () Part attrs extern Module lifetime name ports items'
collectDesc (orig @ (Part _ False kw _ name ports items)) = do else
if kw == Interface PackageItem $ Decl $ CommentDecl $
then when (all fullyResolved items) $ "removed interface-using module: " ++ name
tell (Map.singleton name (ports, items), Map.empty)
else tell (Map.empty, Map.singleton name (params, decls))
where
params = map fst $ parameters items
decls = execWriter $
collectModuleItemsM (collectDeclsM collectDecl) orig
collectDecl :: Decl -> Writer [(Identifier, Type)] ()
collectDecl (Variable _ t ident _ _) =
tell [(ident, t)]
collectDecl _ = return ()
collectDesc _ = return ()
isInterface :: Description -> Bool
isInterface (Part _ False Interface _ _ _ items) =
all fullyResolved items
isInterface _ = False
-- returns whether a ModuleItem still contains TypeOf
fullyResolved :: ModuleItem -> Bool
fullyResolved =
not . any isTypeOf . execWriter .
collectNestedModuleItemsM collectModport
where
collectModport :: ModuleItem -> Writer [Type] ()
collectModport (Modport _ modportDecls) =
mapM collectModportDecl modportDecls >> return ()
collectModport _ = return ()
collectModportDecl :: ModportDecl -> Writer [Type] ()
collectModportDecl (_, _, t, _) = collectType t
collectType :: Type -> Writer [Type] ()
collectType t = tell [t]
isTypeOf TypeOf{} = True
isTypeOf _ = False
convertDescription :: Interfaces -> Modules -> Description -> Description
convertDescription interfaces modules (Part attrs extern Module lifetime name ports items) =
Part attrs extern Module lifetime name ports' items'
where where
items' = map (flattenInstances instances modports) $ items' = evalScoper return traverseModuleItemM return return name items
map (traverseNestedModuleItems expandInterface) items
ports' = concatMap convertPort ports convertNested =
scopeModuleItemT return traverseModuleItemM return return
-- collect the interface type of all interface instances in this module
(instances, modports) = execWriter $ mapM traverseModuleItemM :: ModuleItem -> Scoper [ModportDecl] ModuleItem
(collectNestedModuleItemsM collectInstanceM) items traverseModuleItemM (Modport modportName modportDecls) =
collectInstanceM :: ModuleItem -> Writer (Instances, Modports) () insertElem modportName modportDecls >> return (Generate [])
collectInstanceM (MIPackageItem (Decl (Variable _ t ident _ _))) = traverseModuleItemM (instanceItem @ (Instance _ _ _ [] _)) =
case t of if maybePartInfo == Nothing then
InterfaceT interfaceName (Just modportName) [] -> return instanceItem
when (Map.member interfaceName interfaces) $ else if partKind == Interface then
writeModport interfaceName modportName -- inline instantiation of an interface
Alias interfaceName [] -> convertNested $ Generate $ map GenModuleItem $
when (Map.member interfaceName interfaces) $ inlineInstance [] []
writeModport interfaceName "" partItems instanceName paramBindings portBindings
_ -> return () else if not $ null (extractModportInstances partInfo) then do
modports <- embedScopes (\l () -> l) ()
-- inline instantiation of a module
convertNested $ Generate $ map GenModuleItem $
inlineInstance
(modportBindings modports)
(modportSubstitutions modports)
partItems instanceName paramBindings portBindings
else
return instanceItem
where where
writeModport :: Identifier -> Identifier -> Instance part rawParamBindings instanceName [] rawPortBindings =
Writer (Instances, Modports) () instanceItem
writeModport interfaceName modportName = maybePartInfo = Map.lookup part parts
tell (Map.empty, Map.singleton ident modport) Just partInfo = maybePartInfo
where modport = (interfaceName, modportName) PartInfo partKind partPorts partItems = partInfo
collectInstanceM (Instance part _ ident [] _) =
when (Map.member part interfaces) $ partParams = parameterNames partItems
tell (Map.singleton ident part, Map.empty) paramBindings = resolveBindings partParams rawParamBindings
collectInstanceM _ = return () portBindings = resolveBindings partPorts rawPortBindings
expandInterface :: ModuleItem -> ModuleItem modportInstances = extractModportInstances partInfo
expandInterface (orig @ (MIPackageItem (Decl (Variable _ _ ident _ _)))) = modportBindings modports = mapMaybe
-- expand instantiation of a modport (inferModportBinding modports modportInstances) portBindings
if Map.member ident modports modportSubstitutions modports = concatMap
then Generate $ map GenModuleItem $ (expandModportBinding modports) (modportBindings modports)
filter shouldKeep interfaceItems ++ map makePortDecl
modportDecls traverseModuleItemM other = return other
else orig
-- determines the underlying modport and interface instances associated
-- with the given port binding, if it is a modport binding
inferModportBinding :: Scopes [ModportDecl] -> ModportInstances ->
PortBinding -> Maybe ModportBinding
inferModportBinding _ _ ("", _) =
error "internal inferModportBinding invariant violated"
inferModportBinding modports modportInstances (portName, expr) =
if bindingIsModport then
-- provided specific instance modport
foundModport expr
else if bindingIsBundle && portIsBundle then
-- bundle bound to a generic bundle
foundModport expr
else if bindingIsBundle && not portIsBundle then
-- given entire interface, but just bound to a modport
foundModport $ Dot expr modportName
else
Nothing
where where
Just (interfaceName, modportName) = Map.lookup ident modports bindingIsModport = lookupElem modports expr /= Nothing
interfaceItems = prefixInterface ident $ bindingIsBundle = lookupElem modports (Dot expr "") /= Nothing
snd $ lookupInterface interfaceName portIsBundle = null modportName
modportDecls = lookupModport interfaceItems modportName modportName = case lookup portName modportInstances of
shouldKeep (MIPackageItem (Decl Param{})) = True Just (_, x) -> x
shouldKeep (MIPackageItem Task{}) = True Nothing -> error $ "can't deduce modport for interface "
shouldKeep (MIPackageItem Function{}) = True ++ " bound to port " ++ portName
shouldKeep _ = False
makePortDecl :: ModportDecl -> ModuleItem foundModport modportE =
makePortDecl (dir, port, typ, _) = Just (portName, (instanceE, modportE))
MIPackageItem $ Decl $ Variable dir typ port' [] Nil where instanceE = findInstance modportE
where port' = if null modportName findInstance :: Expr -> Expr
then port findInstance e =
else ident ++ '_' : port case lookupElem modports (Dot e "") of
expandInterface (Instance part params ident [] instancePorts) = Nothing -> case e of
-- expand modport port bindings Bit e' _ -> findInstance e'
case Map.lookup part interfaces of Dot e' _ -> findInstance e'
Just interface -> _ -> error "internal invariant violated"
-- inline instantiation of an interface Just (accesses, _, _) ->
Generate $ map GenModuleItem $ foldl accessToExpr (Ident topName) rest
inlineInterface interface (ident, params, instancePorts) where Access topName Nil : rest = init accesses
Nothing -> accessToExpr :: Expr -> Access -> Expr
if Map.member part modules accessToExpr e (Access x Nil) = Dot e x
then Instance part params' ident [] expandedPorts accessToExpr e (Access x i) = Bit (Dot e x) i
else Instance part params ident [] instancePorts
where -- expand a modport binding into a series of expression substitutions
expandedBindings = map (uncurry $ expandPortBinding part) (zip instancePorts [0..]) expandModportBinding :: Scopes [ModportDecl]
expandedPorts = concatMap snd expandedBindings -> ModportBinding -> [(Expr, Expr)]
Just (moduleParamNames, _) = Map.lookup part modules expandModportBinding modports (portName, (instanceE, modportE)) =
addedParams = concatMap fst expandedBindings (Ident portName, instanceE) :
paramsNamed = resolveParams moduleParamNames params map toPortBinding modportDecls
params' =
if null addedParams
then params
else paramsNamed ++ addedParams
expandInterface other = other
expandPortBinding :: Identifier -> PortBinding -> Int -> ([ParamBinding], [PortBinding])
expandPortBinding moduleName ("", binding) idx =
case Map.lookup moduleName modules of
Nothing -> error $ "could not find module: " ++ moduleName
Just (_, decls) ->
if idx < length decls
then expandPortBinding moduleName
(fst $ decls !! idx, binding) idx
else error $ "could not infer port for "
++ show binding ++ " in module " ++ show moduleName
expandPortBinding _ (origBinding @ (portName, Dot (Ident instanceName) modportName)) _ =
-- expand instance modport bound to a modport
if Map.member instanceName instances
then expandPortBinding' interfaceName portName instanceName
modportDecls
else ([], [origBinding])
where where
interfaceName = instances Map.! instanceName a = lookupElem modports modportE
interfaceItems = snd $ lookupInterface interfaceName b = lookupElem modports (Dot modportE "")
modportDecls = lookupModport interfaceItems modportName Just (_, replacements, modportDecls) =
expandPortBinding moduleName (origBinding @ (portName, Ident ident)) _ = if a == Nothing then b else a
case (instances Map.!? ident, modports Map.!? ident) of toPortBinding (_, x, e) = (x', e')
(Nothing, Nothing) -> ([], [origBinding])
(Just interfaceName, _) ->
-- given entire interface, but just bound to a modport
if Map.notMember moduleName modules then
error $ "could not find module " ++ show moduleName
else
expandPortBinding' interfaceName portName ident
modportDecls
where where
Just (_, decls) = Map.lookup moduleName modules x' = Dot (Ident portName) x
portType = e' = prefixExpr e
case lookup portName decls of
Nothing -> error $ "could not find port "
++ show portName ++ " in module "
++ show moduleName
Just t -> t
interfaceItems = snd $ lookupInterface interfaceName
modportDecls = lookupModport interfaceItems modportName
modportName = case portType of
InterfaceT _ (Just x) [] -> x
Alias _ [] -> ""
_ -> error $ "can't deduce modport for interface "
++ interfaceName ++ " bound to port "
++ portName ++ " of module " ++ moduleName
(_, Just (interfaceName, modportName)) ->
-- modport directly bound to a modport
expandPortBinding' interfaceName portName ident
(map redirect modportDecls)
where
interfaceItems = snd $ lookupInterface interfaceName
modportDecls = lookupModport interfaceItems modportName
redirect (d, x, t, _) = (d, x, t, Ident x)
expandPortBinding _ other _ = ([], [other])
expandPortBinding' :: Identifier -> Identifier -> Identifier ->
[ModportDecl] -> ([ParamBinding], [PortBinding])
expandPortBinding' interfaceName portName instanceName modportDecls =
(paramBindings, portBindings)
where
paramBindings = map toParamBinding interfaceParamNames
interfaceItems = snd $ lookupInterface interfaceName
interfaceParamNames = map fst $ parameters interfaceItems
toParamBinding x = (portName ++ '_' : x, Right $ Ident $ instanceName ++ '_' : x)
portBindings = map toPortBinding modportDecls
toPortBinding (_, x, _, e) = (x', e')
where
x' = portName ++ '_' : x
e' = traverseNestedExprs prefixExpr e
prefixExpr :: Expr -> Expr prefixExpr :: Expr -> Expr
prefixExpr (Ident x) = Ident (instanceName ++ '_' : x) prefixExpr (Ident x) =
prefixExpr other = other case Map.lookup x replacements of
Just replacement -> replacement
lookupInterface :: Identifier -> Interface Nothing ->
lookupInterface interfaceName = if "_tmp_" `isPrefixOf` x
case Map.lookup interfaceName interfaces of then Ident x
Just res -> res else Dot instanceE x
Nothing -> error $ "could not find interface " ++ show interfaceName prefixExpr other = traverseSinglyNestedExprs prefixExpr other
lookupModport :: [ModuleItem] -> Identifier -> [ModportDecl] -- association list of modport instances in the given module body
lookupModport interfaceItems "" = impliedModport interfaceItems extractModportInstances :: PartInfo -> ModportInstances
lookupModport interfaceItems modportName = extractModportInstances partInfo =
case Map.lookup modportName modportMap of execWriter $ mapM (collectDeclsM collectDecl) (pItems partInfo)
Just modportDecls -> modportDecls
Nothing -> error $ "could not find modport " ++ show modportName
where
modportMap = execWriter $
mapM (collectNestedModuleItemsM collectModport) $
interfaceItems
collectModport :: ModuleItem -> Writer (Map.Map Identifier [ModportDecl]) ()
collectModport (Modport ident l) = tell $ Map.singleton ident l
collectModport _ = return ()
impliedModport :: [ModuleItem] -> [ModportDecl]
impliedModport =
execWriter . mapM (collectNestedModuleItemsM collectModportDecls)
where where
collectModportDecls :: ModuleItem -> Writer [ModportDecl] () collectDecl :: Decl -> Writer ModportInstances ()
collectModportDecls (MIPackageItem (Decl (Variable d t x _ _))) = collectDecl (Variable _ t x _ _) =
tell [(d', x, t, Ident x)] if maybeInfo == Nothing then
where d' = if d == Local then Inout else d return ()
collectModportDecls _ = return () else if elem x (pPorts partInfo) then
tell [(x, info)]
convertPort :: Identifier -> [Identifier] else
convertPort ident = error $ "Modport not in port list: " ++ show (t, x)
case Map.lookup ident modports of ++ ". Is this an interface missing a port list?"
Nothing -> [ident]
Just (interfaceName, modportName) ->
map (\(_, x, _, _) -> ident ++ "_" ++ x) modportDecls
where where
interfaceItems = snd $ lookupInterface interfaceName maybeInfo = extractModportInfo t
modportDecls = lookupModport interfaceItems modportName Just info = maybeInfo
collectDecl _ = return ()
convertDescription _ _ other = other
-- replaces accesses of interface or modport members with their corresponding extractModportInfo :: Type -> Maybe (Identifier, Identifier)
-- flattened (exploded) data declarations extractModportInfo (InterfaceT "" Nothing []) = Just ("", "")
flattenInstances :: Instances -> Modports -> ModuleItem -> ModuleItem extractModportInfo (InterfaceT interfaceName (Just modportName) []) =
flattenInstances instances modports = if isInterface interfaceName
\item -> evalState (rewriter item) Set.empty then Just (interfaceName, modportName)
else Nothing
extractModportInfo (Alias interfaceName []) =
if isInterface interfaceName
then Just (interfaceName, "")
else Nothing
extractModportInfo _ = Nothing
isInterface :: Identifier -> Bool
isInterface partName =
case Map.lookup partName parts of
Nothing -> False
Just info -> pKind info == Interface
convertDescription _ other = other
-- produce the implicit modport decls for an interface bundle
impliedModport :: [ModuleItem] -> [ModportDecl]
impliedModport =
execWriter . mapM (collectNestedModuleItemsM collectModportDecls)
where where
rewriter = traverseScopesM traverseDeclM collectModportDecls :: ModuleItem -> Writer [ModportDecl] ()
(traverseNestedModuleItemsM traverseModuleItemM) traverseStmtM collectModportDecls (MIPackageItem (Decl (Variable d _ x _ _))) =
tell [(d', x, Ident x)]
where d' = if d == Local then Inout else d
collectModportDecls _ = return ()
-- convert an interface-bound module instantiation or an interface instantiation
-- into a series of equivalent inlined module items
inlineInstance :: [ModportBinding] -> [(Expr, Expr)] -> [ModuleItem]
-> Identifier -> [ParamBinding] -> [PortBinding] -> [ModuleItem]
inlineInstance modportBindings modportSubstitutions items
instanceName instanceParams instancePorts =
comment :
map (MIPackageItem . Decl) parameterBinds ++
Generate [GenBlock instanceName $ map GenModuleItem items']
: portBindings
where
items' = evalScoper
traverseDeclM traverseModuleItemM traverseGenItemM traverseStmtM ""
$ map (traverseNestedModuleItems rewriteItem) $
if null modportBindings
then Modport "" (impliedModport items) : items
else items
inlineKind =
if null modportBindings
then "interface"
else "interface-using module"
traverseModuleItemM :: ModuleItem -> State Idents ModuleItem comment = MIPackageItem $ Decl $ CommentDecl $
traverseModuleItemM = "expanded " ++ inlineKind ++ " instance: " ++ instanceName
traverseExprsM traverseExprM >=> portBindings = mapMaybe portBindingItem $
traverseLHSsM traverseLHSM filter notSubstituted instancePorts
traverseStmtM :: Stmt -> State Idents Stmt notSubstituted :: PortBinding -> Bool
traverseStmtM = notSubstituted (portName, _) =
traverseStmtExprsM traverseExprM >=> lookup (portName) modportBindings == Nothing
traverseStmtLHSsM traverseLHSM
traverseDeclM :: Decl -> State Idents Decl rewriteItem :: ModuleItem -> ModuleItem
rewriteItem =
removeModportInstance .
removeDeclDir .
traverseDecls overrideParam
traverseDeclM :: Decl -> Scoper Expr Decl
traverseDeclM decl = do traverseDeclM decl = do
item <- traverseModuleItemM (MIPackageItem $ Decl decl) decl' <- traverseDeclExprsM substituteExprM decl
let MIPackageItem (Decl decl') = item
case decl' of case decl' of
Variable _ _ ident _ _ -> modify $ Set.insert ident Variable _ _ x _ _ -> insertElem x Nil
Param _ _ ident _ -> modify $ Set.insert ident Param _ _ x e -> insertElem x e
ParamType{} -> return () ParamType _ x _ -> insertElem x Nil
CommentDecl{} -> return () CommentDecl{} -> return ()
return decl' return decl'
traverseExprM = traverseNestedExprsM convertExprM traverseModuleItemM :: ModuleItem -> Scoper Expr ModuleItem
traverseLHSM = traverseNestedLHSsM convertLHSM traverseModuleItemM (item @ Modport{}) =
traverseExprsM substituteExprM item
convertExprM :: Expr -> State Idents Expr traverseModuleItemM item =
convertExprM (orig @ (Dot (Ident x) y)) = do traverseExprsM traverseExprM item >>=
substituteNonLocal orig repl x traverseLHSsM traverseLHSM
where repl = Ident (x ++ "_" ++ y)
convertExprM other = return other traverseGenItemM :: GenItem -> Scoper Expr GenItem
traverseGenItemM = traverseGenItemExprsM traverseExprM
convertLHSM :: LHS -> State Idents LHS
convertLHSM (orig @ (LHSDot (LHSIdent x) y)) = do traverseStmtM :: Stmt -> Scoper Expr Stmt
substituteNonLocal orig repl x traverseStmtM =
where repl = LHSIdent (x ++ "_" ++ y) traverseStmtExprsM traverseExprM >=>
convertLHSM other = return other traverseStmtLHSsM traverseLHSM
substituteNonLocal :: a -> a -> Identifier -> State Idents a -- used for replacing usages of modports in the module being inlined
substituteNonLocal orig repl ident = do lhsReplacements = map (\(x, y) -> (toLHS x, toLHS y)) exprReplacements
locals <- get exprReplacements = filter ((/= Nil) . snd) modportSubstitutions
return $ if Map.member ident modports || Map.member ident instances -- LHSs are replaced using simple substitutions
then if Set.notMember ident locals traverseLHSM :: LHS -> Scoper Expr LHS
then repl traverseLHSM lhs = do
else orig lhs' <- embedScopes tagLHS lhs
else orig return $ replaceLHS lhs'
tagLHS :: Scopes Expr -> LHS -> LHS
-- add a prefix to all standard identifiers in a module item tagLHS scopes lhs =
prefixModuleItems :: (Identifier -> Identifier) -> ModuleItem -> ModuleItem if lookupElem scopes lhs /= Nothing
prefixModuleItems prefix = then LHSDot lhs "@"
prefixOtherItem . else traverseSinglyNestedLHSs (tagLHS scopes) lhs
traverseDecls prefixDecl . replaceLHS :: LHS -> LHS
traverseExprs (traverseNestedExprs prefixExpr) . replaceLHS (LHSDot lhs "@") = lhs
traverseLHSs (traverseNestedLHSs prefixLHS ) replaceLHS lhs =
where case lookup lhs lhsReplacements of
prefixDecl :: Decl -> Decl Just lhs' -> lhs'
prefixDecl (Variable d t x a e) = Variable d t (prefix x) a e Nothing -> traverseSinglyNestedLHSs replaceLHS lhs
prefixDecl (Param s t x e) = Param s t (prefix x) e -- top-level expressions may be modports bound to other modports
prefixDecl (ParamType s x mt) = ParamType s (prefix x) mt traverseExprM :: Expr -> Scoper Expr Expr
prefixDecl (CommentDecl c) = CommentDecl c traverseExprM expr = do
prefixExpr :: Expr -> Expr expr' <- embedScopes (tagExpr False) expr
prefixExpr (Ident x) = Ident (prefix x) return $ replaceExpr expr'
prefixExpr other = other substituteExprM :: Expr -> Scoper Expr Expr
prefixLHS :: LHS -> LHS substituteExprM expr = do
prefixLHS (LHSIdent x) = LHSIdent (prefix x) expr' <- embedScopes (tagExpr True) expr
prefixLHS other = other return $ replaceExpr expr'
prefixOtherItem :: ModuleItem -> ModuleItem tagExpr :: Bool -> Scopes Expr -> Expr -> Expr
prefixOtherItem (MIPackageItem item) = tagExpr substitute scopes expr =
MIPackageItem $ prefixPackageItem prefix item case lookupElem scopes expr of
prefixOtherItem (Instance m params name rs ports) = Just (_, _, Nil) -> Dot expr "@"
Instance m params (prefix name) rs ports Just ([_, _], replacements, expr') ->
prefixOtherItem (Genvar x) = Genvar $ prefix x if substitute && Map.null replacements
prefixOtherItem other = other then Dot expr' "@"
else Dot expr "@"
-- add a prefix to all standard identifiers in a package item Just (_, _, _) -> Dot expr "@"
prefixPackageItem :: (Identifier -> Identifier) -> PackageItem -> PackageItem Nothing ->
prefixPackageItem prefix (Function lifetime t x decls stmts) = traverseSinglyNestedExprs (tagExpr substitute scopes) expr
Function lifetime t x' decls stmts replaceExpr :: Expr -> Expr
where x' = prefix x replaceExpr (Dot expr "@") = expr
prefixPackageItem prefix (Task lifetime x decls stmts) = replaceExpr (Ident x) =
Task lifetime x' decls stmts case lookup x modportBindings of
where x' = prefix x Just (_, m) -> m
prefixPackageItem _ other = other Nothing -> Ident x
replaceExpr expr =
-- collect all identifiers defined within a module item replaceExpr' expr
collectIdentsM :: ModuleItem -> Writer (Set.Set Identifier) () replaceExpr' :: Expr -> Expr
collectIdentsM (MIPackageItem (Function _ _ x _ _)) = tell $ Set.singleton x replaceExpr' (Dot expr "@") = expr
collectIdentsM (MIPackageItem (Task _ x _ _)) = tell $ Set.singleton x replaceExpr' expr =
collectIdentsM (Instance _ _ x _ _) = tell $ Set.singleton x case lookup expr exprReplacements of
collectIdentsM (Genvar x) = tell $ Set.singleton x Just expr' -> expr'
collectIdentsM item = collectDeclsM collectDecl item Nothing -> traverseSinglyNestedExprs replaceExpr' expr
where
collectDecl :: Decl -> Writer (Set.Set Identifier) () removeModportInstance :: ModuleItem -> ModuleItem
collectDecl (Variable _ _ x _ _) = tell $ Set.singleton x removeModportInstance (MIPackageItem (Decl (Variable d t x a e))) =
collectDecl (Param _ _ x _) = tell $ Set.singleton x MIPackageItem $ Decl $
collectDecl (ParamType _ x _) = tell $ Set.singleton x if lookup x modportBindings /= Nothing
collectDecl (CommentDecl _) = return () then CommentDecl $ "removed modport instance " ++ x
else Variable d t x a e
-- convert an interface instantiation into a series of equivalent module items removeModportInstance other = other
inlineInterface :: Interface -> (Identifier, [ParamBinding], [PortBinding]) -> [ModuleItem]
inlineInterface (ports, items) (instanceName, instanceParams, instancePorts) =
(:) comment $
flip (++) portBindings $
map (traverseNestedModuleItems removeModport) $
map (traverseNestedModuleItems removeDeclDir) $
itemsPrefixed
where
comment = MIPackageItem $ Decl $ CommentDecl $
"expanded instance: " ++ instanceName
prefix = instanceName ++ "_"
itemsPrefixed =
map (traverseDecls overrideParam) $
prefixInterface instanceName items
origInstancePortNames = map fst instancePorts
instancePortExprs = map snd instancePorts
instancePortNames =
map (prefix ++) $
if all ("" ==) origInstancePortNames
then ports
else origInstancePortNames
portBindings =
mapMaybe portBindingItem $
zip instancePortNames instancePortExprs
removeDeclDir :: ModuleItem -> ModuleItem removeDeclDir :: ModuleItem -> ModuleItem
removeDeclDir (MIPackageItem (Decl (Variable _ t x a e))) = removeDeclDir (MIPackageItem (Decl (Variable _ t x a e))) =
...@@ -406,88 +342,80 @@ inlineInterface (ports, items) (instanceName, instanceParams, instancePorts) = ...@@ -406,88 +342,80 @@ inlineInterface (ports, items) (instanceName, instanceParams, instancePorts) =
IntegerVector TLogic Unspecified rs IntegerVector TLogic Unspecified rs
_ -> t _ -> t
removeDeclDir other = other removeDeclDir other = other
removeModport :: ModuleItem -> ModuleItem
removeModport (Modport x _) = paramTmp = "_tmp_" ++ (shortHash (items, instanceName)) ++ "_"
MIPackageItem $ Decl $ CommentDecl $ "removed modport " ++ x
removeModport other = other parameterBinds = map makeParameterBind instanceParams
makeParameterBind :: ParamBinding -> Decl
interfaceParamNames = map fst $ parameters items makeParameterBind (x, Left t) =
instanceParamMap = Map.mapKeys (prefix ++) $ ParamType Localparam (paramTmp ++ x) (Just t)
Map.fromList $ resolveParams interfaceParamNames instanceParams makeParameterBind (x, Right e) =
Param Localparam (TypeOf e) (paramTmp ++ x) e
overrideParam :: Decl -> Decl overrideParam :: Decl -> Decl
overrideParam (Param Parameter t x e) = overrideParam (Param Parameter t x e) =
case Map.lookup x instanceParamMap of case lookup x instanceParams of
Nothing -> Param Parameter t x e Nothing -> Param Localparam t x e
Just (Right e') -> Param Parameter t x e' Just (Right _) -> Param Localparam t x (Ident $ paramTmp ++ x)
Just (Left t') -> Just (Left t') -> error $ inlineKind ++ " param " ++ x
error $ "interface param expected expression, found type: " ++ " expected expr, found type: " ++ show t'
++ show t'
overrideParam (ParamType Parameter x mt) = overrideParam (ParamType Parameter x mt) =
case Map.lookup x instanceParamMap of case lookup x instanceParams of
Nothing -> ParamType Parameter x mt Nothing -> ParamType Localparam x mt
Just (Left t') -> ParamType Parameter x (Just t') Just (Left _) ->
Just (Right e') -> ParamType Localparam x (Just $ Alias (paramTmp ++ x) [])
error $ "interface param expected type, found expression: " Just (Right e') -> error $ inlineKind ++ " param " ++ x
++ show e' ++ " expected type, found expr: " ++ show e'
overrideParam other = other overrideParam other = other
portBindingItem :: PortBinding -> Maybe ModuleItem portBindingItem :: PortBinding -> Maybe ModuleItem
portBindingItem (_, Nil) = Nothing portBindingItem (_, Nil) = Nothing
portBindingItem (ident, expr) = portBindingItem (ident, expr) =
Just $ if declDirs Map.! ident == Input if findDeclDir ident == Input
then Assign AssignOptionNone (LHSIdent ident) expr then bind (LHSDot (LHSIdent instanceName) ident) expr
else Assign AssignOptionNone (toLHS expr) (Ident ident) else bind (toLHS expr) (Dot (Ident instanceName) ident)
where bind a b = Just $ Assign AssignOptionNone a b
declDirs = execWriter $ declDirs = execWriter $
mapM (collectDeclsM collectDeclDir) itemsPrefixed mapM (collectDeclsM collectDeclDir) items
collectDeclDir :: Decl -> Writer (Map.Map Identifier Direction) () collectDeclDir :: Decl -> Writer (Map.Map Identifier Direction) ()
collectDeclDir (Variable dir _ ident _ _) = collectDeclDir (Variable dir _ ident _ _) =
when (dir /= Local) $ when (dir /= Local) $
tell $ Map.singleton ident dir tell $ Map.singleton ident dir
collectDeclDir _ = return () collectDeclDir _ = return ()
findDeclDir :: Identifier -> Direction
findDeclDir ident =
case Map.lookup ident declDirs of
Nothing -> error $ "could not find decl dir of " ++ ident
++ " among " ++ show declDirs
Just dir -> dir
toLHS :: Expr -> LHS toLHS :: Expr -> LHS
toLHS expr = toLHS expr =
case exprToLHS expr of case exprToLHS expr of
Just lhs -> lhs Just lhs -> lhs
Nothing -> error $ "trying to bind an interface output to " ++ Nothing -> error $ "trying to bind an " ++ inlineKind
show expr ++ " but that can't be an LHS" ++ " output to " ++ show expr ++ " but that can't be an LHS"
-- convert an interface instantiation into a series of equivalent module items type Binding t = (Identifier, t)
prefixInterface :: Identifier -> [ModuleItem] -> [ModuleItem] -- give a set of bindings explicit names
prefixInterface instanceName items = resolveBindings :: Show t => [Identifier] -> [Binding t] -> [Binding t]
map prefixItem items resolveBindings available bindings =
where zipWith resolveBinding bindings [0..]
prefix = instanceName ++ "_"
idents = execWriter $
mapM (collectNestedModuleItemsM collectIdentsM) items
prefixIfNecessary :: Identifier -> Identifier
prefixIfNecessary x =
if Set.member x idents
then prefix ++ x
else x
prefixItem = traverseNestedModuleItems $
prefixModuleItems prefixIfNecessary
-- give a set of param bindings explicit names
resolveParams :: [Identifier] -> [ParamBinding] -> [ParamBinding]
resolveParams available bindings =
map (uncurry resolveParam) $ zip bindings [0..]
where where
resolveParam :: ParamBinding -> Int -> ParamBinding resolveBinding ("", e) idx =
resolveParam ("", e) idx =
if idx < length available if idx < length available
then (available !! idx, e) then (available !! idx, e)
else error $ "interface param binding " ++ (show e) else error $ "binding " ++ show e ++ " is out of range "
++ " is out of range" ++ show available
resolveParam other _ = other resolveBinding other _ = other
-- given a list of module items, produces the parameters in order -- given a list of module items, produces the parameter names in order
parameters :: [ModuleItem] -> [(Identifier, Decl)] parameterNames :: [ModuleItem] -> [Identifier]
parameters = parameterNames =
execWriter . mapM (collectNestedModuleItemsM $ collectDeclsM collectDeclM) execWriter . mapM (collectNestedModuleItemsM $ collectDeclsM collectDeclM)
where where
collectDeclM :: Decl -> Writer [(Identifier, Decl)] () collectDeclM :: Decl -> Writer [Identifier] ()
collectDeclM (decl @ (Param Parameter _ x _)) = tell [(x, decl)] collectDeclM (Param Parameter _ x _) = tell [x]
collectDeclM (decl @ (ParamType Parameter x _)) = tell [(x, decl)] collectDeclM (ParamType Parameter x _) = tell [x]
collectDeclM _ = return () collectDeclM _ = return ()
...@@ -39,6 +39,7 @@ module Convert.Scoper ...@@ -39,6 +39,7 @@ module Convert.Scoper
, embedScopes , embedScopes
, withinProcedure , withinProcedure
, withinProcedureM , withinProcedureM
, scopeModuleItemT
) where ) where
import Control.Monad.State import Control.Monad.State
...@@ -254,6 +255,20 @@ evalScoperT declMapper moduleItemMapper genItemMapper stmtMapper topName items = ...@@ -254,6 +255,20 @@ evalScoperT declMapper moduleItemMapper genItemMapper stmtMapper topName items =
return items' return items'
initialState = Scopes [] Map.empty False [] initialState = Scopes [] Map.empty False []
wrappedModuleItemMapper = scopeModuleItemT
declMapper moduleItemMapper genItemMapper stmtMapper
scopeModuleItemT
:: forall a m. Monad m
=> MapperM (ScoperT a m) Decl
-> MapperM (ScoperT a m) ModuleItem
-> MapperM (ScoperT a m) GenItem
-> MapperM (ScoperT a m) Stmt
-> ModuleItem
-> ScoperT a m ModuleItem
scopeModuleItemT declMapper moduleItemMapper genItemMapper stmtMapper =
wrappedModuleItemMapper
where
fullStmtMapper :: Stmt -> ScoperT a m Stmt fullStmtMapper :: Stmt -> ScoperT a m Stmt
fullStmtMapper (Block kw name decls stmts) = do fullStmtMapper (Block kw name decls stmts) = do
enterScope name "" enterScope name ""
......
...@@ -597,10 +597,9 @@ traverseExprsM exprMapper = moduleItemMapper ...@@ -597,10 +597,9 @@ traverseExprsM exprMapper = moduleItemMapper
genItemMapper = traverseGenItemExprsM exprMapper genItemMapper = traverseGenItemExprsM exprMapper
modportDeclMapper (dir, ident, t, e) = do modportDeclMapper (dir, ident, e) = do
t' <- typeMapper t
e' <- exprMapper e e' <- exprMapper e
return (dir, ident, t', e') return (dir, ident, e')
traverseExprs :: Mapper Expr -> Mapper ModuleItem traverseExprs :: Mapper Expr -> Mapper ModuleItem
traverseExprs = unmonad traverseExprsM traverseExprs = unmonad traverseExprsM
...@@ -942,11 +941,6 @@ traverseTypesM' strategy mapper = ...@@ -942,11 +941,6 @@ traverseTypesM' strategy mapper =
then mapper t >>= \t' -> return (i, Left t') then mapper t >>= \t' -> return (i, Left t')
else return (i, Left t) else return (i, Left t)
mapParam (i, Right e) = return $ (i, Right e) mapParam (i, Right e) = return $ (i, Right e)
miMapper (Modport name decls) =
mapM mapModportDecl decls >>= return . Modport name
where
mapModportDecl (d, x, t, e) =
mapper t >>= \t' -> return (d, x, t', e)
miMapper other = return other miMapper other = return other
traverseTypes' :: TypeStrategy -> Mapper Type -> Mapper ModuleItem traverseTypes' :: TypeStrategy -> Mapper Type -> Mapper ModuleItem
......
...@@ -62,6 +62,11 @@ exprToLHS (Dot l x ) = do ...@@ -62,6 +62,11 @@ exprToLHS (Dot l x ) = do
exprToLHS (Concat ls ) = do exprToLHS (Concat ls ) = do
ls' <- mapM exprToLHS ls ls' <- mapM exprToLHS ls
Just $ LHSConcat ls' Just $ LHSConcat ls'
exprToLHS (Pattern ls ) = do
ls' <- mapM exprToLHS $ map snd ls
if all (null . fst) ls
then Just $ LHSConcat ls'
else Nothing
exprToLHS (Stream o e ls) = do exprToLHS (Stream o e ls) = do
ls' <- mapM exprToLHS ls ls' <- mapM exprToLHS ls
Just $ LHSStream o e ls' Just $ LHSStream o e ls'
......
...@@ -28,7 +28,7 @@ import Language.SystemVerilog.AST.Expr (Expr(Nil), pattern Ident, Range, showRan ...@@ -28,7 +28,7 @@ import Language.SystemVerilog.AST.Expr (Expr(Nil), pattern Ident, Range, showRan
import Language.SystemVerilog.AST.GenItem (GenItem) import Language.SystemVerilog.AST.GenItem (GenItem)
import Language.SystemVerilog.AST.LHS (LHS) import Language.SystemVerilog.AST.LHS (LHS)
import Language.SystemVerilog.AST.Stmt (Stmt, AssertionItem, Timing(Delay)) import Language.SystemVerilog.AST.Stmt (Stmt, AssertionItem, Timing(Delay))
import Language.SystemVerilog.AST.Type (Type, Identifier, DriveStrength) import Language.SystemVerilog.AST.Type (Identifier, DriveStrength)
data ModuleItem data ModuleItem
= MIAttr Attr ModuleItem = MIAttr Attr ModuleItem
...@@ -90,14 +90,14 @@ showGate kw d x args = ...@@ -90,14 +90,14 @@ showGate kw d x args =
nameStr = showPad $ Ident x nameStr = showPad $ Ident x
showModportDecl :: ModportDecl -> String showModportDecl :: ModportDecl -> String
showModportDecl (dir, ident, t, e) = showModportDecl (dir, ident, e) =
if e == Ident ident if e == Ident ident
then printf "%s %s" (show dir) ident then printf "%s %s" (show dir) ident
else printf "%s .%s(/* type: %s */ %s)" (show dir) ident (show t) (show e) else printf "%s .%s(%s)" (show dir) ident (show e)
type PortBinding = (Identifier, Expr) type PortBinding = (Identifier, Expr)
type ModportDecl = (Direction, Identifier, Type, Expr) type ModportDecl = (Direction, Identifier, Expr)
data AlwaysKW data AlwaysKW
= Always = Always
......
...@@ -577,9 +577,9 @@ ParamAsgn :: { Decl } ...@@ -577,9 +577,9 @@ ParamAsgn :: { Decl }
: Identifier "=" Expr { Param Parameter (Implicit Unspecified []) $1 $3 } : Identifier "=" Expr { Param Parameter (Implicit Unspecified []) $1 $3 }
PortDecls :: { ([Identifier], [ModuleItem]) } PortDecls :: { ([Identifier], [ModuleItem]) }
: "(" DeclTokens(")") { parseDTsAsPortDecls $2 } : "(" PortDeclTokens(")") { parseDTsAsPortDecls $2 }
| "(" ")" { ([], []) } | "(" ")" { ([], []) }
| {- empty -} { ([], []) } | {- empty -} { ([], []) }
ModportItems :: { [(Identifier, [ModportDecl])] } ModportItems :: { [(Identifier, [ModportDecl])] }
: ModportItem { [$1] } : ModportItem { [$1] }
...@@ -592,7 +592,7 @@ ModportPortsDeclarations :: { [ModportDecl] } ...@@ -592,7 +592,7 @@ ModportPortsDeclarations :: { [ModportDecl] }
ModportPortsDeclaration(delim) :: { [ModportDecl] } ModportPortsDeclaration(delim) :: { [ModportDecl] }
: ModportSimplePortsDeclaration(delim) { $1 } : ModportSimplePortsDeclaration(delim) { $1 }
ModportSimplePortsDeclaration(delim) :: { [ModportDecl] } ModportSimplePortsDeclaration(delim) :: { [ModportDecl] }
: Direction ModportSimplePorts delim { map (\(a, b) -> ($1, a, TypeOf b, b)) $2 } : Direction ModportSimplePorts delim { map (\(a, b) -> ($1, a, b)) $2 }
ModportSimplePorts :: { [(Identifier, Expr)] } ModportSimplePorts :: { [(Identifier, Expr)] }
: ModportSimplePort { [$1] } : ModportSimplePort { [$1] }
| ModportSimplePorts "," ModportSimplePort { $1 ++ [$3] } | ModportSimplePorts "," ModportSimplePort { $1 ++ [$3] }
...@@ -611,11 +611,13 @@ Identifiers :: { [Identifier] } ...@@ -611,11 +611,13 @@ Identifiers :: { [Identifier] }
-- uses delimiter propagation hack to avoid conflicts -- uses delimiter propagation hack to avoid conflicts
DeclTokens(delim) :: { [DeclToken] } DeclTokens(delim) :: { [DeclToken] }
: DeclToken delim { [$1] } : DeclTokensBase(DeclTokens(delim), delim) { $1 }
| DeclToken DeclTokens(delim) { [$1] ++ $2 } DeclTokensBase(repeat, delim) :: { [DeclToken] }
| Identifier ParamBindings DeclTokens(delim) {% posInject \p -> [DTIdent p $1, DTParams p $2] ++ $3 } : DeclToken delim { [$1] }
| DeclTokenAsgn "," DeclTokens(delim) {% posInject \p -> [$1, DTComma p] ++ $3 } | DeclToken repeat { [$1] ++ $2 }
| DeclTokenAsgn delim {% posInject \p -> [$1] } | Identifier ParamBindings repeat {% posInject \p -> [DTIdent p $1, DTParams p $2] ++ $3 }
| DeclTokenAsgn "," repeat {% posInject \p -> [$1, DTComma p] ++ $3 }
| DeclTokenAsgn delim {% posInject \p -> [$1] }
DeclToken :: { DeclToken } DeclToken :: { DeclToken }
: "," {% posInject \p -> DTComma p } : "," {% posInject \p -> DTComma p }
| "[" "]" {% posInject \p -> DTAutoDim p } | "[" "]" {% posInject \p -> DTAutoDim p }
...@@ -640,6 +642,12 @@ DeclToken :: { DeclToken } ...@@ -640,6 +642,12 @@ DeclToken :: { DeclToken }
DeclTokenAsgn :: { DeclToken } DeclTokenAsgn :: { DeclToken }
: "=" opt(DelayOrEvent) Expr {% posInject \p -> DTAsgn p AsgnOpEq $2 $3 } : "=" opt(DelayOrEvent) Expr {% posInject \p -> DTAsgn p AsgnOpEq $2 $3 }
| AsgnBinOp Expr {% posInject \p -> DTAsgn p $1 Nothing $2 } | AsgnBinOp Expr {% posInject \p -> DTAsgn p $1 Nothing $2 }
PortDeclTokens(delim) :: { [DeclToken] }
: DeclTokensBase(PortDeclTokens(delim), delim) { $1 }
| GenericInterfaceDecl PortDeclTokens(delim) { $1 ++ $2}
| GenericInterfaceDecl delim { $1 }
GenericInterfaceDecl :: { [DeclToken] }
: "interface" Identifier {% posInject \p -> [DTType p (\Unspecified -> InterfaceT "" Nothing), DTIdent p $2] }
VariablePortIdentifiers :: { [(Identifier, Expr)] } VariablePortIdentifiers :: { [(Identifier, Expr)] }
: VariablePortIdentifier { [$1] } : VariablePortIdentifier { [$1] }
......
interface bundle; interface bundle;
logic [1:0] index; logic [1:0] index = 0;
logic clock; logic clock = 0;
logic [3:0] inp; logic [3:0] inp = '1;
logic out; logic out;
endinterface endinterface
module rotator(bundle b); module rotator(bundle b);
initial b.index = 0;
always @(posedge b.clock) always @(posedge b.clock)
b.index <= b.index + 1; b.index <= b.index + 1;
endmodule endmodule
module setter(bundle b); module setter(bundle b);
initial b.inp = '1;
always @(posedge b.clock) always @(posedge b.clock)
b.inp[b.index] <= b.out; b.inp[b.index] <= b.out;
endmodule endmodule
...@@ -23,7 +21,6 @@ endmodule ...@@ -23,7 +21,6 @@ endmodule
module clocker(bundle b); module clocker(bundle b);
initial begin initial begin
b.clock <= 0;
forever forever
#5 b.clock <= ~b.clock; #5 b.clock <= ~b.clock;
end end
......
module impl(b_index, b_clock, b_inp, b_out); module impl;
output reg [1:0] b_index; reg [1:0] b_index;
output reg b_clock; reg b_clock;
output reg [3:0] b_inp; reg [3:0] b_inp;
output wire b_out; wire b_out;
initial b_index = 0; initial b_index = 0;
always @(posedge b_clock) always @(posedge b_clock)
...@@ -19,15 +19,6 @@ module impl(b_index, b_clock, b_inp, b_out); ...@@ -19,15 +19,6 @@ module impl(b_index, b_clock, b_inp, b_out);
forever forever
#5 b_clock <= ~b_clock; #5 b_clock <= ~b_clock;
end end
endmodule
module top;
wire [1:0] b_index;
wire b_clock;
wire [3:0] b_inp;
wire b_out;
impl impl(b_index, b_clock, b_inp, b_out);
initial begin initial begin
$monitor("%b %b %b %b", b_index, b_clock, b_inp, b_out); $monitor("%b %b %b %b", b_index, b_clock, b_inp, b_out);
...@@ -36,3 +27,6 @@ module top; ...@@ -36,3 +27,6 @@ module top;
end end
endmodule endmodule
module top;
impl impl();
endmodule
interface Interface #(num_clients = 0);
bit [num_clients-1:0] req;
for (genvar i = 0; i < num_clients; ++i) begin : mps
modport client_mp (output .client_req(req[i]));
end
endinterface
module ClientAnd (client_ifc, bits);
parameter WIDTH = 2;
Interface client_ifc;
input [WIDTH-1:0] bits;
assign client_ifc.client_req = &bits;
endmodule
module ClientTick #(start = 0, period = 1) (Interface client_ifc, input clock);
initial client_ifc.client_req = start;
integer counter;
initial counter = 0;
always @(posedge clock) begin
counter += 1;
if (counter % period == 0)
client_ifc.client_req = ~client_ifc.client_req;
end
endmodule
module top;
logic clock;
initial begin
clock = 1;
forever #1 clock = ~clock;
end
parameter N = 8;
Interface #(.num_clients(N)) intf();
for (genvar j = 0; j < N - 1; j++) begin : clients
ClientTick #(j, j + 1) client(
.clock,
.client_ifc(intf.mps[j + 1].client_mp)
);
end
ClientAnd #(4) client(
.bits(intf.req[4:1]),
.client_ifc(intf.mps[0].client_mp)
);
initial begin
$monitor("%0d %b %b", $time, clock, intf.req);
#100 $finish;
end
endmodule
module ClientAnd (client_req, bits);
parameter WIDTH = 2;
output client_req;
input [WIDTH-1:0] bits;
assign client_req = &bits;
endmodule
module ClientTick #(
parameter start = 0,
parameter period = 1
) (
output reg client_req,
input clock
);
initial client_req = start;
integer counter;
initial counter = 0;
always @(posedge clock) begin
counter += 1;
if (counter % period == 0)
client_req = ~client_req;
end
endmodule
module top;
reg clock;
initial begin
clock = 1;
forever #1 clock = ~clock;
end
parameter N = 8;
generate
begin : intf
wire [N-1:0] req;
end
genvar j;
for (j = 0; j < N - 1; j = j + 1) begin : clients
ClientTick #(j, j + 1) client(
.clock,
.client_req(intf.req[j + 1])
);
end
endgenerate
ClientAnd #(4) client(
.bits(intf.req[4:1]),
.client_req(intf.req[0])
);
initial begin
$monitor("%0d %b %b", $time, clock, intf.req);
#100 $finish;
end
endmodule
interface InterfaceA;
task hello;
input integer inp;
$display("Hello from InterfaceA %0d", inp);
endtask
logic [20:0] x = 21'b01011_00100000_01011110;
endinterface
interface InterfaceB;
task hello;
input integer inp;
$display("Hello from InterfaceB %0d", inp);
endtask
logic [10:0] x = 11'b011_11110100;
endinterface
// could get bound to any of the interfaces or modports
module Module(interface i);
initial #4 i.hello(1);
initial #5 $display("Module got %b", i.x);
endmodule
interface InterfaceM;
logic [4:0] x = 0;
task hello;
input integer inp;
x = x + 1;
$display("Hello from InterfaceM %0d %b", inp, x);
endtask
modport A(input .x(x[0]));
modport B(input .x(x[2:1]));
endinterface
// could get bound to the entire interface bundle, or either modport
module ModuleM(InterfaceM i);
initial i.hello(-1);
initial $display("ModuleM got %b", i.x);
endmodule
module ModuleWrapperMA(InterfaceM.A i); Module m(i); endmodule
module ModuleWrapperMB(InterfaceM.B i); Module m(i); endmodule
module ModuleWrapperM (InterfaceM i); Module m(i); endmodule
module ModuleMWrapperMA(InterfaceM.A i); ModuleM m(i); endmodule
module ModuleMWrapperMB(InterfaceM.B i); ModuleM m(i); endmodule
module ModuleMWrapperM (InterfaceM i); ModuleM m(i); endmodule
module top;
InterfaceM im();
Module c(im.A);
Module d(im.B);
Module e(im);
ModuleM x(im.A);
ModuleM y(im.B);
ModuleM z(im);
InterfaceA ia();
InterfaceB ib();
Module a(ia);
Module b(ib);
ModuleWrapperMA cw(im);
ModuleWrapperMB dw(im);
ModuleWrapperM ew(im);
ModuleMWrapperMA xw(im);
ModuleMWrapperMB yw(im);
ModuleMWrapperM zw(im);
endmodule
module impl;
reg [4:0] im_x = 0;
task im_hello;
input integer inp;
begin
im_x = im_x + 1;
$display("Hello from InterfaceM %0d %b", inp, im_x);
end
endtask
initial #4 im_hello(1);
initial #5 $display("Module got %b", im_x[0]);
initial #4 im_hello(1);
initial #5 $display("Module got %b", im_x[2:1]);
initial #4 im_hello(1);
initial #5 $display("Module got %b", im_x);
initial im_hello(-1);
initial $display("ModuleM got %b", im_x[0]);
initial im_hello(-1);
initial $display("ModuleM got %b", im_x[2:1]);
initial im_hello(-1);
initial $display("ModuleM got %b", im_x);
task ia_hello;
input integer inp;
$display("Hello from InterfaceA %0d", inp);
endtask
wire [20:0] ia_x = 21'b01011_00100000_01011110;
task ib_hello;
input integer inp;
$display("Hello from InterfaceB %0d", inp);
endtask
wire [10:0] ib_x = 11'b011_11110100;
initial #4 ia_hello(1);
initial #5 $display("Module got %b", ia_x);
initial #4 ib_hello(1);
initial #5 $display("Module got %b", ib_x);
initial #4 im_hello(1);
initial #5 $display("Module got %b", im_x[0]);
initial #4 im_hello(1);
initial #5 $display("Module got %b", im_x[2:1]);
initial #4 im_hello(1);
initial #5 $display("Module got %b", im_x);
initial im_hello(-1);
initial $display("ModuleM got %b", im_x[0]);
initial im_hello(-1);
initial $display("ModuleM got %b", im_x[2:1]);
initial im_hello(-1);
initial $display("ModuleM got %b", im_x);
endmodule
module top;
impl impl();
endmodule
module Module(input wire x);
initial $display("Module %d", x);
endmodule
module top; module top;
wire i_x = 0; genvar g;
localparam SOME_VAL = 3; localparam SOME_VAL = 3;
initial $display("Interface %d %d", i_x, SOME_VAL);
Module m(.x(i_x));
generate generate
genvar g; begin : i
for (g = 10; g < 15; g = g + 1) begin wire x = 0;
initial $display(g); initial $display("Interface %d %d", x, SOME_VAL);
for (g = 10; g < 15; g = g + 1) begin
initial $display(g);
end
end end
for (g = 0; g < 5; g = g + 1) begin endgenerate
initial $display(g); generate
begin : m
initial $display("Module %d", i.x);
for (g = 0; g < 5; g = g + 1) begin
initial $display(g);
end
end end
endgenerate endgenerate
endmodule endmodule
...@@ -20,8 +20,8 @@ module ModuleA(Interface.ModportA m); ...@@ -20,8 +20,8 @@ module ModuleA(Interface.ModportA m);
endmodule endmodule
module ModuleB(Interface.ModportB m); module ModuleB(Interface.ModportB m);
parameter WIDTH = 0;
initial m.x = 1; initial m.x = 1;
localparam WIDTH = 2 * m.WIDTH;
always @(posedge m.clock) begin always @(posedge m.clock) begin
logic temp; logic temp;
temp = m.x[WIDTH-1]; temp = m.x[WIDTH-1];
...@@ -33,7 +33,10 @@ module ModuleB(Interface.ModportB m); ...@@ -33,7 +33,10 @@ module ModuleB(Interface.ModportB m);
endmodule endmodule
module ModuleBWrapper(Interface.ModportB m); module ModuleBWrapper(Interface.ModportB m);
ModuleB b(m); parameter WIDTH = 0;
ModuleB #(WIDTH) b(m);
integer i = 0;
initial #1 $display("shadow i = %d, %b", i, m.x);
endmodule endmodule
module ModuleAWrapper(Interface.ModportA m); module ModuleAWrapper(Interface.ModportA m);
...@@ -45,7 +48,7 @@ module Tester(input clock); ...@@ -45,7 +48,7 @@ module Tester(input clock);
logic [WIDTH-1:0] idx1, idx2; logic [WIDTH-1:0] idx1, idx2;
Interface #(2 ** WIDTH) i(clock, '{idx1, idx2}); Interface #(2 ** WIDTH) i(clock, '{idx1, idx2});
ModuleAWrapper a(i); ModuleAWrapper a(i);
ModuleBWrapper b(i); ModuleBWrapper #(2 * 2 ** WIDTH) b(i);
always @(negedge clock) always @(negedge clock)
$display("%d %0d %2d %2d %b", $time, WIDTH, idx1, idx2, i.x); $display("%d %0d %2d %2d %b", $time, WIDTH, idx1, idx2, i.x);
endmodule endmodule
...@@ -10,6 +10,9 @@ module Tester(input clock); ...@@ -10,6 +10,9 @@ module Tester(input clock);
assign idx1 = $clog2(x[2*DATA_WIDTH-1:DATA_WIDTH]); assign idx1 = $clog2(x[2*DATA_WIDTH-1:DATA_WIDTH]);
assign idx2 = $clog2(x[DATA_WIDTH-1:0]); assign idx2 = $clog2(x[DATA_WIDTH-1:0]);
integer i = 0;
initial #1 $display("shadow i = %d, %b", i, x);
always @(posedge clock) begin : block always @(posedge clock) begin : block
localparam SIZE = 2 * DATA_WIDTH; localparam SIZE = 2 * DATA_WIDTH;
integer i; integer i;
......
interface InterfaceA;
logic x;
modport M(input x);
endinterface
interface InterfaceB;
logic y;
modport N(input y);
endinterface
module ModuleA(modport_a);
InterfaceA modport_a;
initial $display("ModuleA %b", modport_a.x);
endmodule
module ModuleB(modport_b);
InterfaceB modport_b;
InterfaceA interface_a();
ModuleA module_a(interface_a.M);
initial $display("ModuleB %b", modport_b.y);
assign interface_a.x = 0;
endmodule
module ModuleC;
InterfaceB interface_b();
ModuleB module_b(interface_b.N);
assign interface_b.y = 1;
endmodule
module top;
ModuleC module_c();
endmodule
module ModuleC;
wire y;
assign y = 1;
initial $display("ModuleB %b", y);
wire x;
assign x = 0;
initial $display("ModuleA %b", x);
endmodule
module top;
ModuleC module_c();
endmodule
module top; module top;
wire x, f_x; wire x = 1;
wire f_a_x, f_b_x; generate
assign x = 1; begin : f
assign f_x = x; wire x;
assign f_a_x = x; begin : a
assign f_b_x = ~x; wire x;
initial begin
initial begin $display("bar got %b", x);
$display("bar got %b", f_a_x); end
$display("bar got %b", f_b_x); end
end assign a.x = x;
begin : b
wire x;
initial begin
$display("bar got %b", x);
end
end
assign b.x = ~x;
end
assign f.x = x;
endgenerate
endmodule endmodule
...@@ -12,10 +12,16 @@ module M(data); ...@@ -12,10 +12,16 @@ module M(data);
endmodule endmodule
module top; module top;
wire [31:0] x_data = 0; generate
wire [9:0] y_data = 0; begin : x
M #(.WIDTH(32)) a(x_data); wire [31:0] data = 0;
M #(.WIDTH(10)) b(y_data); end
M #(3, 32, 4) c(x_data); begin : y
M #(5, 10, 6) d(y_data); wire [9:0] data = 0;
end
endgenerate
M #(.WIDTH(32)) a(x.data);
M #(.WIDTH(10)) b(y.data);
M #(3, 32, 4) c(x.data);
M #(5, 10, 6) d(y.data);
endmodule endmodule
typedef struct packed { logic x; } T;
interface Interface;
integer x;
function z;
input x;
z = ~x;
endfunction
endinterface
module Module(interface y);
function z;
input T y;
z = y.x;
endfunction
integer x = 0;
initial begin
#1;
$display("x = %b", x);
$display("z(x) = %b", z(x));
$display("y.x = %b", y.x);
$display("y.z(x) = %b", y.z(x));
$display("y.z(y.x) = %b", y.z(y.x));
$display("y.z(z(y.x)) = %b", y.z(z(y.x)));
end
endmodule
module top;
Interface x();
initial x.x = 1;
Module y(x);
endmodule
module top;
generate
begin : x
integer x;
function z;
input x;
z = ~x;
endfunction
end
endgenerate
initial x.x = 1;
generate
begin : y
function z;
input x;
z = x;
endfunction
integer x = 0;
initial begin
#1;
$display("x = %b", x);
$display("z(x) = %b", z(x));
$display("y.x = %b", top.x.x);
$display("y.z(x) = %b", top.x.z(x));
$display("y.z(y.x) = %b", top.x.z(top.x.x));
$display("y.z(z(y.x)) = %b", top.x.z(z(top.x.x)));
end
end
endgenerate
endmodule
module top; module top;
wire [3:0] i_x; generate
reg [1:0] i_w; begin : i
assign i_x = 4'b1001; wire [3:0] x;
initial i_w = 2'b10; reg [1:0] w;
end
endgenerate
assign i.x = 4'b1001;
initial i.w = 2'b10;
initial begin initial begin
$display("%b", i_x[3]); $display("%b", i.x[3]);
$display("%b", i_x[2]); $display("%b", i.x[2]);
$display("%b", i_x[1]); $display("%b", i.x[1]);
$display("%b", i_x[0]); $display("%b", i.x[0]);
end end
endmodule endmodule
...@@ -25,7 +25,7 @@ module top; ...@@ -25,7 +25,7 @@ module top;
clear = 1'b1; clear = 1'b1;
last = 8'h0; last = 8'h0;
dataIn = 8'h0; dataIn = 8'h0;
repeat (3) @(posedge clock); repeat (4) @(posedge clock);
clear = 1'b0; clear = 1'b0;
for (dataIn = 8'h0; dataIn <= 9'hff; dataIn = dataIn + 8'h1) begin for (dataIn = 8'h0; dataIn <= 9'hff; dataIn = dataIn + 8'h1) begin
@(posedge clock); @(posedge clock);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment