Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@terapines-osc-circt
Copy link
Member

@terapines-osc-circt terapines-osc-circt commented Jul 24, 2024

Based on the SystemVerilog IEEE Std 1800-2017 § 23.6 Hierarchical names. Hierarchical names are separated into upward and downward. For example:

module Top;
  int x;
  SubA subA();
  assign x = subA.a;  // upward: The Sub module's variable is used at the Top module.
endmodule

module SubA;
  int a;
  assign a = Top.x;  // downward: The Top module's variable is used at the Sub module.
endmodule

Therefore, we mark upward as outputs and downward as inputs, meanwhile, all hierarchical names are marked as RefType.

Unsupported cases:
However, we don't support hierarchical names invoked by two irrelevant modules at the same level. For example:

module A;
  int a = B.b;
endmodule

module B;
  int b = A.a;
endmodule

And we also don't support hierarchical names existing in the repeat modules. For example:

module Bar;
  SubC subC1();
  SubC subC2();
  int u = subC1.a;
  assign subC2.b = u;
endmodule

module SubC();
  int a, b;
endmodule

@terapines-osc-circt terapines-osc-circt force-pushed the hailong/hierarchical-value-and-defparam branch from 4fc101c to 3c3ab48 Compare July 24, 2024 09:37
@fabianschuiki
Copy link
Contributor

Really cool seeing this PR touching a really annoying and difficult corner of SystemVerilog 🥳!

I agree with you @hailongSun2000: simply accessing hierarchical names through the valueSymbols table is not going to work well. One of the reasons is that you cannot directly access an SSA value defined in another module, which is why we use the scopes with valueSymbols to only make SSA values visible within the same block. I'm pretty sure we need an entirely different mechanism for hierarchical paths.

