Skip to content

Commit b12c4e3

Browse files
MrSidimsvmaksimo
authored andcommitted
Implement StreamingInterfaceINTEL execution mode
In an FPGA design, one may want to control the interface that a kernel exposes to the rest of the design. This extension adds a new Execution Mode to indicate that the kernel has a streaming interface, in which invocation and return is synchronized by a handshaking protocol. The decision whether to add StreamingInterfaceINTEL execution mode with 0/1 literal is based on the kernel metadata, in case of: !ip_interface !N !N = !{!"streaming"} the translator emits StreamingInterfaceINTEL 0 and !ip_interface !N !N = !{!"streaming", !"stall_free_return"} the translator emits StreamingInterfaceINTEL 1 Spec update: KhronosGroup/SPIRV-Registry#130 Signed-off-by: Dmitry Sidorov <[email protected]> Original commit: KhronosGroup/SPIRV-LLVM-Translator@4d66fe7
1 parent be3ac5c commit b12c4e3

File tree

10 files changed

+112
-4
lines changed

10 files changed

+112
-4
lines changed

llvm-spirv/lib/SPIRV/PreprocessMetadata.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,34 @@ void PreprocessMetadataBase::visit(Module *M) {
256256
.add(getMDOperandAsInt(SchedulerTargetFmaxMhzINTEL, 0))
257257
.done();
258258
}
259+
260+
// !{void (i32 addrspace(1)*)* @kernel, i32 ip_interface, i32 interface}
261+
if (MDNode *Interface =
262+
Kernel.getMetadata(kSPIR2MD::IntelFPGAIPInterface)) {
263+
std::set<std::string> InterfaceStrSet;
264+
// Default mode is 'csr' aka !ip_interface !N
265+
// !N = !{!”csr”}
266+
// don't emit any particular SPIR-V for it
267+
// Streaming mode metadata be like:
268+
// Not 'stall free' mode (to be mapped on '0' literal)
269+
// !ip_interface !N
270+
// !N = !{!"streaming"}
271+
// 'stall free' mode (to be mapped on '1' literal)
272+
// !ip_interface !N
273+
// !N = !{!"streaming", !"stall_free_return"}
274+
for (size_t I = 0; I != Interface->getNumOperands(); ++I)
275+
InterfaceStrSet.insert(getMDOperandAsString(Interface, I));
276+
if (InterfaceStrSet.find("streaming") != InterfaceStrSet.end()) {
277+
int32_t InterfaceMode = 0;
278+
if (InterfaceStrSet.find("stall_free_return") != InterfaceStrSet.end())
279+
InterfaceMode = 1;
280+
EM.addOp()
281+
.add(&Kernel)
282+
.add(spv::internal::ExecutionModeStreamingInterfaceINTEL)
283+
.add(InterfaceMode)
284+
.done();
285+
}
286+
}
259287
}
260288
}
261289

llvm-spirv/lib/SPIRV/SPIRVInternal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,7 @@ const static char PropDSPPref[] = "propagate_dsp_preference";
428428
const static char InitiationInterval[] = "initiation_interval";
429429
const static char MaxConcurrency[] = "max_concurrency";
430430
const static char DisableLoopPipelining[] = "disable_loop_pipelining";
431+
const static char IntelFPGAIPInterface[] = "ip_interface";
431432
} // namespace kSPIR2MD
432433

433434
enum Spir2SamplerKind {

llvm-spirv/lib/SPIRV/SPIRVReader.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3786,6 +3786,27 @@ bool SPIRVToLLVM::transMetadata() {
37863786
F->setMetadata(kSPIR2MD::FmaxMhz,
37873787
getMDNodeStringIntVec(Context, EM->getLiterals()));
37883788
}
3789+
// Generate metadata for Intel FPGA streaming interface
3790+
if (auto *EM = BF->getExecutionMode(
3791+
internal::ExecutionModeStreamingInterfaceINTEL)) {
3792+
std::vector<uint32_t> InterfaceVec = EM->getLiterals();
3793+
assert(InterfaceVec.size() == 1 &&
3794+
"Expected StreamingInterfaceINTEL to have exactly 1 literal");
3795+
std::vector<Metadata *> InterfaceMDVec =
3796+
[&]() -> std::vector<Metadata *> {
3797+
switch (InterfaceVec[0]) {
3798+
case 0:
3799+
return {MDString::get(*Context, "streaming")};
3800+
case 1:
3801+
return {MDString::get(*Context, "streaming"),
3802+
MDString::get(*Context, "stall_free_return")};
3803+
default:
3804+
llvm_unreachable("Invalid streaming interface mode");
3805+
}
3806+
}();
3807+
F->setMetadata(kSPIR2MD::IntelFPGAIPInterface,
3808+
MDNode::get(*Context, InterfaceMDVec));
3809+
}
37893810
}
37903811
NamedMDNode *MemoryModelMD =
37913812
M->getOrInsertNamedMetadata(kSPIRVMD::MemoryModel);

