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
repeatedConverter :: [AST] -> [AST]
repeatedConverter files =
if files == files'
then files
else repeatedConverter files'
where
files' =
traverseFiles (collectDescriptionsM collectDesc)
(map . uncurry convertDescription)
files
-- we can only collect/map non-extern interfaces
collectDesc :: Description -> Writer (Interfaces, Modules) ()
collectDesc (orig @ (Part _ False kw _ name ports items)) = do
if kw == Interface
then when (all fullyResolved items) $
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) $ -- we can only collect/map non-extern interfaces and modules
map (traverseNestedModuleItems expandInterface) items collectPart :: Description -> Writer PartInfos ()
ports' = concatMap convertPort ports collectPart (Part _ False kw _ name ports items) =
tell $ Map.singleton name $ PartInfo kw ports items
-- collect the interface type of all interface instances in this module collectPart _ = return ()
(instances, modports) = execWriter $ mapM
(collectNestedModuleItemsM collectInstanceM) items convertDescription :: PartInfos -> Description -> Description
collectInstanceM :: ModuleItem -> Writer (Instances, Modports) () convertDescription _ (Part _ _ Interface _ name _ _) =
collectInstanceM (MIPackageItem (Decl (Variable _ t ident _ _))) = PackageItem $ Decl $ CommentDecl $ "removed interface: " ++ name
case t of convertDescription parts (Part attrs extern Module lifetime name ports items) =
InterfaceT interfaceName (Just modportName) [] -> if null $ extractModportInstances $ PartInfo Module ports items then
when (Map.member interfaceName interfaces) $ Part attrs extern Module lifetime name ports items'
writeModport interfaceName modportName else
Alias interfaceName [] -> PackageItem $ Decl $ CommentDecl $
when (Map.member interfaceName interfaces) $ "removed interface-using module: " ++ name
writeModport interfaceName ""
_ -> return ()
where
writeModport :: Identifier -> Identifier ->
Writer (Instances, Modports) ()
writeModport interfaceName modportName =
tell (Map.empty, Map.singleton ident modport)
where modport = (interfaceName, modportName)
collectInstanceM (Instance part _ ident [] _) =
when (Map.member part interfaces) $
tell (Map.singleton ident part, Map.empty)
collectInstanceM _ = return ()
expandInterface :: ModuleItem -> ModuleItem
expandInterface (orig @ (MIPackageItem (Decl (Variable _ _ ident _ _)))) =
-- expand instantiation of a modport
if Map.member ident modports
then Generate $ map GenModuleItem $
filter shouldKeep interfaceItems ++ map makePortDecl
modportDecls
else orig
where where
Just (interfaceName, modportName) = Map.lookup ident modports items' = evalScoper return traverseModuleItemM return return name items
interfaceItems = prefixInterface ident $
snd $ lookupInterface interfaceName convertNested =
modportDecls = lookupModport interfaceItems modportName scopeModuleItemT return traverseModuleItemM return return
shouldKeep (MIPackageItem (Decl Param{})) = True
shouldKeep (MIPackageItem Task{}) = True traverseModuleItemM :: ModuleItem -> Scoper [ModportDecl] ModuleItem
shouldKeep (MIPackageItem Function{}) = True traverseModuleItemM (Modport modportName modportDecls) =
shouldKeep _ = False insertElem modportName modportDecls >> return (Generate [])
makePortDecl :: ModportDecl -> ModuleItem traverseModuleItemM (instanceItem @ (Instance _ _ _ [] _)) =
makePortDecl (dir, port, typ, _) = if maybePartInfo == Nothing then
MIPackageItem $ Decl $ Variable dir typ port' [] Nil return instanceItem
where port' = if null modportName else if partKind == Interface then
then port
else ident ++ '_' : port
expandInterface (Instance part params ident [] instancePorts) =
-- expand modport port bindings
case Map.lookup part interfaces of
Just interface ->
-- inline instantiation of an interface -- inline instantiation of an interface
Generate $ map GenModuleItem $ convertNested $ Generate $ map GenModuleItem $
inlineInterface interface (ident, params, instancePorts) inlineInstance [] []
Nothing -> partItems instanceName paramBindings portBindings
if Map.member part modules else if not $ null (extractModportInstances partInfo) then do
then Instance part params' ident [] expandedPorts modports <- embedScopes (\l () -> l) ()
else Instance part params ident [] instancePorts -- inline instantiation of a module
where convertNested $ Generate $ map GenModuleItem $
expandedBindings = map (uncurry $ expandPortBinding part) (zip instancePorts [0..]) inlineInstance
expandedPorts = concatMap snd expandedBindings (modportBindings modports)
Just (moduleParamNames, _) = Map.lookup part modules (modportSubstitutions modports)
addedParams = concatMap fst expandedBindings partItems instanceName paramBindings portBindings
paramsNamed = resolveParams moduleParamNames params else
params' = return instanceItem
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 Instance part rawParamBindings instanceName [] rawPortBindings =
interfaceItems = snd $ lookupInterface interfaceName instanceItem
modportDecls = lookupModport interfaceItems modportName maybePartInfo = Map.lookup part parts
expandPortBinding moduleName (origBinding @ (portName, Ident ident)) _ = Just partInfo = maybePartInfo
case (instances Map.!? ident, modports Map.!? ident) of PartInfo partKind partPorts partItems = partInfo
(Nothing, Nothing) -> ([], [origBinding])
(Just interfaceName, _) -> partParams = parameterNames partItems
paramBindings = resolveBindings partParams rawParamBindings
portBindings = resolveBindings partPorts rawPortBindings
modportInstances = extractModportInstances partInfo
modportBindings modports = mapMaybe
(inferModportBinding modports modportInstances) portBindings
modportSubstitutions modports = concatMap
(expandModportBinding modports) (modportBindings modports)
traverseModuleItemM other = return other
-- 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 -- given entire interface, but just bound to a modport
if Map.notMember moduleName modules then foundModport $ Dot expr modportName
error $ "could not find module " ++ show moduleName
else else
expandPortBinding' interfaceName portName ident Nothing
modportDecls
where where
Just (_, decls) = Map.lookup moduleName modules bindingIsModport = lookupElem modports expr /= Nothing
portType = bindingIsBundle = lookupElem modports (Dot expr "") /= Nothing
case lookup portName decls of portIsBundle = null modportName
Nothing -> error $ "could not find port " modportName = case lookup portName modportInstances of
++ show portName ++ " in module " Just (_, x) -> x
++ show moduleName Nothing -> error $ "can't deduce modport for interface "
Just t -> t ++ " bound to port " ++ portName
interfaceItems = snd $ lookupInterface interfaceName
modportDecls = lookupModport interfaceItems modportName foundModport modportE =
modportName = case portType of Just (portName, (instanceE, modportE))
InterfaceT _ (Just x) [] -> x where instanceE = findInstance modportE
Alias _ [] -> "" findInstance :: Expr -> Expr
_ -> error $ "can't deduce modport for interface " findInstance e =
++ interfaceName ++ " bound to port " case lookupElem modports (Dot e "") of
++ portName ++ " of module " ++ moduleName Nothing -> case e of
(_, Just (interfaceName, modportName)) -> Bit e' _ -> findInstance e'
-- modport directly bound to a modport Dot e' _ -> findInstance e'
expandPortBinding' interfaceName portName ident _ -> error "internal invariant violated"
(map redirect modportDecls) Just (accesses, _, _) ->
foldl accessToExpr (Ident topName) rest
where Access topName Nil : rest = init accesses
accessToExpr :: Expr -> Access -> Expr
accessToExpr e (Access x Nil) = Dot e x
accessToExpr e (Access x i) = Bit (Dot e x) i
-- expand a modport binding into a series of expression substitutions
expandModportBinding :: Scopes [ModportDecl]
-> ModportBinding -> [(Expr, Expr)]
expandModportBinding modports (portName, (instanceE, modportE)) =
(Ident portName, instanceE) :
map toPortBinding modportDecls
where where
interfaceItems = snd $ lookupInterface interfaceName a = lookupElem modports modportE
modportDecls = lookupModport interfaceItems modportName b = lookupElem modports (Dot modportE "")
redirect (d, x, t, _) = (d, x, t, Ident x) Just (_, replacements, modportDecls) =
expandPortBinding _ other _ = ([], [other]) if a == Nothing then b else a
toPortBinding (_, x, e) = (x', e')
expandPortBinding' :: Identifier -> Identifier -> Identifier ->
[ModportDecl] -> ([ParamBinding], [PortBinding])
expandPortBinding' interfaceName portName instanceName modportDecls =
(paramBindings, portBindings)
where where
paramBindings = map toParamBinding interfaceParamNames x' = Dot (Ident portName) x
interfaceItems = snd $ lookupInterface interfaceName e' = prefixExpr e
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 where
modportMap = execWriter $ collectDecl :: Decl -> Writer ModportInstances ()
mapM (collectNestedModuleItemsM collectModport) $ collectDecl (Variable _ t x _ _) =
interfaceItems if maybeInfo == Nothing then
collectModport :: ModuleItem -> Writer (Map.Map Identifier [ModportDecl]) () return ()
collectModport (Modport ident l) = tell $ Map.singleton ident l else if elem x (pPorts partInfo) then
collectModport _ = return () tell [(x, info)]
else
impliedModport :: [ModuleItem] -> [ModportDecl] error $ "Modport not in port list: " ++ show (t, x)
impliedModport = ++ ". Is this an interface missing a port list?"
where
maybeInfo = extractModportInfo t
Just info = maybeInfo
collectDecl _ = return ()
extractModportInfo :: Type -> Maybe (Identifier, Identifier)
extractModportInfo (InterfaceT "" Nothing []) = Just ("", "")
extractModportInfo (InterfaceT interfaceName (Just modportName) []) =
if isInterface interfaceName
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) execWriter . mapM (collectNestedModuleItemsM collectModportDecls)
where where
collectModportDecls :: ModuleItem -> Writer [ModportDecl] () collectModportDecls :: ModuleItem -> Writer [ModportDecl] ()
collectModportDecls (MIPackageItem (Decl (Variable d t x _ _))) = collectModportDecls (MIPackageItem (Decl (Variable d _ x _ _))) =
tell [(d', x, t, Ident x)] tell [(d', x, Ident x)]
where d' = if d == Local then Inout else d where d' = if d == Local then Inout else d
collectModportDecls _ = return () collectModportDecls _ = return ()
convertPort :: Identifier -> [Identifier] -- convert an interface-bound module instantiation or an interface instantiation
convertPort ident = -- into a series of equivalent inlined module items
case Map.lookup ident modports of inlineInstance :: [ModportBinding] -> [(Expr, Expr)] -> [ModuleItem]
Nothing -> [ident] -> Identifier -> [ParamBinding] -> [PortBinding] -> [ModuleItem]
Just (interfaceName, modportName) -> inlineInstance modportBindings modportSubstitutions items
map (\(_, x, _, _) -> ident ++ "_" ++ x) modportDecls instanceName instanceParams instancePorts =
comment :
map (MIPackageItem . Decl) parameterBinds ++
Generate [GenBlock instanceName $ map GenModuleItem items']
: portBindings
where where
interfaceItems = snd $ lookupInterface interfaceName items' = evalScoper
modportDecls = lookupModport interfaceItems modportName traverseDeclM traverseModuleItemM traverseGenItemM traverseStmtM ""
$ map (traverseNestedModuleItems rewriteItem) $
convertDescription _ _ other = other if null modportBindings
then Modport "" (impliedModport items) : items
else items
inlineKind =
if null modportBindings
then "interface"
else "interface-using module"
-- replaces accesses of interface or modport members with their corresponding comment = MIPackageItem $ Decl $ CommentDecl $
-- flattened (exploded) data declarations "expanded " ++ inlineKind ++ " instance: " ++ instanceName
flattenInstances :: Instances -> Modports -> ModuleItem -> ModuleItem portBindings = mapMaybe portBindingItem $
flattenInstances instances modports = filter notSubstituted instancePorts
\item -> evalState (rewriter item) Set.empty notSubstituted :: PortBinding -> Bool
where notSubstituted (portName, _) =
rewriter = traverseScopesM traverseDeclM lookup (portName) modportBindings == Nothing
(traverseNestedModuleItemsM traverseModuleItemM) traverseStmtM
rewriteItem :: ModuleItem -> ModuleItem
rewriteItem =
removeModportInstance .
removeDeclDir .
traverseDecls overrideParam
traverseDeclM :: Decl -> Scoper Expr Decl
traverseDeclM decl = do
decl' <- traverseDeclExprsM substituteExprM decl
case decl' of
Variable _ _ x _ _ -> insertElem x Nil
Param _ _ x e -> insertElem x e
ParamType _ x _ -> insertElem x Nil
CommentDecl{} -> return ()
return decl'
traverseModuleItemM :: ModuleItem -> State Idents ModuleItem traverseModuleItemM :: ModuleItem -> Scoper Expr ModuleItem
traverseModuleItemM = traverseModuleItemM (item @ Modport{}) =
traverseExprsM traverseExprM >=> traverseExprsM substituteExprM item
traverseModuleItemM item =
traverseExprsM traverseExprM item >>=
traverseLHSsM traverseLHSM traverseLHSsM traverseLHSM
traverseStmtM :: Stmt -> State Idents Stmt
traverseGenItemM :: GenItem -> Scoper Expr GenItem
traverseGenItemM = traverseGenItemExprsM traverseExprM
traverseStmtM :: Stmt -> Scoper Expr Stmt
traverseStmtM = traverseStmtM =
traverseStmtExprsM traverseExprM >=> traverseStmtExprsM traverseExprM >=>
traverseStmtLHSsM traverseLHSM traverseStmtLHSsM traverseLHSM
traverseDeclM :: Decl -> State Idents Decl
traverseDeclM decl = do
item <- traverseModuleItemM (MIPackageItem $ Decl decl)
let MIPackageItem (Decl decl') = item
case decl' of
Variable _ _ ident _ _ -> modify $ Set.insert ident
Param _ _ ident _ -> modify $ Set.insert ident
ParamType{} -> return ()
CommentDecl{} -> return ()
return decl'
traverseExprM = traverseNestedExprsM convertExprM -- used for replacing usages of modports in the module being inlined
traverseLHSM = traverseNestedLHSsM convertLHSM lhsReplacements = map (\(x, y) -> (toLHS x, toLHS y)) exprReplacements
exprReplacements = filter ((/= Nil) . snd) modportSubstitutions
convertExprM :: Expr -> State Idents Expr -- LHSs are replaced using simple substitutions
convertExprM (orig @ (Dot (Ident x) y)) = do traverseLHSM :: LHS -> Scoper Expr LHS
substituteNonLocal orig repl x traverseLHSM lhs = do
where repl = Ident (x ++ "_" ++ y) lhs' <- embedScopes tagLHS lhs
convertExprM other = return other return $ replaceLHS lhs'
tagLHS :: Scopes Expr -> LHS -> LHS
convertLHSM :: LHS -> State Idents LHS tagLHS scopes lhs =
convertLHSM (orig @ (LHSDot (LHSIdent x) y)) = do if lookupElem scopes lhs /= Nothing
substituteNonLocal orig repl x then LHSDot lhs "@"
where repl = LHSIdent (x ++ "_" ++ y) else traverseSinglyNestedLHSs (tagLHS scopes) lhs
convertLHSM other = return other replaceLHS :: LHS -> LHS
replaceLHS (LHSDot lhs "@") = lhs
substituteNonLocal :: a -> a -> Identifier -> State Idents a replaceLHS lhs =
substituteNonLocal orig repl ident = do case lookup lhs lhsReplacements of
locals <- get Just lhs' -> lhs'
return $ if Map.member ident modports || Map.member ident instances Nothing -> traverseSinglyNestedLHSs replaceLHS lhs
then if Set.notMember ident locals -- top-level expressions may be modports bound to other modports
then repl traverseExprM :: Expr -> Scoper Expr Expr
else orig traverseExprM expr = do
else orig expr' <- embedScopes (tagExpr False) expr
return $ replaceExpr expr'
-- add a prefix to all standard identifiers in a module item substituteExprM :: Expr -> Scoper Expr Expr
prefixModuleItems :: (Identifier -> Identifier) -> ModuleItem -> ModuleItem substituteExprM expr = do
prefixModuleItems prefix = expr' <- embedScopes (tagExpr True) expr
prefixOtherItem . return $ replaceExpr expr'
traverseDecls prefixDecl . tagExpr :: Bool -> Scopes Expr -> Expr -> Expr
traverseExprs (traverseNestedExprs prefixExpr) . tagExpr substitute scopes expr =
traverseLHSs (traverseNestedLHSs prefixLHS ) case lookupElem scopes expr of
where Just (_, _, Nil) -> Dot expr "@"
prefixDecl :: Decl -> Decl Just ([_, _], replacements, expr') ->
prefixDecl (Variable d t x a e) = Variable d t (prefix x) a e if substitute && Map.null replacements
prefixDecl (Param s t x e) = Param s t (prefix x) e then Dot expr' "@"
prefixDecl (ParamType s x mt) = ParamType s (prefix x) mt else Dot expr "@"
prefixDecl (CommentDecl c) = CommentDecl c Just (_, _, _) -> Dot expr "@"
prefixExpr :: Expr -> Expr Nothing ->
prefixExpr (Ident x) = Ident (prefix x) traverseSinglyNestedExprs (tagExpr substitute scopes) expr
prefixExpr other = other replaceExpr :: Expr -> Expr
prefixLHS :: LHS -> LHS replaceExpr (Dot expr "@") = expr
prefixLHS (LHSIdent x) = LHSIdent (prefix x) replaceExpr (Ident x) =
prefixLHS other = other case lookup x modportBindings of
prefixOtherItem :: ModuleItem -> ModuleItem Just (_, m) -> m
prefixOtherItem (MIPackageItem item) = Nothing -> Ident x
MIPackageItem $ prefixPackageItem prefix item replaceExpr expr =
prefixOtherItem (Instance m params name rs ports) = replaceExpr' expr
Instance m params (prefix name) rs ports replaceExpr' :: Expr -> Expr
prefixOtherItem (Genvar x) = Genvar $ prefix x replaceExpr' (Dot expr "@") = expr
prefixOtherItem other = other replaceExpr' expr =
case lookup expr exprReplacements of
-- add a prefix to all standard identifiers in a package item Just expr' -> expr'
prefixPackageItem :: (Identifier -> Identifier) -> PackageItem -> PackageItem Nothing -> traverseSinglyNestedExprs replaceExpr' expr
prefixPackageItem prefix (Function lifetime t x decls stmts) =
Function lifetime t x' decls stmts removeModportInstance :: ModuleItem -> ModuleItem
where x' = prefix x removeModportInstance (MIPackageItem (Decl (Variable d t x a e))) =
prefixPackageItem prefix (Task lifetime x decls stmts) = MIPackageItem $ Decl $
Task lifetime x' decls stmts if lookup x modportBindings /= Nothing
where x' = prefix x then CommentDecl $ "removed modport instance " ++ x
prefixPackageItem _ other = other else Variable d t x a e
removeModportInstance other = other
-- collect all identifiers defined within a module item
collectIdentsM :: ModuleItem -> Writer (Set.Set Identifier) ()
collectIdentsM (MIPackageItem (Function _ _ x _ _)) = tell $ Set.singleton x
collectIdentsM (MIPackageItem (Task _ x _ _)) = tell $ Set.singleton x
collectIdentsM (Instance _ _ x _ _) = tell $ Set.singleton x
collectIdentsM (Genvar x) = tell $ Set.singleton x
collectIdentsM item = collectDeclsM collectDecl item
where
collectDecl :: Decl -> Writer (Set.Set Identifier) ()
collectDecl (Variable _ _ x _ _) = tell $ Set.singleton x
collectDecl (Param _ _ x _) = tell $ Set.singleton x
collectDecl (ParamType _ x _) = tell $ Set.singleton x
collectDecl (CommentDecl _) = return ()
-- convert an interface instantiation into a series of equivalent module items
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,7 +577,7 @@ ParamAsgn :: { Decl } ...@@ -577,7 +577,7 @@ 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 -} { ([], []) }
...@@ -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,10 +611,12 @@ Identifiers :: { [Identifier] } ...@@ -611,10 +611,12 @@ Identifiers :: { [Identifier] }
-- uses delimiter propagation hack to avoid conflicts -- uses delimiter propagation hack to avoid conflicts
DeclTokens(delim) :: { [DeclToken] } DeclTokens(delim) :: { [DeclToken] }
: DeclTokensBase(DeclTokens(delim), delim) { $1 }
DeclTokensBase(repeat, delim) :: { [DeclToken] }
: DeclToken delim { [$1] } : DeclToken delim { [$1] }
| DeclToken DeclTokens(delim) { [$1] ++ $2 } | DeclToken repeat { [$1] ++ $2 }
| Identifier ParamBindings DeclTokens(delim) {% posInject \p -> [DTIdent p $1, DTParams p $2] ++ $3 } | Identifier ParamBindings repeat {% posInject \p -> [DTIdent p $1, DTParams p $2] ++ $3 }
| DeclTokenAsgn "," DeclTokens(delim) {% posInject \p -> [$1, DTComma p] ++ $3 } | DeclTokenAsgn "," repeat {% posInject \p -> [$1, DTComma p] ++ $3 }
| DeclTokenAsgn delim {% posInject \p -> [$1] } | DeclTokenAsgn delim {% posInject \p -> [$1] }
DeclToken :: { DeclToken } DeclToken :: { DeclToken }
: "," {% posInject \p -> DTComma p } : "," {% posInject \p -> DTComma 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
wire x = 0;
initial $display("Interface %d %d", x, SOME_VAL);
for (g = 10; g < 15; g = g + 1) begin for (g = 10; g < 15; g = g + 1) begin
initial $display(g); initial $display(g);
end end
end
endgenerate
generate
begin : m
initial $display("Module %d", i.x);
for (g = 0; g < 5; g = g + 1) begin for (g = 0; g < 5; g = g + 1) begin
initial $display(g); 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", f_a_x); $display("bar got %b", x);
$display("bar got %b", f_b_x);
end 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