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();
}