summaryrefslogtreecommitdiff
path: root/scripts/generate_iga64_codes
blob: 3d114ea0e11900f84669282edfbee2d0b1368e3d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#!/bin/bash
# SPDX-License-Identifier: MIT
# Copyright © 2024 Intel Corporation
# Author: Andrzej Hajda <andrzej.hajda@intel.com>

# List of supported platforms, in format gen100:platform, where gen100 equals
# to minimal GPU generation supported by platform multiplied by 100 and platform
# is one of platforms supported by -p switch of iga64.
# Must be in decreasing order, the last one must have gen100 equal 0.
GEN_VERSIONS="2000:2 1272:12p72 1250:12p5 0:12p1"

# Magic values to encode asm template args, must be the the same as in gpgpu_shader.c.
IGA64_ARG0=0xc0ded000
IGA64_ARG_MASK=0xffffff00

warn() {
    echo -e "$1" >/dev/stderr
}

die() {
    warn "DIE: $1"
    exit 1
}

# parse args
while getopts ':i:o:' opt; do
    case $opt in
    i) INPUT=$OPTARG;;
    o) OUTPUT=$OPTARG;;
    ?) die "Usage: $0 -i pre-generated-iga64-file -o generated-iga64-file libs-with-iga64-assembly [...]"
    esac
done
LIBS=${@:OPTIND}

# read all assemblies into ASMS array
ASMS=()
while  read -d $'\0' asm; do
    test -z "$asm" && continue
    ASMS+=( "$asm" )
done < <(for f in $LIBS; do objcopy --dump-section .iga64_assembly=/dev/stdout $f.p/*.o; done)

# check if we need to recompile - checksum difference and compiler present
MD5_ASMS="$(md5sum <<< "${ASMS[@]}" | cut -b1-32)"
MD5_PRE="$(grep -Po '(?<=^#define MD5_SUM_IGA64_ASMS )\S{32,32}' $INPUT 2>/dev/null)"

if [ "$MD5_ASMS" = "$MD5_PRE" ]; then
    echo "iga64 assemblies not changed, reusing pre-compiled file $INPUT."
    cp $INPUT $OUTPUT
    exit 0
fi

type iga64 >/dev/null || {
    warn "WARNING: iga64 assemblies changed, but iga64 compiler not present, CHANGES will have no effect. Install iga64 (libigc-tools package) to re-compile code."
    cp $INPUT $OUTPUT
    exit 0
}

# generate code file
WD=$OUTPUT.d
mkdir -p $WD

# check if all required platforms are supported
touch $WD/empty
for gen in $GEN_VERSIONS; do
    gen_name="${gen#*:}"
    iga64 -p=$gen_name -d $WD/empty 2>/dev/null || {
        warn "WARNING: iga64 assemblies changed, but iga64 compiler does not support platform '$gen_name', CHANGES will have no effect. Update iga64 (libigc-tools package) to re-compile code."
        cp $INPUT $OUTPUT
        exit 0
    }
done

# returns count of numbers in strings of format "0x1234, 0x23434, ..."
dword_count() {
    n=${1//[^x]}
    echo ${#n}
}

echo "Generating new $OUTPUT"

cat <<-EOF >$OUTPUT
// SPDX-License-Identifier: MIT
// Generated using $(iga64 |& head -1)

#include "gpgpu_shader.h"

#define MD5_SUM_IGA64_ASMS $MD5_ASMS
EOF

# Compiles assembly to binary representation sent to stdout.
compile_iga64() {
    cmd="cpp -P - -o $WD/$asm_name.$gen_name.asm"
    cmd+=" -DGEN_VER=$gen_ver -D'ARG(n)=($IGA64_ARG0 + (n))' -imacros ../lib/iga64_macros.h"
    eval "$cmd" <<<"$asm_body" || die "cpp error for $asm_name.$gen_name\ncmd: $cmd"
    cmd="iga64 -Xauto-deps -Wall -p=$gen_name"
    cmd+=" $WD/$asm_name.$gen_name.asm"
    warn "$cmd"
    eval "$cmd" || die "iga64 error for $asm_name.$gen_name\ncmd: $cmd"
}

for asm in "${ASMS[@]}"; do
    asm_name="${asm%%:*}"
    asm_code="${asm_name/assembly/code}"
    asm_body="${asm#*:}"
    cur_code=""
    cur_ver=""
    echo -e "\nstruct iga64_template const $asm_code[] = {" >>$OUTPUT
    for gen in $GEN_VERSIONS; do
        gen_ver="${gen%%:*}"
        gen_name="${gen#*:}"
        warn "Generating $asm_code for platform $gen_name"
        # Verify generated code will not contain IGA64_ARGs.
        for d in $(IGA64_ARG0=0 compile_iga64 | hexdump -v -e '1/4 "0x%08x\n"'); do
            (( (d & IGA64_ARG_MASK) == IGA64_ARG0 )) || continue
            die "Assembly for $asm_name.$gen_name contains instruction which compiles to $d, conflicts with IGA64_ARG0/mask $IGA64_ARG0/$IGA64_ARG_MASK\ncmd: $cmd"
        done
        compile_iga64 > "$WD/$asm_name.$gen_name.bin" || die "Cannot write to $WD/$asm_name.$gen_name.bin"
        code="$(hexdump -v -e '"\t\t" 4/4 "0x%08x, " "\n"' $WD/$asm_name.$gen_name.bin)"
        [ -z "$cur_code" ] && cur_code="$code"
        [ "$cur_code" != "$code" ] && {
            echo -e "\t{ .gen_ver = $cur_ver, .size = $(dword_count "$cur_code"), .code = (const uint32_t []) {\n$cur_code\n\t}}," >>$OUTPUT
            cur_code="$code"
        }
        cur_ver=$gen_ver
    done
    echo -e "\t{ .gen_ver = $cur_ver, .size = $(dword_count "$cur_code"), .code = (const uint32_t []) {\n$cur_code\n\t}}\n};" >>$OUTPUT
done

cp $OUTPUT $INPUT