[ImportVerilog]Dedup module Op (#7245)

Co-authored-by: Fabian Schuiki <fabian@schuiki.ch>
This commit is contained in:
mingzheTerapines 2024-07-18 10:05:44 +08:00 committed by GitHub
parent 815da47151
commit d3ce6f6eb2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 98 additions and 0 deletions

View File

@ -36,6 +36,8 @@ struct PortLowering {
struct ModuleLowering {
moore::SVModuleOp op;
SmallVector<PortLowering> ports;
DenseMap<const slang::syntax::SyntaxNode *, const slang::ast::PortSymbol *>
portsBySyntaxNode;
};
/// A helper class to facilitate the conversion from a Slang AST to MLIR

View File

@ -133,6 +133,10 @@ struct MemberVisitor {
// connection for the port.
if (!expr) {
auto *port = con->port.as_if<PortSymbol>();
if (auto *existingPort =
moduleLowering->portsBySyntaxNode.lookup(port->getSyntax()))
port = existingPort;
switch (port->direction) {
case slang::ast::ArgumentDirection::In: {
auto refType = moore::RefType::get(
@ -191,6 +195,9 @@ struct MemberVisitor {
: context.convertLvalueExpression(*expr);
if (!value)
return failure();
if (auto *existingPort =
moduleLowering->portsBySyntaxNode.lookup(con->port.getSyntax()))
port = existingPort;
portValues.insert({port, value});
continue;
}
@ -206,6 +213,9 @@ struct MemberVisitor {
unsigned offset = 0;
auto i32 = moore::IntType::getInt(context.getContext(), 32);
for (const auto *port : llvm::reverse(multiPort->ports)) {
if (auto *existingPort = moduleLowering->portsBySyntaxNode.lookup(
con->port.getSyntax()))
port = existingPort;
unsigned width = port->getType().getBitWidth();
auto index = builder.create<moore::ConstantOp>(loc, i32, offset);
auto sliceType = context.convertType(port->getType());
@ -470,7 +480,56 @@ ModuleLowering *
Context::convertModuleHeader(const slang::ast::InstanceBodySymbol *module) {
using slang::ast::ArgumentDirection;
using slang::ast::MultiPortSymbol;
using slang::ast::ParameterSymbol;
using slang::ast::PortSymbol;
using slang::ast::TypeParameterSymbol;
auto parameters = module->parameters;
bool hasModuleSame = false;
// If there is already exist a module that has the same name with this
// module ,has the same parent scope and has the same parameters we can
// define this module is a duplicate module
for (auto const &existingModule : modules) {
if (module->getDeclaringDefinition() ==
existingModule.getFirst()->getDeclaringDefinition()) {
auto moduleParameters = existingModule.getFirst()->parameters;
hasModuleSame = true;
for (auto it1 = parameters.begin(), it2 = moduleParameters.begin();
it1 != parameters.end() && it2 != moduleParameters.end();
it1++, it2++) {
// Parameters size different
if (it1 == parameters.end() || it2 == moduleParameters.end()) {
hasModuleSame = false;
break;
}
const auto *para1 = (*it1)->symbol.as_if<ParameterSymbol>();
const auto *para2 = (*it2)->symbol.as_if<ParameterSymbol>();
// Parameters kind different
if ((para1 == nullptr) ^ (para2 == nullptr)) {
hasModuleSame = false;
break;
}
// Compare ParameterSymbol
if (para1 != nullptr) {
hasModuleSame = para1->getValue() == para2->getValue();
}
// Compare TypeParameterSymbol
if (para1 == nullptr) {
auto para1Type = convertType(
(*it1)->symbol.as<TypeParameterSymbol>().getTypeAlias());
auto para2Type = convertType(
(*it2)->symbol.as<TypeParameterSymbol>().getTypeAlias());
hasModuleSame = para1Type == para2Type;
}
if (!hasModuleSame)
break;
}
if (hasModuleSame) {
module = existingModule.first;
break;
}
}
}
auto &slot = modules[module];
if (slot)
@ -553,6 +612,11 @@ Context::convertModuleHeader(const slang::ast::InstanceBodySymbol *module) {
// Schedule the body to be lowered.
moduleWorklist.push(module);
// Map duplicate port by Syntax
for (const auto &port : lowering.ports)
lowering.portsBySyntaxNode.insert({port.ast.getSyntax(), &port.ast});
return &lowering;
}

View File

@ -20,6 +20,38 @@ module Empty;
; // empty member
endmodule
module DedupA(input wire a,
input wire b,
output wire [3:0] c);
endmodule
module DedupB #(parameter p = 32)
(input wire a,
input wire b,
output wire [3:0] c);
endmodule
// CHECK-LABEL: moore.module private @DedupA(in %a : !moore.l1, in %b : !moore.l1, out c : !moore.l4) {
// CHECK-LABEL: moore.module private @DedupB(in %a : !moore.l1, in %b : !moore.l1, out c : !moore.l4) {
// CHECK-LABEL: moore.module private @DedupB_0(in %a : !moore.l1, in %b : !moore.l1, out c : !moore.l4) {
// CHECK-LABEL: moore.module @Dedup
module Dedup;
wire [3:0] a;
wire [3:0] b;
wire [3:0] c;
// CHECK-LABEL: moore.instance "insA" @DedupA
DedupA insA(.a(a), .c(c));
// CHECK-LABEL: moore.instance "insB" @DedupA
DedupA insB(.b(b), .c(c));
// CHECK-LABEL: moore.instance "insC" @DedupB
DedupB insC(.c(c));
// CHECK-LABEL: moore.instance "insD" @DedupB
DedupB insD(.a(a), .b(b), .c(c));
// CHECK-LABEL: moore.instance "insE" @DedupB_0
DedupB #(8) insE(.c(c));
endmodule
// CHECK-LABEL: moore.module @NestedA() {
// CHECK: moore.instance "NestedB" @NestedB
// CHECK: }