Commit 68fa8290 by Zachary Snow

interface instantiation checks for errant name resolution

parent a6ebc0e3
...@@ -64,28 +64,44 @@ convertDescription parts (Part attrs extern Module lifetime name ports items) = ...@@ -64,28 +64,44 @@ convertDescription parts (Part attrs extern Module lifetime name ports items) =
PackageItem $ Decl $ CommentDecl $ PackageItem $ Decl $ CommentDecl $
"removed module with interface ports: " ++ name "removed module with interface ports: " ++ name
where where
items' = evalScoper return traverseModuleItemM return return name items items' = evalScoper
traverseDeclM traverseModuleItemM return return name items
convertNested = convertNested =
scopeModuleItemT return traverseModuleItemM return return scopeModuleItemT traverseDeclM traverseModuleItemM return return
traverseDeclM :: Decl -> Scoper [ModportDecl] Decl
traverseDeclM decl = do
case decl of
Variable _ _ x _ _ -> insertElem x DeclVal
Param _ _ x _ -> insertElem x DeclVal
ParamType _ x _ -> insertElem x DeclVal
CommentDecl{} -> return ()
return decl
lookupIntfElem :: Scopes [ModportDecl] -> Expr -> LookupResult [ModportDecl]
lookupIntfElem modports expr =
case lookupElem modports expr of
Just (_, _, DeclVal) -> Nothing
other -> other
traverseModuleItemM :: ModuleItem -> Scoper [ModportDecl] ModuleItem traverseModuleItemM :: ModuleItem -> Scoper [ModportDecl] ModuleItem
traverseModuleItemM (Modport modportName modportDecls) = traverseModuleItemM (Modport modportName modportDecls) =
insertElem modportName modportDecls >> return (Generate []) insertElem modportName modportDecls >> return (Generate [])
traverseModuleItemM (instanceItem @ Instance{}) = traverseModuleItemM (instanceItem @ Instance{}) = do
modports <- embedScopes (\l () -> l) ()
if isNothing maybePartInfo then if isNothing maybePartInfo then
return instanceItem return instanceItem
else if partKind == Interface then else if partKind == Interface then
-- inline instantiation of an interface -- inline instantiation of an interface
convertNested $ Generate $ map GenModuleItem $ convertNested $ Generate $ map GenModuleItem $
inlineInstance rs [] inlineInstance modports rs []
partItems part instanceName paramBindings portBindings partItems part instanceName paramBindings portBindings
else if null modportInstances then else if null modportInstances then
return instanceItem return instanceItem
else do else do
-- inline instantiation of a module -- inline instantiation of a module
modportBindings <- let modportBindings = getModportBindings modports
embedScopes (\l () -> getModportBindings l) ()
if length modportInstances /= length modportBindings if length modportInstances /= length modportBindings
then then
error $ "instance " ++ instanceName ++ " of " ++ part error $ "instance " ++ instanceName ++ " of " ++ part
...@@ -93,7 +109,7 @@ convertDescription parts (Part attrs extern Module lifetime name ports items) = ...@@ -93,7 +109,7 @@ convertDescription parts (Part attrs extern Module lifetime name ports items) =
++ showKeys modportInstances ++ ", but only " ++ showKeys modportInstances ++ ", but only "
++ showKeys modportBindings ++ " are connected" ++ showKeys modportBindings ++ " are connected"
else convertNested $ Generate $ map GenModuleItem $ else convertNested $ Generate $ map GenModuleItem $
inlineInstance rs modportBindings partItems inlineInstance modports rs modportBindings partItems
part instanceName paramBindings portBindings part instanceName paramBindings portBindings
where where
Instance part paramBindings instanceName rs portBindings = Instance part paramBindings instanceName rs portBindings =
...@@ -114,12 +130,12 @@ convertDescription parts (Part attrs extern Module lifetime name ports items) = ...@@ -114,12 +130,12 @@ convertDescription parts (Part attrs extern Module lifetime name ports items) =
-- add explicit slices for bindings of entire modport instance arrays -- add explicit slices for bindings of entire modport instance arrays
addImpliedSlice :: Scopes [ModportDecl] -> Expr -> Expr addImpliedSlice :: Scopes [ModportDecl] -> Expr -> Expr
addImpliedSlice modports (orig @ (Dot expr modportName)) = addImpliedSlice modports (orig @ (Dot expr modportName)) =
case lookupElem modports (InstArrKey expr) of case lookupIntfElem modports (InstArrKey expr) of
Just (_, _, InstArrVal l r) -> Just (_, _, InstArrVal l r) ->
Dot (Range expr NonIndexed (l, r)) modportName Dot (Range expr NonIndexed (l, r)) modportName
_ -> orig _ -> orig
addImpliedSlice modports expr = addImpliedSlice modports expr =
case lookupElem modports (InstArrKey expr) of case lookupIntfElem modports (InstArrKey expr) of
Just (_, _, InstArrVal l r) -> Just (_, _, InstArrVal l r) ->
Range expr NonIndexed (l, r) Range expr NonIndexed (l, r)
_ -> expr _ -> expr
...@@ -184,8 +200,8 @@ convertDescription parts (Part attrs extern Module lifetime name ports items) = ...@@ -184,8 +200,8 @@ convertDescription parts (Part attrs extern Module lifetime name ports items) =
else else
Nothing Nothing
where where
bindingIsModport = lookupElem modports expr /= Nothing bindingIsModport = lookupIntfElem modports expr /= Nothing
bindingIsBundle = lookupElem modports (Dot expr "") /= Nothing bindingIsBundle = lookupIntfElem modports (Dot expr "") /= Nothing
portIsBundle = null modportName portIsBundle = null modportName
modportName = case lookup portName modportInstances of modportName = case lookup portName modportInstances of
Just x -> x Just x -> x
...@@ -197,7 +213,7 @@ convertDescription parts (Part attrs extern Module lifetime name ports items) = ...@@ -197,7 +213,7 @@ convertDescription parts (Part attrs extern Module lifetime name ports items) =
findInstance :: Expr -> Expr findInstance :: Expr -> Expr
findInstance e = findInstance e =
case lookupElem modports (Dot e "") of case lookupIntfElem modports (Dot e "") of
Nothing -> case e of Nothing -> case e of
Bit e' _ -> findInstance e' Bit e' _ -> findInstance e'
Dot e' _ -> findInstance e' Dot e' _ -> findInstance e'
...@@ -205,11 +221,11 @@ convertDescription parts (Part attrs extern Module lifetime name ports items) = ...@@ -205,11 +221,11 @@ convertDescription parts (Part attrs extern Module lifetime name ports items) =
Just (accesses, _, _) -> accessesToExpr $ init accesses Just (accesses, _, _) -> accessesToExpr $ init accesses
qualifyModport :: Expr -> Expr qualifyModport :: Expr -> Expr
qualifyModport e = qualifyModport e =
case lookupElem modports e of case lookupIntfElem modports e of
Just (accesses, _, _) -> accessesToExpr accesses Just (accesses, _, _) -> accessesToExpr accesses
Nothing -> accessesToExpr $ init accesses Nothing -> accessesToExpr $ init accesses
where Just (accesses, _, _) = where Just (accesses, _, _) =
lookupElem modports (Dot e "") lookupIntfElem modports (Dot e "")
-- expand a modport binding into a series of expression substitutions -- expand a modport binding into a series of expression substitutions
genSubstitutions :: Scopes [ModportDecl] -> Expr -> Expr -> Expr genSubstitutions :: Scopes [ModportDecl] -> Expr -> Expr -> Expr
...@@ -218,8 +234,8 @@ convertDescription parts (Part attrs extern Module lifetime name ports items) = ...@@ -218,8 +234,8 @@ convertDescription parts (Part attrs extern Module lifetime name ports items) =
(baseE, instanceE) : (baseE, instanceE) :
map toPortBinding modportDecls map toPortBinding modportDecls
where where
a = lookupElem modports modportE a = lookupIntfElem modports modportE
b = lookupElem modports (Dot modportE "") b = lookupIntfElem modports (Dot modportE "")
Just (_, replacements, modportDecls) = Just (_, replacements, modportDecls) =
if a == Nothing then b else a if a == Nothing then b else a
toPortBinding (_, x, e) = (x', e') toPortBinding (_, x, e) = (x', e')
...@@ -287,9 +303,10 @@ impliedModport = ...@@ -287,9 +303,10 @@ impliedModport =
-- convert an interface-bound module instantiation or an interface instantiation -- convert an interface-bound module instantiation or an interface instantiation
-- into a series of equivalent inlined module items -- into a series of equivalent inlined module items
inlineInstance :: [Range] -> [ModportBinding] -> [ModuleItem] -> Identifier inlineInstance :: Scopes [ModportDecl] -> [Range] -> [ModportBinding]
-> Identifier -> [ParamBinding] -> [PortBinding] -> [ModuleItem] -> [ModuleItem] -> Identifier -> Identifier -> [ParamBinding]
inlineInstance ranges modportBindings items partName -> [PortBinding] -> [ModuleItem]
inlineInstance global ranges modportBindings items partName
instanceName instanceParams instancePorts = instanceName instanceParams instancePorts =
comment : comment :
map (MIPackageItem . Decl) bindingBaseParams ++ map (MIPackageItem . Decl) bindingBaseParams ++
...@@ -301,7 +318,7 @@ inlineInstance ranges modportBindings items partName ...@@ -301,7 +318,7 @@ inlineInstance ranges modportBindings items partName
traverseDeclM traverseModuleItemM traverseGenItemM traverseStmtM "" traverseDeclM traverseModuleItemM traverseGenItemM traverseStmtM ""
$ map (traverseNestedModuleItems rewriteItem) $ $ map (traverseNestedModuleItems rewriteItem) $
if null modportBindings if null modportBindings
then dimensionModport : bundleModport : items then items ++ [dimensionModport, bundleModport]
else items else items
key = shortHash (partName, instanceName) key = shortHash (partName, instanceName)
...@@ -362,36 +379,37 @@ inlineInstance ranges modportBindings items partName ...@@ -362,36 +379,37 @@ inlineInstance ranges modportBindings items partName
exprReplacements = filter ((/= Nil) . snd) modportSubstitutions exprReplacements = filter ((/= Nil) . snd) modportSubstitutions
-- LHSs are replaced using simple substitutions -- LHSs are replaced using simple substitutions
traverseLHSM :: LHS -> Scoper Expr LHS traverseLHSM :: LHS -> Scoper Expr LHS
traverseLHSM lhs = do traverseLHSM =
lhs' <- embedScopes tagLHS lhs embedScopes tagLHS >=>
return $ replaceLHS lhs' embedScopes replaceLHS
tagLHS :: Scopes Expr -> LHS -> LHS tagLHS :: Scopes Expr -> LHS -> LHS
tagLHS scopes lhs = tagLHS scopes lhs =
if lookupElem scopes lhs /= Nothing if lookupElem scopes lhs /= Nothing
then LHSDot lhs "@" then LHSDot lhs "@"
else traverseSinglyNestedLHSs (tagLHS scopes) lhs else traverseSinglyNestedLHSs (tagLHS scopes) lhs
replaceLHS :: LHS -> LHS replaceLHS :: Scopes Expr -> LHS -> LHS
replaceLHS (LHSDot lhs "@") = lhs replaceLHS _ (LHSDot lhs "@") = lhs
replaceLHS (LHSDot (LHSBit lhs elt) field) = replaceLHS local (LHSDot (LHSBit lhs elt) field) =
case lookup (LHSDot (LHSBit lhs Tag) field) lhsReplacements of case lookup (LHSDot (LHSBit lhs Tag) field) lhsReplacements of
Just resolved -> replaceLHSArrTag elt resolved Just resolved -> replaceLHSArrTag elt resolved
Nothing -> LHSDot (replaceLHS $ LHSBit lhs elt) field Nothing -> LHSDot (replaceLHS local $ LHSBit lhs elt) field
replaceLHS lhs = replaceLHS local lhs =
case lookup lhs lhsReplacements of case lookup lhs lhsReplacements of
Just lhs' -> lhs' Just lhs' -> lhs'
Nothing -> traverseSinglyNestedLHSs replaceLHS lhs Nothing -> checkExprResolution local (lhsToExpr lhs) $
traverseSinglyNestedLHSs (replaceLHS local) lhs
replaceLHSArrTag :: Expr -> LHS -> LHS replaceLHSArrTag :: Expr -> LHS -> LHS
replaceLHSArrTag = replaceLHSArrTag =
traverseNestedLHSs . (traverseLHSExprs . replaceArrTag) traverseNestedLHSs . (traverseLHSExprs . replaceArrTag)
-- top-level expressions may be modports bound to other modports -- top-level expressions may be modports bound to other modports
traverseExprM :: Expr -> Scoper Expr Expr traverseExprM :: Expr -> Scoper Expr Expr
traverseExprM expr = do traverseExprM =
expr' <- embedScopes (tagExpr False) expr embedScopes (tagExpr False) >=>
return $ replaceExpr expr' embedScopes replaceExpr
substituteExprM :: Expr -> Scoper Expr Expr substituteExprM :: Expr -> Scoper Expr Expr
substituteExprM expr = do substituteExprM =
expr' <- embedScopes (tagExpr True) expr embedScopes (tagExpr True) >=>
return $ replaceExpr expr' embedScopes replaceExpr
tagExpr :: Bool -> Scopes Expr -> Expr -> Expr tagExpr :: Bool -> Scopes Expr -> Expr -> Expr
tagExpr substitute scopes expr = tagExpr substitute scopes expr =
case lookupElem scopes expr of case lookupElem scopes expr of
...@@ -401,33 +419,45 @@ inlineInstance ranges modportBindings items partName ...@@ -401,33 +419,45 @@ inlineInstance ranges modportBindings items partName
else Dot expr "@" else Dot expr "@"
Nothing -> Nothing ->
traverseSinglyNestedExprs (tagExpr substitute scopes) expr traverseSinglyNestedExprs (tagExpr substitute scopes) expr
replaceExpr :: Expr -> Expr replaceExpr :: Scopes Expr -> Expr -> Expr
replaceExpr (Dot expr "@") = expr replaceExpr _ (Dot expr "@") = expr
replaceExpr (Ident x) = replaceExpr local (Ident x) =
case lookup x modportBindings of case lookup x modportBindings of
Just (_, m) -> m Just (_, m) -> m
Nothing -> Ident x Nothing -> checkExprResolution local (Ident x) (Ident x)
replaceExpr expr = replaceExpr local expr =
replaceExpr' expr replaceExpr' local expr
replaceExpr' :: Expr -> Expr replaceExpr' :: Scopes Expr -> Expr -> Expr
replaceExpr' (Dot expr "@") = expr replaceExpr' _ (Dot expr "@") = expr
replaceExpr' (Dot (Bit expr elt) field) = replaceExpr' local (Dot (Bit expr elt) field) =
case lookup (Dot (Bit expr Tag) field) exprReplacements of case lookup (Dot (Bit expr Tag) field) exprReplacements of
Just resolved -> replaceArrTag (replaceExpr' elt) resolved Just resolved -> replaceArrTag (replaceExpr' local elt) resolved
Nothing -> Dot (replaceExpr' $ Bit expr elt) field Nothing -> Dot (replaceExpr' local $ Bit expr elt) field
replaceExpr' (Bit expr elt) = replaceExpr' local (Bit expr elt) =
case lookup (Bit expr Tag) exprReplacements of case lookup (Bit expr Tag) exprReplacements of
Just resolved -> replaceArrTag (replaceExpr' elt) resolved Just resolved -> replaceArrTag (replaceExpr' local elt) resolved
Nothing -> Bit (replaceExpr' expr) (replaceExpr' elt) Nothing -> Bit (replaceExpr' local expr) (replaceExpr' local elt)
replaceExpr' expr = replaceExpr' local expr =
case lookup expr exprReplacements of case lookup expr exprReplacements of
Just expr' -> expr' Just expr' -> expr'
Nothing -> traverseSinglyNestedExprs replaceExpr' expr Nothing -> checkExprResolution local expr $
traverseSinglyNestedExprs (replaceExpr' local) expr
replaceArrTag :: Expr -> Expr -> Expr replaceArrTag :: Expr -> Expr -> Expr
replaceArrTag replacement Tag = replacement replaceArrTag replacement Tag = replacement
replaceArrTag replacement expr = replaceArrTag replacement expr =
traverseSinglyNestedExprs (replaceArrTag replacement) expr traverseSinglyNestedExprs (replaceArrTag replacement) expr
checkExprResolution :: Scopes Expr -> Expr -> a -> a
checkExprResolution local expr =
case (lookupElem local expr, lookupElem global expr) of
(Nothing, Just (_, _, DeclVal)) ->
error $ "inlining instance \"" ++ instanceName ++ "\" of "
++ inlineKind ++ " \"" ++ partName
++ "\" would make expression \"" ++ show expr
++ "\" used in \"" ++ instanceName
++ "\" resolvable when it wasn't previously"
_ -> id
removeModportInstance :: ModuleItem -> ModuleItem removeModportInstance :: ModuleItem -> ModuleItem
removeModportInstance (MIPackageItem (Decl (Variable d t x a e))) = removeModportInstance (MIPackageItem (Decl (Variable d t x a e))) =
MIPackageItem $ Decl $ MIPackageItem $ Decl $
...@@ -579,6 +609,10 @@ pattern InstArrKey expr = Dot (Bit expr (RawNum 0)) InstArrName ...@@ -579,6 +609,10 @@ pattern InstArrKey expr = Dot (Bit expr (RawNum 0)) InstArrName
pattern InstArrEncoded :: Expr -> Expr -> ModuleItem pattern InstArrEncoded :: Expr -> Expr -> ModuleItem
pattern InstArrEncoded l r = Modport InstArrName (InstArrVal l r) pattern InstArrEncoded l r = Modport InstArrName (InstArrVal l r)
-- encoding for normal declarations in the current module
pattern DeclVal :: [ModportDecl]
pattern DeclVal = [(Local, "~decl~", Nil)]
-- determines the lower bound for the given slice -- determines the lower bound for the given slice
sliceLo :: PartSelectMode -> Range -> Expr sliceLo :: PartSelectMode -> Range -> Expr
sliceLo NonIndexed (l, r) = endianCondExpr (l, r) r l sliceLo NonIndexed (l, r) = endianCondExpr (l, r) r l
......
...@@ -54,6 +54,7 @@ module Convert.Scoper ...@@ -54,6 +54,7 @@ module Convert.Scoper
, lookupLocalIdentM , lookupLocalIdentM
, scopeModuleItemT , scopeModuleItemT
, Replacements , Replacements
, LookupResult
) where ) where
import Control.Monad.State.Strict import Control.Monad.State.Strict
......
// pattern: inlining instance "intf" of interface "Interface" would make expression "x" used in "intf" resolvable when it wasn't previously
interface Interface;
assign x = 1;
endinterface
module top;
wire x;
Interface intf();
endmodule
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