diff --git a/lib/Dialect/FIRRTL/Transforms/AddSeqMemPorts.cpp b/lib/Dialect/FIRRTL/Transforms/AddSeqMemPorts.cpp index 58c1282004f9..2838a3704303 100644 --- a/lib/Dialect/FIRRTL/Transforms/AddSeqMemPorts.cpp +++ b/lib/Dialect/FIRRTL/Transforms/AddSeqMemPorts.cpp @@ -13,9 +13,11 @@ #include "PassDetails.h" #include "circt/Dialect/Emit/EmitOps.h" #include "circt/Dialect/FIRRTL/AnnotationDetails.h" +#include "circt/Dialect/FIRRTL/FIRRTLAnnotationHelper.h" #include "circt/Dialect/FIRRTL/FIRRTLInstanceGraph.h" #include "circt/Dialect/FIRRTL/FIRRTLOps.h" #include "circt/Dialect/FIRRTL/FIRRTLUtils.h" +#include "circt/Dialect/FIRRTL/Namespace.h" #include "circt/Dialect/FIRRTL/Passes.h" #include "circt/Dialect/HW/InnerSymbolNamespace.h" #include "circt/Dialect/SV/SVOps.h" @@ -66,8 +68,11 @@ struct AddSeqMemPortsPass : public AddSeqMemPortsBase { /// which is for some reason the format of the metadata file. std::vector> instancePaths; }; + + CircuitNamespace circtNamespace; /// This maps a module to information about the memories. DenseMap memInfoMap; + DenseMap innerRefToInstanceMap; InstanceGraph *instanceGraph; @@ -248,12 +253,13 @@ LogicalResult AddSeqMemPortsPass::processModule(FModuleOp module, bool isDUT) { // current module. auto &instancePaths = memInfo.instancePaths; auto ref = getInnerRefTo(inst); + innerRefToInstanceMap[ref] = inst; // If its a mem module, this is the start of a path to the module. if (isa(submodule)) instancePaths.push_back({ref}); // Copy any paths through the submodule to memories, adding the ref to // the current instance. - for (auto subPath : subMemInfo.instancePaths) { + for (const auto &subPath : subMemInfo.instancePaths) { instancePaths.push_back(subPath); instancePaths.back().push_back(ref); } @@ -285,6 +291,9 @@ void AddSeqMemPortsPass::createOutputFile(igraph::ModuleOpInterface module) { std::string buffer; llvm::raw_string_ostream os(buffer); + SymbolTable &symTable = getAnalysis(); + HierPathCache cache(circuit, symTable); + // The current parameter to the verbatim op. unsigned paramIndex = 0; // Parameters to the verbatim op. @@ -308,22 +317,37 @@ void AddSeqMemPortsPass::createOutputFile(igraph::ModuleOpInterface module) { // The current sram we are processing. unsigned sramIndex = 0; - auto dutSymbol = FlatSymbolRefAttr::get(module.getModuleNameAttr()); auto &instancePaths = memInfoMap[module].instancePaths; - for (auto instancePath : instancePaths) { - os << sramIndex++ << " -> "; - addSymbol(dutSymbol); - // The instance path is reverse from the order we print it. - for (auto ref : llvm::reverse(instancePath)) { - os << "."; - addSymbol(ref); - } - os << "\n"; - } + auto dutSymbol = FlatSymbolRefAttr::get(module.getModuleNameAttr()); - // Put the information in a verbatim operation. auto loc = builder.getUnknownLoc(); + // Put the information in a verbatim operation. builder.create(loc, outputFile, [&] { + for (auto instancePath : instancePaths) { + // Note: Reverse instancepath to construct the NLA. + SmallVector path(llvm::reverse(instancePath)); + os << sramIndex++ << " -> "; + addSymbol(dutSymbol); + os << "."; + + auto nlaSymbol = cache.getRefFor(builder.getArrayAttr(path)); + addSymbol(nlaSymbol); + NamedAttrList fields; + // There is no current client for the distinct attr, but it will be used + // by OM::path once the metadata is moved to OM, instead of the verbatim. + auto id = DistinctAttr::create(UnitAttr::get(builder.getContext())); + fields.append("id", id); + fields.append("class", builder.getStringAttr("circt.tracker")); + fields.append("circt.nonlocal", nlaSymbol); + // Now add the nonlocal annotation to the leaf instance. + auto *leafInstance = innerRefToInstanceMap[instancePath.front()]; + + AnnotationSet annos(leafInstance); + annos.addAnnotations(builder.getDictionaryAttr(fields)); + annos.applyToOperation(leafInstance); + + os << "\n"; + } builder.create(loc, buffer, ValueRange{}, builder.getArrayAttr(params)); }); @@ -334,6 +358,7 @@ void AddSeqMemPortsPass::runOnOperation() { auto *context = &getContext(); auto circuit = getOperation(); instanceGraph = &getAnalysis(); + circtNamespace = CircuitNamespace(circuit); // Clear the state. userPorts.clear(); memInfoMap.clear(); diff --git a/test/Dialect/FIRRTL/add-seqmem-ports.mlir b/test/Dialect/FIRRTL/add-seqmem-ports.mlir index 0a117e296f09..abedcd805daa 100644 --- a/test/Dialect/FIRRTL/add-seqmem-ports.mlir +++ b/test/Dialect/FIRRTL/add-seqmem-ports.mlir @@ -156,18 +156,28 @@ firrtl.circuit "Complex" attributes {annotations = [ input = false, width = 4 }]} { + + // CHECK: hw.hierpath private @[[memNLA:.+]] [@DUT::@[[MWRITE_EXT:.+]]] + // CHECK: hw.hierpath private @[[memNLA_0:.+]] [@DUT::@[[CHILD:.+]], @Child::@[[CHILD_MWRITE_EXT:.+]]] + // CHECK: hw.hierpath private @[[memNLA_1:.+]] [@DUT::@[[MWRITE_EXT_0:.+]]] firrtl.memmodule @MWrite_ext(in W0_addr: !firrtl.uint<4>, in W0_en: !firrtl.uint<1>, in W0_clk: !firrtl.clock, in W0_data: !firrtl.uint<42>) attributes {dataWidth = 42 : ui32, depth = 12 : ui64, extraPorts = [], maskBits = 1 : ui32, numReadPorts = 0 : ui32, numReadWritePorts = 0 : ui32, numWritePorts = 1 : ui32, readLatency = 1 : ui32, writeLatency = 1 : ui32} firrtl.module @Child() { - // CHECK: firrtl.instance MWrite_ext sym @[[CHILD_MWRITE_EXT:.+]] @MWrite_ext + // CHECK: firrtl.instance MWrite_ext sym @[[CHILD_MWRITE_EXT]] + // CHECK-SAME: circt.nonlocal = @[[memNLA_0]] + // CHECK-SAME: @MWrite_ext %0:4 = firrtl.instance MWrite_ext @MWrite_ext(in W0_addr: !firrtl.uint<4>, in W0_en: !firrtl.uint<1>, in W0_clk: !firrtl.clock, in W0_data: !firrtl.uint<42>) } firrtl.module @DUT() attributes {annotations = [{class = "sifive.enterprise.firrtl.MarkDUTAnnotation"}]} { // Double check that these instances now have symbols on them: - // CHECK: firrtl.instance MWrite_ext sym @[[MWRITE_EXT:.+]] @MWrite_ext( + // CHECK: firrtl.instance MWrite_ext sym @[[MWRITE_EXT]] + // CHECK-SAME: circt.nonlocal = @[[memNLA]] + // CHECK-SAME: @MWrite_ext( %0:4 = firrtl.instance MWrite_ext @MWrite_ext(in W0_addr: !firrtl.uint<4>, in W0_en: !firrtl.uint<1>, in W0_clk: !firrtl.clock, in W0_data: !firrtl.uint<42>) - // CHECK: firrtl.instance child sym @[[CHILD:.+]] @Child( + // CHECK: firrtl.instance child sym @[[CHILD]] @Child( firrtl.instance child @Child() - // CHECK: firrtl.instance MWrite_ext sym @[[MWRITE_EXT_0:.+]] @MWrite_ext( + // CHECK: firrtl.instance MWrite_ext sym @[[MWRITE_EXT_0]] + // CHECK-SAME: circt.nonlocal = @[[memNLA_1]] + // CHECK-SAME: @MWrite_ext( %1:4 = firrtl.instance MWrite_ext @MWrite_ext(in W0_addr: !firrtl.uint<4>, in W0_en: !firrtl.uint<1>, in W0_clk: !firrtl.clock, in W0_data: !firrtl.uint<42>) } firrtl.module @Complex() { @@ -176,8 +186,8 @@ firrtl.circuit "Complex" attributes {annotations = [ // CHECK: emit.file "metadata{{/|\\\\}}sram.txt" { // CHECK-NEXT: sv.verbatim // CHECK-SAME{LITERAL}: 0 -> {{0}}.{{1}} - // CHECK-SAME{LITERAL}: 1 -> {{0}}.{{2}}.{{3}} - // CHECK-SAME{LITERAL}: 2 -> {{0}}.{{4}} - // CHECK-SAME: {symbols = [@DUT, #hw.innerNameRef<@DUT::@[[MWRITE_EXT]]>, #hw.innerNameRef<@DUT::@[[CHILD]]>, #hw.innerNameRef<@Child::@[[CHILD_MWRITE_EXT]]>, #hw.innerNameRef<@DUT::@[[MWRITE_EXT_0]]>]} + // CHECK-SAME{LITERAL}: 1 -> {{0}}.{{2}} + // CHECK-SAME{LITERAL}: 2 -> {{0}}.{{3}} + // CHECK-SAME: {symbols = [@DUT, @[[memNLA]], @[[memNLA_0]], @[[memNLA_1]]]} // CHECK-NEXT: } }