Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Configure AIE using control packets #1728

Merged
merged 17 commits into from
Aug 30, 2024
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/aie-c/Translation.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ MLIR_CAPI_EXPORTED MlirStringRef aieTranslateAIEVecToCpp(MlirOperation op,
bool aie2);
MLIR_CAPI_EXPORTED MlirStringRef aieTranslateModuleToLLVMIR(MlirOperation op);
MLIR_CAPI_EXPORTED MlirStringRef aieTranslateToNPU(MlirOperation op);
MLIR_CAPI_EXPORTED MlirStringRef aieTranslateToControlPackets(MlirOperation op);
MLIR_CAPI_EXPORTED MlirStringRef aieTranslateToXAIEV2(MlirOperation op);
MLIR_CAPI_EXPORTED MlirStringRef aieTranslateToHSA(MlirOperation op);
MLIR_CAPI_EXPORTED MlirStringRef aieTranslateToBCF(MlirOperation op, int col,
Expand Down
21 changes: 21 additions & 0 deletions include/aie/Dialect/AIEX/IR/AIEX.td
Original file line number Diff line number Diff line change
Expand Up @@ -791,6 +791,27 @@ def AIE_NpuAddressPatchOp: AIEX_Op<"npu.address_patch", []> {
}];
}

def AIE_NpuControlPacketOp: AIEX_Op<"npu.control_packet", []> {
erwei-xilinx marked this conversation as resolved.
Show resolved Hide resolved
let summary = "AIE control packet";
let arguments = (
ins UI32Attr:$address,
OptionalAttr<I32Attr>:$length,
I32Attr:$opcode,
I32Attr:$stream_id,
OptionalAttr<DenseI32ArrayAttr>:$data
);
let results = (outs );
let assemblyFormat = [{ attr-dict }];
let description = [{
The control_packet operation represents a low-level AIE control packet header
and payload.
}];
let extraClassDeclaration = [{
uint32_t getRow();
uint32_t getColumn();
}];
}

// NPU Bd Write operation
def AIE_NpuWriteBdOp: AIEX_Op<"npu.writebd", []> {
let summary = "dma operator";
Expand Down
6 changes: 5 additions & 1 deletion include/aie/Targets/AIETargets.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ mlir::LogicalResult AIETranslateGraphXPE(mlir::ModuleOp module,
llvm::raw_ostream &);
mlir::LogicalResult AIETranslateToNPU(mlir::ModuleOp module,
llvm::raw_ostream &output);
std::vector<uint32_t> AIETranslateToNPU(mlir::ModuleOp);
mlir::LogicalResult AIETranslateToNPU(mlir::ModuleOp, std::vector<uint32_t> &);
mlir::LogicalResult AIETranslateToControlPackets(mlir::ModuleOp module,
llvm::raw_ostream &output);
mlir::LogicalResult AIETranslateToControlPackets(mlir::ModuleOp,
std::vector<uint32_t> &);
mlir::LogicalResult AIETranslateToLdScript(mlir::ModuleOp module,
llvm::raw_ostream &output,
int tileCol, int tileRow);
Expand Down
11 changes: 11 additions & 0 deletions lib/CAPI/Translation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,17 @@ MlirStringRef aieTranslateToNPU(MlirOperation moduleOp) {
return mlirStringRefCreate(cStr, npu.size());
}

MlirStringRef aieTranslateToControlPackets(MlirOperation moduleOp) {
std::string npu;
llvm::raw_string_ostream os(npu);
ModuleOp mod = llvm::cast<ModuleOp>(unwrap(moduleOp));
if (failed(AIETranslateToControlPackets(mod, os)))
return mlirStringRefCreate(nullptr, 0);
char *cStr = static_cast<char *>(malloc(npu.size()));
npu.copy(cStr, npu.size());
return mlirStringRefCreate(cStr, npu.size());
}

MlirStringRef aieTranslateToXAIEV2(MlirOperation moduleOp) {
std::string xaie;
llvm::raw_string_ostream os(xaie);
Expand Down
22 changes: 21 additions & 1 deletion lib/Dialect/AIEX/IR/AIEXDialect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -227,13 +227,13 @@
return forOp->emitOpError(
"Size 1 exceeds the [0:" + std::to_string((1 << wrap_bits) - 1) +
"] range.");
if (hardwareSizes[3] > (1 << iter_bits))

Check warning on line 230 in lib/Dialect/AIEX/IR/AIEXDialect.cpp

View workflow job for this annotation

GitHub Actions / windows-2019 msvc assert=ON rtti=ON

'<<': result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?)

Check warning on line 230 in lib/Dialect/AIEX/IR/AIEXDialect.cpp

View workflow job for this annotation

GitHub Actions / windows-2019 msvc assert=OFF rtti=OFF

'<<': result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?)

