diff --git a/include/circt/Dialect/FIRRTL/FIRRTLStructure.td b/include/circt/Dialect/FIRRTL/FIRRTLStructure.td index 0e03ac4fd291..16a0209e5e26 100644 --- a/include/circt/Dialect/FIRRTL/FIRRTLStructure.td +++ b/include/circt/Dialect/FIRRTL/FIRRTLStructure.td @@ -291,6 +291,7 @@ def FMemModuleOp : FIRRTLModuleLike<"memmodule"> { ArrayRefAttr:$portTypes, DefaultValuedAttr:$ruw, + OptionalAttr:$init, AnnotationArrayAttr:$annotations, DefaultValuedAttr:$layers, DefaultValuedAttr:$domainInfo @@ -308,6 +309,7 @@ def FMemModuleOp : FIRRTLModuleLike<"memmodule"> { "uint32_t":$writeLatency, "uint64_t":$depth, CArg<"firrtl::RUWBehavior", "firrtl::RUWBehavior::Undefined">:$ruw, + CArg<"firrtl::MemoryInitAttr", "{}">:$init, CArg<"ArrayAttr", "ArrayAttr()">:$annotations, CArg<"ArrayAttr", "ArrayAttr()">:$layers)> ]; diff --git a/lib/Dialect/FIRRTL/FIRRTLOps.cpp b/lib/Dialect/FIRRTL/FIRRTLOps.cpp index 00272e92ac5e..e549bab56517 100644 --- a/lib/Dialect/FIRRTL/FIRRTLOps.cpp +++ b/lib/Dialect/FIRRTL/FIRRTLOps.cpp @@ -1188,7 +1188,8 @@ void FMemModuleOp::build(OpBuilder &builder, OperationState &result, uint32_t numReadWritePorts, uint32_t dataWidth, uint32_t maskBits, uint32_t readLatency, uint32_t writeLatency, uint64_t depth, RUWBehavior ruw, - ArrayAttr annotations, ArrayAttr layers) { + MemoryInitAttr init, ArrayAttr annotations, + ArrayAttr layers) { auto *context = builder.getContext(); buildModule(builder, result, name, ports, annotations, layers); auto ui32Type = IntegerType::get(context, 32, IntegerType::Unsigned); @@ -1205,6 +1206,7 @@ void FMemModuleOp::build(OpBuilder &builder, OperationState &result, properties.setDepth(IntegerAttr::get(ui64Type, depth)); properties.setExtraPorts(ArrayAttr::get(context, {})); properties.setRuw(RUWBehaviorAttr::get(context, ruw)); + properties.setInit(init); } /// Print a list of module ports in the following form: diff --git a/lib/Dialect/FIRRTL/Transforms/CreateSiFiveMetadata.cpp b/lib/Dialect/FIRRTL/Transforms/CreateSiFiveMetadata.cpp index 3b3925d2b8cd..5042c8ff50c0 100644 --- a/lib/Dialect/FIRRTL/Transforms/CreateSiFiveMetadata.cpp +++ b/lib/Dialect/FIRRTL/Transforms/CreateSiFiveMetadata.cpp @@ -100,7 +100,18 @@ struct ObjectModelIR { extraPortsClass = ClassOp::create(builderOM, "ExtraPortsMemorySchema", extraPortFields, extraPortsType); - mlir::Type classFieldTypes[14] = { + mlir::Type memInitType[] = { + StringType::get(context), // filename + BoolType::get(context), // isBinary + BoolType::get(context) // isInline + }; + + StringRef memInitFields[3] = {"filename", "isBinary", "isInline"}; + + memInitFileClass = ClassOp::create(builderOM, "MemoryInitFileSchema", + memInitFields, memInitType); + + mlir::Type classFieldTypes[15] = { StringType::get(context), FIntegerType::get(context), FIntegerType::get(context), @@ -117,7 +128,9 @@ struct ObjectModelIR { context, cast( detail::getInstanceTypeForClassLike(extraPortsClass))), ListType::get(context, cast(StringType::get(context))), - }; + ListType::get(context, + cast(detail::getInstanceTypeForClassLike( + memInitFileClass)))}; memorySchemaClass = ClassOp::create(builderOM, "MemorySchema", memoryParamNames, classFieldTypes); @@ -359,6 +372,27 @@ struct ObjectModelIR { } auto extraPorts = ListCreateOp::create( builderOM, memorySchemaClass.getPortType(24), extraPortsList); + + SmallVector memInitFileVec; + if (mem.getInit().has_value()) { + auto filename = createConstField(mem.getInit()->getFilename()); + auto isBinary = createConstField( + BoolAttr::get(context, mem.getInit()->getIsBinary())); + auto isInline = createConstField( + BoolAttr::get(context, mem.getInit()->getIsInline())); + auto memInitFileObj = + ObjectOp::create(builderOM, memInitFileClass, "initFile"); + auto inPort = ObjectSubfieldOp::create(builderOM, memInitFileObj, 0); + PropAssignOp::create(builderOM, inPort, filename); + inPort = ObjectSubfieldOp::create(builderOM, memInitFileObj, 2); + PropAssignOp::create(builderOM, inPort, isBinary); + inPort = ObjectSubfieldOp::create(builderOM, memInitFileObj, 4); + PropAssignOp::create(builderOM, inPort, isInline); + memInitFileVec.push_back(memInitFileObj); + } + auto memInitFile = ListCreateOp::create( + builderOM, memorySchemaClass.getPortType(28), memInitFileVec); + for (auto field : llvm::enumerate(memoryParamNames)) { auto propVal = createConstField( llvm::StringSwitch(field.value()) @@ -375,6 +409,7 @@ struct ObjectModelIR { .Case("inDut", BoolAttr::get(context, inDut)) .Case("extraPorts", {}) .Case("preExtInstName", {}) + .Case("initFile", {}) .Case("ruwBehavior", builderOM.getStringAttr( stringifyRUWBehavior(mem.getRuw())))); if (!propVal) { @@ -382,8 +417,10 @@ struct ObjectModelIR { propVal = hierpaths; else if (field.value() == "preExtInstName") propVal = finalInstNamesList; - else + else if (field.value() == "extraPorts") propVal = extraPorts; + else + propVal = memInitFile; } // The memory schema is a simple class, with input tied to output. The @@ -495,15 +532,15 @@ struct ObjectModelIR { InstanceInfo &instanceInfo; /// Cached module namespaces. DenseMap &moduleNamespaces; - ClassOp memorySchemaClass, extraPortsClass; + ClassOp memorySchemaClass, extraPortsClass, memInitFileClass; ClassOp memoryMetadataClass; ClassOp retimeModulesMetadataClass, retimeModulesSchemaClass; ClassOp blackBoxModulesSchemaClass, blackBoxMetadataClass; - StringRef memoryParamNames[14] = { - "name", "depth", "width", "maskBits", - "readPorts", "writePorts", "readwritePorts", "writeLatency", - "readLatency", "ruwBehavior", "hierarchy", "inDut", - "extraPorts", "preExtInstName"}; + StringRef memoryParamNames[15] = { + "name", "depth", "width", "maskBits", + "readPorts", "writePorts", "readwritePorts", "writeLatency", + "readLatency", "ruwBehavior", "hierarchy", "inDut", + "extraPorts", "preExtInstName", "initFile"}; StringRef retimeModulesParamNames[1] = {"moduleName"}; StringRef blackBoxModulesParamNames[3] = {"moduleName", "inDut", "libraries"}; llvm::SmallDenseSet blackboxModules; @@ -611,14 +648,20 @@ CreateSiFiveMetadataPass::emitMemoryMetadata(ObjectModelIR &omir) { auto maskGranStr = !isMasked ? "" : " mask_gran " + std::to_string(maskGran); - seqMemConfStr = (StringRef(seqMemConfStr) + "name {{" + Twine(symId) + - "}} depth " + Twine(mem.getDepth()) + " width " + - Twine(width) + " ports " + portStr + maskGranStr + - (mem.getRuw() == RUWBehavior::Undefined - ? "" - : " ruw " + stringifyRUWBehavior(mem.getRuw())) + - "\n") - .str(); + seqMemConfStr += ("name {{" + Twine(symId) + "}}").str(); + seqMemConfStr += (" depth " + Twine(mem.getDepth())).str(); + seqMemConfStr += (" width " + Twine(width)).str(); + seqMemConfStr += " ports " + portStr; + seqMemConfStr += maskGranStr; + if (mem.getRuw() != RUWBehavior::Undefined) + seqMemConfStr += (" ruw " + stringifyRUWBehavior(mem.getRuw())).str(); + if (mem.getInit().has_value()) { + seqMemConfStr += + mem.getInit()->getIsBinary() ? " init-bin " : " init-hex "; + seqMemConfStr += + ("\"" + mem.getInit()->getFilename().getValue() + "\"").str(); + } + seqMemConfStr += "\n"; // Do not emit any JSON for memories which are not in the DUT. if (!instanceInfo->anyInstanceInEffectiveDesign(mem)) @@ -636,6 +679,14 @@ CreateSiFiveMetadataPass::emitMemoryMetadata(ObjectModelIR &omir) { jsonStream.attribute("ruw_behavior", stringifyRUWBehavior(mem.getRuw())); if (isMasked) jsonStream.attribute("mask_granularity", (int64_t)maskGran); + if (mem.getInit().has_value()) { + jsonStream.attributeObject("init", [&] { + jsonStream.attribute("filename", + mem.getInit()->getFilename().getValue()); + jsonStream.attribute("isBinary", mem.getInit()->getIsBinary()); + jsonStream.attribute("isInline", mem.getInit()->getIsInline()); + }); + } jsonStream.attributeArray("extra_ports", [&] { for (auto attr : mem.getExtraPorts()) { jsonStream.object([&] { diff --git a/lib/Dialect/FIRRTL/Transforms/LowerMemory.cpp b/lib/Dialect/FIRRTL/Transforms/LowerMemory.cpp index 02780cb44a7a..0877e95e9a35 100644 --- a/lib/Dialect/FIRRTL/Transforms/LowerMemory.cpp +++ b/lib/Dialect/FIRRTL/Transforms/LowerMemory.cpp @@ -207,7 +207,8 @@ LowerMemoryPass::emitMemoryModule(MemOp op, const FirMemory &mem, b, mem.loc, moduleName, ports, mem.numReadPorts, mem.numWritePorts, mem.numReadWritePorts, mem.dataWidth, mem.maskBits, mem.readLatency, mem.writeLatency, mem.depth, - *symbolizeRUWBehavior(static_cast(mem.readUnderWrite))); + *symbolizeRUWBehavior(static_cast(mem.readUnderWrite)), + mem.init); SymbolTable::setSymbolVisibility(moduleOp, SymbolTable::Visibility::Private); return moduleOp; } diff --git a/test/Dialect/FIRRTL/SFCTests/directories.fir b/test/Dialect/FIRRTL/SFCTests/directories.fir index 0fcd5a82bcd6..69a88795c7e9 100644 --- a/test/Dialect/FIRRTL/SFCTests/directories.fir +++ b/test/Dialect/FIRRTL/SFCTests/directories.fir @@ -155,8 +155,8 @@ circuit TestHarness: ; MLIR_OUT: om.class.fields [[OBJ1]], [[OBJ2]], [[OBJ3]] : !om.class.type<@SitestBlackBoxModulesSchema>, !om.class.type<@SitestBlackBoxModulesSchema>, !om.class.type<@SitestBlackBoxModulesSchema> ; MLIR_OUT: } -; MLIR_OUT: om.class @MemorySchema(%basepath: !om.basepath, %name_in: !om.string, %depth_in: !om.integer, %width_in: !om.integer, %maskBits_in: !om.integer, %readPorts_in: !om.integer, %writePorts_in: !om.integer, %readwritePorts_in: !om.integer, %writeLatency_in: !om.integer, %readLatency_in: !om.integer, %ruwBehavior_in: !om.string, %hierarchy_in: !om.list, %inDut_in: i1, %extraPorts_in: !om.list>, %preExtInstName_in: !om.list) -> (name: !om.string, depth: !om.integer, width: !om.integer, maskBits: !om.integer, readPorts: !om.integer, writePorts: !om.integer, readwritePorts: !om.integer, writeLatency: !om.integer, readLatency: !om.integer, ruwBehavior: !om.string, hierarchy: !om.list, inDut: i1, extraPorts: !om.list>, preExtInstName: !om.list) -; MLIR_OUT: om.class.fields %name_in, %depth_in, %width_in, %maskBits_in, %readPorts_in, %writePorts_in, %readwritePorts_in, %writeLatency_in, %readLatency_in, %ruwBehavior_in, %hierarchy_in, %inDut_in, %extraPorts_in, %preExtInstName_in : !om.string, !om.integer, !om.integer, !om.integer, !om.integer, !om.integer, !om.integer, !om.integer, !om.integer, !om.string, !om.list, i1, !om.list>, !om.list +; MLIR_OUT: om.class @MemorySchema(%basepath: !om.basepath, %name_in: !om.string, %depth_in: !om.integer, %width_in: !om.integer, %maskBits_in: !om.integer, %readPorts_in: !om.integer, %writePorts_in: !om.integer, %readwritePorts_in: !om.integer, %writeLatency_in: !om.integer, %readLatency_in: !om.integer, %ruwBehavior_in: !om.string, %hierarchy_in: !om.list, %inDut_in: i1, %extraPorts_in: !om.list>, %preExtInstName_in: !om.list, %initFile_in: !om.list>) -> (name: !om.string, depth: !om.integer, width: !om.integer, maskBits: !om.integer, readPorts: !om.integer, writePorts: !om.integer, readwritePorts: !om.integer, writeLatency: !om.integer, readLatency: !om.integer, ruwBehavior: !om.string, hierarchy: !om.list, inDut: i1, extraPorts: !om.list>, preExtInstName: !om.list, initFile: !om.list>) +; MLIR_OUT: om.class.fields %name_in, %depth_in, %width_in, %maskBits_in, %readPorts_in, %writePorts_in, %readwritePorts_in, %writeLatency_in, %readLatency_in, %ruwBehavior_in, %hierarchy_in, %inDut_in, %extraPorts_in, %preExtInstName_in, %initFile_in : !om.string, !om.integer, !om.integer, !om.integer, !om.integer, !om.integer, !om.integer, !om.integer, !om.integer, !om.string, !om.list, i1, !om.list>, !om.list, !om.list> ; MLIR_OUT-DAG: om.path_create instance %basepath @memHier ; MLIR_OUT-DAG: om.list_create ; MLIR_OUT-DAG: [[OBJ1:%.+]] = om.object @MemorySchema diff --git a/test/Dialect/FIRRTL/emit-metadata.mlir b/test/Dialect/FIRRTL/emit-metadata.mlir index 7f7f4fce404f..6e519a792b2c 100644 --- a/test/Dialect/FIRRTL/emit-metadata.mlir +++ b/test/Dialect/FIRRTL/emit-metadata.mlir @@ -578,6 +578,11 @@ firrtl.circuit "Foo" { // CHECK-NEXT: firrtl.instance m // CHECK-SAME: id = distinct[[[#memId:]]]<> +// CHECK-LABEL: firrtl.class @MemoryInitFileSchema( +// CHECK-NEXT: firrtl.propassign %filename, %filename_in +// CHECK-NEXT: firrtl.propassign %isBinary, %isBinary_in +// CHECK-NEXT: firrtl.propassign %isInline, %isInline_in + // CHECK-LABEL: firrtl.class @MemorySchema( // CHECK-NEXT: firrtl.propassign %name, %name_in // CHECK-NEXT: firrtl.propassign %depth, %depth_in @@ -593,6 +598,7 @@ firrtl.circuit "Foo" { // CHECK-NEXT: firrtl.propassign %inDut, %inDut_in // CHECK-NEXT: firrtl.propassign %extraPorts, %extraPorts_in // CHECK-NEXT: firrtl.propassign %preExtInstName, %preExtInstName_in +// CHECK-NEXT: firrtl.propassign %initFile, %initFile_in // CHECK-LABEL: firrtl.class @MemoryMetadata({{.*$}} // CHECK-NEXT: %0 = firrtl.string "m_ext" @@ -611,45 +617,48 @@ firrtl.circuit "Foo" { // CHECK-NEXT: %9 = firrtl.object.subfield %[[extraPortsObject]][width_in] // CHECK-NEXT: firrtl.propassign %9, %6 // CHECK-NEXT: %10 = firrtl.list.create %[[extraPortsObject]] -// CHECK-NEXT: %11 = firrtl.string "m_ext" -// CHECK-NEXT: %12 = firrtl.object.subfield %[[memoryObject]][name_in] -// CHECK-NEXT: firrtl.propassign %12, %11 -// CHECK-NEXT: %13 = firrtl.integer 16 -// CHECK-NEXT: %14 = firrtl.object.subfield %[[memoryObject]][depth_in] -// CHECK-NEXT: firrtl.propassign %14, %13 -// CHECK-NEXT: %15 = firrtl.integer 8 -// CHECK-NEXT: %16 = firrtl.object.subfield %[[memoryObject]][width_in] -// CHECK-NEXT: firrtl.propassign %16, %15 -// CHECK-NEXT: %17 = firrtl.integer 1 -// CHECK-NEXT: %18 = firrtl.object.subfield %[[memoryObject]][maskBits_in] -// CHECK-NEXT: firrtl.propassign %18, %17 -// CHECK-NEXT: %19 = firrtl.integer 2 -// CHECK-NEXT: %20 = firrtl.object.subfield %[[memoryObject]][readPorts_in] -// CHECK-NEXT: firrtl.propassign %20, %19 -// CHECK-NEXT: %21 = firrtl.integer 3 -// CHECK-NEXT: %22 = firrtl.object.subfield %[[memoryObject]][writePorts_in] -// CHECK-NEXT: firrtl.propassign %22, %21 -// CHECK-NEXT: %23 = firrtl.integer 4 -// CHECK-NEXT: %24 = firrtl.object.subfield %[[memoryObject]][readwritePorts_in] -// CHECK-NEXT: firrtl.propassign %24, %23 -// CHECK-NEXT: %25 = firrtl.integer 1 -// CHECK-NEXT: %26 = firrtl.object.subfield %[[memoryObject]][writeLatency_in] -// CHECK-NEXT: firrtl.propassign %26, %25 -// CHECK-NEXT: %27 = firrtl.integer 1 -// CHECK-NEXT: %28 = firrtl.object.subfield %[[memoryObject]][readLatency_in] -// CHECK-NEXT: firrtl.propassign %28, %27 -// CHECK-NEXT: %29 = firrtl.string "Undefined" -// CHECK-NEXT: %30 = firrtl.object.subfield %[[memoryObject]][ruwBehavior_in] -// CHECK-NEXT: firrtl.propassign %30, %29 -// CHECK-NEXT: %31 = firrtl.object.subfield %[[memoryObject]][hierarchy_in] -// CHECK-NEXT: firrtl.propassign %31, %3 -// CHECK-NEXT: %32 = firrtl.bool true -// CHECK-NEXT: %33 = firrtl.object.subfield %[[memoryObject]][inDut_in] -// CHECK-NEXT: firrtl.propassign %33, %32 -// CHECK-NEXT: %34 = firrtl.object.subfield %[[memoryObject]][extraPorts_in] -// CHECK-NEXT: firrtl.propassign %34, %10 -// CHECK-NEXT: %35 = firrtl.object.subfield %[[memoryObject]][preExtInstName_in] -// CHECK-NEXT: firrtl.propassign %35, %2 +// CHECK-NEXT: %11 = firrtl.list.create : +// CHECK-NEXT: %12 = firrtl.string "m_ext" +// CHECK-NEXT: %13 = firrtl.object.subfield %[[memoryObject]][name_in] +// CHECK-NEXT: firrtl.propassign %13, %12 +// CHECK-NEXT: %14 = firrtl.integer 16 +// CHECK-NEXT: %15 = firrtl.object.subfield %[[memoryObject]][depth_in] +// CHECK-NEXT: firrtl.propassign %15, %14 +// CHECK-NEXT: %16 = firrtl.integer 8 +// CHECK-NEXT: %17 = firrtl.object.subfield %[[memoryObject]][width_in] +// CHECK-NEXT: firrtl.propassign %17, %16 +// CHECK-NEXT: %18 = firrtl.integer 1 +// CHECK-NEXT: %19 = firrtl.object.subfield %[[memoryObject]][maskBits_in] +// CHECK-NEXT: firrtl.propassign %19, %18 +// CHECK-NEXT: %20 = firrtl.integer 2 +// CHECK-NEXT: %21 = firrtl.object.subfield %[[memoryObject]][readPorts_in] +// CHECK-NEXT: firrtl.propassign %21, %20 +// CHECK-NEXT: %22 = firrtl.integer 3 +// CHECK-NEXT: %23 = firrtl.object.subfield %[[memoryObject]][writePorts_in] +// CHECK-NEXT: firrtl.propassign %23, %22 +// CHECK-NEXT: %24 = firrtl.integer 4 +// CHECK-NEXT: %25 = firrtl.object.subfield %[[memoryObject]][readwritePorts_in] +// CHECK-NEXT: firrtl.propassign %25, %24 +// CHECK-NEXT: %26 = firrtl.integer 1 +// CHECK-NEXT: %27 = firrtl.object.subfield %[[memoryObject]][writeLatency_in] +// CHECK-NEXT: firrtl.propassign %27, %26 +// CHECK-NEXT: %28 = firrtl.integer 1 +// CHECK-NEXT: %29 = firrtl.object.subfield %[[memoryObject]][readLatency_in] +// CHECK-NEXT: firrtl.propassign %29, %28 +// CHECK-NEXT: %30 = firrtl.string "Undefined" +// CHECK-NEXT: %31 = firrtl.object.subfield %[[memoryObject]][ruwBehavior_in] +// CHECK-NEXT: firrtl.propassign %31, %30 +// CHECK-NEXT: %32 = firrtl.object.subfield %[[memoryObject]][hierarchy_in] +// CHECK-NEXT: firrtl.propassign %32, %3 +// CHECK-NEXT: %33 = firrtl.bool true +// CHECK-NEXT: %34 = firrtl.object.subfield %[[memoryObject]][inDut_in] +// CHECK-NEXT: firrtl.propassign %34, %33 +// CHECK-NEXT: %35 = firrtl.object.subfield %[[memoryObject]][extraPorts_in] +// CHECK-NEXT: firrtl.propassign %35, %10 +// CHECK-NEXT: %36 = firrtl.object.subfield %[[memoryObject]][preExtInstName_in] +// CHECK-NEXT: firrtl.propassign %36, %2 +// CHECK-NEXT: %37 = firrtl.object.subfield %m_ext[initFile_in] +// CHECK-NEXT: firrtl.propassign %37, %11 // CHECK-NEXT: firrtl.propassign %[[memoryObject]]_field, %[[memoryObject]] // (2) Memory JSON ------------------------------------------------------------- @@ -1293,3 +1302,115 @@ firrtl.circuit "NoInnerSymsOnIntermediaryInstances" { firrtl.instance foo @Foo() } } + +// ----- + +// Test emission of metadata for memory initialization files. + +firrtl.circuit "MemInitHex" { + firrtl.memmodule private @mInit() attributes { + dataWidth = 8 : ui32, + depth = 32 : ui64, + extraPorts = [], + maskBits = 1 : ui32, + numReadPorts = 1 : ui32, + numWritePorts = 1 : ui32, + numReadWritePorts = 0 : ui32, + readLatency = 1 : ui32, + writeLatency = 1 : ui32, + init = #firrtl.meminit<"some_hex_init.mem", false, false> + } + firrtl.module @MemInitHex() attributes { + annotations = [ + { + class = "sifive.enterprise.firrtl.MarkDUTAnnotation" + } + ] + } { + firrtl.instance m sym @mInit @mInit() + } +} + +//------------------------------------------------------------------ (1) OM Info +// CHECK-LABEL: firrtl.circuit "MemInitHex" +// CHECK: firrtl.class @MemoryMetadata({{.*$}} +// CHECK: %[[memoryObject:.+]] = firrtl.object @MemorySchema +// CHECK: %[[#a:]] = firrtl.list.create +// CHECK-NEXT: %[[#b:]] = firrtl.string "some_hex_init.mem" +// CHECK-NEXT: %[[#c:]] = firrtl.bool false +// CHECK-NEXT: %[[#d:]] = firrtl.bool false +// CHECK-NEXT: %[[obj:.+]] = firrtl.object @MemoryInitFileSchema +// CHECK-NEXT: %[[#e:]] = firrtl.object.subfield %[[obj]][filename_in] +// CHECK-NEXT: firrtl.propassign %[[#e]], %[[#b]] +// CHECK-NEXT: %[[#f:]] = firrtl.object.subfield %[[obj]][isBinary_in] +// CHECK-NEXT: firrtl.propassign %[[#f]], %[[#c]] +// CHECK-NEXT: %[[#g:]] = firrtl.object.subfield %[[obj]][isInline_in] +// CHECK-NEXT: firrtl.propassign %[[#g]], %[[#d]] +// CHECK-NEXT: %[[#h:]] = firrtl.list.create %[[obj]] +// CHECK: %[[#i:]] = firrtl.object.subfield %[[memoryObject]][initFile_in] +// CHECK-NEXT: firrtl.propassign %[[#i]], %[[#h]] + +//-------------------------------------------------------------- (2) Memory JSON +// CHECK-LABEL: emit.file "metadata{{/|\\\\}}seq_mems.json" +// CHECK-NEXT: sv.verbatim "[ +// CHECK-SAME: \22init\22: {\0A \22filename\22: \22some_hex_init.mem\22,\0A \22isBinary\22: false,\0A \22isInline\22: false\0A } + +//------------------------------------------------------- (3) Configuration File +// CHECK-LABEL: emit.file "mems.conf" +// CHECK-NEXT: sv.verbatim +// CHECK-SAME: init-hex \22some_hex_init.mem\22 + +// ----- + +firrtl.circuit "MemInitBin" { + firrtl.memmodule private @mInit() attributes { + dataWidth = 8 : ui32, + depth = 32 : ui64, + extraPorts = [], + maskBits = 1 : ui32, + numReadPorts = 1 : ui32, + numWritePorts = 1 : ui32, + numReadWritePorts = 0 : ui32, + readLatency = 1 : ui32, + writeLatency = 1 : ui32, + init = #firrtl.meminit<"some_bin_init.mem", true, false> + } + firrtl.module @MemInitBin() attributes { + annotations = [ + { + class = "sifive.enterprise.firrtl.MarkDUTAnnotation" + } + ] + } { + firrtl.instance m sym @mInit @mInit() + } +} + +//------------------------------------------------------------------ (1) OM Info +// CHECK-LABEL: firrtl.circuit "MemInitBin" +// CHECK: firrtl.class @MemoryMetadata({{.*$}} +// CHECK: %[[memoryObject:.+]] = firrtl.object @MemorySchema +// CHECK: %[[#a:]] = firrtl.list.create +// CHECK-NEXT: %[[#b:]] = firrtl.string "some_bin_init.mem" +// CHECK-NEXT: %[[#c:]] = firrtl.bool true +// CHECK-NEXT: %[[#d:]] = firrtl.bool false +// CHECK-NEXT: %[[obj:.+]] = firrtl.object @MemoryInitFileSchema +// CHECK-NEXT: %[[#e:]] = firrtl.object.subfield %[[obj]][filename_in] +// CHECK-NEXT: firrtl.propassign %[[#e]], %[[#b]] +// CHECK-NEXT: %[[#f:]] = firrtl.object.subfield %[[obj]][isBinary_in] +// CHECK-NEXT: firrtl.propassign %[[#f]], %[[#c]] +// CHECK-NEXT: %[[#g:]] = firrtl.object.subfield %[[obj]][isInline_in] +// CHECK-NEXT: firrtl.propassign %[[#g]], %[[#d]] +// CHECK-NEXT: %[[#h:]] = firrtl.list.create %[[obj]] +// CHECK: %[[#i:]] = firrtl.object.subfield %[[memoryObject]][initFile_in] +// CHECK-NEXT: firrtl.propassign %[[#i]], %[[#h]] + +//-------------------------------------------------------------- (2) Memory JSON +// CHECK-LABEL: emit.file "metadata{{/|\\\\}}seq_mems.json" +// CHECK-NEXT: sv.verbatim "[ +// CHECK-SAME: \22init\22: {\0A \22filename\22: \22some_bin_init.mem\22,\0A \22isBinary\22: true,\0A \22isInline\22: false\0A } + +//------------------------------------------------------- (3) Configuration File +// CHECK-LABEL: emit.file "mems.conf" +// CHECK-NEXT: sv.verbatim +// CHECK-SAME: init-bin \22some_bin_init.mem\22 diff --git a/test/Dialect/FIRRTL/lower-memory.mlir b/test/Dialect/FIRRTL/lower-memory.mlir index c0e74c0c25ef..079ff7917ff2 100644 --- a/test/Dialect/FIRRTL/lower-memory.mlir +++ b/test/Dialect/FIRRTL/lower-memory.mlir @@ -346,3 +346,14 @@ firrtl.module @RUWOld() { %0:2 = firrtl.mem Old {depth = 12 : i64, name = "RUWOld", portNames = ["read", "write"], readLatency = 1 : i32, writeLatency = 1 : i32} : !firrtl.bundle, en: uint<1>, clk: clock, data flip: uint<42>>, !firrtl.bundle, en: uint<1>, clk: clock, data: uint<42>, mask: uint<1>> } } + + +// Check that the memory initialization attribute is preserved + +// CHECK-LABEL: "MemInit" +firrtl.circuit "MemInit" { +// CHECK: firrtl.memmodule private @MemInit_ext{{.*}}, init = #firrtl.meminit<"init.mem", false, true> +firrtl.module @MemInit() { + %0:2 = firrtl.mem New {init = #firrtl.meminit<"init.mem", false, true>, depth = 12 : i64, name = "MemInit", portNames = ["read", "write"], readLatency = 1 : i32, writeLatency = 1 : i32} : !firrtl.bundle, en: uint<1>, clk: clock, data flip: uint<42>>, !firrtl.bundle, en: uint<1>, clk: clock, data: uint<42>, mask: uint<1>> +} +}