Commit 336812ff by Zachary Snow

fix conversion of signed struct fields accessed directly

parent effeded6
......@@ -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
......
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE TupleSections #-}
{- sv2v
- Author: Zachary Snow <zach@zachjs.com>
......@@ -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')
......
......@@ -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;
......
......@@ -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
......@@ -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
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