13 #include "mlir/Dialect/Func/IR/FuncOps.h"
14 #include "mlir/IR/BuiltinDialect.h"
15 #include "mlir/IR/BuiltinOps.h"
16 #include "mlir/Tools/mlir-translate/Translation.h"
17 #include "llvm/Support/Format.h"
23 #include "circt/Dialect/ESI/CosimSchema.h"
26 using namespace circt;
41 struct ErrorCountingHandler :
public mlir::ScopedDiagnosticHandler {
42 ErrorCountingHandler(mlir::MLIRContext *context)
43 :
mlir::ScopedDiagnosticHandler(context) {
44 setHandler([
this](Diagnostic &diag) -> LogicalResult {
45 if (diag.getSeverity() == mlir::DiagnosticSeverity::Error)
51 size_t errorCount = 0;
54 struct ExportCosimSchema {
55 ExportCosimSchema(ModuleOp module, llvm::raw_ostream &os)
56 : module(module), os(os), handler(module.getContext()),
57 unknown(UnknownLoc::
get(module.getContext())) {}
64 LogicalResult visitEndpoint(CosimEndpointOp);
68 llvm::raw_ostream &os;
69 ErrorCountingHandler handler;
70 const Location unknown;
74 llvm::SmallVector<std::shared_ptr<capnp::CapnpTypeSchema>> types;
78 LogicalResult ExportCosimSchema::visitEndpoint(CosimEndpointOp ep) {
80 std::make_shared<capnp::CapnpTypeSchema>(ep.getSend().getType());
81 if (!sendTypeSchema->isSupported())
82 return ep.emitOpError(
"Type ")
83 << ep.getSend().getType() <<
" not supported.";
84 types.push_back(sendTypeSchema);
87 std::make_shared<capnp::CapnpTypeSchema>(ep.getRecv().getType());
88 if (!recvTypeSchema->isSupported())
89 return ep.emitOpError(
"Type '")
90 << ep.getRecv().getType() <<
"' not supported.";
91 types.push_back(recvTypeSchema);
94 StringAttr epName = ep->getAttrOfType<StringAttr>(
"name");
96 os << epName <<
" endpoint at " << ep.getLoc() <<
":\n";
97 os <<
"# Send type: ";
98 sendTypeSchema->writeMetadata(os);
101 os <<
"# Recv type: ";
102 recvTypeSchema->writeMetadata(os);
108 static void emitCosimSchemaBody(llvm::raw_ostream &os) {
109 StringRef entireSchemaFile = circt::esi::cosim::CosimSchema;
110 size_t idLocation = entireSchemaFile.find(
"@0x");
111 size_t newlineAfter = entireSchemaFile.find(
'\n', idLocation);
114 <<
"#########################################################\n"
115 <<
"## Standard RPC interfaces.\n"
116 <<
"#########################################################\n";
117 os << entireSchemaFile.substr(newlineAfter) <<
"\n";
120 LogicalResult ExportCosimSchema::emit() {
121 os <<
"#########################################################\n"
122 <<
"## ESI generated schema.\n"
123 <<
"#########################################################\n";
126 auto walkResult = module.walk([
this](CosimEndpointOp ep) {
127 if (failed(visitEndpoint(ep)))
128 return mlir::WalkResult::interrupt();
129 return mlir::WalkResult::advance();
131 if (walkResult.wasInterrupted())
133 os <<
"#########################################################\n";
136 llvm::sort(types.begin(), types.end(),
137 [](
auto &a,
auto &b) { return a->typeID() > b->typeID(); });
140 uint64_t fileHash = 2544816649379317016;
141 for (
auto &schema : types)
142 fileHash = llvm::hashing::detail::hash_16_bytes(fileHash, schema->typeID());
144 fileHash |= 0x8000000000000000;
147 os <<
"#########################################################\n"
148 <<
"## Types for your design.\n"
149 <<
"#########################################################\n\n";
151 auto end = std::unique(
152 types.begin(), types.end(),
153 [&](
const auto &lhs,
const auto &rhs) { return *lhs == *rhs; });
154 for (
auto typeIter = types.begin(); typeIter != end; ++typeIter) {
155 if (failed((*typeIter)->write(os)))
162 emitCosimSchemaBody(os);
164 return success(handler.errorCount == 0);
168 llvm::raw_ostream &os) {
169 ExportCosimSchema schema(module, os);
170 return schema.emit();
176 llvm::raw_ostream &os) {
178 "Not compiled with CAPNP support");
189 mlir::TranslateFromMLIRRegistration cosimToCapnp(
190 "export-esi-capnp",
"ESI Cosim Cap'nProto schema generation",
192 registry.insert<ESIDialect, circt::hw::HWDialect,
193 circt::seq::SeqDialect, circt::sv::SVDialect,
194 mlir::func::FuncDialect, mlir::BuiltinDialect>();
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
llvm::raw_ostream & emitCapnpID(llvm::raw_ostream &os, int64_t id)
Emit an ID in capnp format.
LogicalResult exportCosimSchema(ModuleOp module, llvm::raw_ostream &os)
void registerESITranslations()
This file defines an intermediate representation for circuits acting as an abstraction for constraint...