Skip to content

Fix semantics of onehot0: at most one bit set - #9166

Merged
kroening merged 1 commit into
diffblue:developfrom
tautschnig:kiro/fix-onehot0
Sep 22, 2026
Merged

kroening merged 1 commit into
diffblue:developfrom
tautschnig:kiro/fix-onehot0

Conversation

@tautschnig

Copy link
Copy Markdown
Collaborator

onehot0_exprt is meant to model SystemVerilog's $onehot0 (IEEE 1800-2017 20.9), which is true iff at most one bit of the operand is set, i.e., the operand is either one-hot or zero. The implementation (both the boolbv flattening and the lowering used by the SMT2 back-end) instead computed "exactly one bit is zero", i.e., onehot of the bitwise negation. Under an assumption $onehot0(x) this let a 4-bit x take the value 4'b1011.

Fix the flattening, the lowering, and the class documentation, and correct the unit tests, which encoded the wrong semantics. onehot and onehot0 now differ exactly on the zero vector.

  • Each commit message has a non-empty body, explaining why the change was made.
  • n/a Methods or procedures I have added are documented, following the guidelines provided in CODING_STANDARD.md.
  • n/a The feature or user visible behaviour I have added or modified has been documented in the User Guide in doc/cprover-manual/
  • Regression or unit tests are included, or existing tests cover the modified code (in this case I have detailed which ones those are in the commit message).
  • n/a My commit message includes data points confirming performance improvements (if claimed).
  • My PR is restricted to a single feature or bugfix.
  • n/a White-space or formatting changes outside the feature-related changed lines are in commits of their own.

onehot0_exprt is meant to model SystemVerilog's $onehot0 (IEEE 1800-2017
20.9), which is true iff at most one bit of the operand is set, i.e., the
operand is either one-hot or zero. The implementation (both the boolbv
flattening and the lowering used by the SMT2 back-end) instead computed
"exactly one bit is zero", i.e., onehot of the bitwise negation. Under an
assumption $onehot0(x) this let a 4-bit x take the value 4'b1011.

Fix the flattening, the lowering, and the class documentation, and
correct the unit tests, which encoded the wrong semantics. onehot and
onehot0 now differ exactly on the zero vector.

Co-authored-by: Kiro <kiro-agent@users.noreply.github.com>
@tautschnig tautschnig self-assigned this Sep 22, 2026
Copilot AI lite review requested due to automatic review settings September 22, 2026 07:14

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟢 Approval recommended

The semantics, documentation, and regression tests are consistently corrected.

Review effort: Lite
Findings: None

What changed in this PR

Corrects $onehot0 to accept vectors with zero or one set bit.

Changes:

  • Fixes expression lowering and BoolBV semantics.
  • Updates class documentation.
  • Corrects unit tests.
File Description
unit/​util/​bitvector_expr.cpp Updates lowering tests.
unit/​solvers/​flattening/​boolbv_onehot.cpp Updates flattening tests.
src/​util/​bitvector_expr.h Documents corrected semantics.
src/​util/​bitvector_expr.cpp Corrects expression lowering.
src/​solvers/​flattening/​boolbv_onehot.cpp Applies at-most-one semantics.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@codecov

codecov Bot commented Sep 22, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 80.84%. Comparing base (820ff0f) to head (00fc8ea).
⚠️ Report is 2 commits behind head on develop.

Additional details and impacted files
@@           Coverage Diff            @@
##           develop    #9166   +/-   ##
========================================
  Coverage    80.83%   80.84%           
========================================
  Files         1717     1717           
  Lines       190069   190084   +15     
  Branches        73       73           
========================================
+ Hits        153647   153678   +31     
+ Misses       36422    36406   -16     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@tautschnig tautschnig assigned kroening and unassigned tautschnig Sep 22, 2026
@kroening
kroening merged commit b31f61b into diffblue:develop Sep 22, 2026
43 checks passed
tautschnig added a commit to diffblue/hw-cbmc that referenced this pull request Sep 22, 2026
Per IEEE 1800-2017 section 20.9, $onehot0(expr) returns true iff at most
one bit of expr is set, i.e., expr is one-hot or zero. Both the Verilog
constant folder and CBMC's onehot0_exprt (flattening and SMT2 lowering)
instead computed "exactly one bit is zero". As a consequence, an
assumption $onehot0(x) permitted, e.g., x == 4'b1011.

The constant folder now checks $countones(expr) <= 1. The CBMC submodule
is bumped to include the fix of onehot0_exprt (diffblue/cbmc#9166). The
existing tests onehot1 and system_verilog_assertion3 encoded the wrong
semantics and are corrected; the new test onehot2 uses $onehot0 on a free
input in an assumption, which exercises the solver back-ends rather than
the constant folder.

Co-authored-by: Kiro <kiro-agent@users.noreply.github.com>
kroening pushed a commit to diffblue/hw-cbmc that referenced this pull request Sep 27, 2026
Per IEEE 1800-2017 section 20.9, $onehot0(expr) returns true iff at most
one bit of expr is set, i.e., expr is one-hot or zero. Both the Verilog
constant folder and CBMC's onehot0_exprt (flattening and SMT2 lowering)
instead computed "exactly one bit is zero". As a consequence, an
assumption $onehot0(x) permitted, e.g., x == 4'b1011.

The constant folder now checks $countones(expr) <= 1. The CBMC submodule
is bumped to include the fix of onehot0_exprt (diffblue/cbmc#9166). The
existing tests onehot1 and system_verilog_assertion3 encoded the wrong
semantics and are corrected; the new test onehot2 uses $onehot0 on a free
input in an assumption, which exercises the solver back-ends rather than
the constant folder.

Co-authored-by: Kiro <kiro-agent@users.noreply.github.com>
tautschnig added a commit to diffblue/hw-cbmc that referenced this pull request Sep 28, 2026
Per IEEE 1800-2017 section 20.9, $onehot0(expr) returns true iff at most
one bit of expr is set, i.e., expr is one-hot or zero. Both the Verilog
constant folder and CBMC's onehot0_exprt (flattening and SMT2 lowering)
instead computed "exactly one bit is zero". As a consequence, an
assumption $onehot0(x) permitted, e.g., x == 4'b1011.

The constant folder now checks $countones(expr) <= 1. The CBMC submodule
is bumped to include the fix of onehot0_exprt (diffblue/cbmc#9166). The
existing tests onehot1 and system_verilog_assertion3 encoded the wrong
semantics and are corrected; the new test onehot2 uses $onehot0 on a free
input in an assumption, which exercises the solver back-ends rather than
the constant folder.

Co-authored-by: Kiro <kiro-agent@users.noreply.github.com>
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.

3 participants