diff --git a/test/arcilator/jit-args-multi-seq.mlir b/test/arcilator/jit-args-multi-seq.mlir new file mode 100644 index 000000000000..e4e4dd074f6d --- /dev/null +++ b/test/arcilator/jit-args-multi-seq.mlir @@ -0,0 +1,13 @@ +// RUN: arcilator --run %s --jit-entry=entry --args=1,2 --args=3,4 | FileCheck %s + +module { + func.func @entry(%arg0: i32, %arg1: i32) { + // CHECK: arg0 = 00000001 + // CHECK: arg1 = 00000002 + // CHECK: arg0 = 00000003 + // CHECK: arg1 = 00000004 + arc.sim.emit "arg0", %arg0 : i32 + arc.sim.emit "arg1", %arg1 : i32 + return + } +} diff --git a/test/arcilator/jit-args.mlir b/test/arcilator/jit-args.mlir new file mode 100644 index 000000000000..a508c6fe7a7d --- /dev/null +++ b/test/arcilator/jit-args.mlir @@ -0,0 +1,11 @@ +// RUN: arcilator --run %s --jit-entry=entry --args=0x10,0x1234567890ABCDEF1234567890ABC | FileCheck %s + +module { + func.func @entry(%arg0: i32, %arg1: i116) { + // CHECK: arg0 = 00000010 + arc.sim.emit "arg0", %arg0 : i32 + // CHECK: arg1 = 1234567890abcdef1234567890abc + arc.sim.emit "arg1", %arg1 : i116 + return + } +} diff --git a/tools/arcilator/arcilator.cpp b/tools/arcilator/arcilator.cpp index 692b48ef5dc5..e590770c1d14 100644 --- a/tools/arcilator/arcilator.cpp +++ b/tools/arcilator/arcilator.cpp @@ -229,6 +229,12 @@ static llvm::cl::list sharedLibs{ "shared-libs", llvm::cl::desc("Libraries to link dynamically"), llvm::cl::MiscFlags::CommaSeparated, llvm::cl::cat(mainCategory)}; +static llvm::cl::list + jitArgs("args", + llvm::cl::desc("Arguments to pass to the JIT entry function"), + llvm::cl::ZeroOrMore, llvm::cl::CommaSeparated, + llvm::cl::cat(mainCategory)); + //===----------------------------------------------------------------------===// // Main Tool Logic //===----------------------------------------------------------------------===// @@ -442,9 +448,23 @@ static LogicalResult processBuffer( return failure(); } - if (toCallFunc.getNumArguments() != 0) { + unsigned numArgs = toCallFunc.getNumArguments(); + if (numArgs) { + if (jitArgs.size() % numArgs != 0) { + llvm::errs() << "entry point '" << jitEntryPoint << "' has " << numArgs + << " arguments, but provided " << jitArgs.size() + << " arguments (not a multiple)\n"; + return failure(); + } + if (jitArgs.empty()) { + llvm::errs() << "entry point '" << jitEntryPoint + << "' must have no arguments\n"; + return failure(); + } + } else if (!jitArgs.empty()) { llvm::errs() << "entry point '" << jitEntryPoint - << "' must have no arguments\n"; + << "' has no arguments, but provided " << jitArgs.size() + << "arguments\n"; return failure(); } @@ -482,7 +502,57 @@ static LogicalResult processBuffer( } void (*simulationFunc)(void **) = *expectedFunc; - (*simulationFunc)(nullptr); + + for (unsigned i = 0, e = jitArgs.size(); i < e; i += numArgs) { + std::vector> argsStorage; + SmallVector args; + argsStorage.reserve(numArgs); + args.reserve(numArgs); + + // Repeated args are concatenated, so break apart in groups of multiples + // of args. + for (auto [val, arg] : + llvm::zip(llvm::make_range(jitArgs.begin() + i, + jitArgs.begin() + i + numArgs), + toCallFunc.getArguments())) { + auto type = arg.getType(); + if (!type.isIntOrIndex()) { + llvm::errs() << "argument " << arg.getArgNumber() + << " of entry point '" << jitEntryPoint + << "' is not an integer or index type\n"; + return failure(); + } + + // TODO: This should probably be checking if DLTI is set on module. + unsigned width = type.isIndex() ? 64 : type.getIntOrFloatBitWidth(); + APInt apVal(width, 0); + if (StringRef(val).getAsInteger(0, apVal)) { + llvm::errs() << "invalid integer argument: '" << val << "'\n"; + return failure(); + } + if (apVal.getBitWidth() > width) { + llvm::errs() << "integer argument '" << val << "' (required width " + << apVal.getBitWidth() << ") is too large for type '" + << type << "'\n"; + return failure(); + } + + std::vector argData; + unsigned numWords = apVal.getNumWords(); + argData.resize(numWords); + const uint64_t *rawData = apVal.getRawData(); + for (unsigned j = 0; j < numWords; ++j) + argData[j] = rawData[j]; + + argsStorage.push_back(std::move(argData)); + args.push_back(argsStorage.back().data()); + } + + (*simulationFunc)(args.data()); + } + // Handle the case without arguments as before. + if (jitArgs.empty()) + (*simulationFunc)(nullptr); return success(); }