From 6788ecbf82a50608fbdab8527b998f7fc1544392 Mon Sep 17 00:00:00 2001 From: Zachary Snow Date: Sat, 18 Sep 2021 21:01:28 -0400 Subject: [PATCH] fix interface traversal of exprs in types, and support module-scoped modport refs --- CHANGELOG.md | 2 ++ src/Convert/Interface.hs | 43 +++++++++++++++++++++++++---------- test/core/interface_typeof.sv | 20 ++++++++++++++++ test/core/interface_typeof.v | 16 +++++++++++++ 4 files changed, 69 insertions(+), 12 deletions(-) create mode 100644 test/core/interface_typeof.sv create mode 100644 test/core/interface_typeof.v diff --git a/CHANGELOG.md b/CHANGELOG.md index bc46ff6..58c31e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,8 @@ separate from the corresponding net or variable declaration * Fix preprocessing of line comments which are neither preceded nor followed by whitespace except for the newline which terminates the comment +* Fix conversion of references to modports nested within types in expressions +* Fix conversion of module-scoped references to modports ## v0.0.8 diff --git a/src/Convert/Interface.hs b/src/Convert/Interface.hs index 57c2055..b8c73b7 100644 --- a/src/Convert/Interface.hs +++ b/src/Convert/Interface.hs @@ -425,10 +425,13 @@ inlineInstance global ranges modportBindings items partName embedScopes tagLHS >=> embedScopes replaceLHS tagLHS :: Scopes () -> LHS -> LHS - tagLHS scopes lhs = - if lookupElem scopes lhs /= Nothing - then LHSDot (renamePartLHS lhs) "@" - else traverseSinglyNestedLHSs (tagLHS scopes) lhs + tagLHS scopes lhs + | lookupElem scopes lhs /= Nothing = + LHSDot (renamePartLHS lhs) "@" + | Just portName <- partScopedModportRef $ lhsToExpr lhs = + LHSIdent portName + | otherwise = + traverseSinglyNestedLHSs (tagLHS scopes) lhs renamePartLHS :: LHS -> LHS renamePartLHS (LHSDot (LHSIdent x) y) = if x == partName @@ -455,16 +458,19 @@ inlineInstance global ranges modportBindings items partName embedScopes tagExpr >=> embedScopes replaceExpr tagExpr :: Scopes () -> Expr -> Expr - tagExpr scopes expr = - if lookupElem scopes expr /= Nothing - then Dot (renamePartExpr expr) "@" - else traverseSinglyNestedExprs (tagExpr scopes) expr + tagExpr scopes expr + | lookupElem scopes expr /= Nothing = + Dot (renamePartExpr expr) "@" + | Just portName <- partScopedModportRef expr = + Ident portName + | otherwise = + visitExprsStep (tagExpr scopes) expr renamePartExpr :: Expr -> Expr renamePartExpr (Dot (Ident x) y) = if x == partName then Dot scopedInstanceExpr y else Dot (Ident x) y - renamePartExpr expr = traverseSinglyNestedExprs renamePartExpr expr + renamePartExpr expr = visitExprsStep renamePartExpr expr replaceExpr :: Scopes () -> Expr -> Expr replaceExpr _ (Dot expr "@") = expr replaceExpr local (Ident x) = @@ -487,7 +493,7 @@ inlineInstance global ranges modportBindings items partName case lookup expr exprReplacements of Just expr' -> expr' Nothing -> checkExprResolution local expr $ - traverseSinglyNestedExprs (replaceExprAny local) expr + visitExprsStep (replaceExprAny local) expr replaceExpr' local (Ident x) = checkExprResolution local (Ident x) (Ident x) replaceExpr' local expr = replaceExprAny local expr @@ -496,11 +502,24 @@ inlineInstance global ranges modportBindings items partName case lookup expr exprReplacements of Just expr' -> expr' Nothing -> checkExprResolution local expr $ - traverseSinglyNestedExprs (replaceExpr' local) expr + visitExprsStep (replaceExpr' local) expr replaceArrTag :: Expr -> Expr -> Expr replaceArrTag replacement Tag = replacement replaceArrTag replacement expr = - traverseSinglyNestedExprs (replaceArrTag replacement) expr + visitExprsStep (replaceArrTag replacement) expr + + partScopedModportRef :: Expr -> Maybe Identifier + partScopedModportRef (Dot (Ident x) y) = + if x == partName && lookup y modportBindings /= Nothing + then Just y + else Nothing + partScopedModportRef _ = Nothing + + visitExprsStep :: (Expr -> Expr) -> Expr -> Expr + visitExprsStep exprMapper = + traverseSinglyNestedExprs exprMapper + . traverseExprTypes (traverseNestedTypes typeMapper) + where typeMapper = traverseTypeExprs exprMapper checkExprResolution :: Scopes () -> Expr -> a -> a checkExprResolution local expr = diff --git a/test/core/interface_typeof.sv b/test/core/interface_typeof.sv new file mode 100644 index 0000000..85960b2 --- /dev/null +++ b/test/core/interface_typeof.sv @@ -0,0 +1,20 @@ +interface intf; + logic [2:0] data; + modport m (output .data(data[0])); +endinterface +module mod(p); + parameter X = 0; + intf p; + initial begin + mod.p.data = 1; + $display("mod %0d A %b %0d", X, p.data, $bits(p.data)); + $display("mod %0d B %b %0d", X, mod.p.data, $bits(mod.p.data)); + $display("mod %0d C %b %0d", X, p.data, $bits(logic [$bits(p.data):1])); + $display("mod %0d D %b %0d", X, mod.p.data, $bits(logic [$bits(mod.p.data):1])); + end +endmodule +module top; + intf i(); + mod #(1) m1(i); + mod #(2) m2(i.m); +endmodule diff --git a/test/core/interface_typeof.v b/test/core/interface_typeof.v new file mode 100644 index 0000000..dae3578 --- /dev/null +++ b/test/core/interface_typeof.v @@ -0,0 +1,16 @@ +module mod(); + parameter X = 0; + parameter W = 0; + reg [W-1:0] data; + initial begin + data = 1; + $display("mod %0d A %b %0d", X, data, $bits(data)); + $display("mod %0d B %b %0d", X, mod.data, $bits(mod.data)); + $display("mod %0d C %b %0d", X, data, $bits(data)); + $display("mod %0d D %b %0d", X, mod.data, $bits(mod.data)); + end +endmodule +module top; + mod #(1, 3) m1(); + mod #(2, 1) m2(); +endmodule