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

splitcells causes an assert failure #4909

Open
mattyoung101 opened this issue Feb 20, 2025 · 3 comments
Open

splitcells causes an assert failure #4909

mattyoung101 opened this issue Feb 20, 2025 · 3 comments
Labels

Comments

@mattyoung101
Copy link

Version

Yosys 0.50+7 (git sha1 9d3ab96, ccache clang++ 19.1.7 -Og -fPIC)

On which OS did this happen?

Linux

Reproduction Steps

The following Verilog sample, 3510.v, causes the splitcells command to fail with an assert failure.

module top  (y, clk, wire2, wire1, wire0);
  output wire [(32'hb):(32'h0)] y;
  input wire [(1'h0):(1'h0)] clk;
  input wire signed [(2'h3):(1'h0)] wire2;
  input wire [(2'h3):(1'h0)] wire1;
  input wire [(2'h2):(1'h0)] wire0;
  wire [(2'h2):(1'h0)] wire4;
  reg signed [(2'h2):(1'h0)] reg7 = (1'h0);
  reg [(2'h3):(1'h0)] reg6 = (1'h0);
  reg [(2'h3):(1'h0)] reg5 = (1'h0);
  assign y = {wire4, reg7, reg6, reg5, (1'h0)};
  assign wire4 = (wire0[(2'h2):(1'h0)] ^~ $unsigned(wire1));
  always
    @(posedge clk) begin
      reg5 <= $signed(wire4);
    end
  always
    @(posedge clk) begin
      reg6 <= wire2;
    end
  always
    @(posedge clk) begin
      reg7 <= ({reg5} ? (~|reg5) : reg5);
    end
endmodule

Please let me know if the above sample is too long, and I will have a go at reducing it further.

Use the following script:

read_verilog 3510.v
prep
splitcells

This was discovered because I have been using the Verismith fuzzer to find bugs in the Yosys pass I'm writing for my thesis, which incidentally discovered this bug, which I believe is an upstream issue.

Expected Behavior

The splitcells command should not cause an assert failure.

Actual Behavior

Yosys crashes with the following assert failure:

3. Executing SPLITCELLS pass (splitting up multi-bit cells).
Splitting $dff cell top/$procdff$14 into 2 slices:
  slice 1: $procdff$14[1:0] => \reg5 [1:0]
  slice 2: $procdff$14[2] => \reg5 [2]
Splitting $xnor cell top/$xnor$3510.v:13$1 into 2 slices:
  slice 1: $xnor$3510.v:13$1[1:0] => \wire4 [1:0]
ERROR: Assert `length >= 0' failed in kernel/rtlil.cc:4882

This is what I believe is the relevant backtrace:

(lldb)
frame #6: 0x00005555557fc808 yosys`Yosys::RTLIL::SigSpec::extract(this=<unavailable>, offset=<unavailable>, length=-1) const at rtlil.cc:4882:2
   4879 RTLIL::SigSpec RTLIL::SigSpec::extract(int offset, int length) const
   4880 {
   4881         log_assert(offset >= 0);
-> 4882         log_assert(length >= 0);
   4883         log_assert(offset + length <= width_);
   4884
   4885         cover("kernel.rtlil.sigspec.extract_pos");
(lldb)
frame #7: 0x0000555555b4ef08 yosys`(anonymous namespace)::SplitcellsWorker::split(this=0x00007fffffffc148, old_sig=SigSpec @ 0x00007fffffffbf60)::'lambda'(Yosys::RTLIL::SigSpec)::operator()(Yosys::RTLIL::SigSpec) const at splitcells.cc:109:30
   106                                          for (int i = 0; i < GetSize(old_sig); i += GetSize(outsig)) {
   107                                                  int offset = i+slice_lsb;
   108                                                  int length = std::min(GetSize(old_sig)-offset, slice_msb-slice_lsb+1);
-> 109                                                  new_sig.append(old_sig.extract(offset, length));
   110                                          }
   111                                          return new_sig;
   112                                  };
(lldb) up
frame #8: 0x0000555555b4cde3 yosys`(anonymous namespace)::SplitcellsWorker::split(this=0x00007fffffffc3b8, cell=0x0000555556ce0440, format="[]:") at splitcells.cc:119:28
   116                                          slice->setParam(ID::A_WIDTH, GetSize(slice->getPort(ID::A)));
   117
   118                                  if (slice->hasPort(ID::B)) {
-> 119                                          slice->setPort(ID::B, slice_signal(slice->getPort(ID::B)));
   120                                          if (slice->hasParam(ID::B_WIDTH))
   121                                                  slice->setParam(ID::B_WIDTH, GetSize(slice->getPort(ID::B)));
   122                                  }
(lldb) up
frame #9: 0x0000555555b4b619 yosys`(anonymous namespace)::SplitcellsPass::execute(this=<unavailable>, args=<unavailable>, design=<unavailable>) at splitcells.cc:251:21
   248                                  SplitcellsWorker worker(module);
   249                                  bool did_something = false;
   250                                  for (auto cell : module->selected_cells()) {
-> 251                                          int n = worker.split(cell, format);
   252                                          did_something |= (n != 0);
   253                                          count_split_pre += (n != 0);
   254                                          count_split_post += n;
(lldb) up
@mattyoung101 mattyoung101 added the pending-verification This issue is pending verification and/or reproduction label Feb 20, 2025
@whitequark
Copy link
Member

Thank you for responsibly submitting a fuzzer-generated testcase! At a glance it looks short enough to dig into, although if you could use the bugpoint pass to minimize it to an RTLIL example that would be appreciated.

@whitequark whitequark added bug and removed pending-verification This issue is pending verification and/or reproduction labels Feb 20, 2025
@mattyoung101
Copy link
Author

No worries! I've just minimised it using bugpoint to RTLIL, this should be it:

# Generated by Yosys 0.50+7 (git sha1 9d3ab964b, ccache clang++ 19.1.7 -Og -fPIC)
autoidx 20
attribute \src "3510.v:2.1-26.10"
attribute \cells_not_processed 1
attribute \tamara_triplicate 1
module \top
  attribute \src "3510.v:14.3-17.8"
  wire width 4 $0\reg5[3:0]
  attribute $bugpoint 1
  wire width 4 $auto$bugpoint.cc:258:simplify_something$12
  wire $delete_wire$14
  attribute \src "3510.v:13.19-13.59"
  wire width 4 $xnor$3510.v:13$1_Y
  attribute \src "3510.v:11.23-11.27"
  wire width 4 \reg5
  attribute \src "3510.v:8.24-8.29"
  wire width 3 \wire4
  attribute \src "3510.v:3.33-3.34"
  wire width 12 output 1 \y
  attribute \src "3510.v:13.19-13.59"
  cell $xnor $xnor$3510.v:13$1
    parameter \A_SIGNED 0
    parameter \A_WIDTH 3
    parameter \B_SIGNED 0
    parameter \B_WIDTH 4
    parameter \Y_WIDTH 4
    connect \A 3'x
    connect \B $auto$bugpoint.cc:258:simplify_something$12
    connect \Y $xnor$3510.v:13$1_Y
  end
  attribute \src "3510.v:14.3-17.8"
  process $proc$3510.v:14$2
    assign $0\reg5[3:0] { \wire4 [2] \wire4 }
    sync posedge $delete_wire$14
      update \reg5 $0\reg5[3:0]
  end
  connect \y [4:0] { \reg5 1'0 }
  connect \wire4 $xnor$3510.v:13$1_Y [2:0]
end

Should be reproducible with:

read_rtlil <file>
prep
splitcells

@whitequark
Copy link
Member

Yep, perfect!

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

No branches or pull requests

2 participants