Commit 1311e449 by Zachary Snow

fix errant expr resolution flagging

- references to other instances are no longer flagged
- special handling for genvars to avoid flagging and modport scoping
- interface inlining visits expressions in declarations
- Scoper has interface for removing entries
parent 1e6fa7b8
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
module Convert.Interface (convert) where module Convert.Interface (convert) where
import Data.Maybe (isNothing, mapMaybe) import Data.Maybe (isJust, isNothing, mapMaybe)
import Control.Monad.Writer.Strict import Control.Monad.Writer.Strict
import qualified Data.Map.Strict as Map import qualified Data.Map.Strict as Map
...@@ -391,17 +391,26 @@ inlineInstance global ranges modportBindings items partName ...@@ -391,17 +391,26 @@ inlineInstance global ranges modportBindings items partName
Param _ _ x _ -> insertElem x () Param _ _ x _ -> insertElem x ()
ParamType _ x _ -> insertElem x () ParamType _ x _ -> insertElem x ()
CommentDecl{} -> return () CommentDecl{} -> return ()
return decl traverseDeclExprsM traverseExprM decl
traverseModuleItemM :: ModuleItem -> Scoper () ModuleItem traverseModuleItemM :: ModuleItem -> Scoper () ModuleItem
traverseModuleItemM (item @ Modport{}) = traverseModuleItemM item@Modport{} =
traverseExprsM (scopeExpr >=> traverseExprM) item traverseExprsM (scopeExpr >=> traverseExprM) item
traverseModuleItemM item@(Instance _ _ x _ _) =
insertElem x () >> traverseExprsM traverseExprM item
traverseModuleItemM item = traverseModuleItemM item =
traverseExprsM traverseExprM item >>= traverseExprsM traverseExprM item >>=
traverseLHSsM traverseLHSM traverseLHSsM traverseLHSM
traverseGenItemM :: GenItem -> Scoper () GenItem traverseGenItemM :: GenItem -> Scoper () GenItem
traverseGenItemM = traverseGenItemExprsM traverseExprM traverseGenItemM item@(GenFor (x, _) _ _ _) = do
-- don't want to be scoped in modports
insertElem x ()
item' <- traverseGenItemExprsM traverseExprM item
removeElem x
return item'
traverseGenItemM item =
traverseGenItemExprsM traverseExprM item
traverseStmtM :: Stmt -> Scoper () Stmt traverseStmtM :: Stmt -> Scoper () Stmt
traverseStmtM = traverseStmtM =
...@@ -497,14 +506,20 @@ inlineInstance global ranges modportBindings items partName ...@@ -497,14 +506,20 @@ inlineInstance global ranges modportBindings items partName
checkExprResolution :: Scopes () -> Expr -> a -> a checkExprResolution :: Scopes () -> Expr -> a -> a
checkExprResolution local expr = checkExprResolution local expr =
case (lookupElem local expr, lookupElem global expr) of if not (exprResolves local expr) && exprResolves global expr
(Nothing, Just (_, _, DeclVal)) -> then
error $ "inlining instance \"" ++ instanceName ++ "\" of " error $ "inlining instance \"" ++ instanceName ++ "\" of "
++ inlineKind ++ " \"" ++ partName ++ inlineKind ++ " \"" ++ partName
++ "\" would make expression \"" ++ show expr ++ "\" would make expression \"" ++ show expr
++ "\" used in \"" ++ instanceName ++ "\" used in \"" ++ instanceName
++ "\" resolvable when it wasn't previously" ++ "\" resolvable when it wasn't previously"
_ -> id else id
exprResolves :: Scopes a -> Expr -> Bool
exprResolves local (Ident x) =
isJust (lookupElem local x) || isLoopVar local x
exprResolves local expr =
isJust (lookupElem local expr)
-- unambiguous reference to the current instance -- unambiguous reference to the current instance
scopedInstanceRaw = accessesToExpr $ localAccesses global instanceName scopedInstanceRaw = accessesToExpr $ localAccesses global instanceName
......
...@@ -37,6 +37,7 @@ module Convert.Scoper ...@@ -37,6 +37,7 @@ module Convert.Scoper
, scopeExpr , scopeExpr
, scopeType , scopeType
, insertElem , insertElem
, removeElem
, injectItem , injectItem
, injectTopItem , injectTopItem
, injectDecl , injectDecl
...@@ -218,10 +219,16 @@ instance ScopePath [Access] where ...@@ -218,10 +219,16 @@ instance ScopePath [Access] where
where Ident y = iy where Ident y = iy
insertElem :: Monad m => ScopePath k => k -> a -> ScoperT a m () insertElem :: Monad m => ScopePath k => k -> a -> ScoperT a m ()
insertElem key element = do insertElem key = setElem key . Just
removeElem :: Monad m => ScopePath k => k -> ScoperT a m ()
removeElem key = setElem key Nothing
setElem :: Monad m => ScopePath k => k -> Maybe a -> ScoperT a m ()
setElem key maybeElement = do
s <- get s <- get
let mapping = sMapping s let mapping = sMapping s
let entry = Entry (Just element) "" Map.empty let entry = Entry maybeElement "" Map.empty
let mapping' = setScope (toTiers s key) entry mapping let mapping' = setScope (toTiers s key) entry mapping
put $ s { sMapping = mapping' } put $ s { sMapping = mapping' }
......
interface intf;
byte x;
endinterface
module mod(intf j);
intf i();
assign j.x = 1;
assign i.x = 2;
genvar z;
for (z = 0; z < 2; z++) begin : blk
wire [7:0] x = $bits(j.x) - 5 + z;
end
endmodule
module top;
byte z = 0;
intf i();
mod m(i);
`define DUMP(expr) $display(`"expr = %b`", expr);
initial begin
`DUMP(z)
`DUMP(i.x)
`DUMP(m.i.x)
`DUMP(m.blk[0].x)
`DUMP(m.blk[1].x)
end
endmodule
module top;
reg [7:0] z = 0;
`define DUMP(expr, val) $display(`"expr = %b`", val);
initial begin
`DUMP(z, z)
`DUMP(i.x, 8'd1)
`DUMP(m.i.x, 8'd2)
`DUMP(m.blk[0].x, 8'd3)
`DUMP(m.blk[1].x, 8'd4)
end
endmodule
// 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;
for (genvar x = 0; x < 2; 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