Commit b2fe865e by Zachary Snow

fix interface modport substitution strategy

The interface conversion no longer substitutes parameters immediately,
instead fully scoping modports and allowing hierarchical constants to be
resolved separately. This fixes an issue where struct parameters could
lose their type information during substitution. The conversion also now
handles renaming references to the module or interface top-level scope.
parent 67c0d22a
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
module Convert.Interface (convert) where module Convert.Interface (convert) where
import Data.List (isPrefixOf)
import Data.Maybe (isNothing, mapMaybe) import Data.Maybe (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
...@@ -272,16 +271,7 @@ convertDescription parts (Part attrs extern Module lifetime name ports items) = ...@@ -272,16 +271,7 @@ convertDescription parts (Part attrs extern Module lifetime name ports items) =
toPortBinding (_, x, e) = (x', e') toPortBinding (_, x, e) = (x', e')
where where
x' = Dot baseE x x' = Dot baseE x
e' = prefixExpr e e' = replaceInExpr replacements e
prefixExpr :: Expr -> Expr
prefixExpr (Ident x) =
case Map.lookup x replacements of
Just replacement -> replacement
Nothing ->
if "_param_" `isPrefixOf` x
then Ident x
else Dot instanceE x
prefixExpr other = traverseSinglyNestedExprs prefixExpr other
-- association list of modport instances in the given module body -- association list of modport instances in the given module body
extractModportInstances :: PartInfo -> ModportInstances extractModportInstances :: PartInfo -> ModportInstances
...@@ -348,9 +338,9 @@ inlineInstance global ranges modportBindings items partName ...@@ -348,9 +338,9 @@ inlineInstance global ranges modportBindings items partName
wrapInstance instanceName items' wrapInstance instanceName items'
: portBindings : portBindings
where where
items' = evalScoper items' = evalScoper traverseDeclM traverseModuleItemM traverseGenItemM
traverseDeclM traverseModuleItemM traverseGenItemM traverseStmtM "" traverseStmtM partName $
$ map (traverseNestedModuleItems rewriteItem) $ map (traverseNestedModuleItems rewriteItem) $
if null modportBindings if null modportBindings
then items ++ [typeModport, dimensionModport, bundleModport] then items ++ [typeModport, dimensionModport, bundleModport]
else items else items
...@@ -393,28 +383,27 @@ inlineInstance global ranges modportBindings items partName ...@@ -393,28 +383,27 @@ inlineInstance global ranges modportBindings items partName
removeDeclDir . removeDeclDir .
overrideParam overrideParam
traverseDeclM :: Decl -> Scoper Expr Decl traverseDeclM :: Decl -> Scoper () Decl
traverseDeclM decl = do traverseDeclM decl = do
decl' <- traverseDeclExprsM substituteExprM decl case decl of
case decl' of Variable _ _ x _ _ -> insertElem x ()
Variable _ _ x _ _ -> insertElem x Nil Net _ _ _ _ x _ _ -> insertElem x ()
Net _ _ _ _ x _ _ -> insertElem x Nil Param _ _ x _ -> insertElem x ()
Param _ _ x e -> insertElem x e ParamType _ x _ -> insertElem x ()
ParamType _ x _ -> insertElem x Nil
CommentDecl{} -> return () CommentDecl{} -> return ()
return decl' return decl
traverseModuleItemM :: ModuleItem -> Scoper Expr ModuleItem traverseModuleItemM :: ModuleItem -> Scoper () ModuleItem
traverseModuleItemM (item @ Modport{}) = traverseModuleItemM (item @ Modport{}) =
traverseExprsM substituteExprM item traverseExprsM (scopeExpr >=> traverseExprM) item
traverseModuleItemM item = traverseModuleItemM item =
traverseExprsM traverseExprM item >>= traverseExprsM traverseExprM item >>=
traverseLHSsM traverseLHSM traverseLHSsM traverseLHSM
traverseGenItemM :: GenItem -> Scoper Expr GenItem traverseGenItemM :: GenItem -> Scoper () GenItem
traverseGenItemM = traverseGenItemExprsM traverseExprM traverseGenItemM = traverseGenItemExprsM traverseExprM
traverseStmtM :: Stmt -> Scoper Expr Stmt traverseStmtM :: Stmt -> Scoper () Stmt
traverseStmtM = traverseStmtM =
traverseStmtExprsM traverseExprM >=> traverseStmtExprsM traverseExprM >=>
traverseStmtLHSsM traverseLHSM traverseStmtLHSsM traverseLHSM
...@@ -424,16 +413,22 @@ inlineInstance global ranges modportBindings items partName ...@@ -424,16 +413,22 @@ inlineInstance global ranges modportBindings items partName
lhsReplacements = map (\(x, y) -> (toLHS x, toLHS y)) exprReplacements lhsReplacements = map (\(x, y) -> (toLHS x, toLHS y)) exprReplacements
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 () LHS
traverseLHSM = traverseLHSM =
embedScopes tagLHS >=> embedScopes tagLHS >=>
embedScopes replaceLHS embedScopes replaceLHS
tagLHS :: Scopes Expr -> LHS -> LHS tagLHS :: Scopes () -> LHS -> LHS
tagLHS scopes lhs = tagLHS scopes lhs =
if lookupElem scopes lhs /= Nothing if lookupElem scopes lhs /= Nothing
then LHSDot lhs "@" then LHSDot (renamePartLHS lhs) "@"
else traverseSinglyNestedLHSs (tagLHS scopes) lhs else traverseSinglyNestedLHSs (tagLHS scopes) lhs
replaceLHS :: Scopes Expr -> LHS -> LHS renamePartLHS :: LHS -> LHS
renamePartLHS (LHSDot (LHSIdent x) y) =
if x == partName
then LHSDot scopedInstanceLHS y
else LHSDot (LHSIdent x) y
renamePartLHS lhs = traverseSinglyNestedLHSs renamePartLHS lhs
replaceLHS :: Scopes () -> LHS -> LHS
replaceLHS _ (LHSDot lhs "@") = lhs replaceLHS _ (LHSDot lhs "@") = lhs
replaceLHS local (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
...@@ -448,24 +443,22 @@ inlineInstance global ranges modportBindings items partName ...@@ -448,24 +443,22 @@ inlineInstance global ranges modportBindings items partName
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
traverseExprM = traverseExprM =
embedScopes (tagExpr False) >=> embedScopes tagExpr >=>
embedScopes replaceExpr embedScopes replaceExpr
substituteExprM :: Expr -> Scoper Expr Expr tagExpr :: Scopes () -> Expr -> Expr
substituteExprM = tagExpr scopes expr =
embedScopes (tagExpr True) >=> if lookupElem scopes expr /= Nothing
embedScopes replaceExpr then Dot (renamePartExpr expr) "@"
tagExpr :: Bool -> Scopes Expr -> Expr -> Expr else traverseSinglyNestedExprs (tagExpr scopes) expr
tagExpr substitute scopes expr = renamePartExpr :: Expr -> Expr
case lookupElem scopes expr of renamePartExpr (Dot (Ident x) y) =
Just (_, _, expr') -> if x == partName
if substitute && expr' /= Nil then Dot scopedInstanceExpr y
then Dot expr' "@" else Dot (Ident x) y
else Dot expr "@" renamePartExpr expr = traverseSinglyNestedExprs renamePartExpr expr
Nothing -> replaceExpr :: Scopes () -> Expr -> Expr
traverseSinglyNestedExprs (tagExpr substitute scopes) expr
replaceExpr :: Scopes Expr -> Expr -> Expr
replaceExpr _ (Dot expr "@") = expr replaceExpr _ (Dot expr "@") = expr
replaceExpr local (Ident x) = replaceExpr local (Ident x) =
case lookup x modportBindings of case lookup x modportBindings of
...@@ -473,7 +466,7 @@ inlineInstance global ranges modportBindings items partName ...@@ -473,7 +466,7 @@ inlineInstance global ranges modportBindings items partName
Nothing -> checkExprResolution local (Ident x) (Ident x) Nothing -> checkExprResolution local (Ident x) (Ident x)
replaceExpr local expr = replaceExpr local expr =
replaceExpr' local expr replaceExpr' local expr
replaceExpr' :: Scopes Expr -> Expr -> Expr replaceExpr' :: Scopes () -> Expr -> Expr
replaceExpr' _ (Dot expr "@") = expr replaceExpr' _ (Dot expr "@") = expr
replaceExpr' local (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
...@@ -491,7 +484,7 @@ inlineInstance global ranges modportBindings items partName ...@@ -491,7 +484,7 @@ inlineInstance global ranges modportBindings items partName
replaceExpr' local (Ident x) = replaceExpr' local (Ident x) =
checkExprResolution local (Ident x) (Ident x) checkExprResolution local (Ident x) (Ident x)
replaceExpr' local expr = replaceExprAny local expr replaceExpr' local expr = replaceExprAny local expr
replaceExprAny :: Scopes Expr -> Expr -> Expr replaceExprAny :: Scopes () -> Expr -> Expr
replaceExprAny local expr = replaceExprAny local expr =
case lookup expr exprReplacements of case lookup expr exprReplacements of
Just expr' -> expr' Just expr' -> expr'
...@@ -502,7 +495,7 @@ inlineInstance global ranges modportBindings items partName ...@@ -502,7 +495,7 @@ inlineInstance global ranges modportBindings items partName
replaceArrTag replacement expr = replaceArrTag replacement expr =
traverseSinglyNestedExprs (replaceArrTag replacement) expr traverseSinglyNestedExprs (replaceArrTag replacement) expr
checkExprResolution :: Scopes Expr -> Expr -> a -> a checkExprResolution :: Scopes () -> Expr -> a -> a
checkExprResolution local expr = checkExprResolution local expr =
case (lookupElem local expr, lookupElem global expr) of case (lookupElem local expr, lookupElem global expr) of
(Nothing, Just (_, _, DeclVal)) -> (Nothing, Just (_, _, DeclVal)) ->
...@@ -513,6 +506,14 @@ inlineInstance global ranges modportBindings items partName ...@@ -513,6 +506,14 @@ inlineInstance global ranges modportBindings items partName
++ "\" resolvable when it wasn't previously" ++ "\" resolvable when it wasn't previously"
_ -> id _ -> id
-- unambiguous reference to the current instance
scopedInstanceRaw = accessesToExpr $ localAccesses global instanceName
scopedInstanceExpr =
if isArray
then Bit scopedInstanceRaw (Ident loopVar)
else scopedInstanceRaw
Just scopedInstanceLHS = exprToLHS scopedInstanceExpr
removeModportInstance :: Decl -> Decl removeModportInstance :: Decl -> Decl
removeModportInstance (Variable d t x a e) = removeModportInstance (Variable d t x a e) =
if maybeModportBinding == Nothing then if maybeModportBinding == Nothing then
......
typedef struct packed {
byte x;
shortint y;
} T;
interface intf;
parameter T P = 0;
wire [P.x-1:0] z = '1;
initial begin
$display("intf.P.x %0d", P.x);
$display("intf.P.y %0d", P.y);
end
if (P.x) begin : blk
wire [31:0] z;
end
wire [31:0] z = P.y;
if (P.x) begin : blk2
integer z;
assign intf.blk.z = intf.z;
end
modport X (
input .x(P),
input .y(intf.blk.z)
);
endinterface
module mod(
intf.X f
);
integer i;
initial begin
$display("mod.f.x %b", f.x);
$display("mod.f.y %b", f.y);
end
endmodule
module top;
localparam T Q = '{ x: 1, y: 2 };
localparam T R = '{ x: 4, y: 6 };
intf #(Q) i();
intf #(R) is [1:0] ();
mod m(i);
mod ms(is[0]);
endmodule
module top;
initial begin
$display("intf.P.x %0d", 1);
$display("intf.P.y %0d", 2);
$display("intf.P.x %0d", 4);
$display("intf.P.y %0d", 6);
$display("intf.P.x %0d", 4);
$display("intf.P.y %0d", 6);
$display("mod.f.x %b", {8'd1, 16'd2});
$display("mod.f.y %b", 32'h1);
$display("mod.f.x %b", {8'd4, 16'd6});
$display("mod.f.y %b", 32'hF);
end
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