Skip to content

Concatenation LHS assignment loses signedness flag in constant evaluation #1705

@CheeksTheGeek

Description

@CheeksTheGeek

Is your bug report related to the C++ slang project or the pyslang Python bindings?
C++ slang

Describe the bug
when a packed concatenation is used as an LHS target in constant evaluation, the SVInt::slice() used to split the RHS value always produces unsigned results, which causes signed target variables to lose their sign flag, leading to incorrect zero-extension instead of sign-extension in subsequent operations.

To Reproduce

module test;
  function [7:0] f(input [7:0] value);
    reg signed [2:0] tmp1, tmp2;
    begin
      {tmp1, tmp2} = {value[2:0], value[6:4]};
      f[7:4] = tmp1;
      f[3:0] = tmp2;
    end
  endfunction

  localparam [7:0] res = f(8'h5a);
  // Expected: 8'h2d (tmp2=3'sb101 sign-extends to 4'b1101)
  // Actual:   8'h25 (tmp2=3'b101 zero-extends to 4'b0101)

  initial begin
    $display("%h", res); // prints 25, should print 2d
  end
endmodule

Additional context

LValue::store() in LValue.cpp splits the RHS via sv.slice(), which returns unsigned values and these are then stored directly into the target variables via elem.store(), overwriting the signed SVInt that was there, so when the variable is later loaded and extended to a wider width, resize() uses the (now incorrect) unsigned flag and zero-extends instead of sign-extending.
one should note that assigning the same variables individually (tmp2 = value[6:4]) works correctly because the normal assignment path goes through ConversionExpression which properly handles signedness.

Fix (can I make a PR if it makes sense? ✨ )

after slicing, set the sign flag to match the target variable's existing signedness before storing:

auto loaded = elem.load();
int32_t width = (int32_t)loaded.integer().getBitWidth();
auto sliced = sv.slice(msb, msb - width + 1);
sliced.setSigned(loaded.integer().isSigned());
elem.store(ConstantValue(std::move(sliced)));

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions