16#include "mlir/Dialect/Func/IR/FuncOps.h"
17#include "mlir/Tools/mlir-translate/MlirTranslateMain.h"
19#include "llvm/ADT/ArrayRef.h"
20#include "llvm/ADT/StringSet.h"
21#include "llvm/ADT/TypeSwitch.h"
22#include "llvm/Support/Format.h"
34void emitNop(CertNopOp op, std::string &text) { text +=
" NOP\n"; }
37void emitMaskWrite32(CertMaskWrite32Op op, std::string &text) {
39 llvm::raw_string_ostream ss(s);
40 ss <<
" MASK_WRITE_32 ";
41 ss << llvm::format(
"0x%08x, ", op.getAddress());
42 ss << llvm::format(
"0x%08x, ", op.getMask());
43 ss << llvm::format(
"0x%08x\n", op.getValue());
48void emitWrite32(CertWrite32Op op, std::string &text) {
50 llvm::raw_string_ostream ss(s);
52 ss << llvm::format(
"0x%08x, ", op.getAddress());
53 ss << llvm::format(
"0x%08x\n", op.getValue());
58void emitUcDmaWriteDesSync(CertUcDmaWriteDesSyncOp op, std::string &text) {
59 text +=
" uC_DMA_WRITE_DES_SYNC ";
60 text +=
"@" + op.getSymbol().str() +
"\n";
64void emitWaitTCTS(CertWaitTCTSOp op, std::string &text) {
65 uint32_t tileId = op.getTileId();
66 uint32_t channelId = op.getChannelId();
67 text +=
" WAIT_TCTS ";
68 text += std::to_string(tileId) +
", ";
69 text += std::to_string(channelId) +
", ";
70 text += std::to_string(op.getTargetTcts()) +
"\n";
74void emitApplyOffset57(CertApplyOffset57Op op, std::string &text) {
75 uint16_t num_entries = op.getNumEntries();
76 uint16_t offset = op.getOffset();
78 llvm::raw_string_ostream ss(s);
79 ss <<
" APPLY_OFFSET_57 ";
80 ss <<
"@" << op.getSymbol().str() <<
", ";
81 ss << num_entries <<
", ";
82 ss << llvm::format(
"0x%04x", offset) <<
"\n";
87void emitLocalBarrier(CertLocalBarrierOp op, std::string &text) {
88 text +=
" LOCAL_BARRIER ";
89 text +=
"$lb" + std::to_string(op.getLocalBarrierId()) +
", ";
90 text += std::to_string(op.getNumParticipants()) +
"\n";
94void emitRemoteBarrier(CertRemoteBarrierOp op, std::string &text) {
95 text +=
" REMOTE_BARRIER ";
96 text +=
"$rb" + std::to_string(op.getRemoteBarrierId()) +
", ";
97 text += std::to_string(op.getPartyMask()) +
"\n";
103void emitJob(CertJobOp jobOp, std::string &text, std::string &data) {
105 text +=
"START_JOB ";
106 text += std::to_string(jobOp.getJobId()) +
"\n";
108 for (
auto &o : jobOp.getBody().front()) {
109 llvm::TypeSwitch<Operation *>(&o)
110 .Case<CertApplyOffset57Op>(
111 [&](
auto op) { emitApplyOffset57(op, text); })
112 .Case<CertLocalBarrierOp>([&](
auto op) { emitLocalBarrier(op, text); })
113 .Case<CertRemoteBarrierOp>(
114 [&](
auto op) { emitRemoteBarrier(op, text); })
115 .Case<CertMaskWrite32Op>([&](
auto op) { emitMaskWrite32(op, text); })
116 .Case<CertNopOp>([&](
auto op) { emitNop(op, text); })
117 .Case<CertUcDmaWriteDesSyncOp>(
118 [&](
auto op) { emitUcDmaWriteDesSync(op, text); })
119 .Case<CertWaitTCTSOp>([&](
auto op) { emitWaitTCTS(op, text); })
120 .Case<CertWrite32Op>([&](
auto op) { emitWrite32(op, text); })
121 .Default([&](Operation *op) {
122 op->emitError(
"Unsupported operation in CertJobOp");
126 text +=
"END_JOB\n\n";
129void emitJobs(llvm::SmallVector<CertJobOp> &jobs, std::string &text,
132 llvm::sort(jobs, [](CertJobOp a, CertJobOp b) {
133 return a.getJobId() < b.getJobId();
136 for (
auto job : jobs) {
137 emitJob(job, text, data);
142void emitAttachToGroupOp(CertAttachToGroupOp groupOp, std::string &text,
144 if (groupOp.getGroupId())
145 text +=
".attach_to_group " + std::to_string(groupOp.getGroupId()) +
"\n\n";
147 llvm::to_vector_of<CertJobOp>(groupOp.getBody().getOps<CertJobOp>());
148 emitJobs(jobs, text, data);
151void emitUcDmaBdData(CertUcDmaBdOp op, std::string &data,
152 llvm::StringSet<> &emittedGlobals) {
154 auto dataSymbol = op.getRemoteAddress();
155 if (emittedGlobals.contains(dataSymbol))
158 auto global = dyn_cast_if_present<memref::GlobalOp>(
159 op->getParentOfType<AIE::DeviceOp>().lookupSymbol(dataSymbol));
161 op.emitError(
"Global symbol not found");
165 auto initVal = global.getInitialValue();
167 op.emitError(
"Global symbol has no initial value");
171 auto initData = dyn_cast<DenseIntElementsAttr>(*initVal);
173 op.emitError(
"Global symbol initial value is not a dense int array");
180 llvm::raw_string_ostream ss(s);
181 ss <<
" .align 16\n";
182 ss << dataSymbol.str() <<
":\n";
183 for (
auto d : initData)
184 ss <<
llvm::format(
" .long 0x%08x\n", d.getZExtValue());
186 emittedGlobals.insert(dataSymbol);
190void emitUcDmaBd(CertUcDmaBdOp op, std::string &chains, std::string &data,
191 llvm::StringSet<> &emittedGlobals) {
193 llvm::raw_string_ostream ss(s);
196 ss << llvm::format(
"0x%08x, ", op.getLocalAddress());
197 ss <<
"@" + op.getRemoteAddress().str() +
", ";
198 ss << op.getLength() <<
", ";
200 ss << (op.getNextBd() ?
"1\n" :
"0\n");
202 emitUcDmaBdData(op, data, emittedGlobals);
208void emitUcDmaChain(CertUcDmaChainOp op, std::string &chains, std::string &data,
209 llvm::StringSet<> &emittedGlobals) {
210 chains +=
" .align 16\n";
211 chains += op.getName().str() +
":\n";
212 for (
auto &o : op.getBody().front()) {
213 llvm::TypeSwitch<Operation *>(&o).Case<CertUcDmaBdOp>(
214 [&](
auto op) { emitUcDmaBd(op, chains, data, emittedGlobals); });
221 std::string &assembly) {
223 DeviceOp deviceOp = *
module.getOps<DeviceOp>().begin();
225 std::vector<std::string> text;
226 std::vector<std::string> data;
227 std::vector<std::string> chains;
228 llvm::StringSet<> emittedGlobals;
230 text.push_back(
"\n;\n; Code\n;\n\n");
231 data.push_back(
"\n;\n; Data\n;\n\n");
232 chains.push_back(
"\n;\n; Data (chains)\n;\n\n");
234 text[0] +=
".attach_to_group 0\n\n";
235 auto jobs = llvm::to_vector_of<CertJobOp>(deviceOp.getOps<CertJobOp>());
236 emitJobs(jobs, text[0], data[0]);
238 auto groups = llvm::to_vector_of<CertAttachToGroupOp>(
239 deviceOp.getOps<CertAttachToGroupOp>());
240 llvm::sort(groups, [](CertAttachToGroupOp a, CertAttachToGroupOp b) {
241 return a.getGroupId() < b.getGroupId();
244 for (
auto o : deviceOp.getBody()->getOps<CertUcDmaChainOp>())
245 emitUcDmaChain(o, chains[0], data[0], emittedGlobals);
248 for (
auto &groupOp : groups) {
250 text.push_back(
"\n;\n; Code\n;\n\n");
251 data.push_back(
"\n;\n; Data\n;\n\n");
252 chains.push_back(
"\n;\n; Data (chains)\n;\n\n");
254 emitAttachToGroupOp(groupOp, text[group_id], data[group_id]);
258 for (
auto const &[t, c, d] :
llvm::zip(text, chains, data)) {
260 assembly += t +
"EOF\n";
266 assembly +=
"\n" + d;
272 raw_ostream &output) {
273 std::string assembly;
Include the generated interface declarations.
mlir::LogicalResult AIETranslateToUcDma(mlir::ModuleOp module, llvm::raw_ostream &output)