Skip to content

[MooreToCore] Support real constants #8269

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

Open
GlowingScrewdriver opened this issue Feb 23, 2025 · 9 comments
Open

[MooreToCore] Support real constants #8269

GlowingScrewdriver opened this issue Feb 23, 2025 · 9 comments
Labels

Comments

@GlowingScrewdriver
Copy link

I'm looking into the failing testcase for real constants on sv-tests-results. Just want to put it up here to make sure no one else has already started working on it.

@GlowingScrewdriver
Copy link
Author

Can I continue working on this? I've made a start, modified MooreToCore.cpp to lower the moore.real_constant to a hw.constant. Not sure if I've done everything right, but I'm getting an idea of where my code should go.

Also, I'm not sure how to test this. I tried compiling the SystemVerilog input file with circt-verilog test.sv and then piping through circt-synth, but it complains about llhd not being registered as a dialect.

@terapines-osc-1
Copy link
Member

Hey, @GlowingScrewdriver! Maybe you can use circt-opt --convert-moore-to-core if you just want to test from Moore IR to Core IR.

@GlowingScrewdriver
Copy link
Author

GlowingScrewdriver commented Mar 10, 2025

Apologies for the long silence. Got busy.

I'm unable to figure out how handle real values when assigned to integral variables. Is this straightforward at all? Should I be modifying moore.conversion at all, or should I introduce a new casting operator from and insert that when assigning a real to an integral type? The SV spec says they should be rounded to integers (nearest, ties to away) when assigned to integral variables.

Also, I'm thinking I should emit reals as f64s. Is this a good way to do it?

Admittedly, this issue is deeper than I thought it was. @hailongSun2000 Based on your inputs about the approach, I'll decide between continuing on this and choosing a less ambitious SV test to fix.

@terapines-osc-1
Copy link
Member

It's nothing! 😃
From my perspective, moore.conversion is enough to convert real to integer type(Maybe I'm wrong). And I recommend you apply slang to check the AST, such as slang xxx.sv(sv source code file) --ast-json xxx.json(output file). And maybe slang has rounded the real type number 🤔 ? If not, I think we can invoke std::round() for the real digit, or define moore.rtoi and moore.itor ops for explicit $rtoi and $itor system functions, or use moore.conversion to convert real to integer roughly.

@terapines-osc-1
Copy link
Member

Also, I'm thinking I should emit reals as f64s. Is this a good way to do it?

If it's possible, keep real type at the Moore dialect level.

@GlowingScrewdriver
Copy link
Author

And maybe slang has rounded the real type number?

I checked Slang's AST dump. You're right; Slang does emit an integer literal along with each real literal.

So far I've added a RealLiteralOpConversion struct with a matchAndRewrite that replaces the moore.real_constant with a hw.constant.

I see that I have to add a type conversion handler like

static void populateTypeConversion(TypeConverter &typeConverter) {
  /* ... */
  typeConverter.addConversion([&](RealType type) {
    // Figure out
  });
  /* ... */
}

so that we can lower

"moore.conversion" : (!moore.real) -> *

using ConversionOpConversion::matchAndRewrite. If not, I'd have to modify ConversionOpConversion to act differently if the input type is real_constant.

Now, about bit width:

  1. I've written RealLiteralOpConversion::matchAndRewrite to calculate the minimum integer bit width to hold the RealLiteral's value.
  2. Casting to integer using the standard features (i.e. stdc++, C compiler features) should work fine as long as the float can fit in an int or even a long. But what about real literals representing numbers too large to fit?
  3. I'm not sure how to do what I did in (1.) within the typeConverter handler or ConversionOpConversion

The easy way out that I can think of is to just generate hw.constants that are large enough to hold any double (2048 bits wide) and rely on the optimizer to clean it up. Doesn't seem elegant though.

It's nothing!

Okay, doesn't sound like too big a deal anymore :)

@GlowingScrewdriver
Copy link
Author

The other way I can think of is to convert to integer in ImportVerilog itself, before it even reaches Moore. But that way we can't use real values at all in Moore, which I suppose is important for running simulations before synthesis.

@sunhailong2001
Copy link

Hey @GlowingScrewdriver! static void populateTypeConversion(TypeConverter &typeConverter) is used to convert Moore Types into other dialects' types. And struct ConstantOpConv : public OpConversionPattern<ConstantOp> lowers Moore Ops, meanwhile, ConstantOpConv must be added in static void populateOpConversion(RewritePatternSet &patterns, TypeConverter &typeConverter).

@GlowingScrewdriver
Copy link
Author

GlowingScrewdriver commented Apr 20, 2025

Apologies for the silence.
I don't think I'll be able to spend time on this until at least mid May; the semester end is approaching, and Uni is getting hectic.

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

No branches or pull requests

3 participants