Skip to content

Conversation

@Scheremo
Copy link
Contributor

@Scheremo Scheremo commented Oct 21, 2025

Introduce full real (f32/f64) operator support in the Moore dialect and the ImportVerilog conversion, including unary, arithmetic, equality, relational, logical, and ++/-- forms. Refactor logical operator lowering to a reusable helper and add comprehensive tests.

  • Dialect (MooreOps.td):

    • New unary real op: NegRealOp -> moore.fneg.
    • Real binary op base: BinaryRealOpBase for typed f32/f64 operands/results.
    • Arithmetic: AddRealOp (fadd), SubRealOp (fsub), MulRealOp (fmul), DivRealOp (fdiv), PowRealOp (fpow).
    • Equality: EqRealOp (feq), NeRealOp (fne).
    • Relational: FltOp (flt), FleOp (fle), FgtOp (fgt), FgeOp (fge).
    • All ops follow IEEE 1800-2023 §11.3.1, §11.4.3–§11.4.5 semantics.
  • Import (Expressions.cpp):

    • Add visitRealUOp and visitRealBOp to lower real-typed unary/binary expressions.
    • Implement pre/post increment/decrement for real variables via fadd/fsub with an exact APFloat "1.0" (IEEEsingle/IEEEdouble) constructor.
    • Add moore.fneg for unary minus; unary plus becomes a no-op.
    • Map real comparisons to feq/fne/flt/fle/fgt/fge.
    • Refactor logical ops into buildLogicalBOp(...) (optional Domain param), shared by int/real paths. (Short-circuit remains TODO.)
    • Route mixed/real expressions early to the real path; keep existing integral flow otherwise.
  • Tests (basic.sv):

    • New end-to-end checks for f64/f32 arithmetic, comparisons, logicals, unary ops, and ++/--.
    • Assert exact opcode emission (moore.fadd/fsub/fmul/fdiv/fpow/feq/fne/flt/fle/fgt/fge/fneg) and constant forms for 1.0.

@Scheremo Scheremo force-pushed the pr-real-binops branch 2 times, most recently from 097315a to d56317d Compare October 21, 2025 10:59
@Scheremo Scheremo changed the title [Moore][ImportVerilog] Add real-valued binary operations [Moore][ImportVerilog] Add real-valued ops + real-aware import; refactor logical handling Oct 21, 2025
@Scheremo Scheremo marked this pull request as ready for review October 21, 2025 11:00
@Scheremo Scheremo force-pushed the pr-real-binops branch 3 times, most recently from 1f1bf2c to 50c009e Compare October 21, 2025 18:57
@Scheremo Scheremo force-pushed the pr-real-binops branch 3 times, most recently from fb132a4 to 658622c Compare October 21, 2025 19:21
Comment on lines 738 to 741
Type lhsTy = context.convertType(*expr.left().type, loc);
Type rhsTy = context.convertType(*expr.right().type, loc);

if (!lhsTy || !rhsTy)
return {};

assert(lhsTy == rhsTy &&
"Slang should have converted both operands to the same type!");
Type targetTy = lhsTy;
Copy link
Contributor

Choose a reason for hiding this comment

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

I would use the type of the binary expression directly: expr.type. Slang computes that using the rules for operands outlined in the SV spec, including finding the widest operand width, signness matching, etc. I think it does the same thing for reals, where a shortreal + real would be determined to have type real for the + result.

That also means you don't need to assert equality on the LHS and RHS type. The assert will abort the compiler. If you don't assert, the conversions further down fail with a proper diagnostic pointing at the failing input, which is going to be much easier to debug and track down if it happens.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep, makes sense. Wasn't aware of expr.type but that simplifies this a lot!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

A bit too much as it turns out! expr.type holds the return type, which sometimes but not always is equal to the RHS types.

Comment on lines 813 to 803
// First check whether we need real or integral BOps
const auto *rhsFloatType =
expr.right().type->as_if<slang::ast::FloatingType>();
const auto *lhsFloatType =
expr.left().type->as_if<slang::ast::FloatingType>();

// If either op is real-typed, treat as real BOp. Bail here.
if (rhsFloatType || lhsFloatType)
return visitRealBOp(expr);

Copy link
Contributor

Choose a reason for hiding this comment

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

Same here: I think you can just check expr.type and see if it is a float. If it is, call out to visitRealBOp.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep! Fixed it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

At least in here, we can't make the shortcut: a BinaryOperator::Equality will have return type i1, so this currently fails. This might also be a bug for the "normal" sbv pipeline if operands are cast to i1!

@Scheremo Scheremo force-pushed the pr-real-binops branch 2 times, most recently from fc55461 to 15433de Compare October 21, 2025 19:33
Copy link
Contributor

@fabianschuiki fabianschuiki left a comment

Choose a reason for hiding this comment

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

Really really cool! Thanks a lot for adding all of this 🥳 💯!

@Scheremo
Copy link
Contributor Author

Really really cool! Thanks a lot for adding all of this 🥳 💯!

Thanks for the thorough review! Let's hope this fixes some more sv-tests 😄

@Scheremo Scheremo force-pushed the pr-real-binops branch 2 times, most recently from 4d11bb2 to 39abea5 Compare October 21, 2025 20:03
…tor logical handling

Introduce full **real (f32/f64)** operator support in the Moore dialect and the ImportVerilog conversion, including unary, arithmetic, equality, relational, logical, and ++/-- forms. Refactor logical operator lowering to a reusable helper and add comprehensive tests.

- **Dialect (`MooreOps.td`):**
  - New unary real op: `NegRealOp` -> `moore.fneg`.
  - Real binary op base: `BinaryRealOpBase` for typed f32/f64 operands/results.
  - Arithmetic: `AddRealOp` (`fadd`), `SubRealOp` (`fsub`), `MulRealOp` (`fmul`), `DivRealOp` (`fdiv`), `PowRealOp` (`fpow`).
  - Equality: `EqRealOp` (`feq`), `NeRealOp` (`fne`).
  - Relational: `FltOp` (`flt`), `FleOp` (`fle`), `FgtOp` (`fgt`), `FgeOp` (`fge`).
  - All ops follow IEEE 1800-2023 §11.3.1, §11.4.3–§11.4.5 semantics.

- **Import (`Expressions.cpp`):**
  - Add `visitRealUOp` and `visitRealBOp` to lower real-typed unary/binary expressions.
  - Implement pre/post **increment/decrement** for real variables via `fadd`/`fsub` with an exact `APFloat` **"1.0"** (IEEEsingle/IEEEdouble) constructor.
  - Add `moore.fneg` for unary minus; unary plus becomes a no-op.
  - Map real comparisons to `feq/fne/flt/fle/fgt/fge`.
  - **Refactor logical ops** into `buildLogicalBOp(...)` (optional `Domain` param), shared by int/real paths. (Short-circuit remains TODO.)
  - Route mixed/real expressions early to the real path; keep existing integral flow otherwise.

- **Tests (`basic.sv`):**
  - New end-to-end checks for f64/f32 arithmetic, comparisons, logicals, unary ops, and ++/--.
  - Assert exact opcode emission (`moore.fadd/fsub/fmul/fdiv/fpow/feq/fne/flt/fle/fgt/fge/fneg`) and constant forms for `1.0`.
@Scheremo Scheremo merged commit 9c89d1c into llvm:main Oct 21, 2025
7 checks passed
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.

2 participants