Check warning on line 230 in lib/Dialect/AIEX/IR/AIEXDialect.cpp

View workflow job for this annotation

GitHub Actions / windows-2019 msvc assert=OFF rtti=ON

'<<': result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?)

Check warning on line 230 in lib/Dialect/AIEX/IR/AIEXDialect.cpp

View workflow job for this annotation

GitHub Actions / windows-2019 msvc assert=ON rtti=OFF

'<<': result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?)
return forOp->emitOpError(
"Size 3 exceeds the [1:" + std::to_string(1 << iter_bits) + "] range.");
if (hardwareStrides[0] > (1 << step_bits))

Check warning on line 233 in lib/Dialect/AIEX/IR/AIEXDialect.cpp

View workflow job for this annotation

GitHub Actions / windows-2019 msvc assert=ON rtti=ON

'<<': result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?)

Check warning on line 233 in lib/Dialect/AIEX/IR/AIEXDialect.cpp

View workflow job for this annotation

GitHub Actions / windows-2019 msvc assert=OFF rtti=OFF

'<<': result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?)

Check warning on line 233 in lib/Dialect/AIEX/IR/AIEXDialect.cpp

View workflow job for this annotation

GitHub Actions / windows-2019 msvc assert=OFF rtti=ON

'<<': result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?)

Check warning on line 233 in lib/Dialect/AIEX/IR/AIEXDialect.cpp

View workflow job for this annotation

GitHub Actions / windows-2019 msvc assert=ON rtti=OFF

'<<': result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?)
return forOp->emitOpError("Stride 0 exceeds the [1:" +
std::to_string(1 << step_bits) + "] range.");
if (hardwareStrides[1] > (1 << step_bits))

Check warning on line 236 in lib/Dialect/AIEX/IR/AIEXDialect.cpp

View workflow job for this annotation

GitHub Actions / windows-2019 msvc assert=ON rtti=ON

'<<': result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?)

Check warning on line 236 in lib/Dialect/AIEX/IR/AIEXDialect.cpp

View workflow job for this annotation

GitHub Actions / windows-2019 msvc assert=OFF rtti=OFF

'<<': result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?)

Check warning on line 236 in lib/Dialect/AIEX/IR/AIEXDialect.cpp

View workflow job for this annotation

GitHub Actions / windows-2019 msvc assert=OFF rtti=ON

'<<': result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?)

Check warning on line 236 in lib/Dialect/AIEX/IR/AIEXDialect.cpp

View workflow job for this annotation

GitHub Actions / windows-2019 msvc assert=ON rtti=OFF

'<<': result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?)
return forOp->emitOpError("Stride 1 exceeds the [1:" +
std::to_string(1 << step_bits) + "] range.");
if (hardwareStrides[2] > (1 << step_bits))
Expand Down Expand Up @@ -641,4 +641,24 @@
}
}
return success();
}
}

//===----------------------------------------------------------------------===//
// NpuControlPacketOp
//===----------------------------------------------------------------------===//

uint32_t AIEX::NpuControlPacketOp::getRow() {
const auto &targetModel = AIE::getTargetModel(*this);
uint32_t addr = getAddress();
uint32_t rowInt =
(addr & (0xff << targetModel.getRowShift())) >> targetModel.getRowShift();
return rowInt;
}
erwei-xilinx marked this conversation as resolved.
Show resolved Hide resolved

uint32_t AIEX::NpuControlPacketOp::getColumn() {
const auto &targetModel = AIE::getTargetModel(*this);
uint32_t addr = getAddress();
uint32_t colInt = (addr & (0xff << targetModel.getColumnShift())) >>
targetModel.getColumnShift();
return colInt;
}
65 changes: 60 additions & 5 deletions lib/Targets/AIETargetNPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,9 +185,9 @@ void appendBlockWrite(std::vector<uint32_t> &instructions, NpuBlockWriteOp op) {

} // namespace

