diff --git a/CHANGELOG.md b/CHANGELOG.md index 04919ad..10bf6b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,8 @@ procedural assignment * `always_comb` and `always_latch` now generate explicit sensitivity lists where necessary because of calls to functions which reference non-local data +* Fixed signed `struct` fields being converted to unsigned expressions when + accessed directly ## v0.0.9 diff --git a/src/Convert/Struct.hs b/src/Convert/Struct.hs index dd3a220..beaf196 100644 --- a/src/Convert/Struct.hs +++ b/src/Convert/Struct.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE TupleSections #-} {- sv2v - Author: Zachary Snow @@ -363,12 +364,19 @@ fallbackType scopes e = Nothing -> UnknownType Just (_, _, typ) -> typ +pattern MakeSigned :: Expr -> Expr +pattern MakeSigned e = Call (Ident "$signed") (Args [e] []) + -- converting LHSs by looking at the innermost types first convertLHS :: LHS -> Scoper Type (Type, LHS) convertLHS l = do let e = lhsToExpr l (t, e') <- embedScopes convertSubExpr e - let Just l' = exprToLHS e' + -- per IEEE 1800-2017 sections 10.7 and 11.8, the signedness of the LHS does + -- not affect the evaluation and sign-extension of the RHS + let Just l' = exprToLHS $ case e' of + MakeSigned e'' -> e'' + _ -> e' return (t, l') -- try expression conversion by looking at the *innermost* type first @@ -379,7 +387,7 @@ convertSubExpr scopes (Dot e x) = else if structIsntReady subExprType then (fieldType, Dot e' x) else - (fieldType, undotted) + (fieldType, undottedWithSign) where (subExprType, e') = convertSubExpr scopes e (fieldType, bounds, dims) = lookupFieldInfo scopes subExprType e' x @@ -388,6 +396,14 @@ convertSubExpr scopes (Dot e x) = undotted = if null dims || rangeSize (head dims) == RawNum 1 then Bit e' (fst bounds) else Range e' IndexedMinus (base, len) + -- retain signedness of fields which would otherwise be lost via the + -- resulting bit or range selection + IntegerVector _ fieldSg _ = fieldType + undottedWithSign = + if fieldSg == Signed + then MakeSigned undotted + else undotted + convertSubExpr scopes (Range (Dot e x) NonIndexed rOuter) = if isntStruct subExprType then (UnknownType, orig') diff --git a/test/core/pattern.sv b/test/core/pattern.sv index ae9d431..38ae06a 100644 --- a/test/core/pattern.sv +++ b/test/core/pattern.sv @@ -5,8 +5,15 @@ module test; logic z; } struct_a; struct_a a; + wire signed [31:0] a_w, a_x; + wire signed [7:0] a_y; + assign a_w = a.w; + assign a_x = a.x; + assign a_y = a.y; initial begin - $monitor("%2d: %b %b %b %b %b", $time, a, a.w, a.x, a.y, a.z); + // TODO: The signed fields should not have to be indirected here, but + // iverilog does not currently support complex arguments to $monitor. + $monitor("%2d: %b %b %b %b %b", $time, a, a_w, a_x, a_y, a.z); #1 a.w = 0; #1 a.x = 0; @@ -41,9 +48,13 @@ module test; logic z; } struct_b; struct_b b; + wire signed [31:0] b_x; + assign b_x = b.x; initial begin #100; - $monitor("%2d: %b %b %b %b", $time, b, b.x, b.y, b.z); + // TODO: The signed fields should not have to be indirected here, but + // iverilog does not currently support complex arguments to $monitor. + $monitor("%2d: %b %b %b %b", $time, b, b_x, b.y, b.z); #1 b.x = 0; #1 b.y = 0; diff --git a/test/core/typeof_signed.sv b/test/core/typeof_signed.sv index b031c89..17ecdea 100644 --- a/test/core/typeof_signed.sv +++ b/test/core/typeof_signed.sv @@ -206,4 +206,34 @@ module top; `ASSERT_UNSIGNED(STR_L) `ASSERT_UNSIGNED(64'(STR_P)) `ASSERT_UNSIGNED(64'(STR_L)) + + struct packed { + logic w; + logic signed x; + logic [1:0] y; + logic signed [1:0] z; + struct packed { + logic w; + logic signed x; + logic [1:0] y; + logic signed [1:0] z; + } i; + } s = '1; + struct packed signed { + logic w; + logic signed x; + logic [1:0] y; + logic signed [1:0] z; + } t = '1; + `ASSERT_UNSIGNED(s) + `ASSERT_UNSIGNED(s.w) + `ASSERT_UNSIGNED(s.y) + `ASSERT_SIGNED(s.x) + `ASSERT_SIGNED(s.z) + `ASSERT_UNSIGNED(s.i) + `ASSERT_UNSIGNED(s.i.w) + `ASSERT_UNSIGNED(s.i.y) + `ASSERT_SIGNED(s.i.x) + `ASSERT_SIGNED(s.i.z) + `ASSERT_SIGNED(t) endmodule diff --git a/test/core/typeof_signed.v b/test/core/typeof_signed.v index 1df0a7c..7521fc1 100644 --- a/test/core/typeof_signed.v +++ b/test/core/typeof_signed.v @@ -27,4 +27,9 @@ module top; `MAKE_PRIM(logic, 1) reg signed [5:0] arr; + + reg signed [11:0] s; + initial s = 1'sb1; + reg [5:0] t; + initial t = 1'sb1; endmodule