Program Listing for File EmitHLSToLaksaHeader.cpp

↰ Return to documentation for file (lib/Target/EmitHLSToLaksaHeader/EmitHLSToLaksaHeader.cpp)

// Implementation of translation EmitHLSToLaksaHeader
//
// @file
// @author     Jiahong Bi (jiahong.bi@tu-dresden.de)

#include "laksa-mlir/Target/EmitHLSToLaksaHeader/LaksaHeaderEmitter.h"
#include "laksa-mlir/Target/LaksaCommon/BufferInfo.h"

#include "llvm/ADT/STLExtras.h"

using namespace mlir;
using namespace mlir::emithls;

//===----------------------------------------------------------------------===//
// Translation entry point
//===----------------------------------------------------------------------===//

LogicalResult
emithls::translateEmitHLSToLaksaHeader(ModuleOp op, raw_ostream &os)
{
    FailureOr<FuncOp> topFunc = findLaksaTopFunc(op);
    if (failed(topFunc)) return failure();
    SmallVector<LaksaBufferInfo> buffers;
    if (failed(collectLaksaBufferInfos(*topFunc, buffers))) return failure();

    StringRef designName = topFunc->getSymName();
    std::string prefix = getLaksaMacroPrefix(designName);
    std::string guard = prefix + "_LAKSA_CONFIG_H";

    os << "// Generated by ladle -t emithls-to-laksa-header.\n"
       << "// Buffer sizes and AXI-Lite register offsets for '" << designName
       << "', matching the\n"
       << "// argument layout expected by laksa.h's IOCTL_START_KERNEL.\n"
       << "#ifndef " << guard << "\n"
       << "#define " << guard << "\n\n"
       << "#define " << prefix << "_NUM_ARGS " << buffers.size() << "\n\n"
       << "#define " << prefix << "_CTRL_OFFSET 0x00 /* ap_ctrl */\n\n";

    // Register offsets follow Vitis HLS's fixed AXI-Lite control layout for
    // m_axi arguments: ap_ctrl/gie/ier/isr occupy 0x00-0x0c, then each
    // 64-bit pointer argument gets a 0xc-byte slot starting at 0x10 (low
    // word, high word, one reserved word).
    for (auto [idx, info] : llvm::enumerate(buffers)) {
        unsigned lowOffset = 0x10 + idx * 0xc;
        unsigned highOffset = lowOffset + 0x4;
        StringRef direction = info.isReadByKernel && info.isWrittenByKernel
                                  ? "input/output"
                              : info.isReadByKernel ? "input"
                                                    : "output";

        os << "/* arg" << idx << ": " << direction << " buffer, "
           << info.numElements << " x " << info.elementBits
           << "-bit elements */\n"
           << "#define " << prefix << "_ARG" << idx << "_LOW_OFFSET  0x";
        os.write_hex(lowOffset);
        os << "\n#define " << prefix << "_ARG" << idx << "_HIGH_OFFSET 0x";
        os.write_hex(highOffset);
        os << "\n#define " << prefix << "_ARG" << idx << "_SIZE        "
           << info.getSizeInBytes() << " /* bytes */\n\n";
    }

    os << "#endif /* " << guard << " */\n";

    return success();
}