std::vector<uint32_t> xilinx::AIE::AIETranslateToNPU(ModuleOp module) {

std::vector<uint32_t> instructions;
LogicalResult
xilinx::AIE::AIETranslateToNPU(ModuleOp module,
std::vector<uint32_t> &instructions) {

auto words = reserveAndGetTail(instructions, 4);

Expand Down Expand Up @@ -236,12 +236,67 @@ std::vector<uint32_t> xilinx::AIE::AIETranslateToNPU(ModuleOp module) {
// write size fields of the txn header
instructions[2] = count;
instructions[3] = instructions.size() * sizeof(uint32_t); // size of the txn
return instructions;
return success();
}

LogicalResult xilinx::AIE::AIETranslateToNPU(ModuleOp module,
raw_ostream &output) {
auto instructions = AIETranslateToNPU(module);
std::vector<uint32_t> instructions;
auto r = AIETranslateToNPU(module, instructions);
if (failed(r))
return r;
for (auto w : instructions)
output << llvm::format("%08X\n", w);
return success();
}

LogicalResult
xilinx::AIE::AIETranslateToControlPackets(ModuleOp module,
std::vector<uint32_t> &instructions) {

DeviceOp deviceOp = *module.getOps<DeviceOp>().begin();
auto sequenceOps = deviceOp.getOps<AIEX::RuntimeSequenceOp>();
for (auto f : sequenceOps) {
Block &entry = f.getBody().front();
for (auto &o : entry) {
llvm::TypeSwitch<Operation *>(&o).Case<NpuControlPacketOp>([&](auto op) {
uint32_t size = 0;
auto data = op.getData();
auto length = op.getLength();
if (data)
size = data->size();
auto words = reserveAndGetTail(instructions, 1 + size);
if (!data && length)
size = *length;
auto parity = [](uint32_t n) {
uint32_t p = 0;
while (n) {
p += n & 1;
n >>= 1;
}
return (p % 2) == 0;
};
uint32_t addr = op.getAddress() & 0xFFFFF;
uint32_t beats = size - 1;
uint32_t opc = op.getOpcode();
uint32_t id = op.getStreamId();
uint32_t hdr = id << 24 | opc << 22 | beats << 20 | addr;
words[0] = hdr | (0x1 & parity(hdr)) << 31;
if (opc == 0x0 || opc == 0x2)
for (unsigned i = 0; i < size; i++)
words[i + 1] = data.value()[i];
});
}
}
return success();
}

LogicalResult xilinx::AIE::AIETranslateToControlPackets(ModuleOp module,
raw_ostream &output) {
std::vector<uint32_t> instructions;
auto r = AIETranslateToControlPackets(module, instructions);
if (failed(r))
return r;
for (auto w : instructions)
output << llvm::format("%08X\n", w);
return success();
Expand Down
32 changes: 26 additions & 6 deletions lib/Targets/AIETargets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,9 +153,11 @@ void registerAIETranslations() {
"cdo-enable-cores", llvm::cl::init(true),
llvm::cl::desc("Enable cores in CDO"));

static llvm::cl::opt<bool> npuInstGenBinary(
"aie-npu-instgen-binary", llvm::cl::init(false),
llvm::cl::desc("Emit binary (true) or text (false) NPU instructions"));
static llvm::cl::opt<bool> outputBinary(
"aie-output-binary", llvm::cl::init(false),
llvm::cl::desc(
"Select binary (true) or text (false) output for supported "
"translations. e.g. aie-npu-instgen, aie-ctrlpkt-to-bin"));

TranslateFromMLIRRegistration registrationMMap(
"aie-generate-mmap", "Generate AIE memory map",
Expand Down Expand Up @@ -352,16 +354,34 @@ void registerAIETranslations() {
},
registerDialects);
TranslateFromMLIRRegistration registrationNPU(
"aie-npu-instgen", "Generate instructions for NPU",
"aie-npu-instgen", "Translate npu instructions to binary",
[](ModuleOp module, raw_ostream &output) {
if (npuInstGenBinary == true) {
auto instructions = AIETranslateToNPU(module);
if (outputBinary == true) {
std::vector<uint32_t> instructions;
auto r = AIETranslateToNPU(module, instructions);
if (failed(r))
return r;
output.write(reinterpret_cast<const char *>(instructions.data()),
instructions.size() * sizeof(uint32_t));
return success();
}
return AIETranslateToNPU(module, output);
},
registerDialects);
TranslateFromMLIRRegistration registrationCtrlPkt(
"aie-ctrlpkt-to-bin", "Translate aiex.control_packet ops to binary",
[](ModuleOp module, raw_ostream &output) {
if (outputBinary == true) {
std::vector<uint32_t> instructions;
auto r = AIETranslateToControlPackets(module, instructions);
if (failed(r))
return r;
output.write(reinterpret_cast<const char *>(instructions.data()),
instructions.size() * sizeof(uint32_t));
return success();
}
return AIETranslateToControlPackets(module, output);
},
registerDialects);
}
} // namespace xilinx::AIE
12 changes: 12 additions & 0 deletions python/AIEMLIRModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,18 @@ PYBIND11_MODULE(_aie, m) {
},
"module"_a);

m.def(
"generate_control_packets",
[&stealCStr](MlirOperation op) {
py::str ctrlPackets = stealCStr(aieTranslateToControlPackets(op));
auto individualInstructions =
ctrlPackets.attr("split")().cast<py::list>();
for (size_t i = 0; i < individualInstructions.size(); ++i)
individualInstructions[i] = individualInstructions[i].attr("strip")();
return individualInstructions;
},
"module"_a);

m.def(
"generate_xaie",
[&stealCStr](MlirOperation op) {
Expand Down
Loading
Loading