llvm-spirv/lib/SPIRV/SPIRVWriter.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3855,6 +3855,7 @@ bool LLVMToSPIRVBase::transExecutionMode() {
38553855
N.get(X).get(Y).get(Z);
38563856
BF->addExecutionMode(BM->add(new SPIRVExecutionMode(
38573857
BF, static_cast<ExecutionMode>(EMode), X, Y, Z)));
3858+
BM->addExtension(ExtensionID::SPV_INTEL_kernel_attributes);
38583859
BM->addCapability(CapabilityKernelAttributesINTEL);
38593860
}
38603861
} break;
@@ -3863,6 +3864,7 @@ bool LLVMToSPIRVBase::transExecutionMode() {
38633864
ExtensionID::SPV_INTEL_kernel_attributes)) {
38643865
BF->addExecutionMode(BM->add(
38653866
new SPIRVExecutionMode(BF, static_cast<ExecutionMode>(EMode))));
3867+
BM->addExtension(ExtensionID::SPV_INTEL_kernel_attributes);
38663868
BM->addCapability(CapabilityKernelAttributesINTEL);
38673869
}
38683870
} break;
@@ -3876,13 +3878,15 @@ bool LLVMToSPIRVBase::transExecutionMode() {
38763878
} break;
38773879
case spv::ExecutionModeNumSIMDWorkitemsINTEL:
38783880
case spv::ExecutionModeSchedulerTargetFmaxMhzINTEL:
3879-
case spv::ExecutionModeMaxWorkDimINTEL: {
3881+
case spv::ExecutionModeMaxWorkDimINTEL:
3882+
case spv::internal::ExecutionModeStreamingInterfaceINTEL: {
38803883
if (BM->isAllowedToUseExtension(
38813884
ExtensionID::SPV_INTEL_kernel_attributes)) {
38823885
unsigned X;
38833886
N.get(X);
38843887
BF->addExecutionMode(BM->add(new SPIRVExecutionMode(
38853888
BF, static_cast<ExecutionMode>(EMode), X)));
3889+
BM->addExtension(ExtensionID::SPV_INTEL_kernel_attributes);
38863890
BM->addCapability(CapabilityFPGAKernelAttributesINTEL);
38873891
}
38883892
} break;

llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEntry.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -552,7 +552,7 @@ void SPIRVExecutionMode::encode(spv_ostream &O) const {
552552

553553
void SPIRVExecutionMode::decode(std::istream &I) {
554554
getDecoder(I) >> Target >> ExecMode;
555-
switch (ExecMode) {
555+
switch (static_cast<uint32_t>(ExecMode)) {
556556
case ExecutionModeLocalSize:
557557
case ExecutionModeLocalSizeHint:
558558
case ExecutionModeMaxWorkgroupSizeINTEL:
@@ -575,6 +575,7 @@ void SPIRVExecutionMode::decode(std::istream &I) {
575575
case ExecutionModeMaxWorkDimINTEL:
576576
case ExecutionModeNumSIMDWorkitemsINTEL:
577577
case ExecutionModeSchedulerTargetFmaxMhzINTEL:
578+
case internal::ExecutionModeStreamingInterfaceINTEL:
578579
WordLiterals.resize(1);
579580
break;
580581
default:

llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEnum.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,8 @@ template <> inline void SPIRVMap<SPIRVExecutionModeKind, SPIRVCapVec>::init() {
261261
{CapabilityVectorComputeINTEL});
262262
ADD_VEC_INIT(internal::ExecutionModeFastCompositeKernelINTEL,
263263
{internal::CapabilityFastCompositeINTEL});
264+
ADD_VEC_INIT(internal::ExecutionModeStreamingInterfaceINTEL,
265+
{CapabilityFPGAKernelAttributesINTEL});
264266
}
265267

266268
template <> inline void SPIRVMap<SPIRVMemoryModelKind, SPIRVCapVec>::init() {

llvm-spirv/lib/SPIRV/libSPIRV/SPIRVIsValidEnum.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ using namespace spv;
5555
namespace SPIRV {
5656

5757
inline bool isValid(spv::ExecutionModel V) {
58-
switch (V) {
58+
switch (static_cast<uint32_t>(V)) {
5959
case ExecutionModelVertex:
6060
case ExecutionModelTessellationControl:
6161
case ExecutionModelTessellationEvaluation:
@@ -71,6 +71,7 @@ inline bool isValid(spv::ExecutionModel V) {
7171
case ExecutionModelClosestHitKHR:
7272
case ExecutionModelMissKHR:
7373
case ExecutionModelCallableKHR:
74+
case internal::ExecutionModeStreamingInterfaceINTEL:
7475
return true;
7576
default:
7677
return false;

llvm-spirv/lib/SPIRV/libSPIRV/spirv_internal.hpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,10 @@ enum InternalMemoryAccessMask {
8686
IMemAccessNoAliasINTELMask = 0x20000
8787
};
8888

89-
enum InternalExecutionMode { IExecModeFastCompositeKernelINTEL = 6088 };
89+
enum InternalExecutionMode {
90+
IExecModeFastCompositeKernelINTEL = 6088,
91+
IExecModeStreamingInterfaceINTEL = 6154
92+
};
9093

9194
enum InternalLoopControlMask { ILoopControlLoopCountINTELMask = 0x1000000 };
9295

@@ -168,6 +171,8 @@ constexpr MemoryAccessMask MemoryAccessNoAliasINTELMask =
168171

169172
constexpr ExecutionMode ExecutionModeFastCompositeKernelINTEL =
170173
static_cast<ExecutionMode>(IExecModeFastCompositeKernelINTEL);
174+
constexpr ExecutionMode ExecutionModeStreamingInterfaceINTEL =
175+
static_cast<ExecutionMode>(IExecModeStreamingInterfaceINTEL);
171176

172177
constexpr LoopControlMask LoopControlLoopCountINTELMask =
173178
static_cast<LoopControlMask>(ILoopControlLoopCountINTELMask);
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
; RUN: llvm-as %s -o %t.bc
2+
; RUN: llvm-spirv %t.bc --spirv-ext=+SPV_INTEL_kernel_attributes -o %t.spv
3+
; RUN: llvm-spirv %t.spv -to-text -o %t.spt
4+
; RUN: FileCheck < %t.spt %s --check-prefix=CHECK-SPIRV
5+
6+
; RUN: llvm-spirv -r %t.spv -o %t.rev.bc
7+
; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM
8+
9+
; CHECK-SPIRV: Capability FPGAKernelAttributesINTEL
10+
; CHECK-SPIRV: Extension "SPV_INTEL_kernel_attributes"
11+
; CHECK-SPIRV: EntryPoint [[#]] [[#KERNEL1:]] "test_1"
12+
; CHECK-SPIRV: EntryPoint [[#]] [[#KERNEL2:]] "test_2"
13+
; CHECK-SPIRV: ExecutionMode [[#KERNEL1]] 6154 0
14+
; CHECK-SPIRV: ExecutionMode [[#KERNEL2]] 6154 1
15+
; CHECK-SPIRV: Function [[#]] [[#KERNEL1]]
16+
; CHECK-SPIRV: Function [[#]] [[#KERNEL2]]
17+
18+
19+
; CHECK-LLVM: define spir_kernel void @test_1{{.*}} !ip_interface ![[#NOSTALLFREE:]]
20+
; CHECK-LLVM: define spir_kernel void @test_2{{.*}} !ip_interface ![[#STALLFREE:]]
21+
; CHECK-LLVM: ![[#NOSTALLFREE:]] = !{!"streaming"}
22+
; CHECK-LLVM: ![[#STALLFREE:]] = !{!"streaming", !"stall_free_return"}
23+
24+
; ModuleID = 'test.bc'
25+
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v24:32:32-v32:32:32-v48:64:64-v64:64:64-v96:128:128-v128:128:128-v192:256:256-v256:256:256-v512:512:512-v1024:1024:1024"
26+
target triple = "spir64-unknown-unknown"
27+
28+
; Function Attrs: nounwind
29+
define spir_kernel void @test_1() #0 !ip_interface !0
30+
{
31+
entry:
32+
ret void
33+
}
34+
35+
; Function Attrs: nounwind
36+
define spir_kernel void @test_2() #0 !ip_interface !1
37+
{
38+
entry:
39+
ret void
40+
}
41+
42+
attributes #0 = { nounwind }
43+
44+
!0 = !{!"streaming"}
45+
!1 = !{!"streaming", !"stall_free_return"}

0 commit comments

Comments
 (0)