Program Listing for File EmitHLSToLaksaRunScript.cpp

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

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

#include "laksa-mlir/Target/EmitHLSToLaksaRunScript/LaksaRunScriptEmitter.h"
#include "laksa-mlir/Target/LaksaCommon/BufferInfo.h"

#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/CommandLine.h"

using namespace mlir;
using namespace mlir::emithls;

namespace {

llvm::cl::opt<std::string> clLaksaRunDtsi(
    "laksa-run-dtsi",
    llvm::cl::desc(
        "Device tree overlay source the generated script compiles, as produced "
        "by the emithls-to-kria-dtsi translation"),
    llvm::cl::init("app.dtsi"));

llvm::cl::opt<std::string> clLaksaRunApp(
    "laksa-run-app",
    llvm::cl::desc(
        "Driver source the generated script builds, as produced by the "
        "emithls-to-laksa-app translation"),
    llvm::cl::init("app.c"));

llvm::cl::opt<std::string> clLaksaRunRef(
    "laksa-run-ref",
    llvm::cl::desc(
        "Checker source the generated script builds, as produced by the "
        "emitc-to-laksa-ref translation"),
    llvm::cl::init("ref.c"));

// The name a path carries once its extension is dropped.
StringRef getStem(StringRef path)
{
    size_t dot = path.rfind('.');
    return dot == StringRef::npos ? path : path.substr(0, dot);
}

} // namespace

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

LogicalResult
emithls::translateEmitHLSToLaksaRunScript(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();
    StringRef dtsiStem = getStem(clLaksaRunDtsi);
    StringRef appStem = getStem(clLaksaRunApp);
    StringRef refStem = getStem(clLaksaRunRef);

    os << "#!/bin/sh\n"
          "\n"
          "# Generated by ladle -t emithls-to-laksa-run-script.\n"
          "# Runs on the board, and needs root to load the overlay and the "
          "kernel.\n"
          "\n"
          "set -eu\n"
          "\n"
          "cd \"$(dirname \"$0\")\"\n"
          "\n"
          "echo \"INFO: Compiling "
       << clLaksaRunDtsi
       << "...\"\n"
          "dtc -@ -O dtb -o "
       << dtsiStem << ".dtbo " << clLaksaRunDtsi
       << "\n"
          "\n"
          "echo \"INFO: Removing the overlay currently loaded...\"\n"
          "sudo fpgautil -R\n"
          "\n"
          "echo \"INFO: Loading "
       << dtsiStem
       << ".dtbo...\"\n"
          "sudo fpgautil -o "
       << dtsiStem
       << ".dtbo\n"
          "\n"
          "echo \"INFO: Loading "
       << designName
       << ".bit...\"\n"
          "sudo fpgautil -b "
       << designName
       << ".bit\n"
          "\n"
          "echo \"INFO: Building "
       << appStem << " and " << refStem
       << "...\"\n"
          "gcc -O2 -I. -o "
       << appStem << " " << clLaksaRunApp << "\n"
       << "gcc -O2 -I. -o " << refStem << " " << clLaksaRunRef << "\n";

    unsigned numInputs = 0;
    bool wroteInput = false;
    for (const LaksaBufferInfo &info : buffers) {
        if (!info.isReadByKernel) continue;
        if (!wroteInput) {
            os << "\necho \"INFO: Filling every missing input with random "
                  "bytes...\"\n";
            wroteInput = true;
        }
        std::string file = "input" + std::to_string(numInputs++) + ".bin";
        os << "[ -f " << file << " ] || head -c " << info.getSizeInBytes()
           << " /dev/urandom > " << file << "\n";
    }

    os << "\necho \"INFO: Running " << designName
       << " on the board...\"\n"
          "sudo ./"
       << appStem
       << "\n"
          "\necho \"INFO: Checking the output against the reference...\"\n"
          "./"
       << refStem << "\n";

    return success();
}