Commit 336812ff by Zachary Snow

fix conversion of signed struct fields accessed directly

parent effeded6
...@@ -33,6 +33,8 @@ ...@@ -33,6 +33,8 @@
procedural assignment procedural assignment
* `always_comb` and `always_latch` now generate explicit sensitivity lists where * `always_comb` and `always_latch` now generate explicit sensitivity lists where
necessary because of calls to functions which reference non-local data 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 ## v0.0.9
......
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE TupleSections #-} {-# LANGUAGE TupleSections #-}
{- sv2v {- sv2v
- Author: Zachary Snow <zach@zachjs.com> - Author: Zachary Snow <zach@zachjs.com>
...@@ -363,12 +364,19 @@ fallbackType scopes e = ...@@ -363,12 +364,19 @@ fallbackType scopes e =
Nothing -> UnknownType Nothing -> UnknownType
Just (_, _, typ) -> typ Just (_, _, typ) -> typ
pattern MakeSigned :: Expr -> Expr
pattern MakeSigned e = Call (Ident "$signed") (Args [e] [])
-- converting LHSs by looking at the innermost types first -- converting LHSs by looking at the innermost types first
convertLHS :: LHS -> Scoper Type (Type, LHS) convertLHS :: LHS -> Scoper Type (Type, LHS)
convertLHS l = do convertLHS l = do
let e = lhsToExpr l let e = lhsToExpr l
(t, e') <- embedScopes convertSubExpr e (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') return (t, l')
-- try expression conversion by looking at the *innermost* type first -- try expression conversion by looking at the *innermost* type first
...@@ -379,7 +387,7 @@ convertSubExpr scopes (Dot e x) = ...@@ -379,7 +387,7 @@ convertSubExpr scopes (Dot e x) =
else if structIsntReady subExprType then else if structIsntReady subExprType then
(fieldType, Dot e' x) (fieldType, Dot e' x)
else else
(fieldType, undotted) (fieldType, undottedWithSign)
where where
(subExprType, e') = convertSubExpr scopes e (subExprType, e') = convertSubExpr scopes e
(fieldType, bounds, dims) = lookupFieldInfo scopes subExprType e' x (fieldType, bounds, dims) = lookupFieldInfo scopes subExprType e' x
...@@ -388,6 +396,14 @@ convertSubExpr scopes (Dot e x) = ...@@ -388,6 +396,14 @@ convertSubExpr scopes (Dot e x) =
undotted = if null dims || rangeSize (head dims) == RawNum 1 undotted = if null dims || rangeSize (head dims) == RawNum 1
then Bit e' (fst bounds) then Bit e' (fst bounds)
else Range e' IndexedMinus (base, len) 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) = convertSubExpr scopes (Range (Dot e x) NonIndexed rOuter) =
if isntStruct subExprType then if isntStruct subExprType then
(UnknownType, orig') (UnknownType, orig')
......
...@@ -5,8 +5,15 @@ module test; ...@@ -5,8 +5,15 @@ module test;
logic z; logic z;
} struct_a; } struct_a;
struct_a 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 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.w = 0;
#1 a.x = 0; #1 a.x = 0;
...@@ -41,9 +48,13 @@ module test; ...@@ -41,9 +48,13 @@ module test;
logic z; logic z;
} struct_b; } struct_b;
struct_b b; struct_b b;
wire signed [31:0] b_x;
assign b_x = b.x;
initial begin initial begin
#100; #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.x = 0;
#1 b.y = 0; #1 b.y = 0;
......
...@@ -206,4 +206,34 @@ module top; ...@@ -206,4 +206,34 @@ module top;
`ASSERT_UNSIGNED(STR_L) `ASSERT_UNSIGNED(STR_L)
`ASSERT_UNSIGNED(64'(STR_P)) `ASSERT_UNSIGNED(64'(STR_P))
`ASSERT_UNSIGNED(64'(STR_L)) `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 endmodule
...@@ -27,4 +27,9 @@ module top; ...@@ -27,4 +27,9 @@ module top;
`MAKE_PRIM(logic, 1) `MAKE_PRIM(logic, 1)
reg signed [5:0] arr; reg signed [5:0] arr;
reg signed [11:0] s;
initial s = 1'sb1;
reg [5:0] t;
initial t = 1'sb1;
endmodule 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