DI-OSVISE (De:sign Initiative – Open Source Verification von RISC-V Instruktionssatzerweiterungen) is a project sponsored by BMBF to foster the development of open-source tools, to make microelectronics sustainable and trustworthy in Germany and Europe. The objective of DI-OSVISE is to develop a series of instruments to automate the definition, generation, and verification of custom instructions for the RISC-V ISA. In particular, one of the goals of our participation in the project is to bridge the gap between open source verification and industry benchmarks by contributing to the UVM support to Verilator. In this blog series, we want to tell you the story of this journey.

This blog series discusses the progress made under the OSVISE project by PlanV, which aims to enable UVM support in Verilator to assist in getting open-source RISC-V verification tools to an industrial standard.

The first step was to get acquainted with the Verilator codebase and its workflow. The well-written and commented source code and the extensive documentation made this initial step easy. But it was not enough to resolve an actual issue. Fortunately, there’s a subset of Verilator issues, labeled “good first issue” – we followed the hint and got our hands dirty with one of these. The best way to learn is to try
resolving the prevailing issue in the Verilator.

The issue with the monitor printing the delta values was our first learning task.

This prints the intermediate values within the delta cycles.

In the first observation, we figured out that the monitor was printing the values from the NBA region. Non-Blocking Assignment Event (NBA) region is a part of System Verilog(SV) scheduling schematic construct where an update to the LHS (Left Hand Side) variables of all the nonblocking assignments whose RHS(Right Hand Side) are evaluated in the Active region. So, each update of the variable triggers the entry into the NBA region, where the $monitor prints the delta values. On the other hand, $strobe was working perfectly as it was in the postponed region. So, as per SV standard, we placed monitor operation in the postponed region, and the problem of multiple entries into NBA region was resolved, but it was printing the values even when there was no change in values.

In the second attempt, we tried to create a variable that tracks the changes in the values and prints only when the value is changed from the NBA region, but it was not possible as the track variable scope should be beyond the NBA region resulting in a huge overhead incurred by this approach.

The $monitor operation is implemented as the always statement in the verilator AST (always if(__VmonitorOn && __VmonitorNum==N) $display(…);) . We finally observed that the sensitivity list provided for the monitor always node is empty. So, extracting the reference of those variables of which the monitor prints the values, creating a sensitivity tree from those references, and providing it to the monitor always node solved the issue. The current display node ( nodep ) holds the expression of the monitor and the reference of the variable.

Conclusion

This exercise effectively enhanced our understanding of Verilator’s internal structure and mechanisms. The exploration of the Codebase provided valuable insight into Verilator implementation of the visitor pattern, conversion from the SV code into the different AST nodes, regression test implementation, etc. The PR #5294 from PlanV resolves this issue and merges with the master branch. We believe we are now prepared to tackle more challenging tasks.