Skip to content

Commit 1b50431

Browse files
tiwaria1FreddyLeaf
authored andcommitted
Implement RegisterMapInterfaceINTEL execution mode (intel#1774)
This PR adds the new execution mode RegisterMapInterfaceINTEL, see the Khronos SPIRV spec here: KhronosGroup/SPIRV-Registry#176 This execution mode allows specifying a 'register' based interface for FPGA kernels. The RegisterMapInterfaceINTEL execution mode is added with a 0/1 literal based on the kernel metadata. When the metadata is: !ip_interface !N !N = !{!"csr"} The translator emits RegisterMapInterfaceINTEL 0, and when the metadata is: !ip_interface !N !N = !{!"csr", !"accept_downstream_stall"} The translator emits RegisterMapInterfaceINTEL 1 NOTE The new mode is under capability FPGAKernelAttributesv2INTEL which implicitly defines the capability FPGAKernelAttributesv2INTEL. This PR is very similar to Implement StreamingInterfaceINTEL execution mode intel#1218 Original commit: KhronosGroup/SPIRV-LLVM-Translator@a9f4f25
1 parent edba4b3 commit 1b50431

File tree

9 files changed

+126
-22
lines changed

9 files changed

+126
-22
lines changed

llvm-spirv/lib/SPIRV/PreprocessMetadata.cpp

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -229,18 +229,38 @@ void PreprocessMetadataBase::visit(Module *M) {
229229
if (MDNode *Interface =
230230
Kernel.getMetadata(kSPIR2MD::IntelFPGAIPInterface)) {
231231
std::set<std::string> InterfaceStrSet;
232-
// Default mode is 'csr' aka !ip_interface !N
233-
// !N = !{!”csr”}
234-
// don't emit any particular SPIR-V for it
232+
for (size_t I = 0; I != Interface->getNumOperands(); ++I)
233+
InterfaceStrSet.insert(getMDOperandAsString(Interface, I).str());
234+
235+
// ip_interface metadata will either have Register Map metadata or
236+
// Streaming metadata.
237+
//
238+
// Register Map mode metadata:
239+
// Not 'WaitForDoneWrite' mode (to be mapped on '0' literal)
240+
// !ip_interface !N
241+
// !N = !{!"csr"}
242+
// 'WaitForDoneWrite' mode (to be mapped on '1' literal)
243+
// !ip_interface !N
244+
// !N = !{!"csr", !"wait_for_done_write"}
245+
if (InterfaceStrSet.find("csr") != InterfaceStrSet.end()) {
246+
int32_t InterfaceMode = 0;
247+
if (InterfaceStrSet.find("wait_for_done_write") !=
248+
InterfaceStrSet.end())
249+
InterfaceMode = 1;
250+
EM.addOp()
251+
.add(&Kernel)
252+
.add(spv::ExecutionModeRegisterMapInterfaceINTEL)
253+
.add(InterfaceMode)
254+
.done();
255+
}
256+
235257
// Streaming mode metadata be like:
236258
// Not 'stall free' mode (to be mapped on '0' literal)
237259
// !ip_interface !N
238260
// !N = !{!"streaming"}
239261
// 'stall free' mode (to be mapped on '1' literal)
240262
// !ip_interface !N
241263
// !N = !{!"streaming", !"stall_free_return"}
242-
for (size_t I = 0; I != Interface->getNumOperands(); ++I)
243-
InterfaceStrSet.insert(getMDOperandAsString(Interface, I).str());
244264
if (InterfaceStrSet.find("streaming") != InterfaceStrSet.end()) {
245265
int32_t InterfaceMode = 0;
246266
if (InterfaceStrSet.find("stall_free_return") != InterfaceStrSet.end())
@@ -325,17 +345,16 @@ void PreprocessMetadataBase::preprocessVectorComputeMetadata(Module *M,
325345
FPRoundingModeExecModeMap::map(getFPRoundingMode(Mode));
326346
spv::ExecutionMode ExecFloatMode =
327347
FPOperationModeExecModeMap::map(getFPOperationMode(Mode));
328-
VCFloatTypeSizeMap::foreach (
329-
[&](VCFloatType FloatType, unsigned TargetWidth) {
330-
EM.addOp().add(&F).add(ExecRoundMode).add(TargetWidth).done();
331-
EM.addOp().add(&F).add(ExecFloatMode).add(TargetWidth).done();
332-
EM.addOp()
333-
.add(&F)
334-
.add(FPDenormModeExecModeMap::map(
335-
getFPDenormMode(Mode, FloatType)))
336-
.add(TargetWidth)
337-
.done();
338-
});
348+
VCFloatTypeSizeMap::foreach ([&](VCFloatType FloatType,
349+
unsigned TargetWidth) {
350+
EM.addOp().add(&F).add(ExecRoundMode).add(TargetWidth).done();
351+
EM.addOp().add(&F).add(ExecFloatMode).add(TargetWidth).done();
352+
EM.addOp()
353+
.add(&F)
354+
.add(FPDenormModeExecModeMap::map(getFPDenormMode(Mode, FloatType)))
355+
.add(TargetWidth)
356+
.done();
357+
});
339358
}
340359
if (Attrs.hasFnAttr(kVCMetadata::VCSLMSize)) {
341360
SPIRVWord SLMSize = 0;

llvm-spirv/lib/SPIRV/SPIRVReader.cpp

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1257,7 +1257,7 @@ static void replaceOperandWithAnnotationIntrinsicCallResult(Value *&V) {
12571257
template <typename SPIRVInstType>
12581258
void SPIRVToLLVM::transAliasingMemAccess(SPIRVInstType *BI, Instruction *I) {
12591259
static_assert(std::is_same<SPIRVInstType, SPIRVStore>::value ||
1260-
std::is_same<SPIRVInstType, SPIRVLoad>::value,
1260+
std::is_same<SPIRVInstType, SPIRVLoad>::value,
12611261
"Only stores and loads can be aliased by memory access mask");
12621262
if (BI->SPIRVMemoryAccess::isNoAlias())
12631263
addMemAliasMetadata(I, BI->SPIRVMemoryAccess::getNoAliasInstID(),
@@ -2051,10 +2051,10 @@ Value *SPIRVToLLVM::transValueWithoutDecoration(SPIRVValue *BV, Function *F,
20512051

20522052
case 4: {
20532053
for (int Idx = 0; Idx < 4; ++Idx) {
2054-
Value *V1 = Builder.CreateShuffleVector(
2055-
MCache[0], MCache[1], ArrayRef<int>({Idx, Idx + 4}));
2056-
Value *V2 = Builder.CreateShuffleVector(
2057-
MCache[2], MCache[3], ArrayRef<int>({Idx, Idx + 4}));
2054+
Value *V1 = Builder.CreateShuffleVector(MCache[0], MCache[1],
2055+
ArrayRef<int>{Idx, Idx + 4});
2056+
Value *V2 = Builder.CreateShuffleVector(MCache[2], MCache[3],
2057+
ArrayRef<int>{Idx, Idx + 4});
20582058
Value *V3 =
20592059
Builder.CreateShuffleVector(V1, V2, ArrayRef<int>({0, 1, 2, 3}));
20602060
V = Builder.CreateInsertValue(V, V3, Idx);
@@ -4006,6 +4006,27 @@ bool SPIRVToLLVM::transMetadata() {
40064006
F->setMetadata(kSPIR2MD::FmaxMhz,
40074007
getMDNodeStringIntVec(Context, EM->getLiterals()));
40084008
}
4009+
// Generate metadata for Intel FPGA register map interface
4010+
if (auto *EM =
4011+
BF->getExecutionMode(ExecutionModeRegisterMapInterfaceINTEL)) {
4012+
std::vector<uint32_t> InterfaceVec = EM->getLiterals();
4013+
assert(InterfaceVec.size() == 1 &&
4014+
"Expected RegisterMapInterfaceINTEL to have exactly 1 literal");
4015+
std::vector<Metadata *> InterfaceMDVec =
4016+
[&]() -> std::vector<Metadata *> {
4017+
switch (InterfaceVec[0]) {
4018+
case 0:
4019+
return {MDString::get(*Context, "csr")};
4020+
case 1:
4021+
return {MDString::get(*Context, "csr"),
4022+
MDString::get(*Context, "wait_for_done_write")};
4023+
default:
4024+
llvm_unreachable("Invalid register map interface mode");
4025+
}
4026+
}();
4027+
F->setMetadata(kSPIR2MD::IntelFPGAIPInterface,
4028+
MDNode::get(*Context, InterfaceMDVec));
4029+
}
40094030
// Generate metadata for Intel FPGA streaming interface
40104031
if (auto *EM = BF->getExecutionMode(ExecutionModeStreamingInterfaceINTEL)) {
40114032
std::vector<uint32_t> InterfaceVec = EM->getLiterals();

llvm-spirv/lib/SPIRV/SPIRVWriter.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5032,6 +5032,19 @@ bool LLVMToSPIRVBase::transExecutionMode() {
50325032
case spv::ExecutionModeNumSIMDWorkitemsINTEL:
50335033
case spv::ExecutionModeSchedulerTargetFmaxMhzINTEL:
50345034
case spv::ExecutionModeMaxWorkDimINTEL:
5035+
case spv::ExecutionModeRegisterMapInterfaceINTEL: {
5036+
if (!BM->isAllowedToUseExtension(
5037+
ExtensionID::SPV_INTEL_kernel_attributes))
5038+
break;
5039+
AddSingleArgExecutionMode(static_cast<ExecutionMode>(EMode));
5040+
BM->addExtension(ExtensionID::SPV_INTEL_kernel_attributes);
5041+
BM->addCapability(CapabilityFPGAKernelAttributesINTEL);
5042+
// RegisterMapInterfaceINTEL mode is defined by the
5043+
// CapabilityFPGAKernelAttributesv2INTEL capability and that
5044+
// capability implicitly defines CapabilityFPGAKernelAttributesINTEL
5045+
if (EMode == spv::ExecutionModeRegisterMapInterfaceINTEL)
5046+
BM->addCapability(CapabilityFPGAKernelAttributesv2INTEL);
5047+
} break;
50355048
case spv::ExecutionModeStreamingInterfaceINTEL: {
50365049
if (!BM->isAllowedToUseExtension(
50375050
ExtensionID::SPV_INTEL_kernel_attributes))

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,7 @@ void SPIRVExecutionMode::decode(std::istream &I) {
612612
case ExecutionModeMaxWorkDimINTEL:
613613
case ExecutionModeNumSIMDWorkitemsINTEL:
614614
case ExecutionModeSchedulerTargetFmaxMhzINTEL:
615+
case ExecutionModeRegisterMapInterfaceINTEL:
615616
case ExecutionModeStreamingInterfaceINTEL:
616617
WordLiterals.resize(1);
617618
break;

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,8 @@ template <> inline void SPIRVMap<SPIRVExecutionModeKind, SPIRVCapVec>::init() {
277277
{CapabilityVectorComputeINTEL});
278278
ADD_VEC_INIT(internal::ExecutionModeFastCompositeKernelINTEL,
279279
{internal::CapabilityFastCompositeINTEL});
280+
ADD_VEC_INIT(ExecutionModeRegisterMapInterfaceINTEL,
281+
{CapabilityFPGAKernelAttributesv2INTEL});
280282
ADD_VEC_INIT(ExecutionModeStreamingInterfaceINTEL,
281283
{CapabilityFPGAKernelAttributesINTEL});
282284
ADD_VEC_INIT(ExecutionModeNamedBarrierCountINTEL,

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ inline bool isValid(spv::ExecutionModel V) {
7171
case ExecutionModelClosestHitKHR:
7272
case ExecutionModelMissKHR:
7373
case ExecutionModelCallableKHR:
74+
case ExecutionModeRegisterMapInterfaceINTEL:
7475
case ExecutionModeStreamingInterfaceINTEL:
7576
return true;
7677
default:

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,7 @@ template <> inline void SPIRVMap<Capability, std::string>::init() {
594594
add(CapabilityFPGALoopControlsINTEL, "FPGALoopControlsINTEL");
595595
add(CapabilityKernelAttributesINTEL, "KernelAttributesINTEL");
596596
add(CapabilityFPGAKernelAttributesINTEL, "FPGAKernelAttributesINTEL");
597+
add(CapabilityFPGAKernelAttributesv2INTEL, "FPGAKernelAttributesv2INTEL");
597598
add(CapabilityFPGAMemoryAccessesINTEL, "FPGAMemoryAccessesINTEL");
598599
add(CapabilityFPGAClusterAttributesINTEL, "FPGAClusterAttributesINTEL");
599600
add(CapabilityLoopFuseINTEL, "LoopFuseINTEL");

llvm-spirv/spirv-headers-tag.conf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
36c7694279dfb3ea7e6e086e368bb8bee076792a
1+
295cf5fb3bfe2454360e82b26bae7fc0de699abe
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
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 -emit-opaque-pointers %t.spv -o %t.rev.bc
7+
; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM
8+
9+
; FPGAKernelAttributesv2INTEL implicitly defines FPGAKernelAttributesINTEL
10+
; CHECK-SPIRV: Capability FPGAKernelAttributesINTEL
11+
; CHECK-SPIRV: Capability FPGAKernelAttributesv2INTEL
12+
; CHECK-SPIRV: Extension "SPV_INTEL_kernel_attributes"
13+
; CHECK-SPIRV: EntryPoint [[#]] [[#KERNEL1:]] "test_1"
14+
; CHECK-SPIRV: EntryPoint [[#]] [[#KERNEL2:]] "test_2"
15+
; CHECK-SPIRV: ExecutionMode [[#KERNEL1]] 6160 0
16+
; CHECK-SPIRV: ExecutionMode [[#KERNEL2]] 6160 1
17+
; CHECK-SPIRV: Function [[#]] [[#KERNEL1]]
18+
; CHECK-SPIRV: Function [[#]] [[#KERNEL2]]
19+
20+
; CHECK-LLVM: define spir_kernel void @test_1{{.*}} !ip_interface ![[#NOWAITFORDONEWRITE:]]
21+
; CHECK-LLVM: define spir_kernel void @test_2{{.*}} !ip_interface ![[#WAITFORDONEWRITE:]]
22+
; CHECK-LLVM: ![[#NOWAITFORDONEWRITE:]] = !{!"csr"}
23+
; CHECK-LLVM: ![[#WAITFORDONEWRITE:]] = !{!"csr", !"wait_for_done_write"}
24+
25+
; ModuleID = 'test.bc'
26+
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"
27+
target triple = "spir64-unknown-unknown"
28+
29+
; Function Attrs: nounwind
30+
define spir_kernel void @test_1() #0 !ip_interface !0
31+
{
32+
entry:
33+
ret void
34+
}
35+
36+
; Function Attrs: nounwind
37+
define spir_kernel void @test_2() #0 !ip_interface !1
38+
{
39+
entry:
40+
ret void
41+
}
42+
43+
attributes #0 = { nounwind }
44+
45+
!0 = !{!"csr"}
46+
!1 = !{!"csr", !"wait_for_done_write"}

0 commit comments

Comments
 (0)