mirror of https://github.com/llvm/circt.git
[FIRRTL] Add Memory Annotation Parsing
Add parsing of the two memory initialization annotations which implement the Chisel loadMemoryFromFile and loadMemoryFromFileInline APIs: - firrtl.annotations.LoadMemoryAnnotation - firrtl.annotations.MemoryFileInlineAnnotation These are parsed into the optional MemoryInitAttr on CHIRRTL or FIRRTL memory operations. Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
This commit is contained in:
parent
8a2d2bb83d
commit
b387c034f0
|
@ -197,6 +197,12 @@ constexpr const char *addSeqMemPortAnnoClass =
|
|||
constexpr const char *addSeqMemPortsFileAnnoClass =
|
||||
"sifive.enterprise.firrtl.AddSeqMemPortsFileAnnotation";
|
||||
|
||||
// Memory file loading annotations.
|
||||
constexpr const char *loadMemoryFromFileAnnoClass =
|
||||
"firrtl.annotations.LoadMemoryAnnotation";
|
||||
constexpr const char *loadMemoryFromFileInlineAnnoClass =
|
||||
"firrtl.annotations.MemoryFileInlineAnnotation";
|
||||
|
||||
} // namespace firrtl
|
||||
} // namespace circt
|
||||
|
||||
|
|
|
@ -277,6 +277,62 @@ static LogicalResult drop(const AnnoPathValue &target, DictionaryAttr anno,
|
|||
return success();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Customized Appliers
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// Update a memory op with attributes about memory file loading.
|
||||
template <bool isInline>
|
||||
static LogicalResult applyLoadMemoryAnno(const AnnoPathValue &target,
|
||||
DictionaryAttr anno,
|
||||
ApplyState &state) {
|
||||
if (!target.isLocal()) {
|
||||
mlir::emitError(state.circuit.getLoc())
|
||||
<< "has a " << anno.get("class")
|
||||
<< " annotation which is non-local, but this annotation is not allowed "
|
||||
"to be non-local";
|
||||
return failure();
|
||||
}
|
||||
|
||||
auto *op = target.ref.getOp();
|
||||
|
||||
if (!target.isOpOfType<MemOp, CombMemOp, SeqMemOp>()) {
|
||||
mlir::emitError(op->getLoc())
|
||||
<< "can only apply a load memory annotation to a memory";
|
||||
return failure();
|
||||
}
|
||||
|
||||
// The two annotations have different case usage in "filename".
|
||||
StringAttr filename = tryGetAs<StringAttr>(
|
||||
anno, anno, isInline ? "filename" : "fileName", op->getLoc(),
|
||||
anno.getAs<StringAttr>("class").getValue());
|
||||
if (!filename)
|
||||
return failure();
|
||||
|
||||
auto hexOrBinary =
|
||||
tryGetAs<StringAttr>(anno, anno, "hexOrBinary", op->getLoc(),
|
||||
anno.getAs<StringAttr>("class").getValue());
|
||||
if (!hexOrBinary)
|
||||
return failure();
|
||||
|
||||
auto hexOrBinaryValue = hexOrBinary.getValue();
|
||||
if (hexOrBinaryValue != "h" && hexOrBinaryValue != "b") {
|
||||
auto diag = mlir::emitError(op->getLoc())
|
||||
<< "has memory initialization annotation with invalid format, "
|
||||
"'hexOrBinary' field must be either 'h' or 'b'";
|
||||
diag.attachNote() << "the full annotation is: " << anno;
|
||||
return failure();
|
||||
}
|
||||
|
||||
op->setAttr("init",
|
||||
MemoryInitAttr::get(
|
||||
op->getContext(), filename,
|
||||
BoolAttr::get(op->getContext(), hexOrBinaryValue == "b"),
|
||||
BoolAttr::get(op->getContext(), isInline)));
|
||||
|
||||
return success();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Driving table
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -400,6 +456,9 @@ static const llvm::StringMap<AnnoRecord> annotationRecords{{
|
|||
{blackBoxTargetDirAnnoClass, NoTargetAnnotation},
|
||||
{traceNameAnnoClass, {stdResolve, applyTraceName}},
|
||||
{traceAnnoClass, {stdResolve, applyWithoutTarget<true>}},
|
||||
{loadMemoryFromFileAnnoClass, {stdResolve, applyLoadMemoryAnno<false>}},
|
||||
{loadMemoryFromFileInlineAnnoClass,
|
||||
{stdResolve, applyLoadMemoryAnno<true>}},
|
||||
|
||||
}};
|
||||
|
||||
|
|
|
@ -1749,3 +1749,80 @@ firrtl.circuit "Top" attributes {rawAnnotations = [{
|
|||
// CHECK: firrtl.ref.resolve %[[localparam__gen_ref]] : !firrtl.ref<uint<1>>
|
||||
}
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
// Test memory initialization setting.
|
||||
// CHECK-LABEL: firrtl.circuit "MemoryInitializationAnnotations"
|
||||
firrtl.circuit "MemoryInitializationAnnotations" attributes {
|
||||
rawAnnotations = [
|
||||
{
|
||||
class = "firrtl.annotations.LoadMemoryAnnotation",
|
||||
fileName = "mem1.txt",
|
||||
hexOrBinary = "b",
|
||||
originalMemoryNameOpt = "m",
|
||||
target = "~MemoryInitializationAnnotations|MemoryInitializationAnnotations>m1"
|
||||
},
|
||||
{
|
||||
class = "firrtl.annotations.MemoryFileInlineAnnotation",
|
||||
filename = "mem2.txt",
|
||||
hexOrBinary = "h",
|
||||
target = "~MemoryInitializationAnnotations|MemoryInitializationAnnotations>m2"
|
||||
},
|
||||
{
|
||||
class = "firrtl.annotations.LoadMemoryAnnotation",
|
||||
fileName = "mem3.txt",
|
||||
hexOrBinary = "b",
|
||||
originalMemoryNameOpt = "m",
|
||||
target = "~MemoryInitializationAnnotations|MemoryInitializationAnnotations>m3"
|
||||
},
|
||||
{
|
||||
class = "firrtl.annotations.MemoryFileInlineAnnotation",
|
||||
filename = "mem4.txt",
|
||||
hexOrBinary = "h",
|
||||
target = "~MemoryInitializationAnnotations|MemoryInitializationAnnotations>m4"
|
||||
},
|
||||
{
|
||||
class = "firrtl.annotations.LoadMemoryAnnotation",
|
||||
fileName = "mem5.txt",
|
||||
hexOrBinary = "b",
|
||||
originalMemoryNameOpt = "m",
|
||||
target = "~MemoryInitializationAnnotations|MemoryInitializationAnnotations>m5"
|
||||
},
|
||||
{
|
||||
class = "firrtl.annotations.MemoryFileInlineAnnotation",
|
||||
filename = "mem6.txt",
|
||||
hexOrBinary = "h",
|
||||
target = "~MemoryInitializationAnnotations|MemoryInitializationAnnotations>m6"
|
||||
}
|
||||
]
|
||||
} {
|
||||
firrtl.module @MemoryInitializationAnnotations() {
|
||||
// CHECK: %m1_r = firrtl.mem
|
||||
// CHECK-SAME: #firrtl.meminit<"mem1.txt", true, false>
|
||||
%m1_r = firrtl.mem Undefined {
|
||||
depth = 2 : i64,
|
||||
name = "m1",
|
||||
portNames = ["r"],
|
||||
readLatency = 1 : i32,
|
||||
writeLatency = 1 : i32
|
||||
} : !firrtl.bundle<addr: uint<1>, en: uint<1>, clk: clock, data flip: uint<8>>
|
||||
// CHECK-NEXT: %m2_r = firrtl.mem
|
||||
// CHECK-SAME: #firrtl.meminit<"mem2.txt", false, true>
|
||||
%m2_r = firrtl.mem Undefined {
|
||||
depth = 2 : i64,
|
||||
name = "m2",
|
||||
portNames = ["r"],
|
||||
readLatency = 1 : i32,
|
||||
writeLatency = 1 : i32
|
||||
} : !firrtl.bundle<addr: uint<1>, en: uint<1>, clk: clock, data flip: uint<8>>
|
||||
// CHECK-NEXT: %m3 = chirrtl.seqmem Undefined {init = #firrtl.meminit<"mem3.txt", true, false>}
|
||||
%m3 = chirrtl.seqmem Undefined : !chirrtl.cmemory<uint<8>, 32>
|
||||
// CHECK-NEXT: %m4 = chirrtl.seqmem Undefined {init = #firrtl.meminit<"mem4.txt", false, true>}
|
||||
%m4 = chirrtl.seqmem Undefined : !chirrtl.cmemory<uint<8>, 32>
|
||||
// CHECK-NEXT: %m5 = chirrtl.combmem {init = #firrtl.meminit<"mem5.txt", true, false>}
|
||||
%m5 = chirrtl.combmem : !chirrtl.cmemory<uint<8>, 32>
|
||||
// CHECK-NEXT: %m6 = chirrtl.combmem {init = #firrtl.meminit<"mem6.txt", false, true>}
|
||||
%m6 = chirrtl.combmem : !chirrtl.cmemory<uint<8>, 32>
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue