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

Feat/MULH opcode #492

Merged
merged 15 commits into from
Nov 1, 2024
Merged

Feat/MULH opcode #492

merged 15 commits into from
Nov 1, 2024

Conversation

bgillesp
Copy link
Collaborator

@bgillesp bgillesp commented Oct 29, 2024

Implement MULH opcode

Circuit is validated by the following strategy:

  1. Compute the signed values associated with rs1, rs2 and rd registers
  2. Verify that the product of signed inputs rs1 and rs2 is equal to the result of interpreting rd as the high limb of a 2s complement value with some 32-bit low limb.

The latter value in step 2 is expressed as: the 32-bit signed 2s complement value of the rd register times 2^32, plus the unsigned value of the 32-bit low limb.

The soundness here is a bit subtle. The signed values of 32-bit inputs rs1 and rs2 have values between -2^31 and 2^31 - 1, so their product is constrained to lie between -2^62 + 2^31 and 2^62. In a prime field of size smaller than 2^64, the range of values represented by a 64-bit 2s complement value, integers between -2^63 and 2^63 - 1, have some ambiguity. If p = 2^64 - k, then the values between -2^63 and -2^63 + k - 1 correspond with the values between 2^63 - k and 2^63 - 1.

However, as long as the values required by signed products don't overlap with this ambiguous range, an arbitrary 64-bit 2s complement value can represent a signed 32-bit product in only one way, so there is no ambiguity in the representation. This is the case for the Goldilocks field with order p = 2^64 - 2^32 + 1.

@bgillesp bgillesp changed the title (WIP) Feat/MULH opcode Feat/MULH opcode Oct 30, 2024
@bgillesp bgillesp marked this pull request as ready for review October 30, 2024 20:37
@bgillesp
Copy link
Collaborator Author

The circuit design has been updated from the initial description above; see the doc comment of the MULH circuit constructor for an overview and analysis. This could use a careful look from reviewers, as the design is a bit subtle and relies on the size of the Goldilocks field for correctness.

@matthiasgoergens
Copy link
Collaborator

@bgillesp Did you / could you update the PR description to reflect the updated circuit design? Thanks!

let rd_sign_bit = IsLtConfig::construct_circuit(
circuit_builder,
|| "rd_sign_bit",
((1u64 << (LIMB_BITS - 1)) - 1).into(),
Copy link
Collaborator

Choose a reason for hiding this comment

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

You can use IsLtConfig::constrain_last_limb from #506 to make this a bit easier to read.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

See my comment in #506 about making it a separate gadget MSBConfig rather than an extra constructor variant of IsLtConfig, but whatever design we decide I can definitely use it here. Will make the change once #506 is merged with master.

ceno_zkvm/src/instructions/riscv/mulh.rs Outdated Show resolved Hide resolved
@naure
Copy link
Collaborator

naure commented Oct 31, 2024

Thanks for the documentation of the constraints too!

It helped me to double-check numerically:

# Range of variables:
u32max = 2**32 - 1
pos = 2**31 - 1
neg = -2**31
p = 2**64 - 2**32 + 1 # Goldilocks.

# Range of the constraint:
#          rs1 * rs2 - (rd * 2**32 + low)
greatest = neg * neg - (neg * 2**32 + 0)
smallest = neg * pos - (pos * 2**32 + u32max)
assert -p < smallest < 0 < greatest < p
  • The range contains a single instance of 0 mod p so the constraint works the same as in ℤ.
  • The constraint is directly a hi/lo decomposition of the product.

Copy link
Collaborator

@naure naure left a comment

Choose a reason for hiding this comment

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

Beautiful!

@kunxian-xia kunxian-xia linked an issue Nov 1, 2024 that may be closed by this pull request
@naure naure merged commit 31e65d6 into master Nov 1, 2024
6 checks passed
@naure naure deleted the feat/mulh-opcode branch November 1, 2024 01:58
matthiasgoergens added a commit that referenced this pull request Nov 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

mulh
4 participants