normalize names and artifact paths
This commit is contained in:
@@ -19,7 +19,7 @@ struct ResolvedContiguousAddress {
|
||||
};
|
||||
|
||||
/// Records compile-time facts used when interpreting address arithmetic and
|
||||
/// loop-carried aliases inside PIM regions.
|
||||
/// loop-carried aliases inside Pim regions.
|
||||
struct StaticValueKnowledge {
|
||||
llvm::DenseMap<mlir::Value, int64_t> indexValues;
|
||||
llvm::DenseMap<mlir::Value, mlir::Value> aliases;
|
||||
|
||||
@@ -85,12 +85,12 @@ static mlir::LogicalResult walkPimCoreBlockImpl(mlir::Block& block,
|
||||
auto step = resolveIndexValue(forOp.getStep(), knowledge);
|
||||
if (failed(lower) || failed(upper) || failed(step)
|
||||
|| (mode == CoreWalkMode::ExecuteCommunication && *step <= 0)) {
|
||||
forOp.emitOpError() << "requires statically evaluable scf.for bounds for PIM " << purpose;
|
||||
forOp.emitOpError() << "requires statically evaluable scf.for bounds for Pim " << purpose;
|
||||
hasFailure = true;
|
||||
continue;
|
||||
}
|
||||
if (*step <= 0) {
|
||||
forOp.emitOpError("requires positive scf.for step for PIM verification");
|
||||
forOp.emitOpError("requires positive scf.for step for Pim verification");
|
||||
hasFailure = true;
|
||||
continue;
|
||||
}
|
||||
@@ -126,7 +126,7 @@ static mlir::LogicalResult walkPimCoreBlockImpl(mlir::Block& block,
|
||||
if (auto ifOp = mlir::dyn_cast<mlir::scf::IfOp>(op)) {
|
||||
auto condition = resolveIndexValue(ifOp.getCondition(), knowledge);
|
||||
if (failed(condition)) {
|
||||
ifOp.emitOpError() << "requires statically evaluable scf.if condition for PIM " << purpose;
|
||||
ifOp.emitOpError() << "requires statically evaluable scf.if condition for Pim " << purpose;
|
||||
hasFailure = true;
|
||||
continue;
|
||||
}
|
||||
@@ -147,7 +147,7 @@ static mlir::LogicalResult walkPimCoreBlockImpl(mlir::Block& block,
|
||||
if (auto switchOp = mlir::dyn_cast<mlir::scf::IndexSwitchOp>(op)) {
|
||||
auto selector = resolveIndexValue(switchOp.getArg(), knowledge);
|
||||
if (failed(selector)) {
|
||||
switchOp.emitOpError() << "requires a statically evaluable scf.index_switch selector for PIM " << purpose;
|
||||
switchOp.emitOpError() << "requires a statically evaluable scf.index_switch selector for Pim " << purpose;
|
||||
hasFailure = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace onnx_mlir {
|
||||
using PimCoreCommunicationPlan = llvm::DenseMap<mlir::Block*, llvm::SmallVector<mlir::Operation*, 8>>;
|
||||
|
||||
/// Returns true for ops in a `pim.core` body that only participate in static
|
||||
/// address or index computation and therefore do not emit PIM instructions.
|
||||
/// address or index computation and therefore do not emit Pim instructions.
|
||||
bool isCoreStaticAddressOp(mlir::Operation* op);
|
||||
|
||||
/// Walks a `pim.core` body's communication stream, statically unrolling
|
||||
|
||||
@@ -9,7 +9,7 @@ llvm::FailureOr<mlir::func::FuncOp> getPimEntryFunc(mlir::ModuleOp moduleOp) {
|
||||
|
||||
llvm::SmallVector<mlir::ONNXEntryPointOp> entryPoints(moduleOp.getOps<mlir::ONNXEntryPointOp>());
|
||||
if (entryPoints.size() > 1) {
|
||||
moduleOp.emitError("PIM pipeline requires a single ONNX entry point, but found ") << entryPoints.size();
|
||||
moduleOp.emitError("Pim pipeline requires a single ONNX entry point, but found ") << entryPoints.size();
|
||||
return mlir::failure();
|
||||
}
|
||||
if (!entryPoints.empty()) {
|
||||
@@ -38,7 +38,7 @@ llvm::FailureOr<mlir::func::FuncOp> getPimEntryFunc(mlir::ModuleOp moduleOp) {
|
||||
if (nonExternalFuncs.size() == 1)
|
||||
return nonExternalFuncs.front();
|
||||
|
||||
moduleOp.emitError("could not resolve a unique PIM entry function");
|
||||
moduleOp.emitError("could not resolve a unique Pim entry function");
|
||||
return mlir::failure();
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
namespace onnx_mlir {
|
||||
|
||||
/// Resolves the function the PIM pipeline should treat as its entry point.
|
||||
/// Resolves the function the Pim pipeline should treat as its entry point.
|
||||
/// Prefers ONNX entry-point metadata, then `main_graph`, then the only
|
||||
/// non-external function if the module is otherwise unambiguous.
|
||||
llvm::FailureOr<mlir::func::FuncOp> getPimEntryFunc(mlir::ModuleOp moduleOp);
|
||||
|
||||
@@ -32,7 +32,7 @@ struct ResolvedWeightView {
|
||||
bool hasWeightAlways(mlir::Operation* op);
|
||||
|
||||
/// Tags an op as producing a value that should stay materialized as a reusable
|
||||
/// weight across later PIM lowering/codegen stages.
|
||||
/// weight across later Pim lowering/codegen stages.
|
||||
void markWeightAlways(mlir::Operation* op);
|
||||
|
||||
bool isSpatialMvmVmmWeightUse(mlir::OpOperand& use);
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace onnx_mlir::pim {
|
||||
namespace {
|
||||
|
||||
static void emitCrashMessage(llvm::StringRef fieldName, llvm::StringRef message) {
|
||||
llvm::errs() << "PIM " << fieldName << " " << message << "\n";
|
||||
llvm::errs() << "Pim " << fieldName << " " << message << "\n";
|
||||
}
|
||||
|
||||
template <typename To, typename From>
|
||||
@@ -65,7 +65,7 @@ InFlightDiagnostic emitCheckedArithmeticError(Operation* anchor, llvm::StringRef
|
||||
}
|
||||
|
||||
InFlightDiagnostic emitCheckedArithmeticError(Location loc, llvm::StringRef fieldName, llvm::StringRef message) {
|
||||
return emitError(loc) << "PIM " << fieldName << " " << message;
|
||||
return emitError(loc) << "Pim " << fieldName << " " << message;
|
||||
}
|
||||
|
||||
FailureOr<int32_t> checkedI32(int64_t value, Operation* anchor, llvm::StringRef fieldName) {
|
||||
@@ -174,7 +174,7 @@ FailureOr<uint64_t> getCheckedShapedTypeSizeInBytes(ShapedType type, Location lo
|
||||
int32_t checkedI32OrCrash(int64_t value, llvm::StringRef fieldName) {
|
||||
if (value < std::numeric_limits<int32_t>::min() || value > std::numeric_limits<int32_t>::max()) {
|
||||
emitCrashMessage(fieldName, "is outside representable range");
|
||||
llvm_unreachable("PIM checked arithmetic failure");
|
||||
llvm_unreachable("Pim checked arithmetic failure");
|
||||
}
|
||||
return static_cast<int32_t>(value);
|
||||
}
|
||||
@@ -182,7 +182,7 @@ int32_t checkedI32OrCrash(int64_t value, llvm::StringRef fieldName) {
|
||||
int32_t checkedI32OrCrash(uint64_t value, llvm::StringRef fieldName) {
|
||||
if (value > static_cast<uint64_t>(std::numeric_limits<int32_t>::max())) {
|
||||
emitCrashMessage(fieldName, "is outside representable range");
|
||||
llvm_unreachable("PIM checked arithmetic failure");
|
||||
llvm_unreachable("Pim checked arithmetic failure");
|
||||
}
|
||||
return static_cast<int32_t>(value);
|
||||
}
|
||||
@@ -190,7 +190,7 @@ int32_t checkedI32OrCrash(uint64_t value, llvm::StringRef fieldName) {
|
||||
uint8_t checkedU8OrCrash(uint64_t value, llvm::StringRef fieldName) {
|
||||
if (value > static_cast<uint64_t>(std::numeric_limits<uint8_t>::max())) {
|
||||
emitCrashMessage(fieldName, "is outside representable range");
|
||||
llvm_unreachable("PIM checked arithmetic failure");
|
||||
llvm_unreachable("Pim checked arithmetic failure");
|
||||
}
|
||||
return static_cast<uint8_t>(value);
|
||||
}
|
||||
@@ -198,7 +198,7 @@ uint8_t checkedU8OrCrash(uint64_t value, llvm::StringRef fieldName) {
|
||||
size_t checkedSizeOrCrash(int64_t value, llvm::StringRef fieldName) {
|
||||
if (value < 0) {
|
||||
emitCrashMessage(fieldName, "is outside representable range");
|
||||
llvm_unreachable("PIM checked arithmetic failure");
|
||||
llvm_unreachable("Pim checked arithmetic failure");
|
||||
}
|
||||
return static_cast<size_t>(value);
|
||||
}
|
||||
@@ -206,7 +206,7 @@ size_t checkedSizeOrCrash(int64_t value, llvm::StringRef fieldName) {
|
||||
size_t checkedAddOrCrash(size_t lhs, size_t rhs, llvm::StringRef fieldName) {
|
||||
if (rhs > std::numeric_limits<size_t>::max() - lhs) {
|
||||
emitCrashMessage(fieldName, "addition overflow");
|
||||
llvm_unreachable("PIM checked arithmetic failure");
|
||||
llvm_unreachable("Pim checked arithmetic failure");
|
||||
}
|
||||
return lhs + rhs;
|
||||
}
|
||||
@@ -214,7 +214,7 @@ size_t checkedAddOrCrash(size_t lhs, size_t rhs, llvm::StringRef fieldName) {
|
||||
size_t checkedMulOrCrash(size_t lhs, size_t rhs, llvm::StringRef fieldName) {
|
||||
if (lhs != 0 && rhs > std::numeric_limits<size_t>::max() / lhs) {
|
||||
emitCrashMessage(fieldName, "multiplication overflow");
|
||||
llvm_unreachable("PIM checked arithmetic failure");
|
||||
llvm_unreachable("Pim checked arithmetic failure");
|
||||
}
|
||||
return lhs * rhs;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
namespace onnx_mlir {
|
||||
|
||||
/// Returns the directory that should hold PIM artifacts/debug dumps for the
|
||||
/// Returns the directory that should hold Pim artifacts/debug dumps for the
|
||||
/// current compiler invocation.
|
||||
std::string getOutputDir();
|
||||
|
||||
|
||||
@@ -171,19 +171,19 @@ inline Opcode opcodeFromString(llvm::StringRef opName) {
|
||||
for (auto [index, name] : llvm::enumerate(kOpcodeNames))
|
||||
if (opName == name)
|
||||
return static_cast<Opcode>(index);
|
||||
llvm_unreachable("Unsupported PIM binary opcode");
|
||||
llvm_unreachable("Unsupported Pim binary opcode");
|
||||
}
|
||||
|
||||
inline llvm::StringRef opcodeToString(Opcode opcode) {
|
||||
size_t index = static_cast<size_t>(opcode);
|
||||
assert(index < kOpcodeNames.size() && "Unsupported PIM binary opcode");
|
||||
assert(index < kOpcodeNames.size() && "Unsupported Pim binary opcode");
|
||||
return kOpcodeNames[index];
|
||||
}
|
||||
|
||||
inline InstructionRecord makeInstructionRecord(const llvm::json::Object& instruction) {
|
||||
InstructionRecord record;
|
||||
std::optional<llvm::StringRef> opName = instruction.getString("op");
|
||||
assert(opName && "Missing op field in PIM instruction");
|
||||
assert(opName && "Missing op field in Pim instruction");
|
||||
record.opcode = opcodeFromString(*opName);
|
||||
const auto& format = kInstructionJsonFormats[static_cast<size_t>(record.opcode)];
|
||||
if (format.rd)
|
||||
|
||||
@@ -125,7 +125,7 @@ static bool isZeroSplatGlobal(mlir::Value value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// PIM instruction immediates are serialized as signed int32_t fields today
|
||||
// Pim instruction immediates are serialized as signed int32_t fields today
|
||||
// (`sldi` goes through checkedI32OrCrash), so local addresses must stay within
|
||||
// the non-negative int32_t range.
|
||||
static FailureOr<size_t> checkedAlignTo(size_t value, size_t alignment, Operation* anchor, StringRef fieldName) {
|
||||
@@ -141,7 +141,7 @@ static void printMemoryOverflowDiagnostic(const MemoryValueKey& key,
|
||||
size_t requestedSize,
|
||||
size_t currentFirstAvailableAddress,
|
||||
size_t alignedEndAddress) {
|
||||
llvm::errs() << "PIM local memory allocation overflow\n";
|
||||
llvm::errs() << "Pim local memory allocation overflow\n";
|
||||
llvm::errs() << "Requested allocation size: " << requestedSize << " bytes\n";
|
||||
llvm::errs() << "Current firstAvailableAddress: " << currentFirstAvailableAddress << "\n";
|
||||
llvm::errs() << "Aligned end address: " << alignedEndAddress << "\n";
|
||||
@@ -187,7 +187,7 @@ size_t PimMemory::allocateAddress(size_t size, const MemoryValueKey& key) {
|
||||
size,
|
||||
firstAvailableAddress,
|
||||
succeeded(checkedAlignedEnd) ? *checkedAlignedEnd : kPimLocalMemoryAddressLimit);
|
||||
llvm_unreachable("PIM local memory allocation overflow");
|
||||
llvm_unreachable("Pim local memory allocation overflow");
|
||||
}
|
||||
firstAvailableAddress = *checkedAlignedEnd;
|
||||
return address;
|
||||
@@ -276,7 +276,7 @@ void PimMemory::allocateCore(const CompiledCoreMemoryPlan& plan, std::optional<u
|
||||
}
|
||||
else if (*localArenaSize != plan.arenaSize || reportRow.logicalLocalAllocationCount != plan.logicalAllocationCount
|
||||
|| reportRow.logicalLocalBytes != plan.logicalBytes)
|
||||
llvm_unreachable("inconsistent PIM local-memory plan across core-batch lanes");
|
||||
llvm_unreachable("inconsistent Pim local-memory plan across core-batch lanes");
|
||||
for (const CompiledLocalMemoryEntry& entry : plan.entries) {
|
||||
MemoryValueKey key = getMemoryValueKey(entry.value, lane);
|
||||
ownedMemEntriesMap[key] = entry.memory;
|
||||
@@ -352,8 +352,8 @@ size_t PimAcceleratorMemory::getValueAddress(mlir::Value value,
|
||||
llvm_unreachable("Missing mem entry");
|
||||
}
|
||||
|
||||
size_t byteOffset = pim::checkedSizeOrCrash(resolvedAddress->byteOffset, "resolved PIM byte offset");
|
||||
return pim::checkedAddOrCrash(iter->second.address, byteOffset, "resolved PIM address");
|
||||
size_t byteOffset = pim::checkedSizeOrCrash(resolvedAddress->byteOffset, "resolved Pim byte offset");
|
||||
return pim::checkedAddOrCrash(iter->second.address, byteOffset, "resolved Pim address");
|
||||
}
|
||||
|
||||
llvm::FailureOr<int64_t> PimAcceleratorMemory::getIndexValue(mlir::Value value,
|
||||
@@ -706,6 +706,8 @@ void PimCodeGen::codeGenSendOp(pim::PimSendOp sendOp, const StaticValueKnowledge
|
||||
|
||||
void PimCodeGen::codeGenWaitOp(
|
||||
pim::PimWaitOp waitOp, const StaticValueKnowledge& knowledge) const {
|
||||
if (pimDisableSynchronization)
|
||||
return;
|
||||
auto eventRegister = indexOf(waitOp.getEventRegister(), knowledge);
|
||||
auto waitValue = indexOf(waitOp.getWaitValue(), knowledge);
|
||||
assert(succeeded(eventRegister) && succeeded(waitValue)
|
||||
@@ -722,6 +724,8 @@ void PimCodeGen::codeGenWaitOp(
|
||||
|
||||
void PimCodeGen::codeGenSyncOp(
|
||||
pim::PimSyncOp syncOp, const StaticValueKnowledge& knowledge) const {
|
||||
if (pimDisableSynchronization)
|
||||
return;
|
||||
auto targetCoreId = indexOf(syncOp.getTargetCoreId(), knowledge);
|
||||
auto eventRegister = indexOf(syncOp.getEventRegister(), knowledge);
|
||||
assert(succeeded(targetCoreId) && succeeded(eventRegister)
|
||||
@@ -958,7 +962,7 @@ static LogicalResult executeCompiledCorePlan(
|
||||
auto step = node.step.evaluate(knowledge);
|
||||
auto forOp = cast<mlir::scf::ForOp>(node.op);
|
||||
if (failed(lowerBound) || failed(upperBound) || failed(step) || *step <= 0) {
|
||||
forOp.emitOpError("requires statically evaluable scf.for bounds for PIM codegen");
|
||||
forOp.emitOpError("requires statically evaluable scf.for bounds for Pim codegen");
|
||||
return failure();
|
||||
}
|
||||
|
||||
@@ -984,7 +988,7 @@ static LogicalResult executeCompiledCorePlan(
|
||||
auto condition = node.condition.evaluate(knowledge);
|
||||
auto ifOp = cast<mlir::scf::IfOp>(node.op);
|
||||
if (failed(condition)) {
|
||||
ifOp.emitOpError("requires statically evaluable scf.if condition for PIM codegen");
|
||||
ifOp.emitOpError("requires statically evaluable scf.if condition for Pim codegen");
|
||||
return failure();
|
||||
}
|
||||
|
||||
@@ -998,7 +1002,7 @@ static LogicalResult executeCompiledCorePlan(
|
||||
auto selector = node.condition.evaluate(knowledge);
|
||||
auto switchOp = cast<mlir::scf::IndexSwitchOp>(node.op);
|
||||
if (failed(selector)) {
|
||||
switchOp.emitOpError("requires a statically evaluable scf.index_switch selector for PIM codegen");
|
||||
switchOp.emitOpError("requires a statically evaluable scf.index_switch selector for Pim codegen");
|
||||
return failure();
|
||||
}
|
||||
const llvm::SmallVectorImpl<CompiledCoreNode>* selectedBody = node.defaultBody.get();
|
||||
@@ -1184,12 +1188,12 @@ OnnxMlirCompilerErrorCodes onnx_mlir::compileToPimCode(ModuleOp& moduleOp, std::
|
||||
}
|
||||
auto getCompiledProgram = [&](Operation* op) {
|
||||
auto it = compiledPrograms.find(op);
|
||||
assert(it != compiledPrograms.end() && "missing compiled PIM core program");
|
||||
assert(it != compiledPrograms.end() && "missing compiled Pim core program");
|
||||
return it->second.get();
|
||||
};
|
||||
auto getMemoryPlan = [&](Operation* op) {
|
||||
auto it = memoryPlans.find(op);
|
||||
assert(it != memoryPlans.end() && "missing PIM core memory plan");
|
||||
assert(it != memoryPlans.end() && "missing Pim core memory plan");
|
||||
return it->second.get();
|
||||
};
|
||||
|
||||
@@ -1267,7 +1271,7 @@ OnnxMlirCompilerErrorCodes onnx_mlir::compileToPimCode(ModuleOp& moduleOp, std::
|
||||
if (failed(weightView)) {
|
||||
std::string message;
|
||||
llvm::raw_string_ostream os(message);
|
||||
os << "requires a statically resolvable dense global weight view during PIM codegen; weight="
|
||||
os << "requires a statically resolvable dense global weight view during Pim codegen; weight="
|
||||
<< vmmOp.getWeight() << " type=" << vmmOp.getWeight().getType();
|
||||
result.recordDiagnostic(vmmOp, os.str());
|
||||
return failure();
|
||||
@@ -1275,7 +1279,7 @@ OnnxMlirCompilerErrorCodes onnx_mlir::compileToPimCode(ModuleOp& moduleOp, std::
|
||||
if (weightView->shape.size() != 2) {
|
||||
std::string message;
|
||||
llvm::raw_string_ostream os(message);
|
||||
os << "requires a rank-2 matrix weight view during PIM codegen; resolved shape=[";
|
||||
os << "requires a rank-2 matrix weight view during Pim codegen; resolved shape=[";
|
||||
llvm::interleaveComma(weightView->shape, os);
|
||||
os << "] weight=" << vmmOp.getWeight() << " type=" << vmmOp.getWeight().getType();
|
||||
result.recordDiagnostic(vmmOp, os.str());
|
||||
@@ -1387,7 +1391,7 @@ OnnxMlirCompilerErrorCodes onnx_mlir::compileToPimCode(ModuleOp& moduleOp, std::
|
||||
}
|
||||
if (diagnostics.hasFailure())
|
||||
diagnostics.emitSuppressedSummary(summaryAnchor ? summaryAnchor : moduleOp.getOperation(),
|
||||
"PIM codegen diagnostic(s)");
|
||||
"Pim codegen diagnostic(s)");
|
||||
|
||||
for (size_t jobIndex = 0; jobIndex < jobs.size(); ++jobIndex)
|
||||
if (jobResults[jobIndex].status != CompilerSuccess)
|
||||
@@ -1453,7 +1457,7 @@ OnnxMlirCompilerErrorCodes onnx_mlir::compileToPimCode(ModuleOp& moduleOp, std::
|
||||
if (!batchPerCoreRow)
|
||||
batchPerCoreRow = result.reportRow;
|
||||
else if (!(*batchPerCoreRow == result.reportRow))
|
||||
llvm_unreachable("one PIM core batch produced inconsistent per-core memory reports");
|
||||
llvm_unreachable("one Pim core batch produced inconsistent per-core memory reports");
|
||||
}
|
||||
|
||||
uint64_t batchReportId = jobs[group.front()].batchReportId.value_or(0);
|
||||
|
||||
@@ -9,25 +9,25 @@
|
||||
namespace onnx_mlir {
|
||||
|
||||
llvm::cl::opt<PimEmissionTargetType> pimEmissionTarget(
|
||||
llvm::cl::desc("[Optional] Choose PIM-related target to emit (once selected it will cancel the other targets):"),
|
||||
llvm::cl::values(clEnumVal(EmitSpatial, "Lower model to spatial IR")),
|
||||
llvm::cl::values(clEnumVal(EmitPim, "Lower model to PIM IR")),
|
||||
llvm::cl::values(clEnumVal(EmitPimBufferized, "Lower model to PIM IR and bufferize it")),
|
||||
llvm::cl::values(clEnumVal(EmitPimCodegen, "Lower model to PIM IR and generate code for PIM")),
|
||||
llvm::cl::desc("[Optional] Choose Pim-related target to emit (once selected it will cancel the other targets):"),
|
||||
llvm::cl::values(clEnumVal(EmitSpatial, "Lower model to Spatial IR")),
|
||||
llvm::cl::values(clEnumVal(EmitPim, "Lower model to Pim IR")),
|
||||
llvm::cl::values(clEnumVal(EmitPimBufferized, "Lower model to Pim IR and bufferize it")),
|
||||
llvm::cl::values(clEnumVal(EmitPimCodegen, "Lower model to Pim IR and generate code for Pim")),
|
||||
llvm::cl::init(EmitPimCodegen),
|
||||
llvm::cl::cat(OnnxMlirOptions));
|
||||
|
||||
llvm::cl::opt<PimMemoryReportLevel> pimMemoryReport(
|
||||
"pim-memory-report",
|
||||
llvm::cl::desc("Emit a human-readable PIM memory planning report"),
|
||||
llvm::cl::values(clEnumValN(PimMemoryReportNone, "none", "Do not emit any PIM memory planning report")),
|
||||
llvm::cl::values(clEnumValN(PimMemoryReportSummary, "summary", "Emit a concise PIM memory summary")),
|
||||
llvm::cl::desc("Emit a human-readable Pim memory planning report"),
|
||||
llvm::cl::values(clEnumValN(PimMemoryReportNone, "none", "Do not emit any Pim memory planning report")),
|
||||
llvm::cl::values(clEnumValN(PimMemoryReportSummary, "summary", "Emit a concise Pim memory summary")),
|
||||
llvm::cl::init(PimMemoryReportSummary),
|
||||
llvm::cl::cat(OnnxMlirOptions));
|
||||
|
||||
llvm::cl::opt<PimConvLoweringType> pimConvLowering(
|
||||
"pim-conv-lowering",
|
||||
llvm::cl::desc("Convolution lowering strategy for PIM"),
|
||||
llvm::cl::desc("Convolution lowering strategy for Pim"),
|
||||
llvm::cl::values(clEnumValN(PimConvLoweringAuto, "auto", "Select the Conv lowering strategy automatically")),
|
||||
llvm::cl::values(clEnumValN(PimConvLoweringLegacy, "legacy", "Use the legacy explicit-im2col Conv lowering")),
|
||||
llvm::cl::values(clEnumValN(PimConvLoweringDepthwise, "depthwise", "Force the depthwise-specialized Conv lowering")),
|
||||
@@ -55,20 +55,20 @@ llvm::cl::opt<PimSpatialDataflowExportType> pimExportSpatialDataflow(
|
||||
llvm::cl::desc("Emit Gephi-importable CSV dataflow reports for Spatial pipeline snapshots"),
|
||||
llvm::cl::values(clEnumValN(SpatialDataflowExportNone, "none", "Do not emit Spatial dataflow CSV reports")),
|
||||
llvm::cl::values(
|
||||
clEnumValN(SpatialDataflowExportSpatial1, "spatial1", "Emit spatial1 graph dataflow CSV reports")),
|
||||
clEnumValN(SpatialDataflowExportSpatial1, "spatial1", "Emit Spatial1 graph dataflow CSV reports")),
|
||||
llvm::cl::values(
|
||||
clEnumValN(SpatialDataflowExportSpatial2, "spatial2", "Emit spatial2 trivially merged graph dataflow CSV reports")),
|
||||
clEnumValN(SpatialDataflowExportSpatial2, "spatial2", "Emit Spatial2 trivially merged graph dataflow CSV reports")),
|
||||
llvm::cl::values(
|
||||
clEnumValN(SpatialDataflowExportSpatial3, "spatial3", "Emit spatial3 scheduled dataflow CSV reports")),
|
||||
clEnumValN(SpatialDataflowExportSpatial3, "spatial3", "Emit Spatial3 scheduled dataflow CSV reports")),
|
||||
llvm::cl::values(
|
||||
clEnumValN(SpatialDataflowExportSpatial4, "spatial4", "Emit spatial4 realized dataflow CSV reports")),
|
||||
clEnumValN(SpatialDataflowExportSpatial4, "spatial4", "Emit Spatial4 realized dataflow CSV reports")),
|
||||
llvm::cl::values(clEnumValN(SpatialDataflowExportAll, "all", "Emit all Spatial dataflow CSV reports")),
|
||||
llvm::cl::init(SpatialDataflowExportNone),
|
||||
llvm::cl::cat(OnnxMlirOptions));
|
||||
|
||||
llvm::cl::opt<bool>
|
||||
pimOnlyCodegen("pim-only-codegen",
|
||||
llvm::cl::desc("Only generate code for PIM (assume input is already in bufferized PIM IR)"),
|
||||
llvm::cl::desc("Only generate code for Pim (assume input is already in bufferized Pim IR)"),
|
||||
llvm::cl::init(false),
|
||||
llvm::cl::cat(OnnxMlirOptions));
|
||||
|
||||
@@ -96,21 +96,37 @@ llvm::cl::opt<bool> pimEmitJson("pim-emit-json",
|
||||
|
||||
llvm::cl::opt<bool> pimDetectCommunicationDeadlock(
|
||||
"pim-detect-communication-deadlock",
|
||||
llvm::cl::desc("Expensively simulate the statically expanded PIM send/receive order at verification time and fail if a blocking communication deadlock is found"),
|
||||
llvm::cl::desc("Expensively simulate the statically expanded Pim send/receive order at verification time and fail if a blocking communication deadlock is found"),
|
||||
llvm::cl::init(false),
|
||||
llvm::cl::cat(OnnxMlirOptions));
|
||||
|
||||
llvm::cl::opt<bool> pimVerifyBufferizationCopyFreedom(
|
||||
"pim-verify-bufferization-copy-freedom",
|
||||
llvm::cl::desc("Run the expensive official PIM tensor-copy freedom proof before bufferization"),
|
||||
llvm::cl::desc("Run the expensive official Pim tensor-copy freedom proof before bufferization"),
|
||||
llvm::cl::init(false),
|
||||
llvm::cl::cat(OnnxMlirOptions));
|
||||
|
||||
llvm::cl::opt<bool> pimDisableSynchronization(
|
||||
"pim-disable-synchronization",
|
||||
llvm::cl::desc("Omit Pim wait/sync instructions from generated code for performance ablation"),
|
||||
llvm::cl::init(false),
|
||||
llvm::cl::cat(OnnxMlirOptions));
|
||||
|
||||
llvm::cl::opt<bool> pimDisableSpatialPlanning(
|
||||
"pim-disable-spatial-planning",
|
||||
llvm::cl::desc("Select the trivial Spatial layout plan for performance ablation"),
|
||||
llvm::cl::init(false),
|
||||
llvm::cl::cat(OnnxMlirOptions));
|
||||
|
||||
llvm::cl::opt<size_t>
|
||||
crossbarSize("crossbar-size", llvm::cl::desc("Width and height of a single crossbar"), llvm::cl::init(128));
|
||||
crossbarSize("crossbar-size",
|
||||
llvm::cl::desc("Width and height of a single crossbar (required for Pim compilation)"),
|
||||
llvm::cl::init(0));
|
||||
|
||||
llvm::cl::opt<size_t>
|
||||
crossbarCountInCore("crossbar-count", llvm::cl::desc("Number of crossbars in each core"), llvm::cl::init(64));
|
||||
crossbarCountInCore("crossbar-count",
|
||||
llvm::cl::desc("Number of crossbars in each core (required for Pim compilation)"),
|
||||
llvm::cl::init(0));
|
||||
|
||||
llvm::cl::opt<size_t> pipelineStages(
|
||||
"pipeline",
|
||||
@@ -119,32 +135,35 @@ llvm::cl::opt<size_t> pipelineStages(
|
||||
llvm::cl::cat(OnnxMlirOptions));
|
||||
|
||||
llvm::cl::opt<long> coresCount("core-count",
|
||||
llvm::cl::desc("Number of cores in the chip. Required for PIM compilation."),
|
||||
llvm::cl::desc("Number of cores in the chip. Required for Pim compilation."),
|
||||
llvm::cl::init(-1));
|
||||
|
||||
llvm::cl::opt<std::string> pimTargetConfig(
|
||||
"pim-target-config",
|
||||
llvm::cl::desc("PIM target configuration used to construct the Spatial scheduling cost model"),
|
||||
llvm::cl::desc("Pim target configuration used to construct the Spatial scheduling cost model"),
|
||||
llvm::cl::init(""),
|
||||
llvm::cl::cat(OnnxMlirOptions));
|
||||
|
||||
bool hasExplicitPimCoreCount() { return coresCount.getNumOccurrences() != 0; }
|
||||
|
||||
void verifyExplicitPimCoreCount() {
|
||||
if (!hasExplicitPimCoreCount())
|
||||
llvm::report_fatal_error("PIM compilation requires an explicit --core-count=<positive integer>");
|
||||
void verifyPimCompilerOptions() {
|
||||
if (coresCount.getNumOccurrences() == 0)
|
||||
llvm::report_fatal_error("Pim compilation requires an explicit --core-count=<positive integer>");
|
||||
if (coresCount.getValue() <= 0)
|
||||
llvm::report_fatal_error("PIM compilation requires --core-count to be a positive integer");
|
||||
}
|
||||
|
||||
void verifyPimPipelineStages() {
|
||||
llvm::report_fatal_error("Pim compilation requires --core-count to be a positive integer");
|
||||
if (crossbarSize.getNumOccurrences() == 0)
|
||||
llvm::report_fatal_error("Pim compilation requires an explicit --crossbar-size=<positive integer>");
|
||||
if (crossbarSize.getValue() == 0)
|
||||
llvm::report_fatal_error("Pim compilation requires --crossbar-size to be a positive integer");
|
||||
if (crossbarCountInCore.getNumOccurrences() == 0)
|
||||
llvm::report_fatal_error("Pim compilation requires an explicit --crossbar-count=<positive integer>");
|
||||
if (crossbarCountInCore.getValue() == 0)
|
||||
llvm::report_fatal_error("Pim compilation requires --crossbar-count to be a positive integer");
|
||||
if (pipelineStages.getValue() == 0)
|
||||
llvm::report_fatal_error("PIM compilation requires --pipeline to be positive");
|
||||
llvm::report_fatal_error("Pim compilation requires --pipeline to be positive");
|
||||
if (static_cast<size_t>(coresCount.getValue()) < pipelineStages.getValue())
|
||||
llvm::report_fatal_error("PIM compilation requires --pipeline not to exceed --core-count");
|
||||
llvm::report_fatal_error("Pim compilation requires --pipeline not to exceed --core-count");
|
||||
if (crossbarCountInCore.getValue()
|
||||
> std::numeric_limits<size_t>::max() / pipelineStages.getValue())
|
||||
llvm::report_fatal_error("PIM compilation --crossbar-count * --pipeline overflows");
|
||||
llvm::report_fatal_error("Pim compilation --crossbar-count * --pipeline overflows");
|
||||
}
|
||||
|
||||
} // namespace onnx_mlir
|
||||
|
||||
@@ -59,6 +59,8 @@ extern llvm::cl::opt<bool> pimEmitJson;
|
||||
extern llvm::cl::opt<bool> pimReportConvLowering;
|
||||
extern llvm::cl::opt<bool> pimDetectCommunicationDeadlock;
|
||||
extern llvm::cl::opt<bool> pimVerifyBufferizationCopyFreedom;
|
||||
extern llvm::cl::opt<bool> pimDisableSynchronization;
|
||||
extern llvm::cl::opt<bool> pimDisableSpatialPlanning;
|
||||
|
||||
extern llvm::cl::opt<size_t> crossbarSize;
|
||||
extern llvm::cl::opt<size_t> crossbarCountInCore;
|
||||
@@ -68,8 +70,6 @@ extern llvm::cl::opt<std::string> pimTargetConfig;
|
||||
extern llvm::cl::opt<uint64_t> pimConvIm2colMaxElements;
|
||||
extern llvm::cl::opt<uint64_t> pimConvStreamChunkPositions;
|
||||
|
||||
bool hasExplicitPimCoreCount();
|
||||
void verifyExplicitPimCoreCount();
|
||||
void verifyPimPipelineStages();
|
||||
void verifyPimCompilerOptions();
|
||||
|
||||
} // namespace onnx_mlir
|
||||
|
||||
@@ -97,7 +97,7 @@ spatial::ConvLoweringStrategy getSpatialConvLoweringStrategy(PimConvLoweringType
|
||||
case PimConvLoweringInputKTiled: return spatial::ConvLoweringStrategy::InputKTiled;
|
||||
case PimConvLoweringTiled2D: return spatial::ConvLoweringStrategy::Tiled2D;
|
||||
}
|
||||
llvm_unreachable("unknown PIM Conv lowering strategy");
|
||||
llvm_unreachable("unknown Pim Conv lowering strategy");
|
||||
}
|
||||
|
||||
spatial::SpatialDataflowExportStage getPimSpatialDataflowExportStage(
|
||||
@@ -110,7 +110,7 @@ spatial::SpatialDataflowExportStage getPimSpatialDataflowExportStage(
|
||||
case SpatialDataflowExportSpatial4: return spatial::SpatialDataflowExportStage::Spatial4;
|
||||
case SpatialDataflowExportAll: return spatial::SpatialDataflowExportStage::All;
|
||||
}
|
||||
llvm_unreachable("unknown PIM Spatial dataflow export stage");
|
||||
llvm_unreachable("unknown Pim Spatial dataflow export stage");
|
||||
}
|
||||
|
||||
spatial::SpatialTargetResources getPimSpatialTargetResources(const spatial::SchedulingTarget& target) {
|
||||
@@ -120,7 +120,7 @@ spatial::SpatialTargetResources getPimSpatialTargetResources(const spatial::Sche
|
||||
resources.processorCount = target.processorCount;
|
||||
resources.vectorWidth = target.vectorWidth;
|
||||
if (failed(resources.verify()))
|
||||
llvm::report_fatal_error("PIM target resources are incomplete");
|
||||
llvm::report_fatal_error("Pim target resources are incomplete");
|
||||
return resources;
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ const llvm::json::Object& requireObject(const llvm::json::Object& object,
|
||||
llvm::StringRef path) {
|
||||
const llvm::json::Object* nested = object.getObject(key);
|
||||
if (!nested)
|
||||
llvm::report_fatal_error("PIM target config is missing object '" + path + "." + key + "'");
|
||||
llvm::report_fatal_error("Pim target config is missing object '" + path + "." + key + "'");
|
||||
return *nested;
|
||||
}
|
||||
|
||||
@@ -151,7 +151,7 @@ Cost getConfigCost(const llvm::json::Object& object,
|
||||
return fallback;
|
||||
if (!std::isfinite(*number) || *number < 0.0 || (!allowZero && *number == 0.0)
|
||||
|| *number > static_cast<double>(std::numeric_limits<Cost>::max()))
|
||||
llvm::report_fatal_error("PIM target config field '" + key + "' must be a valid positive number");
|
||||
llvm::report_fatal_error("Pim target config field '" + key + "' must be a valid positive number");
|
||||
return static_cast<Cost>(std::ceil(*number));
|
||||
}
|
||||
|
||||
@@ -159,11 +159,11 @@ std::pair<size_t, size_t> getConfigPair(const llvm::json::Object& object,
|
||||
llvm::StringRef key) {
|
||||
const llvm::json::Array* values = object.getArray(key);
|
||||
if (!values || values->size() != 2)
|
||||
llvm::report_fatal_error("PIM target config field '" + key + "' must contain two integers");
|
||||
llvm::report_fatal_error("Pim target config field '" + key + "' must contain two integers");
|
||||
std::optional<int64_t> first = (*values)[0].getAsInteger();
|
||||
std::optional<int64_t> second = (*values)[1].getAsInteger();
|
||||
if (!first || !second || *first <= 0 || *second <= 0)
|
||||
llvm::report_fatal_error("PIM target config field '" + key + "' must contain two positive integers");
|
||||
llvm::report_fatal_error("Pim target config field '" + key + "' must contain two positive integers");
|
||||
return {static_cast<size_t>(*first), static_cast<size_t>(*second)};
|
||||
}
|
||||
|
||||
@@ -174,7 +174,7 @@ void loadPimInterProcessorLatencies(
|
||||
network.getString("net_config_file_path");
|
||||
if (!filename)
|
||||
llvm::report_fatal_error(
|
||||
"PIM target config is missing network latency file path");
|
||||
"Pim target config is missing network latency file path");
|
||||
|
||||
llvm::SmallString<256> networkPath(*filename);
|
||||
if (!llvm::sys::path::is_absolute(networkPath)) {
|
||||
@@ -187,19 +187,19 @@ void loadPimInterProcessorLatencies(
|
||||
auto buffer = llvm::MemoryBuffer::getFile(networkPath);
|
||||
if (!buffer)
|
||||
llvm::report_fatal_error(
|
||||
llvm::Twine("failed to read PIM network config '")
|
||||
llvm::Twine("failed to read Pim network config '")
|
||||
+ networkPath + "': " + buffer.getError().message());
|
||||
auto parsed = llvm::json::parse(buffer.get()->getBuffer());
|
||||
if (!parsed)
|
||||
llvm::report_fatal_error(
|
||||
llvm::Twine("failed to parse PIM network config '")
|
||||
llvm::Twine("failed to parse Pim network config '")
|
||||
+ networkPath + "': " + llvm::toString(parsed.takeError()));
|
||||
const llvm::json::Object* root = parsed->getAsObject();
|
||||
const llvm::json::Object* latencies =
|
||||
root ? root->getObject("latency") : nullptr;
|
||||
if (!latencies)
|
||||
llvm::report_fatal_error(
|
||||
"PIM network config is missing its latency matrix");
|
||||
"Pim network config is missing its latency matrix");
|
||||
|
||||
target.interProcessorLatencyNs.assign(
|
||||
target.processorCount * target.processorCount, 0);
|
||||
@@ -210,7 +210,7 @@ void loadPimInterProcessorLatencies(
|
||||
const llvm::json::Object* row = latencies->getObject(sourceKey);
|
||||
if (!row)
|
||||
llvm::report_fatal_error(
|
||||
llvm::Twine("PIM network config is missing latency row ")
|
||||
llvm::Twine("Pim network config is missing latency row ")
|
||||
+ sourceKey);
|
||||
for (size_t destination = 0;
|
||||
destination < target.processorCount; ++destination) {
|
||||
@@ -220,7 +220,7 @@ void loadPimInterProcessorLatencies(
|
||||
std::optional<double> latency = row->getNumber(destinationKey);
|
||||
if (!latency || !std::isfinite(*latency) || *latency <= 0.0)
|
||||
llvm::report_fatal_error(
|
||||
llvm::Twine("PIM network config is missing latency ")
|
||||
llvm::Twine("Pim network config is missing latency ")
|
||||
+ sourceKey + " -> " + destinationKey);
|
||||
Cost roundedLatency = static_cast<Cost>(std::ceil(*latency));
|
||||
target.interProcessorLatencyNs[
|
||||
@@ -244,17 +244,17 @@ spatial::SchedulingTarget getPimSchedulingTarget() {
|
||||
auto buffer = llvm::MemoryBuffer::getFile(pimTargetConfig);
|
||||
if (!buffer)
|
||||
llvm::report_fatal_error(
|
||||
llvm::Twine("failed to read PIM target config '")
|
||||
llvm::Twine("failed to read Pim target config '")
|
||||
+ pimTargetConfig.getValue() + "': " + buffer.getError().message());
|
||||
auto parsed = llvm::json::parse(buffer.get()->getBuffer());
|
||||
if (!parsed)
|
||||
llvm::report_fatal_error(
|
||||
llvm::Twine("failed to parse PIM target config '")
|
||||
llvm::Twine("failed to parse Pim target config '")
|
||||
+ pimTargetConfig.getValue() + "': "
|
||||
+ llvm::toString(parsed.takeError()));
|
||||
const llvm::json::Object* root = parsed->getAsObject();
|
||||
if (!root)
|
||||
llvm::report_fatal_error("PIM target config must contain a JSON object");
|
||||
llvm::report_fatal_error("Pim target config must contain a JSON object");
|
||||
|
||||
const llvm::json::Object& chip = requireObject(*root, "chip_config", "root");
|
||||
const llvm::json::Object& core = requireObject(chip, "core_config", "chip_config");
|
||||
@@ -267,7 +267,7 @@ spatial::SchedulingTarget getPimSchedulingTarget() {
|
||||
|
||||
std::optional<int64_t> coreCount = chip.getInteger("core_cnt");
|
||||
if (!coreCount || *coreCount <= 0)
|
||||
llvm::report_fatal_error("PIM target config field 'core_cnt' must be a positive integer");
|
||||
llvm::report_fatal_error("Pim target config field 'core_cnt' must be a positive integer");
|
||||
target.processorCount = static_cast<size_t>(*coreCount);
|
||||
target.residentWeightCapacity =
|
||||
getConfigCost(matrix, "xbar_array_count", target.residentWeightCapacity);
|
||||
@@ -278,7 +278,7 @@ spatial::SchedulingTarget getPimSchedulingTarget() {
|
||||
|| target.residentWeightCapacity != crossbarCountInCore.getValue()
|
||||
|| target.matrixRows != crossbarSize.getValue()
|
||||
|| target.matrixColumns != crossbarSize.getValue())
|
||||
llvm::report_fatal_error("PIM target config resources do not match --core-count, "
|
||||
llvm::report_fatal_error("Pim target config resources do not match --core-count, "
|
||||
"--crossbar-count, and --crossbar-size");
|
||||
loadPimInterProcessorLatencies(target, network);
|
||||
|
||||
@@ -331,8 +331,7 @@ void addPassesPim(OwningOpRef<ModuleOp>& module,
|
||||
PassManager& pm,
|
||||
EmissionTargetType& emissionTarget,
|
||||
std::string outputNameNoExt) {
|
||||
verifyExplicitPimCoreCount();
|
||||
verifyPimPipelineStages();
|
||||
verifyPimCompilerOptions();
|
||||
spatial::SchedulingTarget schedulingTarget = getPimSchedulingTarget();
|
||||
spatial::SpatialTargetResources targetResources = getPimSpatialTargetResources(schedulingTarget);
|
||||
|
||||
@@ -352,7 +351,8 @@ void addPassesPim(OwningOpRef<ModuleOp>& module,
|
||||
spatial::SpatialDataflowExportStage exportStage =
|
||||
getPimSpatialDataflowExportStage(pimExportSpatialDataflow.getValue());
|
||||
pm.addPass(createONNXToSpatialPass(targetResources, planningOptions));
|
||||
pm.addPass(createSpatialLayoutPlanningPass(targetResources));
|
||||
pm.addPass(createSpatialLayoutPlanningPass(
|
||||
targetResources, pimDisableSpatialPlanning.getValue()));
|
||||
pm.addPass(createLowerSpatialPlansPass(targetResources, planningOptions, exportStage));
|
||||
pm.addPass(createTrivialGraphComputeMergePass(
|
||||
schedulingTarget.residentWeightCapacity, exportStage));
|
||||
|
||||
@@ -46,7 +46,7 @@ static LogicalResult compileCoreEmissionPlan(Block& block, SmallVectorImpl<Compi
|
||||
auto upper = compileIndexExpr(forOp.getUpperBound());
|
||||
auto step = compileIndexExpr(forOp.getStep());
|
||||
if (failed(lower) || failed(upper) || failed(step)) {
|
||||
forOp.emitOpError("requires statically evaluable scf.for bounds for PIM codegen");
|
||||
forOp.emitOpError("requires statically evaluable scf.for bounds for Pim codegen");
|
||||
return failure();
|
||||
}
|
||||
CompiledCoreNode node;
|
||||
@@ -63,7 +63,7 @@ static LogicalResult compileCoreEmissionPlan(Block& block, SmallVectorImpl<Compi
|
||||
if (auto ifOp = dyn_cast<scf::IfOp>(op)) {
|
||||
auto condition = compileIndexExpr(ifOp.getCondition());
|
||||
if (failed(condition)) {
|
||||
ifOp.emitOpError("requires statically evaluable scf.if condition for PIM codegen");
|
||||
ifOp.emitOpError("requires statically evaluable scf.if condition for Pim codegen");
|
||||
return failure();
|
||||
}
|
||||
CompiledCoreNode node;
|
||||
@@ -82,7 +82,7 @@ static LogicalResult compileCoreEmissionPlan(Block& block, SmallVectorImpl<Compi
|
||||
if (auto switchOp = dyn_cast<scf::IndexSwitchOp>(op)) {
|
||||
auto selector = compileIndexExpr(switchOp.getArg());
|
||||
if (failed(selector)) {
|
||||
switchOp.emitOpError("requires a statically evaluable scf.index_switch selector for PIM codegen");
|
||||
switchOp.emitOpError("requires a statically evaluable scf.index_switch selector for Pim codegen");
|
||||
return failure();
|
||||
}
|
||||
CompiledCoreNode node;
|
||||
|
||||
@@ -249,7 +249,7 @@ auto createEmptySpatGraphComputeBatch(RewriterT& rewriter,
|
||||
if (laneCount <= 0 || laneCount > std::numeric_limits<int32_t>::max())
|
||||
return mlir::FailureOr<spatial::SpatGraphComputeBatch>(mlir::failure());
|
||||
|
||||
auto laneCountAttr = pim::getCheckedI32Attr(rewriter, loc, laneCount, "spatial compute_batch lane count");
|
||||
auto laneCountAttr = pim::getCheckedI32Attr(rewriter, loc, laneCount, "Spatial compute_batch lane count");
|
||||
if (mlir::failed(laneCountAttr))
|
||||
return mlir::FailureOr<spatial::SpatGraphComputeBatch>(mlir::failure());
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ llvm::SmallVector<mlir::Value> sliceVector(const mlir::Value& vectorToSlice,
|
||||
mlir::Location loc);
|
||||
|
||||
/// Partitions one logical vector into per-core crossbar-sized slices using the
|
||||
/// current PIM target geometry.
|
||||
/// current Pim target geometry.
|
||||
llvm::DenseMap<CoreId, llvm::SmallVector<mlir::Value>> sliceVectorPerCrossbarPerCore(
|
||||
const mlir::Value& vectorToSlice,
|
||||
mlir::PatternRewriter& rewriter,
|
||||
|
||||
@@ -46,7 +46,7 @@ struct LowerSpatialPlansPass final
|
||||
}
|
||||
auto entryFunc = getPimEntryFunc(moduleOp);
|
||||
if (failed(entryFunc)) {
|
||||
moduleOp.emitError("failed to locate the PIM entry function during LowerSpatialPlans");
|
||||
moduleOp.emitError("failed to locate the Pim entry function during LowerSpatialPlans");
|
||||
signalPassFailure();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -158,7 +158,7 @@ void ONNXToSpatialPass::runOnOperation() {
|
||||
|
||||
auto entryFunc = getPimEntryFunc(moduleOp);
|
||||
if (failed(entryFunc)) {
|
||||
moduleOp.emitError("failed to locate the PIM entry function during ONNX-to-Spatial lowering");
|
||||
moduleOp.emitError("failed to locate the Pim entry function during ONNX-to-Spatial lowering");
|
||||
signalPassFailure();
|
||||
return;
|
||||
}
|
||||
@@ -245,7 +245,7 @@ void ONNXToSpatialPass::runOnOperation() {
|
||||
RewritePatternSet postPatterns(ctx);
|
||||
populatePostPatterns(postPatterns, ctx);
|
||||
if (failed(applyPartialConversion(*entryFunc, postTarget, std::move(postPatterns)))) {
|
||||
moduleOp.emitError("failed to normalize weight-like Spatial compute operands before Spatial-to-PIM lowering");
|
||||
moduleOp.emitError("failed to normalize weight-like Spatial compute operands before Spatial-to-Pim lowering");
|
||||
signalPassFailure();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -42,8 +42,9 @@ static SmallVector<spatial::PhysicalLayout> getOperandLayouts(
|
||||
class SpatialLayoutAnalysis {
|
||||
public:
|
||||
SpatialLayoutAnalysis(func::FuncOp funcOp,
|
||||
const spatial::SpatialTargetResources& target)
|
||||
: funcOp(funcOp), target(target) {}
|
||||
const spatial::SpatialTargetResources& target,
|
||||
bool selectTrivialPlan)
|
||||
: funcOp(funcOp), target(target), selectTrivialPlan(selectTrivialPlan) {}
|
||||
|
||||
FailureOr<SpatialLayoutSelection> run() {
|
||||
SpatialLayoutSelection selection;
|
||||
@@ -56,6 +57,9 @@ public:
|
||||
selection.selectedAlternative[&op] = 0;
|
||||
}
|
||||
|
||||
if (selectTrivialPlan)
|
||||
return selection;
|
||||
|
||||
const size_t maxRounds = 2 * planOps.size() + 1;
|
||||
for (size_t round = 0; round < maxRounds; ++round) {
|
||||
bool changed = false;
|
||||
@@ -168,6 +172,7 @@ private:
|
||||
|
||||
func::FuncOp funcOp;
|
||||
const spatial::SpatialTargetResources& target;
|
||||
bool selectTrivialPlan;
|
||||
};
|
||||
|
||||
static LogicalResult materializeMismatchedUses(
|
||||
@@ -251,8 +256,9 @@ struct SpatialLayoutPlanningPass final
|
||||
}
|
||||
|
||||
SpatialLayoutPlanningPass() = default;
|
||||
explicit SpatialLayoutPlanningPass(const spatial::SpatialTargetResources& target)
|
||||
: target(target), hasTarget(true) {}
|
||||
SpatialLayoutPlanningPass(const spatial::SpatialTargetResources& target,
|
||||
bool selectTrivialPlan)
|
||||
: target(target), selectTrivialPlan(selectTrivialPlan), hasTarget(true) {}
|
||||
|
||||
void runOnOperation() override {
|
||||
ModuleOp moduleOp = getOperation();
|
||||
@@ -263,13 +269,13 @@ struct SpatialLayoutPlanningPass final
|
||||
}
|
||||
auto entryFunc = getPimEntryFunc(moduleOp);
|
||||
if (failed(entryFunc)) {
|
||||
moduleOp.emitError("failed to locate the PIM entry function during Spatial layout planning");
|
||||
moduleOp.emitError("failed to locate the Pim entry function during Spatial layout planning");
|
||||
signalPassFailure();
|
||||
return;
|
||||
}
|
||||
|
||||
func::FuncOp funcOp = *entryFunc;
|
||||
SpatialLayoutAnalysis analysis(funcOp, target);
|
||||
SpatialLayoutAnalysis analysis(funcOp, target, selectTrivialPlan);
|
||||
FailureOr<SpatialLayoutSelection> selection = analysis.run();
|
||||
if (failed(selection)) {
|
||||
signalPassFailure();
|
||||
@@ -301,6 +307,7 @@ struct SpatialLayoutPlanningPass final
|
||||
}
|
||||
|
||||
spatial::SpatialTargetResources target;
|
||||
bool selectTrivialPlan = false;
|
||||
bool hasTarget = false;
|
||||
};
|
||||
|
||||
@@ -311,8 +318,8 @@ std::unique_ptr<Pass> createSpatialLayoutPlanningPass() {
|
||||
}
|
||||
|
||||
std::unique_ptr<Pass> createSpatialLayoutPlanningPass(
|
||||
const spatial::SpatialTargetResources& target) {
|
||||
return std::make_unique<SpatialLayoutPlanningPass>(target);
|
||||
const spatial::SpatialTargetResources& target, bool selectTrivialPlan) {
|
||||
return std::make_unique<SpatialLayoutPlanningPass>(target, selectTrivialPlan);
|
||||
}
|
||||
|
||||
} // namespace onnx_mlir
|
||||
|
||||
@@ -199,7 +199,7 @@ static bool writeConvLoweringReport(const ConvLoweringReportEntry& entry,
|
||||
return false;
|
||||
}
|
||||
|
||||
reportFile << "# PIM Conv Lowering Report (bounded to 512 rows)\n\n";
|
||||
reportFile << "# Pim conv lowering report (bounded to 512 rows)\n\n";
|
||||
reportFile << "## Plan selection\n";
|
||||
writeConvReportTableHeader(reportFile, "Selector");
|
||||
bool realizationSectionStarted = false;
|
||||
|
||||
@@ -307,7 +307,7 @@ LogicalResult raptor::SpatialToPimPass::lowerComputeBatchOp(spatial::SpatSchedul
|
||||
"resultful compute_batch lowering currently requires a spat.in_parallel terminator");
|
||||
}
|
||||
|
||||
auto coreIds = getRequiredScheduledBatchCoreIds(computeBatchOp, "spatial compute_batch core id");
|
||||
auto coreIds = getRequiredScheduledBatchCoreIds(computeBatchOp, "Spatial compute_batch core id");
|
||||
if (failed(coreIds))
|
||||
return failure();
|
||||
SmallVector<Value> batchWeights(computeBatchOp.getWeights().begin(), computeBatchOp.getWeights().end());
|
||||
@@ -317,7 +317,7 @@ LogicalResult raptor::SpatialToPimPass::lowerComputeBatchOp(spatial::SpatSchedul
|
||||
|
||||
rewriter.setInsertionPointAfter(computeBatchOp);
|
||||
auto laneCountAttr = pim::getCheckedI32Attr(
|
||||
rewriter, computeBatchOp, static_cast<uint64_t>(computeBatchOp.getLaneCount()), "pim core_batch lane count");
|
||||
rewriter, computeBatchOp, static_cast<uint64_t>(computeBatchOp.getLaneCount()), "Pim core_batch lane count");
|
||||
if (failed(laneCountAttr))
|
||||
return failure();
|
||||
auto coreBatchOp =
|
||||
|
||||
@@ -410,7 +410,7 @@ LogicalResult raptor::SpatialToPimPass::lowerComputeOp(spatial::SpatScheduledCom
|
||||
continue;
|
||||
}
|
||||
|
||||
return computeOp.emitOpError("has an unsupported remaining result use during Spatial-to-PIM lowering");
|
||||
return computeOp.emitOpError("has an unsupported remaining result use during Spatial-to-Pim lowering");
|
||||
}
|
||||
|
||||
rewriter.setInsertionPoint(yieldOp);
|
||||
@@ -420,7 +420,7 @@ LogicalResult raptor::SpatialToPimPass::lowerComputeOp(spatial::SpatScheduledCom
|
||||
if (!computeOp.getWeights().empty())
|
||||
computeWeights.append(computeOp.getWeights().begin(), computeOp.getWeights().end());
|
||||
rewriter.setInsertionPointAfter(computeOp);
|
||||
auto checkedCoreId = getRequiredScheduledCoreId(computeOp, "spatial compute core id");
|
||||
auto checkedCoreId = getRequiredScheduledCoreId(computeOp, "Spatial compute core id");
|
||||
if (failed(checkedCoreId))
|
||||
return failure();
|
||||
auto coreIdAttr = pim::getCheckedI32Attr(rewriter, computeOp, static_cast<int64_t>(*checkedCoreId), "pim core id");
|
||||
|
||||
@@ -734,7 +734,7 @@ raptor::SpatialToPimPass::ReturnPathLoweringResult raptor::SpatialToPimPass::low
|
||||
auto storedType = dyn_cast<RankedTensorType>(storedValue.getType());
|
||||
if (!storedType) {
|
||||
producerOp->emitOpError(
|
||||
"has an unsupported non-ranked concat-return helper yield during Spatial-to-PIM lowering");
|
||||
"has an unsupported non-ranked concat-return helper yield during Spatial-to-Pim lowering");
|
||||
return ReturnPathLoweringResult::Failure;
|
||||
}
|
||||
rewriter.setInsertionPointAfterValue(storedValue);
|
||||
@@ -748,7 +748,7 @@ raptor::SpatialToPimPass::ReturnPathLoweringResult raptor::SpatialToPimPass::low
|
||||
SmallVector<int64_t> destinationIndices;
|
||||
if (failed(mapIndicesThroughHelperChain(
|
||||
sourceIndices, concatReturnUse->concatShape, concatReturnUse->helperChain, destinationIndices))) {
|
||||
producerOp->emitOpError("has an unsupported concat-return helper chain during Spatial-to-PIM lowering");
|
||||
producerOp->emitOpError("has an unsupported concat-return helper chain during Spatial-to-Pim lowering");
|
||||
return ReturnPathLoweringResult::Failure;
|
||||
}
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ void onnx_mlir::raptor::SpatialToPimPass::runOnOperation() {
|
||||
operationsToRemove.clear();
|
||||
ModuleOp moduleOp = getOperation();
|
||||
if (!hasTarget || failed(targetResources.verify())) {
|
||||
moduleOp.emitError("Spatial-to-PIM lowering requires valid injected target resources");
|
||||
moduleOp.emitError("Spatial-to-Pim lowering requires valid injected target resources");
|
||||
signalPassFailure();
|
||||
return;
|
||||
}
|
||||
@@ -96,7 +96,7 @@ void onnx_mlir::raptor::SpatialToPimPass::runOnOperation() {
|
||||
|
||||
auto entryFunc = getPimEntryFunc(moduleOp);
|
||||
if (failed(entryFunc)) {
|
||||
moduleOp.emitError("failed to locate the PIM entry function during Spatial-to-PIM lowering");
|
||||
moduleOp.emitError("failed to locate the Pim entry function during Spatial-to-Pim lowering");
|
||||
signalPassFailure();
|
||||
return;
|
||||
}
|
||||
@@ -135,7 +135,7 @@ void onnx_mlir::raptor::SpatialToPimPass::runOnOperation() {
|
||||
RewritePatternSet initialPatterns(ctx);
|
||||
populateInitialPatterns(initialPatterns);
|
||||
if (failed(applyPartialConversion(moduleOp, target, std::move(initialPatterns)))) {
|
||||
moduleOp.emitError("failed to lower required Spatial ops to the initial PIM form");
|
||||
moduleOp.emitError("failed to lower required Spatial ops to the initial Pim form");
|
||||
signalPassFailure();
|
||||
return;
|
||||
}
|
||||
@@ -153,7 +153,7 @@ void onnx_mlir::raptor::SpatialToPimPass::runOnOperation() {
|
||||
auto returnOp = cast<func::ReturnOp>(funcOp.front().getTerminator());
|
||||
addReturnOutputBuffers(returnOp, rewriter);
|
||||
if (failed(allocateAndInitializeCoreLocalVariables(funcOp, rewriter))) {
|
||||
funcOp.emitOpError("failed to allocate or initialize core-local tensors during Spatial-to-PIM lowering");
|
||||
funcOp.emitOpError("failed to allocate or initialize core-local tensors during Spatial-to-Pim lowering");
|
||||
signalPassFailure();
|
||||
return;
|
||||
}
|
||||
@@ -285,7 +285,7 @@ void onnx_mlir::raptor::SpatialToPimPass::runOnOperation() {
|
||||
RewritePatternSet communicationPatterns(ctx);
|
||||
populateChannelLoweringPatterns(communicationPatterns);
|
||||
if (failed(applyFullConversion(funcOp, communicationTarget, std::move(communicationPatterns)))) {
|
||||
funcOp.emitOpError("failed to lower Spatial communication ops to PIM communication ops");
|
||||
funcOp.emitOpError("failed to lower Spatial communication ops to Pim communication ops");
|
||||
signalPassFailure();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace raptor {
|
||||
struct SpatialToPimPass : mlir::PassWrapper<SpatialToPimPass, mlir::OperationPass<mlir::ModuleOp>> {
|
||||
MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(SpatialToPimPass)
|
||||
llvm::StringRef getArgument() const override { return "convert-spatial-to-pim"; }
|
||||
llvm::StringRef getDescription() const override { return "Lower Spatial ops to PIM-ready format"; }
|
||||
llvm::StringRef getDescription() const override { return "Lower Spatial ops to Pim-ready format"; }
|
||||
|
||||
SpatialToPimPass() = default;
|
||||
explicit SpatialToPimPass(const spatial::SpatialTargetResources& target)
|
||||
|
||||
@@ -402,7 +402,7 @@ static LogicalResult verifyPimCoresNeedNoTensorCopies(
|
||||
|
||||
bufferization::BufferizationState state;
|
||||
if (failed(bufferization::insertTensorCopies(*clone, options, state))) {
|
||||
moduleOp.emitError("official one-shot analysis failed while verifying PIM core copy freedom");
|
||||
moduleOp.emitError("official one-shot analysis failed while verifying Pim core copy freedom");
|
||||
return failure();
|
||||
}
|
||||
|
||||
@@ -415,10 +415,10 @@ static LogicalResult verifyPimCoresNeedNoTensorCopies(
|
||||
Operation* requiredBy = alloc->getUsers().empty()
|
||||
? alloc.getOperation() : *alloc->getUsers().begin();
|
||||
diagnostics.report(requiredBy, [](Operation* op) {
|
||||
op->emitOpError("official one-shot bufferization requires a tensor copy inside a PIM core");
|
||||
op->emitOpError("official one-shot bufferization requires a tensor copy inside a Pim core");
|
||||
});
|
||||
});
|
||||
diagnostics.emitSuppressedSummary(moduleOp, "required PIM core tensor copies");
|
||||
diagnostics.emitSuppressedSummary(moduleOp, "required Pim core tensor copies");
|
||||
return success(!diagnostics.hasFailure());
|
||||
}
|
||||
|
||||
@@ -440,7 +440,7 @@ static LogicalResult runOneShotPimBufferization(
|
||||
bufferization::BufferizationState state;
|
||||
if (failed(bufferization::insertTensorCopies(moduleOp, hostOptions, state))
|
||||
|| failed(bufferization::bufferizeModuleOp(moduleOp, options, state))) {
|
||||
moduleOp.emitError("Failed to bufferize PIM and Spatial ops");
|
||||
moduleOp.emitError("Failed to bufferize Pim and Spatial ops");
|
||||
return failure();
|
||||
}
|
||||
return success();
|
||||
@@ -478,7 +478,7 @@ static LogicalResult verifyContiguousRuntimeOperands(ModuleOp moduleOp) {
|
||||
if (succeeded(resolveContiguousAddress(operand, knowledge)) || succeeded(compileContiguousAddressExpr(operand)))
|
||||
return;
|
||||
op.emitOpError() << "operand #" << operandIndex
|
||||
<< " is not backed by contiguous addressable storage after PIM bufferization";
|
||||
<< " is not backed by contiguous addressable storage after Pim bufferization";
|
||||
hasFailure = true;
|
||||
};
|
||||
|
||||
@@ -552,7 +552,7 @@ static LogicalResult verifyContiguousRuntimeOperands(ModuleOp moduleOp) {
|
||||
});
|
||||
|
||||
if (hasFailure) {
|
||||
moduleOp.emitError("PIM bufferization must fully normalize executable runtime operand contiguity before codegen");
|
||||
moduleOp.emitError("Pim bufferization must fully normalize executable runtime operand contiguity before codegen");
|
||||
return failure();
|
||||
}
|
||||
return success();
|
||||
@@ -589,7 +589,7 @@ static LogicalResult verifyPimCopyAddressSpaces(ModuleOp moduleOp) {
|
||||
});
|
||||
if (failureCount != 0)
|
||||
moduleOp.emitError() << "found " << failureCount
|
||||
<< " PIM copy address-space violation(s); the first is reported above";
|
||||
<< " Pim copy address-space violation(s); the first is reported above";
|
||||
return success(failureCount == 0);
|
||||
}
|
||||
|
||||
@@ -673,7 +673,7 @@ static LogicalResult normalizePimMemory(ModuleOp moduleOp, func::FuncOp funcOp)
|
||||
GreedyRewriteConfig contiguityConfig;
|
||||
contiguityConfig.enableFolding(false);
|
||||
if (failed(applyPatternsGreedily(moduleOp, std::move(contiguityPatterns), contiguityConfig))) {
|
||||
moduleOp.emitError("failed to normalize PIM copy contiguity during bufferization");
|
||||
moduleOp.emitError("failed to normalize Pim copy contiguity during bufferization");
|
||||
return failure();
|
||||
}
|
||||
annotateWeightsMemrefs(moduleOp, funcOp);
|
||||
@@ -684,7 +684,7 @@ static LogicalResult normalizePimMemory(ModuleOp moduleOp, func::FuncOp funcOp)
|
||||
static FailureOr<func::FuncOp> requirePimEntryFunc(ModuleOp moduleOp, StringRef phase) {
|
||||
auto entryFunc = getPimEntryFunc(moduleOp);
|
||||
if (failed(entryFunc)) {
|
||||
moduleOp.emitError("failed to locate the PIM entry function during ") << phase;
|
||||
moduleOp.emitError("failed to locate the Pim entry function during ") << phase;
|
||||
return failure();
|
||||
}
|
||||
return *entryFunc;
|
||||
@@ -701,12 +701,12 @@ struct PimBufferizationPreparationPass
|
||||
|
||||
StringRef getArgument() const override { return "pim-bufferization-preparation"; }
|
||||
StringRef getDescription() const override {
|
||||
return "Prepare writable tensor destinations for PIM one-shot bufferization.";
|
||||
return "Prepare writable tensor destinations for Pim one-shot bufferization.";
|
||||
}
|
||||
|
||||
void runOnOperation() final {
|
||||
ModuleOp moduleOp = getOperation();
|
||||
auto funcOp = requirePimEntryFunc(moduleOp, "PIM bufferization preparation");
|
||||
auto funcOp = requirePimEntryFunc(moduleOp, "Pim bufferization preparation");
|
||||
if (failed(funcOp)) {
|
||||
signalPassFailure();
|
||||
return;
|
||||
@@ -725,7 +725,7 @@ struct PimOneShotBufferizationPass
|
||||
|
||||
StringRef getArgument() const override { return "pim-one-shot-bufferization"; }
|
||||
StringRef getDescription() const override {
|
||||
return "Run one-shot bufferization for PIM and Spatial tensors.";
|
||||
return "Run one-shot bufferization for Pim and Spatial tensors.";
|
||||
}
|
||||
|
||||
void runOnOperation() final {
|
||||
@@ -740,12 +740,12 @@ struct PimMemoryNormalizationPass
|
||||
|
||||
StringRef getArgument() const override { return "pim-memory-normalization"; }
|
||||
StringRef getDescription() const override {
|
||||
return "Normalize PIM memory copies and verify addressable operands.";
|
||||
return "Normalize Pim memory copies and verify addressable operands.";
|
||||
}
|
||||
|
||||
void runOnOperation() final {
|
||||
ModuleOp moduleOp = getOperation();
|
||||
auto funcOp = requirePimEntryFunc(moduleOp, "PIM memory normalization");
|
||||
auto funcOp = requirePimEntryFunc(moduleOp, "Pim memory normalization");
|
||||
if (failed(funcOp)) {
|
||||
signalPassFailure();
|
||||
return;
|
||||
@@ -761,20 +761,20 @@ static LogicalResult verifyNoTensorValues(ModuleOp moduleOp) {
|
||||
if (failureCount >= 8)
|
||||
return;
|
||||
if (op->getDialect()->getNamespace() == "tensor") {
|
||||
op->emitOpError("tensor operation remains after PIM bufferization");
|
||||
op->emitOpError("tensor operation remains after Pim bufferization");
|
||||
++failureCount;
|
||||
return;
|
||||
}
|
||||
for (Value value : op->getOperands()) {
|
||||
if (isa<TensorType>(value.getType())) {
|
||||
op->emitOpError("tensor operand remains after PIM bufferization");
|
||||
op->emitOpError("tensor operand remains after Pim bufferization");
|
||||
++failureCount;
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (Value value : op->getResults()) {
|
||||
if (isa<TensorType>(value.getType())) {
|
||||
op->emitOpError("tensor result remains after PIM bufferization");
|
||||
op->emitOpError("tensor result remains after Pim bufferization");
|
||||
++failureCount;
|
||||
return;
|
||||
}
|
||||
@@ -782,7 +782,7 @@ static LogicalResult verifyNoTensorValues(ModuleOp moduleOp) {
|
||||
});
|
||||
if (failureCount != 0)
|
||||
moduleOp.emitError() << "found " << failureCount
|
||||
<< " tensor value(s) after PIM bufferization"
|
||||
<< " tensor value(s) after Pim bufferization"
|
||||
<< (failureCount == 8 ? " (first 8 reported)" : "");
|
||||
return success(failureCount == 0);
|
||||
}
|
||||
@@ -793,7 +793,7 @@ struct PimBufferizationVerificationPass
|
||||
|
||||
StringRef getArgument() const override { return "pim-bufferization-verification"; }
|
||||
StringRef getDescription() const override {
|
||||
return "Verify tensor elimination, contiguity, and PIM copy address spaces.";
|
||||
return "Verify tensor elimination, contiguity, and Pim copy address spaces.";
|
||||
}
|
||||
|
||||
void runOnOperation() final {
|
||||
|
||||
+2
-2
@@ -16,7 +16,7 @@ struct HostConstantFoldingPass : PassWrapper<HostConstantFoldingPass, OperationP
|
||||
MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(HostConstantFoldingPass)
|
||||
|
||||
StringRef getArgument() const override { return "pim-host-constant-folding-pass"; }
|
||||
StringRef getDescription() const override { return "Fold host-side constant expressions before PIM verification"; }
|
||||
StringRef getDescription() const override { return "Fold host-side constant expressions before Pim verification"; }
|
||||
|
||||
LogicalResult initialize(MLIRContext* context) override {
|
||||
RewritePatternSet owningPatterns(context);
|
||||
@@ -38,7 +38,7 @@ struct HostConstantFoldingPass : PassWrapper<HostConstantFoldingPass, OperationP
|
||||
GreedyRewriteConfig config;
|
||||
config.enableFolding();
|
||||
if (failed(applyPatternsGreedily(moduleOp, *patterns, config))) {
|
||||
moduleOp.emitError("PIM host constant folding failed in the greedy rewrite driver");
|
||||
moduleOp.emitError("Pim host constant folding failed in the greedy rewrite driver");
|
||||
signalPassFailure();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -472,7 +472,7 @@ struct FoldConstantHostCopyPattern final : OpRewritePattern<memref::CopyOp> {
|
||||
}
|
||||
};
|
||||
|
||||
// Converts PIM copies from dense globals into direct folded globals before codegen.
|
||||
// Converts Pim copies from dense globals into direct folded globals before codegen.
|
||||
struct FoldConstantMemCpPattern final : OpRewritePattern<pim::PimMemCopyOp> {
|
||||
using OpRewritePattern::OpRewritePattern;
|
||||
|
||||
|
||||
+2
-2
@@ -40,7 +40,7 @@ struct LowerTransposePattern final : OpRewritePattern<pim::PimTransposeOp> {
|
||||
auto sourceType = dyn_cast<MemRefType>(op.getInput().getType());
|
||||
auto targetType = dyn_cast<MemRefType>(op.getOutputBuffer().getType());
|
||||
if (!sourceType || !targetType || !sourceType.hasStaticShape() || !targetType.hasStaticShape())
|
||||
return op.emitOpError("requires static memref operands before PIM instruction selection");
|
||||
return op.emitOpError("requires static memref operands before Pim instruction selection");
|
||||
|
||||
ArrayRef<int64_t> sourceShape = sourceType.getShape();
|
||||
size_t rank = sourceShape.size();
|
||||
@@ -147,7 +147,7 @@ struct InstructionSelectionPass : PassWrapper<InstructionSelectionPass, Operatio
|
||||
MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(InstructionSelectionPass)
|
||||
|
||||
StringRef getArgument() const override { return "pim-instruction-selection"; }
|
||||
StringRef getDescription() const override { return "Select explicit PIM ISA operations"; }
|
||||
StringRef getDescription() const override { return "Select explicit Pim ISA operations"; }
|
||||
|
||||
void runOnOperation() override {
|
||||
RewritePatternSet patterns(&getContext());
|
||||
|
||||
@@ -36,7 +36,7 @@ struct PimLocalMemoryPlanningPass : PassWrapper<PimLocalMemoryPlanningPass, Oper
|
||||
|
||||
StringRef getArgument() const override { return "pim-local-memory-planning"; }
|
||||
StringRef getDescription() const override {
|
||||
return "Plan liveness-based addresses for PIM core-local memory";
|
||||
return "Plan liveness-based addresses for Pim core-local memory";
|
||||
}
|
||||
|
||||
void runOnOperation() override {
|
||||
@@ -149,14 +149,14 @@ FailureOr<CoreMemoryPlan> buildCoreMemoryPlan(Operation* coreLikeOp) {
|
||||
plan.intervals = std::move(*intervals);
|
||||
auto placements = planLocalMemoryPlacements(plan.intervals, kPimLocalMemoryAddressLimit);
|
||||
if (failed(placements)) {
|
||||
coreLikeOp->emitError("PIM local-memory plan exceeds the signed int32 address range");
|
||||
coreLikeOp->emitError("Pim local-memory plan exceeds the signed int32 address range");
|
||||
return failure();
|
||||
}
|
||||
plan.placements = std::move(*placements);
|
||||
for (const LocalMemoryPlacement& placement : plan.placements) {
|
||||
auto end = alignedEnd(placement.address, placement.size, kPimLocalMemoryAddressLimit);
|
||||
if (failed(end)) {
|
||||
coreLikeOp->emitError("PIM local-memory plan has invalid address arithmetic");
|
||||
coreLikeOp->emitError("Pim local-memory plan has invalid address arithmetic");
|
||||
return failure();
|
||||
}
|
||||
plan.arenaSize = std::max(plan.arenaSize, *end);
|
||||
|
||||
@@ -117,7 +117,7 @@ verifyLocalMemoryPlan(Operation* coreLikeOp, pim::CappedDiagnosticReporter& diag
|
||||
for (StringRef name : kRemovedLocalMemoryPlanAttrNames)
|
||||
if (coreLikeOp->hasAttr(name)) {
|
||||
diagnostics.report(coreLikeOp, [name](Operation* op) {
|
||||
op->emitError() << "contains removed PIM local-memory planning attribute '" << name << "'";
|
||||
op->emitError() << "contains removed Pim local-memory planning attribute '" << name << "'";
|
||||
});
|
||||
hasFailure = true;
|
||||
}
|
||||
@@ -137,7 +137,7 @@ verifyLocalMemoryPlan(Operation* coreLikeOp, pim::CappedDiagnosticReporter& diag
|
||||
auto analyzed = pim::analyzeLocalMemoryLifetimes(coreLikeOp);
|
||||
if (failed(analyzed)) {
|
||||
diagnostics.report(coreLikeOp, [](Operation* op) {
|
||||
op->emitError("cannot analyze PIM local-memory lifetimes for plan verification");
|
||||
op->emitError("cannot analyze Pim local-memory lifetimes for plan verification");
|
||||
});
|
||||
return failure();
|
||||
}
|
||||
@@ -156,7 +156,7 @@ verifyLocalMemoryPlan(Operation* coreLikeOp, pim::CappedDiagnosticReporter& diag
|
||||
for (StringRef name : kRemovedLocalMemoryPlanAttrNames)
|
||||
if (allocation->hasAttr(name)) {
|
||||
diagnostics.report(allocation, [name](Operation* op) {
|
||||
op->emitOpError() << "contains removed PIM local-memory planning attribute '" << name << "'";
|
||||
op->emitOpError() << "contains removed Pim local-memory planning attribute '" << name << "'";
|
||||
});
|
||||
hasFailure = true;
|
||||
}
|
||||
@@ -171,7 +171,7 @@ verifyLocalMemoryPlan(Operation* coreLikeOp, pim::CappedDiagnosticReporter& diag
|
||||
uint64_t address = static_cast<uint64_t>(addressAttr.getInt());
|
||||
if (address % 4 != 0 || address > arenaSize || interval.size > arenaSize - address) {
|
||||
diagnostics.report(allocation, [&](Operation* op) {
|
||||
op->emitOpError() << "has invalid PIM local-memory range [" << address << ", "
|
||||
op->emitOpError() << "has invalid Pim local-memory range [" << address << ", "
|
||||
<< (address <= arenaSize && interval.size <= arenaSize - address
|
||||
? address + interval.size
|
||||
: arenaSize)
|
||||
@@ -221,7 +221,7 @@ verifyLocalMemoryPlan(Operation* coreLikeOp, pim::CappedDiagnosticReporter& diag
|
||||
memref::AllocOp otherAllocation = other.allocation;
|
||||
diagnostics.report(allocation, [&](Operation*) {
|
||||
auto diagnostic = allocation.emitOpError()
|
||||
<< "PIM local-memory plan assigns simultaneously live allocations to overlapping ranges; first range ["
|
||||
<< "Pim local-memory plan assigns simultaneously live allocations to overlapping ranges; first range ["
|
||||
<< conflicting->first << ", " << conflicting->first + other.size << "), second range [" << address
|
||||
<< ", " << address + interval.size << "), live positions overlap at ["
|
||||
<< std::max(interval.start, other.start) << ", " << std::min(interval.end, other.end) << "]";
|
||||
@@ -471,7 +471,7 @@ static LogicalResult appendCoreCommunicationEvents(Block& block,
|
||||
auto targetCoreId = resolveIndexValue(sendOp.getTargetCoreId(), knowledge);
|
||||
if (failed(targetCoreId)) {
|
||||
diagnostics.report(&op, [](Operation* illegalOp) {
|
||||
illegalOp->emitOpError("cannot statically resolve send target core for PIM communication deadlock check");
|
||||
illegalOp->emitOpError("cannot statically resolve send target core for Pim communication deadlock check");
|
||||
});
|
||||
return failure();
|
||||
}
|
||||
@@ -490,7 +490,7 @@ static LogicalResult appendCoreCommunicationEvents(Block& block,
|
||||
if (failed(sourceCoreId)) {
|
||||
diagnostics.report(&op, [](Operation* illegalOp) {
|
||||
illegalOp->emitOpError(
|
||||
"cannot statically resolve receive source core for PIM communication deadlock check");
|
||||
"cannot statically resolve receive source core for Pim communication deadlock check");
|
||||
});
|
||||
return failure();
|
||||
}
|
||||
@@ -530,7 +530,7 @@ static void printCommunicationWindow(llvm::raw_ostream& os,
|
||||
static void printCommunicationDeadlockReport(const DenseMap<int64_t, CommunicationEventVector>& coreEvents,
|
||||
const DenseMap<int64_t, size_t>& programCounters,
|
||||
ArrayRef<int64_t> cycle) {
|
||||
llvm::errs() << "\n=== PIM static communication deadlock report ===\n";
|
||||
llvm::errs() << "\n=== Pim static communication deadlock report ===\n";
|
||||
llvm::errs() << "wait cycle:";
|
||||
for (int64_t coreId : cycle)
|
||||
llvm::errs() << " " << coreId;
|
||||
@@ -565,7 +565,7 @@ static void printCommunicationDeadlockReport(const DenseMap<int64_t, Communicati
|
||||
continue;
|
||||
printCommunicationWindow(llvm::errs(), coreEvents, coreId, pcIt->second);
|
||||
}
|
||||
llvm::errs() << "=== end PIM static communication deadlock report ===\n\n";
|
||||
llvm::errs() << "=== end Pim static communication deadlock report ===\n\n";
|
||||
}
|
||||
|
||||
static void emitCommunicationDeadlockCycle(ModuleOp moduleOp,
|
||||
@@ -576,8 +576,8 @@ static void emitCommunicationDeadlockCycle(ModuleOp moduleOp,
|
||||
|
||||
auto diagnostic =
|
||||
moduleOp.emitError()
|
||||
<< "PIM communication deadlock check found a blocking send/receive cycle while statically simulating the "
|
||||
"expanded per-core communication streams; see the PIM static communication deadlock report above";
|
||||
<< "Pim communication deadlock check found a blocking send/receive cycle while statically simulating the "
|
||||
"expanded per-core communication streams; see the Pim static communication deadlock report above";
|
||||
|
||||
for (int64_t coreId : cycle) {
|
||||
auto eventsIt = coreEvents.find(coreId);
|
||||
@@ -728,7 +728,7 @@ static LogicalResult verifyNoStaticCommunicationDeadlock(ModuleOp moduleOp,
|
||||
|
||||
auto diagnostic =
|
||||
moduleOp.emitError()
|
||||
<< "PIM communication deadlock check stalled without finding a closed wait cycle; this usually means a "
|
||||
<< "Pim communication deadlock check stalled without finding a closed wait cycle; this usually means a "
|
||||
"send/receive peer is missing or ordered after a finished core";
|
||||
for (const auto& [coreId, events] : coreEvents) {
|
||||
size_t pc = programCounters[coreId];
|
||||
@@ -746,7 +746,7 @@ struct VerificationPass : PassWrapper<VerificationPass, OperationPass<ModuleOp>>
|
||||
|
||||
StringRef getArgument() const override { return "verify-pim-pass"; }
|
||||
StringRef getDescription() const override {
|
||||
return "Verify that bufferized PIM IR contains only explicit host/device transfers";
|
||||
return "Verify that bufferized Pim IR contains only explicit host/device transfers";
|
||||
}
|
||||
|
||||
VerificationPass() {}
|
||||
@@ -763,7 +763,7 @@ struct VerificationPass : PassWrapper<VerificationPass, OperationPass<ModuleOp>>
|
||||
pim::CappedDiagnosticReporter diagnostics;
|
||||
|
||||
if (!hasTarget || failed(targetResources.verify())) {
|
||||
moduleOp.emitError("PIM codegen verification requires valid injected target resources");
|
||||
moduleOp.emitError("Pim codegen verification requires valid injected target resources");
|
||||
signalPassFailure();
|
||||
return;
|
||||
}
|
||||
@@ -792,7 +792,7 @@ struct VerificationPass : PassWrapper<VerificationPass, OperationPass<ModuleOp>>
|
||||
return;
|
||||
|
||||
diagnostics.report(op, [](Operation* illegalOp) {
|
||||
illegalOp->emitError("illegal Spatial operation reached PIM codegen verification");
|
||||
illegalOp->emitError("illegal Spatial operation reached Pim codegen verification");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -833,7 +833,7 @@ struct VerificationPass : PassWrapper<VerificationPass, OperationPass<ModuleOp>>
|
||||
|
||||
if (!isAddressOnlyHostOp(&op)) {
|
||||
diagnostics.report(&op, [](Operation* illegalOp) {
|
||||
illegalOp->emitOpError("illegal host-side runtime op remains after PIM bufferization; "
|
||||
illegalOp->emitOpError("illegal host-side runtime op remains after Pim bufferization; "
|
||||
"fold it to constants or lower it into pim.core");
|
||||
});
|
||||
continue;
|
||||
@@ -849,7 +849,7 @@ struct VerificationPass : PassWrapper<VerificationPass, OperationPass<ModuleOp>>
|
||||
|
||||
if (diagnostics.hasFailure()) {
|
||||
diagnostics.emitSuppressedSummary(moduleOp, "verification failures");
|
||||
moduleOp.emitError("PIM codegen verification failed; see diagnostics above");
|
||||
moduleOp.emitError("Pim codegen verification failed; see diagnostics above");
|
||||
hasFailure = true;
|
||||
}
|
||||
|
||||
@@ -928,7 +928,7 @@ private:
|
||||
bool hasFailure = false;
|
||||
if (!isSupportedCoreInstructionOp(&op)) {
|
||||
diagnostics.report(&op, [](Operation* illegalOp) {
|
||||
illegalOp->emitOpError("unsupported executable op reached PIM codegen verification");
|
||||
illegalOp->emitOpError("unsupported executable op reached Pim codegen verification");
|
||||
});
|
||||
hasFailure = true;
|
||||
}
|
||||
@@ -990,7 +990,7 @@ private:
|
||||
if (failed(resolveIndexValue(storeOp.getHostTargetOffset(), knowledge))
|
||||
|| failed(resolveIndexValue(storeOp.getDeviceSourceOffset(), knowledge))) {
|
||||
diagnostics.report(&op, [](Operation* illegalOp) {
|
||||
illegalOp->emitOpError("offset operands must be statically evaluable for PIM codegen");
|
||||
illegalOp->emitOpError("offset operands must be statically evaluable for Pim codegen");
|
||||
});
|
||||
hasFailure = true;
|
||||
}
|
||||
@@ -1006,7 +1006,7 @@ private:
|
||||
if (failed(resolveIndexValue(loadOp.getDeviceTargetOffset(), knowledge))
|
||||
|| failed(resolveIndexValue(loadOp.getHostSourceOffset(), knowledge))) {
|
||||
diagnostics.report(&op, [](Operation* illegalOp) {
|
||||
illegalOp->emitOpError("offset operands must be statically evaluable for PIM codegen");
|
||||
illegalOp->emitOpError("offset operands must be statically evaluable for Pim codegen");
|
||||
});
|
||||
hasFailure = true;
|
||||
}
|
||||
@@ -1022,7 +1022,7 @@ private:
|
||||
if (failed(resolveIndexValue(copyOp.getTargetOffset(), knowledge))
|
||||
|| failed(resolveIndexValue(copyOp.getSourceOffset(), knowledge))) {
|
||||
diagnostics.report(&op, [](Operation* illegalOp) {
|
||||
illegalOp->emitOpError("offset operands must be statically evaluable for PIM codegen");
|
||||
illegalOp->emitOpError("offset operands must be statically evaluable for Pim codegen");
|
||||
});
|
||||
hasFailure = true;
|
||||
}
|
||||
@@ -1032,7 +1032,7 @@ private:
|
||||
&& failed(resolveIndexValue(receiveOp.getOutputOffset(), knowledge))) {
|
||||
diagnostics.report(&op, [](Operation* illegalOp) {
|
||||
illegalOp->emitOpError(
|
||||
"output offset must be statically evaluable for PIM codegen");
|
||||
"output offset must be statically evaluable for Pim codegen");
|
||||
});
|
||||
hasFailure = true;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ include "mlir/Dialect/Bufferization/IR/BufferViewFlowOpInterface.td"
|
||||
|
||||
def PimDialect : Dialect {
|
||||
let name = "pim";
|
||||
let summary = "A low-level dialect for the PIM coprocessors on ReRAM crossbars";
|
||||
let summary = "A low-level dialect for the Pim coprocessors on ReRAM crossbars";
|
||||
let cppNamespace = "::onnx_mlir::pim";
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ def PimTensor :
|
||||
|
||||
def PimCoreOp : PimOp<"core", [SingleBlock,
|
||||
DeclareOpInterfaceMethods<OpAsmOpInterface, ["getAsmBlockArgumentNames"]>]> {
|
||||
let summary = "Execute a block on a PIM core";
|
||||
let summary = "Execute a block on a Pim core";
|
||||
|
||||
let regions = (region SizedRegion<1>:$body);
|
||||
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ static bool hasValidTarget(const SchedulingTarget& target) {
|
||||
static FailureOr<func::FuncOp> requireEntry(ModuleOp moduleOp) {
|
||||
auto entry = getPimEntryFunc(moduleOp);
|
||||
if (failed(entry)) {
|
||||
moduleOp.emitError("failed to locate the PIM entry function during Spatial scheduling and realization");
|
||||
moduleOp.emitError("failed to locate the Pim entry function during Spatial scheduling and realization");
|
||||
return failure();
|
||||
}
|
||||
return *entry;
|
||||
|
||||
+2
-2
@@ -193,7 +193,7 @@ FailureOr<TopLevelOpInfo> buildTopLevelOpInfo(Operation& op, bool isScheduled, s
|
||||
|
||||
if constexpr (std::is_same_v<ComputeOpTy, SpatScheduledCompute>) {
|
||||
if (auto compute = dyn_cast<ComputeOpTy>(&op)) {
|
||||
auto coreId = getOptionalScheduledCoreId(compute, "spatial dataflow export core id");
|
||||
auto coreId = getOptionalScheduledCoreId(compute, "Spatial dataflow export core id");
|
||||
if (failed(coreId))
|
||||
return failure();
|
||||
if (*coreId)
|
||||
@@ -207,7 +207,7 @@ FailureOr<TopLevelOpInfo> buildTopLevelOpInfo(Operation& op, bool isScheduled, s
|
||||
template <typename BatchOpTy>
|
||||
FailureOr<SmallVector<int32_t, 8>> getBatchLaneCoreIds(BatchOpTy batch) {
|
||||
if constexpr (std::is_same_v<BatchOpTy, SpatScheduledComputeBatch>) {
|
||||
auto coreIds = getOptionalScheduledBatchCoreIds(batch, "spatial dataflow export core ids");
|
||||
auto coreIds = getOptionalScheduledBatchCoreIds(batch, "Spatial dataflow export core ids");
|
||||
if (failed(coreIds))
|
||||
return failure();
|
||||
if (!*coreIds)
|
||||
|
||||
@@ -13,7 +13,7 @@ include "mlir/Interfaces/SideEffectInterfaces.td"
|
||||
|
||||
def SpatialDialect : Dialect {
|
||||
let name = "spat";
|
||||
let summary = "Dialect designed for deep learning computation in a spatial architecture";
|
||||
let summary = "Dialect designed for deep learning computation in a Spatial architecture";
|
||||
let cppNamespace = "::onnx_mlir::spatial";
|
||||
let useDefaultAttributePrinterParser = 0;
|
||||
let extraClassDeclaration = [{
|
||||
|
||||
@@ -25,7 +25,8 @@ std::unique_ptr<mlir::Pass> createONNXToSpatialPass(
|
||||
const spatial::SpatialTargetResources& target,
|
||||
const ONNXToSpatialPlanningOptions& options);
|
||||
std::unique_ptr<mlir::Pass> createSpatialLayoutPlanningPass();
|
||||
std::unique_ptr<mlir::Pass> createSpatialLayoutPlanningPass(const spatial::SpatialTargetResources& target);
|
||||
std::unique_ptr<mlir::Pass> createSpatialLayoutPlanningPass(
|
||||
const spatial::SpatialTargetResources& target, bool selectTrivialPlan = false);
|
||||
std::unique_ptr<mlir::Pass> createLowerSpatialPlansPass();
|
||||
std::unique_ptr<mlir::Pass> createLowerSpatialPlansPass(
|
||||
const spatial::SpatialTargetResources& target,
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace {
|
||||
struct EmitPimCodePass : PassWrapper<EmitPimCodePass, OperationPass<ModuleOp>> {
|
||||
MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(EmitPimCodePass);
|
||||
StringRef getArgument() const override { return "emit-pim-code-pass"; }
|
||||
StringRef getDescription() const override { return "Emit PIM simulator code artifacts"; }
|
||||
StringRef getDescription() const override { return "Emit Pim simulator code artifacts"; }
|
||||
|
||||
EmitPimCodePass() {}
|
||||
EmitPimCodePass(const EmitPimCodePass& pass) {}
|
||||
@@ -25,7 +25,7 @@ struct EmitPimCodePass : PassWrapper<EmitPimCodePass, OperationPass<ModuleOp>> {
|
||||
|
||||
int compiler_error_code = compileToPimCode(moduleOp, pimDir);
|
||||
if (compiler_error_code != CompilerSuccess) {
|
||||
moduleOp.emitError() << "failed to emit PIM simulator code artifacts; compiler error code "
|
||||
moduleOp.emitError() << "failed to emit Pim simulator code artifacts; compiler error code "
|
||||
<< compiler_error_code;
|
||||
signalPassFailure();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user