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

Issue with Simulation When Setting --max-runs Greater Than 1 #6

Open
Gloria-cpu opened this issue Sep 26, 2024 · 3 comments
Open

Issue with Simulation When Setting --max-runs Greater Than 1 #6

Gloria-cpu opened this issue Sep 26, 2024 · 3 comments
Assignees
Labels
question Further information is requested

Comments

@Gloria-cpu
Copy link

Describe the question

I am currently using the xfuzz and difftest frameworks. When I set --max-runs to 1 in xfuzz, the execution works normally. However, when I set --max-runs to a value greater than 1, the first run executes as expected, but starting from the second run, the simulation begins to show anomalies. Upon inspecting the waveform, we observed sudden unexpected values during the simulation.

Interestingly, when I export the case from the second run and execute it individually, it runs perfectly without any issues.

What you expect us to do for you

Have you encountered a similar problem before? Your insights would be greatly appreciated.

@Gloria-cpu Gloria-cpu added the question Further information is requested label Sep 26, 2024
@poemonsense
Copy link
Member

Can you describe the "sudden unexpected values" with more details?

I did observe differences in the outputs between the first run and the following runs. They are caused by reset values of the simulation. For example, Chisel inserts the random initialization for the variables and they are randomly reset upon initialization. However, this issue should be fixed by the random seed (-s command line argument). By default, the seed is zero. Therefore, this random reset should not affect the simulation between multiple runs.

Other possibilities include any C/C++ data structure or Verilog/SV variables without a reset. After a case is executed, if you do not reset them or they are not reset by the reset IO pin, their values will remain unchanged, the same as the previous run results. Then, this run will be different from a total clean run.

@Gloria-cpu
Copy link
Author

After some investigation, we found that certain Verilog/SV variables were not properly reset. I would like to ask, in the current designs such as Xiangshan or RocketChip, how do they ensure that these Verilog/SV variables are fully reset?

@poemonsense
Copy link
Member

I would like to ask, in the current designs such as Xiangshan or RocketChip, how do they ensure that these Verilog/SV variables are fully reset?

There're two types of reset.

The first one is any variable with an explicit reset in Verilog (always @(..) if (reset) ...). They will be explicitly reset to the specified reset values during the reset period (https://github.com/OpenXiangShan/difftest/blob/master/src/test/csrc/verilator/emu.cpp#L385).

The others (registers without an explicit reset) are deterministically reset by the macros generated by Chisel. Basically, Chisel generates the reset expressions for every register, and these expressions are wrapped by the macro RANDOMIZE_REG_INIT and put in the initial scope. Therefore, all registers will have a reset during the simulation, though not actually in the hardware. These random reset values is controlled by the random seed I mentioned before.

The code generated generally looks like:

    initial begin       // src/main/scala/nutcore/backend/fu/MDU.scala:135:7
      automatic logic [31:0] _RANDOM[0:0];      // src/main/scala/nutcore/backend/fu/MDU.scala:135:7
      `ifdef INIT_RANDOM_PROLOG_        // src/main/scala/nutcore/backend/fu/MDU.scala:135:7
        `INIT_RANDOM_PROLOG_    // src/main/scala/nutcore/backend/fu/MDU.scala:135:7
      `endif // INIT_RANDOM_PROLOG_
      `ifdef RANDOMIZE_REG_INIT // src/main/scala/nutcore/backend/fu/MDU.scala:135:7
        _RANDOM[/*Zero width*/ 1'b0] = `RANDOM; // src/main/scala/nutcore/backend/fu/MDU.scala:135:7
        isDivReg_REG = _RANDOM[/*Zero width*/ 1'b0][0]; // src/main/scala/nutcore/backend/fu/MDU.scala:135:7, :184:48
      `endif // RANDOMIZE_REG_INIT
    end // initial

For non-Chisel-generated designs, it may be hard to implement such features. However, Verilator also provides the support for random or fixed reset. See https://verilator.org/guide/latest/exe_verilator.html#cmdoption-x-assign. I just noticed difftest is using --x-assign unique in https://github.com/OpenXiangShan/difftest/blob/master/verilator.mk#L109. Probably you can change it to --x-assign 0 or others to get a fixed reset values for all registers if you are not using Chisel-generated code. VCS provides similar arguments as well. Hope that helps.

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

No branches or pull requests

2 participants