One thing that would be great is if our solution to hierarchical paths wouldn't just magically refer to something defined in another module, but if we actually used SSA values (and maybe special module ports) to represent the hierarchical path. For example, when you see a hierarchical path a.b.c, it's non-trivial to figure out whether a refers to an instance in the current module (and you're accessing the hierarchy downwards), or if a is one of the current module's parents (and you're accessing the hierarchy upwards). It would be great if our mechanism for hierarchical paths in the IR would make this obvious and unambiguous, for example by passing around hierarchical pointers or references to what is being accessed.

@dtzWill has done a lot of awesome work on FIRRTL references/probes that we could draw a lot of inspiration from 🥇. We could take a similar approach and pass around references/pointers in the hierarchy:

module A;
  B b();
  assign b.c.y = b.c.x + 1;
endmodule

module B;
  C c();
endmodule

module C;
  int x = 42;
  int y;
endmodule
moore.module @A() {
  %b.href.c.x, %b.href.c.y = moore.instance "b" @B() -> (href.c.x: !moore.ref<i32>, href.c.y: !moore.ref<i32>)
  %0 = moore.read %b.href.c.x : <i32>  // read `b.c.x`
  %1 = moore.constant 1 : i32
  %2 = moore.add %0, %1 : i32
  moore.assign %b.href.c.y, %2 : <i32> // assign `b.c.y`
}

moore.module @B(
  out %href.c.x : !moore.ref<i32>,
  out %href.c.y : !moore.ref<i32>
) {
  %c.href.x, %c.href.y = moore.instance "c" @C() -> (href.x: !moore.ref<i32>, href.y: !moore.ref<i32>)
  moore.output %c.href.x, %c.href.y
}

moore.module @C(
  out %href.x : !moore.ref<i32>,
  out %href.y : !moore.ref<i32>
) {
  %0 = moore.constant 42 : i32
  %x = moore.variable %0 : i32
  %y = moore.variable : i32
  moore.output %x, %y  // return references to the hierarchically-accessed values
}

A potentially very nice part of materializing hierarchical references as actual references being passed around the hierarchy is that we may be able to write optimization passes later that turn these hierarchical references into regular ports. In the example above, we may later on figure out that b.c.x is only read, and b.c.y is only written, and therefore convert them accordingly:

  • out %href.c.x : !moore.ref<i32> converted to out %href.c.x : i32
  • out %href.c.y : !moore.ref<i32> converted to in %href.c.y : i32

To implement something like the reference-passing above, we would already have to know which variables are accessed via hierarchical paths when we convert a module body. Because if a variable is accessed through a hierarchical path, we have to create additional ports to make sure we can pass its reference around. To know this, we may have to do a pre-pass over the entire AST to find all hierarchical names, and determine what exactly they access and through which modules the references have to pass. In the example above, the path b.c.x means that module C has to make x available as a ref port, but it also means that module B has to pass the reference through to its parent. So in a sense we need to precompute information about all hierarchical names and which paths they take through the hierarchy. And then teach the module body lowering to look at that information and generate the necessary ports and ops.

What do you think about that @hailongSun2000, @dtzSiFive?

@terapines-osc-circt
Copy link
Member Author

terapines-osc-circt commented Jul 25, 2024

It looks like so reasonable! Let me get this straight.

To know this, we may have to do a pre-pass over the entire AST to find all hierarchical names, and determine what exactly they access and through which modules the references have to pass.

This is the first step.
Then make these hierarchical names as the outputs of the instance and module.
And we must be careful with hierarchy downwards or upwards.
I'll try it 😃!

@terapines-osc-circt terapines-osc-circt force-pushed the hailong/hierarchical-value-and-defparam branch 2 times, most recently from b692188 to f6b1e50 Compare August 23, 2024 11:08
@terapines-osc-circt terapines-osc-circt marked this pull request as draft August 23, 2024 11:09
@terapines-osc-circt
Copy link
Member Author

A lot of cases are not considered. Such as Top.sub.x = a, sub.x = a & b = sub.x, etc...
I just want to know whether my thought is correct. Only if it's right can I continue. @fabianschuiki Thanks for your guidance in advance ❤️!

@terapines-osc-circt terapines-osc-circt force-pushed the hailong/hierarchical-value-and-defparam branch 4 times, most recently from 28c0763 to be5d86d Compare August 27, 2024 03:23
@terapines-osc-circt terapines-osc-circt changed the title [ImportVerilog] Support hierarchical values and defparam. [ImportVerilog] Add HierarchicalNames.cpp to support hierarchical names/values. Aug 27, 2024
@terapines-osc-circt terapines-osc-circt changed the title [ImportVerilog] Add HierarchicalNames.cpp to support hierarchical names/values. [ImportVerilog] Add HierarchicalNames.cpp to support hierarchical names. Aug 27, 2024
@terapines-osc-circt terapines-osc-circt marked this pull request as ready for review August 27, 2024 03:24
@terapines-osc-circt terapines-osc-circt force-pushed the hailong/hierarchical-value-and-defparam branch from be5d86d to b58e91a Compare August 27, 2024 03:25
@terapines-osc-circt terapines-osc-circt marked this pull request as draft August 27, 2024 04:02
@terapines-osc-circt
Copy link
Member Author

I think I cannot mark Top.sub.var(Top.sub.var = x) as an input port, because we cannot assign a value to an input port 😅. I'll tweak it.

@terapines-osc-circt terapines-osc-circt force-pushed the hailong/hierarchical-value-and-defparam branch 3 times, most recently from cfba379 to 7c2876c Compare September 3, 2024 09:11
@terapines-osc-circt terapines-osc-circt force-pushed the hailong/hierarchical-value-and-defparam branch 2 times, most recently from bb6d878 to 56999b8 Compare September 18, 2024 07:17
@terapines-osc-circt terapines-osc-circt marked this pull request as ready for review September 18, 2024 07:20
@terapines-osc-circt terapines-osc-circt force-pushed the hailong/hierarchical-value-and-defparam branch from 56999b8 to e0191bf Compare September 19, 2024 08:47
@terapines-osc-circt terapines-osc-circt force-pushed the hailong/hierarchical-value-and-defparam branch 2 times, most recently from 55663e3 to 69b2d2c Compare September 26, 2024 07:15
@terapines-osc-circt terapines-osc-circt force-pushed the hailong/hierarchical-value-and-defparam branch from 69b2d2c to 475e5bb Compare December 4, 2024 08:08
// CHECK: [[RD_SC1_SD_Z:%.+]] = moore.read %subC1.subD.z : <i32>
// CHECK: moore.variable [[RD_SC1_SD_Z]] : <i32>
int u = subC1.subD.z;
// assign subC2.subD.z = u;
Copy link
Member Author

Choose a reason for hiding this comment

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

I'll fix this later.

@terapines-osc-circt
Copy link
Member Author

Hey, @fabianschuiki! I update this PR! Please check it, thanks in advance 😃!

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 working this out 🥳 And it's great to have all those tests around! 💯

@terapines-osc-circt terapines-osc-circt force-pushed the hailong/hierarchical-value-and-defparam branch from 475e5bb to 0d4cd40 Compare December 6, 2024 03:47
@terapines-osc-circt terapines-osc-circt merged commit 4a73177 into llvm:main Dec 6, 2024
4 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