Hi, everybody! I’ve come up with an idea of my custom dialect. Say, I have something like this:
mydialerct.module @name inputs(...) outputs(...)
{
mydialect.pull %input // pull something out of the input channels
ops // some other ops of upstream dialects
mydialect.push (%something_to_push) %output // push something out to the output channels
}
What I want to do is to wrap all these ops inbetween pulles and pushes into a func.func
and insert it at the top of the module. Instead these ops will become a mydialect.instace
, which will later be lowered into hw.instance
. With this approach I could easily use the existing passes to lower this new FuncOp into the core dialect of CIRCT, so I could only focus on the lowering of ops in mydialect
.
But here comes the problem: In a design, it’s apparently that there won’t be only one mydialerct.module
, so with this method I would have multiple func.func
inserted at the top. These FuncOps can be lowered into handshake.func
ops with no other efforts. But when trying to lower handshake to hw, the pass will report an error saying:
error: 'builtin.module' op multiple candidate top-level modules detected (...). Please remove one of these from the source program.
I know that if I create one handshake.func
and call al the others in it, the problem is solved, because the pass will consider this func as the top one. But in my design, there is another custom op having the top function semantics, which won’t be lowered into handshake but directly into hw.
To solve this problem, I firstly thought that I could print all these new created func/func
into seperate files and replace them with a hw.module.extern
. But this method would require user to manually use hlstool to generate the hw modules.
So how could I manage this? And why exactly we need this check, since we can set up a top in vendors’ tool later?