diff --git a/CMakeLists.txt b/CMakeLists.txt index 6f0b7bf47c..20f4337a3b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -155,6 +155,7 @@ install ( FILES ${CMAKE_CURRENT_SOURCE_DIR}/bin/rpl_run.sh ${CMAKE_CURRENT_SOURCE_DIR}/bin/txt2xml.sh ${CMAKE_CURRENT_SOURCE_DIR}/bin/txt2params.py + ${CMAKE_CURRENT_SOURCE_DIR}/bin/spmltgen.py ${CMAKE_CURRENT_SOURCE_DIR}/bin/tblextr.py ${CMAKE_CURRENT_SOURCE_DIR}/bin/dform.py ${CMAKE_CURRENT_SOURCE_DIR}/bin/mem_manager.py diff --git a/bin/rpl_run.sh b/bin/rpl_run.sh index ae989c5109..5ae505c2cc 100755 --- a/bin/rpl_run.sh +++ b/bin/rpl_run.sh @@ -35,6 +35,10 @@ RPL_PATH=$PKG_DIR/lib TLIB_PATH=$PKG_DIR/tool TTLIB_PATH=$TT_DIR/tool +GFX=`/opt/rocm/bin/rocm_agent_enumerator | tail -1` + +SPM_COUNTERS_FILE="spm_counters.txt" + if [ -z "$ROCP_PYTHON_VERSION" ] ; then ROCP_PYTHON_VERSION=python3 fi @@ -551,6 +555,10 @@ for name in $input_list; do fi done +if [ -e "$SPM_COUNTERS_FILE" ] ; then + $ROCP_PYTHON_VERSION $BIN_DIR/spmltgen.py $GFX -f $SPM_COUNTERS_FILE +fi + if [ -n "$csv_output" ] ; then merge_output $OUTPUT_LIST if [ "$GEN_STATS" = "1" ] ; then diff --git a/bin/spmltgen.py b/bin/spmltgen.py new file mode 100755 index 0000000000..218459bf99 --- /dev/null +++ b/bin/spmltgen.py @@ -0,0 +1,295 @@ +import sys +import enum + +#source file handling: from last command line argument or default +argc = len(sys.argv) +if argc == 1 or sys.argv[1] == "-h" or sys.argv[1] == "--help": + print("Usage:") + print("python3 spmltgen.py _]>") + print("python3 spmltgen.py -f counter_events_file") + print(" GPU gfx id, i.e. gfx908") + print(" SPM block name, one of CPC, CPF, GDS, SPI, SQ, SX, TA, TCA, TCC, TCP, TD") + print(" SPM block event names specified by above") + print(" counter_events_file lists one event counter _ per line" + print(" spmltgen.py print out the layout of counter events in SPM sample data buffer") + print(" Output layout lines format:") + print(" : ") + print(" T64 - for 64bit timestamp") + print(" X - for Nbit gap") + sys.exit(0) + +# set the number of shader engines +se_no = 4 +if sys.argv[1] == "gfx908" or sys.argv[1] == "gfx90a" or sys.argv[1] == "gfx1030": + se_no = 8 +else: + print("Unknown gfx chip: " + sys.argv[1]) + sys.exit(0) + +# test if a block is a global block +def is_global_block(block_name): + if block_name == "CPC" or block_name == "CPF" or block_name == "GDS" or block_name == "TCC" or block_name == "TCA": + return True + else: + return False + +# extract counter events from either the command line or the counter_events_file +counter_args = [] +if sys.argv[2] == "-f": + if argc < 4: + print("Missing counter_event_file") + sys.exit(0) + file = open(sys.argv[3], 'r') + for line in file: + counter_args.append(line.strip()) + file.close() +else: + for i in range(argc): + if i > 1: + counter_args.append(sys.argv[i]) + +# build counter events +counters = [] +for event in counter_args: + block_name = event.partition('_')[0] + name = event.partition(':')[0] + id = event.partition(':')[2] + counter_des = [] + counter_des.append(block_name) + counter_des.append(name) + counter_des.append(id) + counters.append(counter_des) + +even_counters = [] +odd_counters = [] + +# SPM block id enum +class block_idx(enum.IntEnum): + CPC = 0 + CPF = 1 + GDS = 2 + SPI = 3 + SQ = 4 + SX = 5 + TA = 6 + TCA = 7 + TCC = 8 + TCP = 9 + TD = 10 + +# Return SPM block id enum from its block name +def get_block_idx(block_name): + if block_name == "CPC": + return block_idx.CPC + elif block_name == "CPF": + return block_idx.CPF + elif block_name == "GDS": + return block_idx.GDS + elif block_name == "SPI": + return block_idx.SPI + elif block_name == "SQ": + return block_idx.SQ + elif block_name == "SX": + return block_idx.SX + elif block_name == "TA": + return block_idx.TA + elif block_name == "TCA": + return block_idx.TCA + elif block_name == "TCC": + return block_idx.TCC + elif block_name == "TCP": + return block_idx.TCP + elif block_name == "TD": + return block_idx.TD + else: + print("Unknown SPM block name: " + block_name + " encountered") + print("Exiting ...") + sys.exit(0) + +# is SQ SPM counters treated as 32-bit mode +sq_32b_mode = True + +# Odd and even counter events (dictionary value list) according to each SPM block id (dictionary key) +odd = {} +even = {} + +# Check if a key is already in the dictionary +def check_key(dict, key): + if key in dict.keys(): + return True + return False + +# Assign counter events of a block (id used as key) to odd and even events (event list as value) of its own +for counter in counters: + key = get_block_idx(counter[0]) + is_odd_inserted = check_key(odd, key) + is_even_inserted = check_key(even, key) + if counter[0] == "SQ" and sq_32b_mode: + if not is_even_inserted: + evens = [] + evens.append(counter) + even[key] = evens + else: + evens = even[key] + evens.append(counter) + even[key] = evens + if not is_odd_inserted: + odds = [] + odds.append(counter) + odd[key] = odds + else: + odds = odd[key] + odds.append(counter) + odd[key] = odds + else: + if not is_even_inserted: + evens = [] + evens.append(counter) + even[key] = evens + elif not is_odd_inserted: + odds = [] + odds.append(counter) + odd[key] = odds + elif len(even[key]) == len(odd[key]): + # push to evens + evens = even[key] + evens.append(counter) + even[key] = evens + else: + # push to odds + odds = odd[key] + odds.append(counter) + odd[key] = odds + +# Total global and shader engine even and odd counter events +cntr_array_even = [["T64"], []] +cntr_array_odd = [[], []] + +# Assign all odd and even counter events from each block to the total global and shader engine odd and even counter events +for s in block_idx: + if check_key(even, s): + even_blk_counters = even[s] + even_blk_counter = even_blk_counters[0] + if is_global_block(even_blk_counter[0]): + for even_blk_counter in even_blk_counters: + cntr_array_even[0].append(even_blk_counter[1]) + else: + for even_blk_counter in even_blk_counters: + cntr_array_even[1].append(even_blk_counter[1]) + + if check_key(odd, s): + odd_blk_counters = odd[s] + odd_blk_counter = odd_blk_counters[0] + if is_global_block(odd_blk_counter[0]): + for odd_blk_counter in odd_blk_counters: + cntr_array_odd[0].append(odd_blk_counter[1]) + else: + for odd_blk_counter in odd_blk_counters: + cntr_array_odd[1].append(odd_blk_counter[1]) + +# Accumulated even and odd counter events (max 16 events per even or odd) for print set to empty +even_layout = [] +odd_layout = [] + +# Print 16-event even and odd segments on a single line +def print_layout(odd_layout, even_layout): + for i in even_layout: + print(i, end = " ") + for i in odd_layout: + print(i, end = " ") + print() + +# Function to print all global counter events per 16-event even and odd segment +def print_global_layout(odd_counters, even_counters): + global even_layout + global odd_layout + # segments of even event counters + segs = (len(even_counters) + 3) >> 4 + if (len(even_counters) % 16) != 0: + segs += 1 + idx_even = 0 + idx_odd = 0 + even_padding = "X0" + odd_padding = "X0" + for i in range(segs * 16): + # fill in 16 even global counters as they exist + if i >= 13 and i <= 15: + pass + elif i < len(even_counters): + even_layout.append(even_counters[idx_even]) + idx_even += 1 + else: + # padding with X + padding = int(even_padding[1:]) + padding += 16 + even_padding = "X" + str(padding) + # fill in corresponding odd 16 global counters as they exist + if i < len(odd_counters): + odd_layout.append(odd_counters[idx_odd]) + idx_odd += 1 + else: + # padding with X + padding = int(odd_padding[1:]) + padding += 16 + odd_padding = "X" + str(padding) + if i % 16 == 15: + # after accumulated one segment of both even and odd events print their layout + if even_padding != "X0": + even_layout.append(even_padding) + even_padding = "X0" + if odd_padding != "X0": + odd_layout.append(odd_padding) + odd_padding = "X0" + print("1: ", end = '') + print_layout(odd_layout, even_layout) + even_layout = [] + odd_layout = [] + +# Accumulated even and odd counter events (max 16 events per even or odd) for print set to empty +even_layout = [] +odd_layout = [] + +# Function to print all shader engine counter events per 16-event even and odd segment +def print_se_layout(se_no, odd_counters, even_counters): + global even_layout + global odd_layout + print(str(se_no) + ": ", end = '') + # segments of even event counters + segs = len(even_counters) >> 4 + if (len(even_counters) % 16) != 0: + segs += 1 + even_padding = "X0" + odd_padding = "X0" + # process each event in all segments + for i in range(segs * 16): + # fill in 16 even global counters as they exist + if i < len(even_counters): + even_layout.append(even_counters[i]) + else: + # padding with X + padding = int(even_padding[1:]) + padding += 16 + even_padding = "X" + str(padding) + # fill in corresponding odd 16 global counters as they exist + if i < len(odd_counters): + odd_layout.append(odd_counters[i]) + else: + # padding with X + padding = int(odd_padding[1:]) + padding += 16 + odd_padding = "X" + str(padding) + if i % 16 == 15: + # after accumulated one segment of both even and odd events print their layout + if even_padding != "X0": + even_layout.append(even_padding) + even_padding = "X0" + if odd_padding != "X0": + odd_layout.append(odd_padding) + odd_padding = "X0" + print_layout(odd_layout, even_layout) + even_layout = [] + odd_layout = [] + +# Print alll even and odd events +print_global_layout(cntr_array_odd[0], cntr_array_even[0]) +print_se_layout(se_no, cntr_array_odd[1], cntr_array_even[1]) diff --git a/test/tool/tool.cpp b/test/tool/tool.cpp index c945fa1ac9..1934e40aa6 100644 --- a/test/tool/tool.cpp +++ b/test/tool/tool.cpp @@ -460,14 +460,27 @@ void spm_ctrl_start(rocprofiler_feature_t* features, uint32_t features_found) { rocprofiler_properties_t properties{}; properties.queue_depth = 256; + std::ostringstream oss; + oss << result_prefix << "spm_counters.txt"; + FILE* spm_counters_file = fopen(oss.str().c_str(), "w"); + if (spm_counters_file == NULL) { + std::ostringstream errmsg; + errmsg << "ROCProfiler: fopen error, file '" << oss.str().c_str() << "'"; + perror(errmsg.str().c_str()); + abort(); + } + for (rocprofiler_feature_t* p = features; p < features + features_found; ++p) { int val = p->kind; if (val == ROCPROFILER_FEATURE_KIND_METRIC) { val = ROCPROFILER_FEATURE_KIND_TRACE | ROCPROFILER_FEATURE_KIND_SPM_MOD; p->kind = (rocprofiler_feature_kind_t)val; + fprintf(spm_counters_file, "%s\n", p->name); } } + fclose(spm_counters_file); + // Creating SPM context rocprofiler_t* context = NULL; hsa_status_t status = rocprofiler_open(agent, features, features_found, &context,