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

[ImportVerilog] Support for Procedural assign statements #8010

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

owlxiao
Copy link
Contributor

@owlxiao owlxiao commented Dec 19, 2024

This pr aims to add support for parsing Procedural assign statements in ImportVerilog.

Copy link
Member

@hailongSun2000 hailongSun2000 left a comment

Choose a reason for hiding this comment

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

Thanks for working on this feature 😄.

Comment on lines +598 to +601

// CHECK: [[TMP1:%.+]] = moore.read %y
// CHECK: moore.blocking_assign %x, [[TMP1]] : i1
assign x = y;
Copy link
Member

Choose a reason for hiding this comment

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

Based on SystemVerilog IEEE Std 1800-2017 § 10.6 "Procedural continuous assignments", the assign x = y; should be treated as a continuous assignment.
image

Therefore, I think maybe we should translate this into moore.assign, rather than moore.blocking_assign. WDYH 🤔? @fabianschuiki

Copy link
Member

Choose a reason for hiding this comment

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

I need your @fabianschuiki help 👍 ❤️ ! Thanks in advance!

Copy link
Contributor

Choose a reason for hiding this comment

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

Hey! Sorry for taking so long to respond 😞

I agree with @hailongSun2000: procedural continuous assignments are a bit strange in SystemVerilog. They act like an assign at the module level that can be turned on or off. The assign starts out turned off, and as soon as the assign x = y; statement in a process is executed, the assignment at the module-level is turned on. Similarly, there are the release-style statements that can disable such an assignment again.

We currently don't have any operation in the Moore dialect which implements this conditional/enabled assignment. We could either add a new op, something like moore.conditional_assign %x, %y, %condition, or we could implement it as a

moore.procedure always_comb {
  cf.cond_br %condition, ^bb1, ^bb2
^bb1:
  %0 = moore.read %y
  moore.blocking_assign %x, %0
  br ^bb2:
^bb2:
  moore.return
}

My suggestion would be to first try to implement it as a moore.procedure since that wouldn't need any additional operations, and to only define a new operation if it is really necessary to represent the detailed semantics of procedural continuous assignments.

Generally, I think a procedural continuous assignment needs the following two ingredients:

  1. An optional/enabled assignment at the module-level (outside the process/block where the assign statement is located).
  2. Enabling the module-level assignment whenever the assign statement in the process/block is executed. Also, when a corresponding deassign statement is encountered, the module-level assignment has to be disabled.

It would be great to add the procedural assign and deassign statements in parallel, since they perform complementary operations.

As an example, consider the following snippet of Verilog:

module Foo;
  int x, y;
  initial begin
    assign x = y;
    deassign x;
  end
endmodule

We should be able to lower this to something like the following:

moore.module @Foo() {
  %x = moore.variable : <i32>
  %y = moore.variable : <i32>

  // Conditional module-level assignment created for `assign x = y`.
  // `%0` is a helper variable created for `assign x = y` that is used to
  // enable or disable the assignment when `assign` or `deassign` is 
  // executed:
  %c0_i1 = moore.constant 0 : i1
  %0 = moore.variable %c0_i1 : <i1>
  moore.procedure always_comb {
    cf.cond_br %0, ^bb1, ^bb2
  ^bb1:
    %1 = moore.read %y : <i32>
    moore.blocking_assign %x, %1 : i32
    br ^bb2:
  ^bb2:
    moore.return
  }

  moore.procedure initial {
    // Lowering of `assign x = y`.
    // Enables the module-level assignment.
    %c1_i1 = moore.constant 1 : i1
    moore.blocking_assign %0, %c1_i1 : i1

    // Lowering of `deassign x`.
    // Disables the module-level assignment.
    %c0_i1 = moore.constant 0 : i1
    moore.blocking_assign %0, %c0_i1 : i1
  }
}

What do you guys think about this?

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.

3 participants