From 8cfd05de1a821cc91986643b48249e637882b81f Mon Sep 17 00:00:00 2001 From: Zachary Snow Date: Sun, 14 Jun 2020 21:43:32 -0400 Subject: [PATCH] unbased unsized literals are context-aware --- src/Convert/TypeOf.hs | 1 + src/Convert/UnbasedUnsized.hs | 73 +++++++++++++++++++++++------------ test/basic/typeof.sv | 2 + test/basic/typeof.v | 3 ++ test/basic/unbased_unsized.sv | 25 +++++++++++- test/basic/unbased_unsized.v | 25 +++++++++++- 6 files changed, 103 insertions(+), 26 deletions(-) diff --git a/src/Convert/TypeOf.hs b/src/Convert/TypeOf.hs index f3c0f21..5c00724 100644 --- a/src/Convert/TypeOf.hs +++ b/src/Convert/TypeOf.hs @@ -106,6 +106,7 @@ typeof (orig @ (Cast (Right (Ident x)) _)) = do then return $ typeOfSize (Ident x) else return $ TypeOf orig typeof (Cast (Right s) _) = return $ typeOfSize s +typeof (UniOp UniSub e ) = typeof e typeof (UniOp BitNot e ) = typeof e typeof (BinOp Pow e _) = typeof e typeof (BinOp ShiftL e _) = typeof e diff --git a/src/Convert/UnbasedUnsized.hs b/src/Convert/UnbasedUnsized.hs index 739cbd6..1f787b0 100644 --- a/src/Convert/UnbasedUnsized.hs +++ b/src/Convert/UnbasedUnsized.hs @@ -3,13 +3,10 @@ - - Conversion for unbased, unsized literals ('0, '1, 'z, 'x) - - - The literals are given a binary base, a size of 1, and are made signed to - - allow sign extension. This enables the desired implicit casting in - - Verilog-2005. - - - - However, in a ternary expressions, these literals should take on the sign and - - size of their counterpart. To work around this, we explicitly size cast these - - literlas when they appear within a ternary expression. + - The literals are given a binary base and are made signed to allow sign + - extension. This enables the desired implicit casting in Verilog-2005. + - However, in self-determined contextes, the literals are given an explicit + - size of 1. -} module Convert.UnbasedUnsized (convert) where @@ -18,32 +15,60 @@ import Convert.Traverse import Language.SystemVerilog.AST convert :: [AST] -> [AST] -convert = - map $ - traverseDescriptions $ traverseModuleItems $ - traverseExprs $ traverseNestedExprs convertExpr +convert = map $ traverseDescriptions $ traverseModuleItems convertModuleItem + +convertModuleItem :: ModuleItem -> ModuleItem +convertModuleItem = + traverseExprs (traverseNestedExprs convertExpr) . + traverseStmts (traverseNestedStmts convertStmt) . + traverseTypes (traverseNestedTypes convertType) digits :: [Char] digits = ['0', '1', 'x', 'z', 'X', 'Z'] -literalFor :: Char -> Expr -literalFor ch = +literalFor :: String -> Char -> Expr +literalFor prefix ch = if elem ch digits - then Number ("1'sb" ++ [ch]) + then Number (prefix ++ [ch]) else error $ "unexpected unbased-unsized digit: " ++ [ch] +sizedLiteralFor :: Char -> Expr +sizedLiteralFor = literalFor "1'sb" + +unsizedLiteralFor :: Char -> Expr +unsizedLiteralFor '1' = UniOp UniSub $ Number "'sd1" +unsizedLiteralFor ch = literalFor "'sd" ch + convertExpr :: Expr -> Expr -convertExpr (Mux cond left right) = - Mux cond (convertExprCast left right) (convertExprCast right left) +convertExpr (DimsFn fn (Right e)) = + DimsFn fn $ Right $ convertSizeExpr e +convertExpr (Concat exprs) = + Concat $ map convertSelfDeterminedExpr exprs +convertExpr (Repeat count exprs) = + Repeat count $ map convertSelfDeterminedExpr exprs convertExpr (Number ['\'', ch]) = - literalFor ch + unsizedLiteralFor ch convertExpr other = other -convertExprCast :: Expr -> Expr -> Expr -convertExprCast (Number ['\'', ch]) other = - Cast (Right size) (literalFor ch) +convertSelfDeterminedExpr :: Expr -> Expr +convertSelfDeterminedExpr (Number ['\'', ch]) = + sizedLiteralFor ch +convertSelfDeterminedExpr other = other + +convertStmt :: Stmt -> Stmt +convertStmt (Subroutine (fn @ (Ident ('$' : _))) (Args args [])) = + Subroutine fn (Args args' []) + where args' = map convertSelfDeterminedExpr args +convertStmt other = other + +convertType :: Type -> Type +convertType (TypeOf e) = TypeOf $ convertSizeExpr e +convertType other = other + +convertSizeExpr :: Expr -> Expr +convertSizeExpr (Mux cond e1 e2) = + Mux cond e1' e2' where - size = case other of - Number ['\'', _] -> Number "32" - _ -> DimsFn FnBits $ Right other -convertExprCast other _ = other + e1' = convertSelfDeterminedExpr e1 + e2' = convertSelfDeterminedExpr e2 +convertSizeExpr e = convertSelfDeterminedExpr e diff --git a/test/basic/typeof.sv b/test/basic/typeof.sv index a39bbd4..288cb03 100644 --- a/test/basic/typeof.sv +++ b/test/basic/typeof.sv @@ -42,9 +42,11 @@ module top; parameter W = 4; initial begin + type('1) w = '1; logic [W-1:0] x = 4'hA; type(FLAG ? x : '1) y = FLAG ? x : '1; type(!FLAG ? y : '1) z = !FLAG ? y : '1; + $display("%b %d %d", w, $left(w), $right(w)); $display("%b %d %d", x, $left(x), $right(x)); $display("%b %d %d", y, $left(y), $right(y)); $display("%b %d %d", z, $left(z), $right(z)); diff --git a/test/basic/typeof.v b/test/basic/typeof.v index fe687d7..4780475 100644 --- a/test/basic/typeof.v +++ b/test/basic/typeof.v @@ -51,10 +51,13 @@ module top; parameter W = 4; initial begin : block3 + reg w; reg [W-1:0] x, y, z; + w = 1; x = 4'hA; y = FLAG ? x : 4'hF; z = !FLAG ? y : 4'hF; + $display("%b %d %d", w, 0, 0); $display("%b %d %d", x, W-1, 0); $display("%b %d %d", y, W-1, 0); $display("%b %d %d", z, W-1, 0); diff --git a/test/basic/unbased_unsized.sv b/test/basic/unbased_unsized.sv index cdd908e..0956609 100644 --- a/test/basic/unbased_unsized.sv +++ b/test/basic/unbased_unsized.sv @@ -1,6 +1,9 @@ `define TEST(value) \ logic [63:0] val_``value = 'value; \ - initial $display(`"'value -> %b %b", val_``value, 'value); + initial $display(`"'value -> %b (%0d) %b (%0d)", \ + val_``value, $bits(val_``value), \ + 'value, $bits('value) \ + ); module top; `TEST(1); @@ -13,14 +16,34 @@ module top; logic [31:0] a; logic [31:0] b; logic [31:0] c; + logic [63:0] j; + logic [63:0] d; + logic [63:0] e; initial begin i = 42; + j = 42; flag = 1; a = (flag ? '1 : i); b = (flag ? 'x : i); c = (flag ? '1 : '0); + d = (flag ? '1 : j); + e = (flag ? 'x : j); $display("%b", a); $display("%b", b); $display("%b", c); + $display("%b", d); + $display("%b", e); + end + + initial begin + $display("%b", {'1, 'x, 'z, '0}); + $display("%b", {2 {'1, 'x, 'z, '0}}); + end + + initial begin + $display($bits('1)); + $display($bits(flag ? '1 : 'x)); + $display($bits(type('1))); + $display($bits(type(flag ? '1 : 'x))); end endmodule diff --git a/test/basic/unbased_unsized.v b/test/basic/unbased_unsized.v index d03d9f2..a0ecd13 100644 --- a/test/basic/unbased_unsized.v +++ b/test/basic/unbased_unsized.v @@ -1,6 +1,9 @@ `define TEST(value) \ wire [63:0] val_``value = {64{1'b``value}}; \ - initial $display(`"'value -> %b %b", val_``value, 1'b``value); + initial $display(`"'value -> %b (%0d) %b (%0d)", \ + val_``value, $bits(val_``value), \ + 1'b``value, $bits(1'b``value) \ + ); module top; `TEST(1) @@ -13,14 +16,34 @@ module top; reg [31:0] a; reg [31:0] b; reg [31:0] c; + reg [63:0] j; + reg [63:0] d; + reg [63:0] e; initial begin i = 42; + j = 42; flag = 1; a = (flag ? 32'hFFFFFFFF : i); b = (flag ? 32'hXXXXXXXX : i); c = (flag ? 32'hFFFFFFFF: i); + d = (flag ? 64'hFFFFFFFFFFFFFFFF : j); + e = (flag ? 64'hXXXXXXXXXXXXXXXX : j); $display("%b", a); $display("%b", b); $display("%b", c); + $display("%b", d); + $display("%b", e); + end + + initial begin + $display("%b", 4'b1xz0); + $display("%b", {4'b1xz0, 4'b1xz0}); + end + + initial begin + $display(1); + $display(1); + $display(1); + $display(1); end endmodule