mirror of https://github.com/zachjs/sv2v.git
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
This commit is contained in:
parent
5161a9e71b
commit
67466eaa60
|
|
@ -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' =
|
|
||||||
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 :: PartInfos -> Description -> Description
|
||||||
convertDescription interfaces modules (Part attrs extern Module lifetime name ports items) =
|
convertDescription _ (Part _ _ Interface _ name _ _) =
|
||||||
Part attrs extern Module lifetime name ports' items'
|
PackageItem $ Decl $ CommentDecl $ "removed interface: " ++ name
|
||||||
|
convertDescription parts (Part attrs extern Module lifetime name ports items) =
|
||||||
|
if null $ extractModportInstances $ PartInfo Module ports items then
|
||||||
|
Part attrs extern Module lifetime name ports items'
|
||||||
|
else
|
||||||
|
PackageItem $ Decl $ CommentDecl $
|
||||||
|
"removed interface-using module: " ++ name
|
||||||
where
|
where
|
||||||
items' = map (flattenInstances instances modports) $
|
items' = evalScoper return traverseModuleItemM return return name items
|
||||||
map (traverseNestedModuleItems expandInterface) items
|
|
||||||
ports' = concatMap convertPort ports
|
|
||||||
|
|
||||||
-- collect the interface type of all interface instances in this module
|
convertNested =
|
||||||
(instances, modports) = execWriter $ mapM
|
scopeModuleItemT return traverseModuleItemM return return
|
||||||
(collectNestedModuleItemsM collectInstanceM) items
|
|
||||||
collectInstanceM :: ModuleItem -> Writer (Instances, Modports) ()
|
|
||||||
collectInstanceM (MIPackageItem (Decl (Variable _ t ident _ _))) =
|
|
||||||
case t of
|
|
||||||
InterfaceT interfaceName (Just modportName) [] ->
|
|
||||||
when (Map.member interfaceName interfaces) $
|
|
||||||
writeModport interfaceName modportName
|
|
||||||
Alias interfaceName [] ->
|
|
||||||
when (Map.member interfaceName interfaces) $
|
|
||||||
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
|
traverseModuleItemM :: ModuleItem -> Scoper [ModportDecl] ModuleItem
|
||||||
expandInterface (orig @ (MIPackageItem (Decl (Variable _ _ ident _ _)))) =
|
traverseModuleItemM (Modport modportName modportDecls) =
|
||||||
-- expand instantiation of a modport
|
insertElem modportName modportDecls >> return (Generate [])
|
||||||
if Map.member ident modports
|
traverseModuleItemM (instanceItem @ (Instance _ _ _ [] _)) =
|
||||||
then Generate $ map GenModuleItem $
|
if maybePartInfo == Nothing then
|
||||||
filter shouldKeep interfaceItems ++ map makePortDecl
|
return instanceItem
|
||||||
modportDecls
|
else if partKind == Interface then
|
||||||
else orig
|
-- inline instantiation of an interface
|
||||||
|
convertNested $ Generate $ map GenModuleItem $
|
||||||
|
inlineInstance [] []
|
||||||
|
partItems instanceName paramBindings portBindings
|
||||||
|
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
|
||||||
Just (interfaceName, modportName) = Map.lookup ident modports
|
Instance part rawParamBindings instanceName [] rawPortBindings =
|
||||||
interfaceItems = prefixInterface ident $
|
instanceItem
|
||||||
snd $ lookupInterface interfaceName
|
maybePartInfo = Map.lookup part parts
|
||||||
modportDecls = lookupModport interfaceItems modportName
|
Just partInfo = maybePartInfo
|
||||||
shouldKeep (MIPackageItem (Decl Param{})) = True
|
PartInfo partKind partPorts partItems = partInfo
|
||||||
shouldKeep (MIPackageItem Task{}) = True
|
|
||||||
shouldKeep (MIPackageItem Function{}) = True
|
|
||||||
shouldKeep _ = False
|
|
||||||
makePortDecl :: ModportDecl -> ModuleItem
|
|
||||||
makePortDecl (dir, port, typ, _) =
|
|
||||||
MIPackageItem $ Decl $ Variable dir typ port' [] Nil
|
|
||||||
where port' = if null modportName
|
|
||||||
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
|
|
||||||
Generate $ map GenModuleItem $
|
|
||||||
inlineInterface interface (ident, params, instancePorts)
|
|
||||||
Nothing ->
|
|
||||||
if Map.member part modules
|
|
||||||
then Instance part params' ident [] expandedPorts
|
|
||||||
else Instance part params ident [] instancePorts
|
|
||||||
where
|
|
||||||
expandedBindings = map (uncurry $ expandPortBinding part) (zip instancePorts [0..])
|
|
||||||
expandedPorts = concatMap snd expandedBindings
|
|
||||||
Just (moduleParamNames, _) = Map.lookup part modules
|
|
||||||
addedParams = concatMap fst expandedBindings
|
|
||||||
paramsNamed = resolveParams moduleParamNames params
|
|
||||||
params' =
|
|
||||||
if null addedParams
|
|
||||||
then params
|
|
||||||
else paramsNamed ++ addedParams
|
|
||||||
expandInterface other = other
|
|
||||||
|
|
||||||
expandPortBinding :: Identifier -> PortBinding -> Int -> ([ParamBinding], [PortBinding])
|
partParams = parameterNames partItems
|
||||||
expandPortBinding moduleName ("", binding) idx =
|
paramBindings = resolveBindings partParams rawParamBindings
|
||||||
case Map.lookup moduleName modules of
|
portBindings = resolveBindings partPorts rawPortBindings
|
||||||
Nothing -> error $ "could not find module: " ++ moduleName
|
|
||||||
Just (_, decls) ->
|
modportInstances = extractModportInstances partInfo
|
||||||
if idx < length decls
|
modportBindings modports = mapMaybe
|
||||||
then expandPortBinding moduleName
|
(inferModportBinding modports modportInstances) portBindings
|
||||||
(fst $ decls !! idx, binding) idx
|
modportSubstitutions modports = concatMap
|
||||||
else error $ "could not infer port for "
|
(expandModportBinding modports) (modportBindings modports)
|
||||||
++ show binding ++ " in module " ++ show moduleName
|
|
||||||
expandPortBinding _ (origBinding @ (portName, Dot (Ident instanceName) modportName)) _ =
|
traverseModuleItemM other = return other
|
||||||
-- expand instance modport bound to a modport
|
|
||||||
if Map.member instanceName instances
|
-- determines the underlying modport and interface instances associated
|
||||||
then expandPortBinding' interfaceName portName instanceName
|
-- with the given port binding, if it is a modport binding
|
||||||
modportDecls
|
inferModportBinding :: Scopes [ModportDecl] -> ModportInstances ->
|
||||||
else ([], [origBinding])
|
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
|
||||||
interfaceName = instances Map.! instanceName
|
bindingIsModport = lookupElem modports expr /= Nothing
|
||||||
interfaceItems = snd $ lookupInterface interfaceName
|
bindingIsBundle = lookupElem modports (Dot expr "") /= Nothing
|
||||||
modportDecls = lookupModport interfaceItems modportName
|
portIsBundle = null modportName
|
||||||
expandPortBinding moduleName (origBinding @ (portName, Ident ident)) _ =
|
modportName = case lookup portName modportInstances of
|
||||||
case (instances Map.!? ident, modports Map.!? ident) of
|
Just (_, x) -> x
|
||||||
(Nothing, Nothing) -> ([], [origBinding])
|
Nothing -> error $ "can't deduce modport for interface "
|
||||||
(Just interfaceName, _) ->
|
++ " bound to port " ++ portName
|
||||||
-- given entire interface, but just bound to a modport
|
|
||||||
if Map.notMember moduleName modules then
|
foundModport modportE =
|
||||||
error $ "could not find module " ++ show moduleName
|
Just (portName, (instanceE, modportE))
|
||||||
else
|
where instanceE = findInstance modportE
|
||||||
expandPortBinding' interfaceName portName ident
|
findInstance :: Expr -> Expr
|
||||||
modportDecls
|
findInstance e =
|
||||||
|
case lookupElem modports (Dot e "") of
|
||||||
|
Nothing -> case e of
|
||||||
|
Bit e' _ -> findInstance e'
|
||||||
|
Dot e' _ -> findInstance e'
|
||||||
|
_ -> error "internal invariant violated"
|
||||||
|
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
|
||||||
|
a = lookupElem modports modportE
|
||||||
|
b = lookupElem modports (Dot modportE "")
|
||||||
|
Just (_, replacements, modportDecls) =
|
||||||
|
if a == Nothing then b else a
|
||||||
|
toPortBinding (_, x, e) = (x', e')
|
||||||
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
|
||||||
|
Nothing ->
|
||||||
|
if "_tmp_" `isPrefixOf` x
|
||||||
|
then Ident x
|
||||||
|
else Dot instanceE x
|
||||||
|
prefixExpr other = traverseSinglyNestedExprs prefixExpr other
|
||||||
|
|
||||||
lookupInterface :: Identifier -> Interface
|
-- association list of modport instances in the given module body
|
||||||
lookupInterface interfaceName =
|
extractModportInstances :: PartInfo -> ModportInstances
|
||||||
case Map.lookup interfaceName interfaces of
|
extractModportInstances partInfo =
|
||||||
Just res -> res
|
execWriter $ mapM (collectDeclsM collectDecl) (pItems partInfo)
|
||||||
Nothing -> error $ "could not find interface " ++ show interfaceName
|
|
||||||
|
|
||||||
lookupModport :: [ModuleItem] -> Identifier -> [ModportDecl]
|
|
||||||
lookupModport interfaceItems "" = impliedModport interfaceItems
|
|
||||||
lookupModport interfaceItems modportName =
|
|
||||||
case Map.lookup modportName modportMap of
|
|
||||||
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?"
|
||||||
execWriter . mapM (collectNestedModuleItemsM collectModportDecls)
|
|
||||||
where
|
|
||||||
collectModportDecls :: ModuleItem -> Writer [ModportDecl] ()
|
|
||||||
collectModportDecls (MIPackageItem (Decl (Variable d t x _ _))) =
|
|
||||||
tell [(d', x, t, Ident x)]
|
|
||||||
where d' = if d == Local then Inout else d
|
|
||||||
collectModportDecls _ = return ()
|
|
||||||
|
|
||||||
convertPort :: Identifier -> [Identifier]
|
|
||||||
convertPort ident =
|
|
||||||
case Map.lookup ident modports of
|
|
||||||
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
|
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
|
||||||
|
|
||||||
-- replaces accesses of interface or modport members with their corresponding
|
isInterface :: Identifier -> Bool
|
||||||
-- flattened (exploded) data declarations
|
isInterface partName =
|
||||||
flattenInstances :: Instances -> Modports -> ModuleItem -> ModuleItem
|
case Map.lookup partName parts of
|
||||||
flattenInstances instances modports =
|
Nothing -> False
|
||||||
\item -> evalState (rewriter item) Set.empty
|
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 ()
|
||||||
|
|
||||||
traverseModuleItemM :: ModuleItem -> State Idents ModuleItem
|
-- convert an interface-bound module instantiation or an interface instantiation
|
||||||
traverseModuleItemM =
|
-- into a series of equivalent inlined module items
|
||||||
traverseExprsM traverseExprM >=>
|
inlineInstance :: [ModportBinding] -> [(Expr, Expr)] -> [ModuleItem]
|
||||||
traverseLHSsM traverseLHSM
|
-> Identifier -> [ParamBinding] -> [PortBinding] -> [ModuleItem]
|
||||||
traverseStmtM :: Stmt -> State Idents Stmt
|
inlineInstance modportBindings modportSubstitutions items
|
||||||
traverseStmtM =
|
instanceName instanceParams instancePorts =
|
||||||
traverseStmtExprsM traverseExprM >=>
|
comment :
|
||||||
traverseStmtLHSsM traverseLHSM
|
map (MIPackageItem . Decl) parameterBinds ++
|
||||||
traverseDeclM :: Decl -> State Idents Decl
|
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"
|
||||||
|
|
||||||
|
comment = MIPackageItem $ Decl $ CommentDecl $
|
||||||
|
"expanded " ++ inlineKind ++ " instance: " ++ instanceName
|
||||||
|
portBindings = mapMaybe portBindingItem $
|
||||||
|
filter notSubstituted instancePorts
|
||||||
|
notSubstituted :: PortBinding -> Bool
|
||||||
|
notSubstituted (portName, _) =
|
||||||
|
lookup (portName) modportBindings == Nothing
|
||||||
|
|
||||||
|
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
|
||||||
|
traverseModuleItemM item =
|
||||||
|
traverseExprsM traverseExprM item >>=
|
||||||
|
traverseLHSsM traverseLHSM
|
||||||
|
|
||||||
convertExprM :: Expr -> State Idents Expr
|
traverseGenItemM :: GenItem -> Scoper Expr GenItem
|
||||||
convertExprM (orig @ (Dot (Ident x) y)) = do
|
traverseGenItemM = traverseGenItemExprsM traverseExprM
|
||||||
substituteNonLocal orig repl x
|
|
||||||
where repl = Ident (x ++ "_" ++ y)
|
|
||||||
convertExprM other = return other
|
|
||||||
|
|
||||||
convertLHSM :: LHS -> State Idents LHS
|
traverseStmtM :: Stmt -> Scoper Expr Stmt
|
||||||
convertLHSM (orig @ (LHSDot (LHSIdent x) y)) = do
|
traverseStmtM =
|
||||||
substituteNonLocal orig repl x
|
traverseStmtExprsM traverseExprM >=>
|
||||||
where repl = LHSIdent (x ++ "_" ++ y)
|
traverseStmtLHSsM traverseLHSM
|
||||||
convertLHSM other = return other
|
|
||||||
|
|
||||||
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
|
||||||
|
tagLHS scopes lhs =
|
||||||
|
if lookupElem scopes lhs /= Nothing
|
||||||
|
then LHSDot lhs "@"
|
||||||
|
else traverseSinglyNestedLHSs (tagLHS scopes) lhs
|
||||||
|
replaceLHS :: LHS -> LHS
|
||||||
|
replaceLHS (LHSDot lhs "@") = lhs
|
||||||
|
replaceLHS lhs =
|
||||||
|
case lookup lhs lhsReplacements of
|
||||||
|
Just lhs' -> lhs'
|
||||||
|
Nothing -> traverseSinglyNestedLHSs replaceLHS lhs
|
||||||
|
-- top-level expressions may be modports bound to other modports
|
||||||
|
traverseExprM :: Expr -> Scoper Expr Expr
|
||||||
|
traverseExprM expr = do
|
||||||
|
expr' <- embedScopes (tagExpr False) expr
|
||||||
|
return $ replaceExpr expr'
|
||||||
|
substituteExprM :: Expr -> Scoper Expr Expr
|
||||||
|
substituteExprM expr = do
|
||||||
|
expr' <- embedScopes (tagExpr True) expr
|
||||||
|
return $ replaceExpr expr'
|
||||||
|
tagExpr :: Bool -> Scopes Expr -> Expr -> Expr
|
||||||
|
tagExpr substitute scopes expr =
|
||||||
|
case lookupElem scopes expr of
|
||||||
|
Just (_, _, Nil) -> Dot expr "@"
|
||||||
|
Just ([_, _], replacements, expr') ->
|
||||||
|
if substitute && Map.null replacements
|
||||||
|
then Dot expr' "@"
|
||||||
|
else Dot expr "@"
|
||||||
|
Just (_, _, _) -> Dot expr "@"
|
||||||
|
Nothing ->
|
||||||
|
traverseSinglyNestedExprs (tagExpr substitute scopes) expr
|
||||||
|
replaceExpr :: Expr -> Expr
|
||||||
|
replaceExpr (Dot expr "@") = expr
|
||||||
|
replaceExpr (Ident x) =
|
||||||
|
case lookup x modportBindings of
|
||||||
|
Just (_, m) -> m
|
||||||
|
Nothing -> Ident x
|
||||||
|
replaceExpr expr =
|
||||||
|
replaceExpr' expr
|
||||||
|
replaceExpr' :: Expr -> Expr
|
||||||
|
replaceExpr' (Dot expr "@") = expr
|
||||||
|
replaceExpr' expr =
|
||||||
|
case lookup expr exprReplacements of
|
||||||
|
Just expr' -> expr'
|
||||||
|
Nothing -> traverseSinglyNestedExprs replaceExpr' expr
|
||||||
|
|
||||||
-- add a prefix to all standard identifiers in a module item
|
removeModportInstance :: ModuleItem -> ModuleItem
|
||||||
prefixModuleItems :: (Identifier -> Identifier) -> ModuleItem -> ModuleItem
|
removeModportInstance (MIPackageItem (Decl (Variable d t x a e))) =
|
||||||
prefixModuleItems prefix =
|
MIPackageItem $ Decl $
|
||||||
prefixOtherItem .
|
if lookup x modportBindings /= Nothing
|
||||||
traverseDecls prefixDecl .
|
then CommentDecl $ "removed modport instance " ++ x
|
||||||
traverseExprs (traverseNestedExprs prefixExpr) .
|
else Variable d t x a e
|
||||||
traverseLHSs (traverseNestedLHSs prefixLHS )
|
removeModportInstance other = other
|
||||||
where
|
|
||||||
prefixDecl :: Decl -> Decl
|
|
||||||
prefixDecl (Variable d t x a e) = Variable d t (prefix x) a e
|
|
||||||
prefixDecl (Param s t x e) = Param s t (prefix x) e
|
|
||||||
prefixDecl (ParamType s x mt) = ParamType s (prefix x) mt
|
|
||||||
prefixDecl (CommentDecl c) = CommentDecl c
|
|
||||||
prefixExpr :: Expr -> Expr
|
|
||||||
prefixExpr (Ident x) = Ident (prefix x)
|
|
||||||
prefixExpr other = other
|
|
||||||
prefixLHS :: LHS -> LHS
|
|
||||||
prefixLHS (LHSIdent x) = LHSIdent (prefix x)
|
|
||||||
prefixLHS other = other
|
|
||||||
prefixOtherItem :: ModuleItem -> ModuleItem
|
|
||||||
prefixOtherItem (MIPackageItem item) =
|
|
||||||
MIPackageItem $ prefixPackageItem prefix item
|
|
||||||
prefixOtherItem (Instance m params name rs ports) =
|
|
||||||
Instance m params (prefix name) rs ports
|
|
||||||
prefixOtherItem (Genvar x) = Genvar $ prefix x
|
|
||||||
prefixOtherItem other = other
|
|
||||||
|
|
||||||
-- add a prefix to all standard identifiers in a package item
|
|
||||||
prefixPackageItem :: (Identifier -> Identifier) -> PackageItem -> PackageItem
|
|
||||||
prefixPackageItem prefix (Function lifetime t x decls stmts) =
|
|
||||||
Function lifetime t x' decls stmts
|
|
||||||
where x' = prefix x
|
|
||||||
prefixPackageItem prefix (Task lifetime x decls stmts) =
|
|
||||||
Task lifetime x' decls stmts
|
|
||||||
where x' = prefix x
|
|
||||||
prefixPackageItem _ 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) =
|
||||||
IntegerVector TLogic Unspecified rs
|
IntegerVector TLogic Unspecified rs
|
||||||
_ -> t
|
_ -> t
|
||||||
removeDeclDir other = other
|
removeDeclDir other = other
|
||||||
removeModport :: ModuleItem -> ModuleItem
|
|
||||||
removeModport (Modport x _) =
|
|
||||||
MIPackageItem $ Decl $ CommentDecl $ "removed modport " ++ x
|
|
||||||
removeModport other = other
|
|
||||||
|
|
||||||
interfaceParamNames = map fst $ parameters items
|
paramTmp = "_tmp_" ++ (shortHash (items, instanceName)) ++ "_"
|
||||||
instanceParamMap = Map.mapKeys (prefix ++) $
|
|
||||||
Map.fromList $ resolveParams interfaceParamNames instanceParams
|
parameterBinds = map makeParameterBind instanceParams
|
||||||
|
makeParameterBind :: ParamBinding -> Decl
|
||||||
|
makeParameterBind (x, Left t) =
|
||||||
|
ParamType Localparam (paramTmp ++ x) (Just t)
|
||||||
|
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 =
|
||||||
|
zipWith resolveBinding bindings [0..]
|
||||||
where
|
where
|
||||||
prefix = instanceName ++ "_"
|
resolveBinding ("", e) idx =
|
||||||
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
|
|
||||||
resolveParam :: ParamBinding -> Int -> ParamBinding
|
|
||||||
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
|
||||||
, 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 =
|
||||||
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
|
||||||
|
|
||||||
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 =
|
||||||
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
|
||||||
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
|
||||||
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 =
|
||||||
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 }
|
||||||
: 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] }
|
||||||
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] }
|
||||||
|
|
||||||
-- 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 }
|
||||||
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] }
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,16 @@
|
||||||
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
|
||||||
|
|
||||||
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
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
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);
|
||||||
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;
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
module top;
|
||||||
|
impl impl();
|
||||||
|
endmodule
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
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
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
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
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
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
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
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
|
||||||
|
|
@ -1,18 +1,21 @@
|
||||||
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);
|
||||||
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);
|
||||||
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);
|
||||||
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);
|
||||||
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;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
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
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
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
|
||||||
|
|
@ -1,13 +1,23 @@
|
||||||
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);
|
||||||
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
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
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
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
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
|
||||||
|
|
@ -1,12 +1,16 @@
|
||||||
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;
|
||||||
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);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue