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
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions lib/Conversion/ImportVerilog/Statements.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,21 @@ struct StmtVisitor {
return false;
}

/// Handle procedural assign statements.
LogicalResult visit(const slang::ast::ProceduralAssignStatement &stmt) {
if (stmt.isForce) {
auto loc = context.convertLocation(stmt.sourceRange);
mlir::emitError(loc, "force assignments not supported.");
return mlir::failure();
}

auto value = context.convertRvalueExpression(stmt.assignment);
if (!value)
return mlir::failure();

return mlir::success();
}

/// Create the optional diagnostic message print for finish-like ops.
void createFinishMessage(const slang::ast::Expression *verbosityExpr) {
unsigned verbosity = 1;
Expand Down
4 changes: 4 additions & 0 deletions test/Conversion/ImportVerilog/basic.sv
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,10 @@ module Statements;
// CHECK: [[TMP1:%.+]] = moore.read %y
// CHECK: moore.nonblocking_assign %x, [[TMP1]] : i1
x <= y;

// CHECK: [[TMP1:%.+]] = moore.read %y
// CHECK: moore.blocking_assign %x, [[TMP1]] : i1
assign x = y;
Comment on lines +598 to +601
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?

end
endmodule

Expand Down
Loading