Hello there!
I’ve recently been exposed to Circt at my student assistant job and have been playing around with it, seeing what kind of stuff the IR supports. There I have run into a very curios bug regarding Arrays and Parameters. I’ll write a more detailed Issue on Github later, but I wanted to try and debug the issue myself a bit before that.
Short summary of the bug for the curious
If you instantiate a module that outputs a parametrized array the verifier will fail if the left side is parametrized. A short example:
hw.module.extern @submodule<A: i32 = 3, B: i32 = 8>(
) -> (out : !hw.array<#hw.param.decl.ref<"A">x!hw.int<#hw.param.decl.ref<"B">>>)
hw.module @test<A: i32 = 3, B: i32 = 8>(
) -> (out: !hw.array<#hw.param.decl.ref<"A">x!hw.int<#hw.param.decl.ref<"B">>>) {
%out = hw.instance "submodule" @submodule<
A: i32 = #hw.param.decl.ref<"A">,
B: i32 = #hw.param.decl.ref<"B">>() -> (out : !hw.array<#hw.param.decl.ref<"A">x!hw.int<#hw.param.decl.ref<"B">>>)
hw.output %out : !hw.array<#hw.param.decl.ref<"A">x!hw.int<#hw.param.decl.ref<"B">>>
}
This causes a very perplexing error where it says two equal things are not equal:
error: 'hw.instance' op result type #0 must be '!hw.array<#hw.param.decl.ref<"A">xint<#hw.param.decl.ref<"B">>>', but got '!hw.array<#hw.param.decl.ref<"A">xint<#hw.param.decl.ref<"B">>>'
%out = hw.instance "submodule" @submodule<
Parametrizing only the right side of the array works however and produces correct Verilog.
Now I’ve, got a look at the stack trace and inspected the relevant code (instance_like_impl::verifyOutputs
and hw::evaluateParametricType
in particular) and I still can’t quite figure out where the problem comes from, so I’ve decided to try compiling CIRCT with debug information (-DCMAKE_BUILD_TYPE=DEBUG
) and using a debugger.
Now the problem however is, that I’m having issues getting any useful information. While I can evaluate some expressions like expectedType.getTypeID()
or expectedType.dump()
(which both show equality with resultType
btw.), the following kind of stuff fails:
p resultType == expectedType
error: Couldn't lookup symbols:
mlir::Type::Type(mlir::Type const&)
p resultType.cast<hw::ArrayType>()
error: <user expression 1>:1:12: no member named 'cast' in 'mlir::Type'
1 | resultType.cast<hw::ArrayType>()
| ~~~~~~~~~~ ^
error: <user expression 1>:1:30: expected '(' for function-style cast or type construction
1 | resultType.cast<hw::ArrayType>()
| ~~~~~~~~~~~~~^
error: <user expression 1>:1:32: expected expression
1 | resultType.cast<hw::ArrayType>()
|
p mlir::cast<hw:ArrayType>(expectedType)
error: <user expression 3>:1:7: no member named 'cast' in namespace 'mlir'
1 | mlir::cast<hw:ArrayType>(expectedType)
| ~~~~~~^
error: <user expression 3>:1:14: unexpected ':' in nested name specifier; did you mean '::'?
1 | mlir::cast<hw:ArrayType>(expectedType)
| ^
| ::
error: <user expression 3>:1:24: expected '(' for function-style cast or type construction
1 | mlir::cast<hw:ArrayType>(expectedType)
| ~~~~~~~~~~~~^
So no casting to ArrayType to see what Attr is actually stored in size
of the array, which is blocking me off from investigating further.
Does anyone have some tips on Debugging CIRCT or an idea what I’m doing wrong here? I’m pretty new to C++ debugging, so maybe I missed a flag somewhere or made another error. I’ve tried it both with the CodeLLDB extension in VSCode, LLDB on the command line and quickly with the gdb debugger from the C/C++ extension and always got similar errors.
launch.json in VSCode
{
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Launch",
"type": "cppdbg",
"request": "launch",
"program": "/local/llvm-project/build/bin/circt-opt",
"args": [
"-pass-pipeline='builtin.module(convert-fsm-to-sv,lower-seq-to-sv,lower-hwarith-to-hw,export-split-verilog{dir-name=/local/projects/circt_cnn/src/hdl/gen})'",
"/local/projects/circt_cnn/src/mlir/array.mlir"
],
"cwd": "${workspaceFolder}",
"stopAtEntry": false,
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "Set Disassembly Flavor to Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
}
]
},
{
"type": "lldb",
"request": "launch",
"name": "Debug LLDB",
"program": "/local/llvm-project/build/bin/circt-opt",
"args": [
"-pass-pipeline='builtin.module(convert-fsm-to-sv,lower-seq-to-sv,lower-hwarith-to-hw,export-split-verilog{dir-name=/local/projects/circt_cnn/src/hdl/gen})'",
"--mlir-print-ir-after-failure",
"/local/projects/circt_cnn/src/mlir/example_notworking.mlir"
],
"cwd": "/local/llvm-project",
"relativePathBase": "/local/llvm-project"
}
]
}
Sequence of commands in lldb console
lldb /local/llvm-project/build/bin/circt-opt
(lldb) target create "/local/llvm-project/build/bin/circt-opt"
Current executable set to '/local/llvm-project/build/bin/circt-opt' (x86_64).
(lldb) breakpoint set --file circt/lib/Dialect/HW/InstanceImplementation.cpp --line 148
Breakpoint 1: 2 locations
(lldb) process launch -- -pass-pipeline='builtin.module(convert-fsm-to-sv,lower-seq-to-sv,lower-hwarith-to-hw,export-split-verilog{dir-name=/local/circt_cnn/src/hdl/gen})' /local/circt_cnn/src/mlir/array.mlir
Process 1554738 launched: '/local/llvm-project/build/bin/circt-opt' (x86_64)
Process 1554738 stopped
* thread #1, name = 'circt-opt', stop reason = breakpoint 1.1
frame #0: 0x00000000018be4bb circt-opt`circt::hw::instance_like_impl::verifyOutputs(resultNames=ArrayAttr @ 0x00007fffffffafd0, moduleResultNames=ArrayAttr @ 0x00007fffffffafc8, resultTypes=TypeRange @ 0x00007fffffffafb8, moduleResultTypes=ArrayRef<mlir::Type> @ 0x00007fffffffafa8, emitError=0x00007fffffffb248)>)> const&) at InstanceImplementation.cpp:149:7
146
147 if (resultType != expectedType) {
148 // if (resultType.getTypeID() != expectedType.getTypeID()) {
-> 149 emitError([&](auto &diag) {
150 diag << "result type #" << i << " must be " << expectedType
151 << ", but got " << resultType;
152 return true;
(lldb) p expectedType == resultType
warning: (x86_64) /local/llvm-project/build/bin/circt-opt 0x0776c478: DW_AT_specification(0x07764bdb) has no decl
warning: (x86_64) /local/llvm-project/build/bin/circt-opt 0x09b70a61: DW_AT_specification(0x09b6da60) has no decl
error: expression failed to parse:
error: Couldn't lookup symbols:
mlir::Type::Type(mlir::Type const&)