Visible to Intel only — GUID: GUID-5E0C9C98-B61B-4ECB-A22F-B68337CE2CE6
Visible to Intel only — GUID: GUID-5E0C9C98-B61B-4ECB-A22F-B68337CE2CE6
User-defined Migration Rules
Intel® DPC++ Compatibility Tool uses migration rules to migrate CUDA* code to SYCL* code. There are three categories of migration rules used by the tool:
Default migration rules. A set of built-in migration rules used by the Intel® DPC++ Compatibility Tool for all migrations.
Optional predefined migration rules. A set of predefined migration rules that can optionally be used for migration. Available predefined migration rules are in the extensions/opt_rules folder on the installation path of the Intel® DPC++ Compatibility Tool.
User-defined migration rules. Custom migration rules defined by the user. User-defined migration rules extend the migration capability of the Intel® DPC++ Compatibility Tool and can target the migration of specific CUDA syntax to SYCL syntax.
Specify Migration Rule Files
To specify a predefined or user-defined migration rule file for use in migration, use the –rule-file command line option with your migration command.
The –rule-file option can be used multiple times with a single command to specify multiple migration rule files. For example:
dpct sample.cu --rule-file=rule_file1.YAML --rule-file=rule_file2.YAML
See the Command Line Options Reference for additional information.
Write User-defined Migration Rules
Migration rules are specified in YAML files. A single rule file may contain multiple migration rules. To define a rule, use the following <key>: <value> pairs:
Key |
Value |
Description |
---|---|---|
Rule |
String value |
Required. Specifies the unique name of the rule. |
Priority |
Takeover | Default | Fallback |
Required. Specifies the priority of the rule: Takeover > Default > Fallback. When there are rule conflicts, the rule with higher priority will take precedence. |
Kind |
Macro | API | Header | Type | Class | Enum |
Required. Specifies the rule type. |
In |
String value |
Required. Specifies the target name in the input source code. |
Out |
String value |
Required. Specifies the final format in the output source code. |
Includes |
List of header files |
Required. Specifies the header files which should be included in the output source code. The value can be an empty list. |
EnumName |
String value |
Specifies the name of an enum for an Enum rule type. |
Fields |
String value |
Specifies the migration rule of fields in a Class rule type. |
Methods |
String value |
Specifies the migration rule of methods in a Class rule type. |
Prefix |
String value |
Specifies the prefix of a Header rule type. For example: #ifdef ... |
Postfix |
String value |
Specifies the postfix of a Header rule type. For example: #endif ... |
For example, the following user-defined migration rule file demonstrates different rule types. The behavior of each rule is explained in the corresponding comment:
--- # [YAML syntax] Begin the document - Rule: rule_forceinline # Rule to migrate "__forceinline__" to "inline" Kind: Macro # Rule type Priority: Takeover # Rule priority In: __forceinline__ # Target macro name in the input source code Out: inline # Migrated name of the macro in the output source code Includes: ["header1.h", "\"header2.h\""] # List of header file names which the new macro depends on - Rule: rule_foo # Rule to migrate "foo(a,b)" to "int *new_ptr=bar(*b)" Kind: API Priority: Takeover In: foo # Target function name in the input source code Out: $type_name_of($2) *new_ptr = bar($deref($1)) # Format of the migrated result in the output source code Includes: ["<header3>"] - Rule: rule_cmath # Rule to migrate "include<cmath>" to "#include<mymath>" Kind: Header Priority: Takeover In: cmath Out: mymath Prefix: "#ifdef USE_MYMATH\n" # Add prefix before "#include<mymath>" Postfix: "#endif\n" # Add postfix after "#include<mymath>" Includes: [""] - Rule: rule_classA # Rule to migrate "classA" to "classB" Kind: Class Priority: Takeover In: classA Out: classB Includes: [] Fields: # Specify the migration rule of fields of classA - In: fieldA # Migrate classA.fieldA to getter and setter OutGetter: get_a # Migrate value reference of classA.fieldA to classB.get_a() OutSetter: set_a # Migrate value assignment of classA.fieldA to classB.set_a() - In: fieldC Out: fieldD # Migrate classA.fieldC to classB.fieldD Methods: - In: methodA Out: a.methodB($2) # Migrate classA.methodA(x,y) to a.methodB(y) - Rule: rule_Fruit # Rule to migrate "Fruit:apple" to "Fruit:pineapple" Kind: Enum Priority: Takeover EnumName: Fruit In: apple Out: pineapple Includes: ["fruit.h"] - Rule: type_rule # Migrate "OldType" to "NewType" Kind: Type Priority: Takeover In: OldType Out: NewType Includes: [] ... # [YAML syntax] End the document
Grammar for Out Key in a User-defined API Migration Rule
To describe the value format for the Out key in a migration rule of Kind: API, use the following Backus-Naur form grammar:
OutValue::= Token | Token OutValue # OutValue is the value for the “out” key Token::= AnyString | Keyword # AnyString is a string provided by the user Keyword::= ArgIndex | $queue # Represents the queue string | $context # Represents the context string | $device # Represents the device string | $deref(ArgIndex) # The dereferenced value of the argument | $type_name_of(ArgIndex) # The type name of the argument | $deref_type(ArgIndex) # The dereferenced type name of the argument | $addr_of(ArgIndex) # The address of the argument ArgIndex::= $Int # Int should be a greater than zero integer
The following scenario describes how the tool makes use of a user-defined migration rule that uses this grammar to migrate code.
Consider the following user-defined API migration rule:
- Rule: rule_foo Kind: API Priority: Takeover In: foo Out: $type_name_of($2) new_ptr = bar($deref($1), $3) Includes: [“<header3>”]
If the input source code contains a function call that matches the rule, the tool parses the value of the In and Out keys and builds a keyword mapping between the input and output source code. For example, with input source code:
int *ptr, *ptr2; foo(ptr, ptr2, 30);
The tool creates the following mapping:
Keyword |
Input Source Code Match |
Migration Result |
---|---|---|
$1 |
ptr |
ptr |
$2 |
ptr2 |
ptr2 |
$3 |
30 |
30 |
$type_name_of($2) |
N/A |
int* |
$deref($1) |
N/A |
*ptr |
Using this mapping, the tool migrates the input source code into the following output source code:
int *ptr, *ptr2; int * new_ptr = bar(*ptr, 30);