mirror of https://github.com/llvm/circt.git
[ImportVerilog]Dedup module Op (#7245)
Co-authored-by: Fabian Schuiki <fabian@schuiki.ch>
This commit is contained in:
parent
815da47151
commit
d3ce6f6eb2
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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: }
|
||||
|
|
Loading…
Reference in New Issue