Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(#4402):missing sign while for loop iteration variable is signed #4416

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

YoYo-0513
Copy link

Reseaon
issue #4402

RCA:
Like the code blow, iteration variable forvar14 is signed. However, the iteration variable lost the signed information during the ast simplify. For example, the value of forvar14 should be $signed(3'h0) instead of 3'h0 in the first loop cycle.

reg signed [2:0] forvar14 = (1'h0);
for (forvar14 = (1'h0); (forvar14 < (1'h1)); forvar14 = (forvar14 + (1'h1)))  begin
      .......
end

Fixes:

  1. backends/verilog/verilog_backend.cc
    Signed should be writed while dump verilog;

  2. frontends/ast/genrtlil.cc
    Before this change, children[0] will use the children[1]'s width_hint and sign_hint when genRTLIL, because they use the same variables and children[1]'s will overide children[0]'s.

  3. frontends/ast/simplify.cc
    Record iteration variable is signed or not;

Test
A case was provided in #4402 , use PR branch to build a new yosys, read the 'rtl.v' and dump the verilog after synthesis. Then follow the reproduce steps in issue #4402 , result will meet expectations.

@YoYo-0513 YoYo-0513 requested a review from zachjs as a code owner May 26, 2024 08:53
Copy link
Collaborator

@zachjs zachjs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for submitting these 3 bug fixes! Do you think you could also include (perhaps 3 separate) test cases for these bug fixes?

  • See tests/verilog/const_arst.ys for an existing test that exercises write_verilog, then read_verilog, and confirms the two versions match (yours could likely be simpler for checking this particular bug).
  • There are plenty of existing examples testing Verilog expression semantics in tests/verilog/ and tests/various/, which could be applicable for your other two changes.

if (wire->width != 1) {
if (wire->upto)
range = stringf(" [%d:%d]", wire->start_offset, wire->width - 1 + wire->start_offset);
else
range = stringf(" [%d:%d]", wire->width - 1 + wire->start_offset, wire->start_offset);
}
if (wire->is_signed)
sign = " signed ";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the second space extra?

RTLIL::SigSpec left = children[0]->genRTLIL(width_hint, sign_hint);
children[1]->detectSignWidthWorker(width_hint, sign_hint);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit surprised at by this change. It seems like we probably need to account for the sign and width of both sides of the comparison before generating the RTLIL for either side. The existing code should produce the Verilog semantics we're looking for: the comparison is done on signed operands with both are signed, and using the maximum of the widths of each side. I'm sure I'm missing something here. Can you help me understand?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants