diff --git a/samples/counter_collection/client.cpp b/samples/counter_collection/client.cpp index 903956be44..a9a261635d 100644 --- a/samples/counter_collection/client.cpp +++ b/samples/counter_collection/client.cpp @@ -38,13 +38,24 @@ test_callback(rocprofiler_queue_id_t queue_id, rocprofiler_correlation_id_t corr_id, const hsa_kernel_dispatch_packet_t*, void*, - rocprofiler_dispatch_profile_counting_record_t**, - size_t, + rocprofiler_record_counter_t* out_counters, + size_t out_size, rocprofiler_profile_config_id_t) { + static int enter_count = 0; + enter_count++; + // Limit output to avoid massive log size + if(enter_count % 100 != 0) return; + + std::stringstream ss; + for(size_t i = 0; i < out_size; i++) + { + ss << "(Id: " << out_counters[i].id << " Value [D]: " << out_counters[i].derived_counter + << ", Value [I]: " << out_counters[i].hw_counter << "),"; + } // Callback containing counter data. std::clog << "[" << __FUNCTION__ << "] " << queue_id.handle << " | " << agent_id.id.handle - << " | " << corr_id.internal << "\n"; + << " | " << corr_id.internal << "|" << ss.str() << "\n"; } int diff --git a/source/include/rocprofiler/counters.h b/source/include/rocprofiler/counters.h index b11c03dbbc..cbbca05c7a 100644 --- a/source/include/rocprofiler/counters.h +++ b/source/include/rocprofiler/counters.h @@ -34,6 +34,44 @@ ROCPROFILER_EXTERN_C_INIT * @{ */ +/** + * @brief Query counter id information from record_id + * + * @param [in] id record id from rocprofiler_record_counter_t + * @param [out] counter_id counter id associated with the record + * @return ::rocprofiler_status_t + */ +rocprofiler_status_t ROCPROFILER_API +rocprofiler_query_record_counter_id(rocprofiler_counter_instance_id_t id, + rocprofiler_counter_id_t* counter_id) ROCPROFILER_NONNULL(2); + +/** + * @brief Query dimension position from record_id + * + * @param [in] id record id from rocprofiler_record_counter_t + * @param [in] dim dimension for which positional info is requested + * @param [out] pos value of the dimension in id. + * @return ::rocprofiler_status_t + */ +rocprofiler_status_t ROCPROFILER_API +rocprofiler_query_record_dimension_position(rocprofiler_counter_instance_id_t id, + rocprofiler_counter_dimension_id_t dim, + size_t* pos) ROCPROFILER_NONNULL(3); + +/** + * @brief Return information about the dimension for a specified counter + * + * @param [in] id counter id to query dimension info for. + * @param [in] dim dimension + * @param [out] info info on the dimension (name, instance_size) + * @return ::rocprofiler_status_t + */ +rocprofiler_status_t ROCPROFILER_API +rocprofiler_query_record_dimension_info(rocprofiler_counter_id_t id, + rocprofiler_counter_dimension_id_t dim, + rocprofiler_record_dimension_info_t* info) + ROCPROFILER_NONNULL(3); + /** * @brief Query Counter name. * diff --git a/source/include/rocprofiler/dispatch_profile.h b/source/include/rocprofiler/dispatch_profile.h index 236883c09b..e86765fb6f 100644 --- a/source/include/rocprofiler/dispatch_profile.h +++ b/source/include/rocprofiler/dispatch_profile.h @@ -69,14 +69,14 @@ typedef struct * @param [in] config */ typedef void (*rocprofiler_profile_counting_dispatch_callback_t)( - rocprofiler_queue_id_t queue_id, - rocprofiler_agent_t agent_id, - rocprofiler_correlation_id_t correlation_id, - const hsa_kernel_dispatch_packet_t* dispatch_packet, - void* callback_data_args, - rocprofiler_dispatch_profile_counting_record_t** records, - size_t record_count, - rocprofiler_profile_config_id_t config); + rocprofiler_queue_id_t queue_id, + rocprofiler_agent_t agent_id, + rocprofiler_correlation_id_t correlation_id, + const hsa_kernel_dispatch_packet_t* dispatch_packet, + void* callback_data_args, + rocprofiler_record_counter_t* records, + size_t record_count, + rocprofiler_profile_config_id_t config); /** * @brief Configure Dispatch Profile Counting Service. diff --git a/source/include/rocprofiler/fwd.h b/source/include/rocprofiler/fwd.h index e770397a79..8783d638e8 100644 --- a/source/include/rocprofiler/fwd.h +++ b/source/include/rocprofiler/fwd.h @@ -251,14 +251,23 @@ typedef uint64_t rocprofiler_thread_id_t; */ typedef uint32_t rocprofiler_tracing_operation_t; -/** - * @brief Needs non-typedef specification? - */ -typedef uint32_t rocprofiler_counter_instance_id_t; - // forward declaration of struct typedef struct rocprofiler_pc_sampling_configuration_s rocprofiler_pc_sampling_configuration_t; +/** + * @brief Unique record id encoding both the counter + * and dimensional values (positions) for the record. + */ +typedef uint64_t rocprofiler_counter_instance_id_t; + +/** + * @brief A dimension for counter instances. Some example + * dimensions include XCC, SM (Shader), etc. This + * value represents the dimension beind described + * or queried about. + */ +typedef uint64_t rocprofiler_counter_dimension_id_t; + //--------------------------------------------------------------------------------------// // // UNIONS @@ -415,14 +424,26 @@ rocprofiler_record_header_compute_hash(uint32_t category, uint32_t kind) return value; } +/** + * @brief Details for the dimension, including its size, for a counter. + */ +typedef struct +{ + const char* name; + size_t instance_size; +} rocprofiler_record_dimension_info_t; + /** * @brief ROCProfiler Profile Counting Counter per instance. */ typedef struct { - rocprofiler_counter_id_t counter_id; - rocprofiler_counter_instance_id_t instance_id; - double counter_value; + rocprofiler_counter_instance_id_t id; + union + { + int64_t hw_counter; //<< physical hardware counter + double derived_counter; //<< derived counter value + }; } rocprofiler_record_counter_t; /** diff --git a/source/lib/rocprofiler/aql/packet_construct.cpp b/source/lib/rocprofiler/aql/packet_construct.cpp index 502eaae37c..832c3c1cd2 100644 --- a/source/lib/rocprofiler/aql/packet_construct.cpp +++ b/source/lib/rocprofiler/aql/packet_construct.cpp @@ -38,6 +38,10 @@ AQLPacketConstruct::AQLPacketConstruct(const hsa::AgentCache& agen HSA_STATUS_SUCCESS); LOG_IF(FATAL, !validate_event_result) << "Invalid Metric: " << block_index << " " << event_id; + _event_to_metric[std::make_tuple( + static_cast(query_info.id), + block_index, + event_id)] = x; } } // Check that we can collect all of the metrics in a single execution @@ -152,6 +156,18 @@ AQLPacketConstruct::get_all_events() const return ret; } +const counters::Metric* +AQLPacketConstruct::event_to_metric(const hsa_ven_amd_aqlprofile_event_t& event) const +{ + if(const auto* ptr = rocprofiler::common::get_val( + _event_to_metric, + std::make_tuple(event.block_name, event.block_index, event.counter_id))) + { + return ptr; + } + return nullptr; +} + void AQLPacketConstruct::can_collect() { diff --git a/source/lib/rocprofiler/aql/packet_construct.hpp b/source/lib/rocprofiler/aql/packet_construct.hpp index 25214ef3ae..948ddcb5a3 100644 --- a/source/lib/rocprofiler/aql/packet_construct.hpp +++ b/source/lib/rocprofiler/aql/packet_construct.hpp @@ -31,6 +31,8 @@ public: AQLPacketConstruct(const hsa::AgentCache& agent, const std::vector& metrics); std::unique_ptr construct_packet(const AmdExtTable&) const; + const counters::Metric* event_to_metric(const hsa_ven_amd_aqlprofile_event_t& event) const; + private: struct AQLProfileMetric { @@ -44,6 +46,8 @@ private: const hsa::AgentCache& _agent; std::vector _metrics; std::vector _events; + std::map, counters::Metric> + _event_to_metric; }; } // namespace aql diff --git a/source/lib/rocprofiler/counters.cpp b/source/lib/rocprofiler/counters.cpp index 7ea22f27c4..82075885b8 100644 --- a/source/lib/rocprofiler/counters.cpp +++ b/source/lib/rocprofiler/counters.cpp @@ -3,6 +3,7 @@ #include "lib/common/synchronized.hpp" #include "lib/rocprofiler/aql/helpers.hpp" #include "lib/rocprofiler/counters/evaluate_ast.hpp" +#include "lib/rocprofiler/counters/id_decode.hpp" #include "lib/rocprofiler/counters/metrics.hpp" #include "lib/rocprofiler/hsa/agent_cache.hpp" #include "lib/rocprofiler/hsa/queue.hpp" @@ -110,4 +111,48 @@ rocprofiler_iterate_agent_supported_counters(rocprofiler_agent_t return cb(ids.data(), ids.size(), user_data); } + +/** + * @brief Query counter id information from record_id + * + * @param [in] id record id from rocprofiler_record_counter_t + * @param [out] counter_id counter id associated with the record + * @return ::rocprofiler_status_t + */ +rocprofiler_status_t ROCPROFILER_API +rocprofiler_query_record_counter_id(rocprofiler_counter_instance_id_t id, + rocprofiler_counter_id_t* counter_id) +{ + // Get counter id from record + *counter_id = rocprofiler::counters::rec_to_counter_id(id); + return ROCPROFILER_STATUS_SUCCESS; +} + +rocprofiler_status_t ROCPROFILER_API +rocprofiler_query_record_dimension_position(rocprofiler_counter_instance_id_t id, + rocprofiler_counter_dimension_id_t dim, + size_t* pos) +{ + *pos = rocprofiler::counters::rec_to_dim_pos( + id, static_cast(dim)); + return ROCPROFILER_STATUS_SUCCESS; +} + +rocprofiler_status_t ROCPROFILER_API +rocprofiler_query_record_dimension_info(rocprofiler_counter_id_t, + rocprofiler_counter_dimension_id_t dim, + rocprofiler_record_dimension_info_t* info) +{ + if(const auto* ptr = rocprofiler::common::get_val( + rocprofiler::counters::dimension_map(), + static_cast(dim))) + { + info->name = ptr->c_str(); + // TODO: Needs info on the instance size per block to fill in. + // counter_id will be used to lookup this information. + info->instance_size = 0; + return ROCPROFILER_STATUS_SUCCESS; + } + return ROCPROFILER_STATUS_ERROR; +} } diff --git a/source/lib/rocprofiler/counters/CMakeLists.txt b/source/lib/rocprofiler/counters/CMakeLists.txt index 8b304222fb..b8858a5142 100644 --- a/source/lib/rocprofiler/counters/CMakeLists.txt +++ b/source/lib/rocprofiler/counters/CMakeLists.txt @@ -1,5 +1,7 @@ -set(ROCPROFILER_LIB_COUNTERS_SOURCES metrics.cpp evaluate_ast.cpp core.cpp) -set(ROCPROFILER_LIB_COUNTERS_HEADERS metrics.hpp evaluate_ast.hpp core.hpp) +set(ROCPROFILER_LIB_COUNTERS_SOURCES metrics.cpp dimensions.cpp evaluate_ast.cpp core.cpp + id_decode.cpp) +set(ROCPROFILER_LIB_COUNTERS_HEADERS metrics.hpp dimensions.hpp evaluate_ast.hpp core.hpp + id_decode.hpp) target_sources(rocprofiler-object-library PRIVATE ${ROCPROFILER_LIB_COUNTERS_SOURCES} ${ROCPROFILER_LIB_COUNTERS_HEADERS}) diff --git a/source/lib/rocprofiler/counters/core.cpp b/source/lib/rocprofiler/counters/core.cpp index f2176e0013..5a40ff8884 100644 --- a/source/lib/rocprofiler/counters/core.cpp +++ b/source/lib/rocprofiler/counters/core.cpp @@ -34,6 +34,38 @@ queue_cb(const std::shared_ptr& in // This ensures that HSA exists if(!info->pkt_generator) { + // One time setup of profile config + if(info->profile_cfg.reqired_hw_counters.empty()) + { + auto& config = info->profile_cfg; + auto agent_name = std::string(config.agent.name); + for(const auto& metric : config.metrics) + { + auto req_counters = + rocprofiler::counters::get_required_hardware_counters(agent_name, metric); + if(!req_counters) + { + throw std::runtime_error( + fmt::format("Could not find counter {}", metric.name())); + } + config.reqired_hw_counters.insert(req_counters->begin(), req_counters->end()); + + const auto& asts = rocprofiler::counters::get_ast_map(); + const auto* agent_map = rocprofiler::common::get_val(asts, agent_name); + if(!agent_map) + throw std::runtime_error( + fmt::format("Coult not build AST for {}", agent_name)); + const auto* counter_ast = + rocprofiler::common::get_val(*agent_map, metric.name()); + if(!counter_ast) + { + throw std::runtime_error( + fmt::format("Coult not find AST for {}", metric.name())); + } + config.asts.push_back(*counter_ast); + } + } + info->pkt_generator = std::make_unique( queue.get_agent(), std::vector{info->profile_cfg.reqired_hw_counters.begin(), @@ -70,6 +102,7 @@ completed_cb(const std::shared_ptr // auto out_buf = pkt->profile.output_buffer.ptr; // Read data and create user return.... + auto decoded_pkt = EvaluateAST::read_pkt(info->pkt_generator.get(), *pkt); // return AQL packet for reuse. @@ -82,13 +115,22 @@ completed_cb(const std::shared_ptr if(!info->user_cb) return; + std::vector out; + for(auto& ast : info->profile_cfg.asts) + { + auto* ret = ast.evaluate(decoded_pkt); + CHECK(ret); + out.insert(out.end(), ret->begin(), ret->end()); + } + + // Maybe move to its own thread? info->user_cb(queue.get_id(), info->profile_cfg.agent, rocprofiler_correlation_id_t{}, reinterpret_cast(&kernel), info->callback_args, - nullptr, // Date pointer does here. - 0, // Number of objects + out.data(), // Date pointer does here. + out.size(), // Number of objects info->profile_cfg.id); } diff --git a/source/lib/rocprofiler/counters/dimensions.cpp b/source/lib/rocprofiler/counters/dimensions.cpp new file mode 100644 index 0000000000..4906fd867e --- /dev/null +++ b/source/lib/rocprofiler/counters/dimensions.cpp @@ -0,0 +1,109 @@ +#include "dimensions.hpp" + +#include +#include +#include +#include + +#include + +#include "lib/common/synchronized.hpp" +#include "lib/common/utility.hpp" +#include "lib/rocprofiler/aql/helpers.hpp" +#include "lib/rocprofiler/hsa/queue_controller.hpp" + +namespace rocprofiler +{ +namespace counters +{ +// namespace +// { +// void +// create_block_dimensions(std::string& agent, +// std::string& block_name, +// std::vector& dimension_list) +// { +// static std::atomic id = 0; +// // query hsa/aqlprofile/kfd etc here to get dimension sizes +// // create MetricDimension objects and push_back() in dimension_list +// } + +// } // namespace + +// BlockDimensionMap& +// getBlockDimensionsMap(std::string& agent) +// { +// static std::unique_ptr map = [&]() { +// auto data = std::make_unique(); +// // TODO: populate this vector with list of all blocks +// std::vector block_names; + +// for(auto& block : block_names) +// { +// auto& dimensions = data->emplace(block, +// std::vector()).first->second; create_block_dimensions(agent, block, +// dimensions); +// } +// return data; +// }(); +// return *map; +// } + +// const AgentBlockDimensionsMap& +// getAgentBlockDimensionsMap() +// { +// static std::unique_ptr map = [&]() { +// auto data = std::make_unique(); +// // TODO: fill this up with agent iteration or through xml +// std::vector agent_names; + +// // insert the BlockDimensionMap for each agent +// for(auto& agent : agent_names) +// { +// auto& val = getBlockDimensionsMap(agent); +// data->emplace(agent, val); +// } +// return data; +// }(); +// return *map; +// } + +std::vector +getBlockDimensions(const std::string& agent, const Metric& metric) +{ + if(!metric.special().empty()) + { + // Special non-hardware counters without dimension data + return std::vector{ + {dimension_map().at(ROCPROFILER_DIMENSION_NONE), 1, ROCPROFILER_DIMENSION_NONE}}; + } + + for(const auto& [_, maybe_agent] : hsa::get_queue_controller().get_supported_agents()) + { + if(maybe_agent.name() == agent) + { + return std::vector{ + {dimension_map().at(ROCPROFILER_DIMENSION_SHADER_ENGINE), + maybe_agent.get_rocp_agent().num_shader_banks, + ROCPROFILER_DIMENSION_SHADER_ENGINE}, + {dimension_map().at(ROCPROFILER_DIMENSION_XCC), + maybe_agent.get_rocp_agent().num_xcc, + ROCPROFILER_DIMENSION_XCC}, + {dimension_map().at(ROCPROFILER_DIMENSION_CU), + maybe_agent.get_rocp_agent().cu_count, + ROCPROFILER_DIMENSION_CU}, + {dimension_map().at(ROCPROFILER_DIMENSION_AGENT), + maybe_agent.get_rocp_agent().id.handle, + ROCPROFILER_DIMENSION_AGENT}}; + + // auto query_info = aql::get_query_info(maybe_agent.get_agent(), metric); + // return std::vector{ + // {metric.block(), query_info.instance_count, ROCPROFILER_DIMENSION_NONE}}; + } + } + + return {}; +} + +} // namespace counters +} // namespace rocprofiler \ No newline at end of file diff --git a/source/lib/rocprofiler/counters/dimensions.hpp b/source/lib/rocprofiler/counters/dimensions.hpp new file mode 100644 index 0000000000..af554d07ef --- /dev/null +++ b/source/lib/rocprofiler/counters/dimensions.hpp @@ -0,0 +1,81 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "lib/rocprofiler/counters/id_decode.hpp" +#include "lib/rocprofiler/counters/metrics.hpp" + +namespace rocprofiler +{ +namespace counters +{ +class MetricDimension +{ +public: + MetricDimension(std::string name, + uint64_t dim_size, + rocprofiler_profile_counter_instance_types type) + : name_(std::move(name)) + , size_(dim_size) + , type_(type){}; + + const std::string& name() const { return name_; } + uint64_t size() const { return size_; } + rocprofiler_profile_counter_instance_types type() const { return type_; } + bool operator==(const MetricDimension& dim) const + { + return std::tie(name_, size_, type_) == std::tie(dim.name_, dim.size_, dim.type_); + } + +private: + std::string name_; + uint64_t size_; + rocprofiler_profile_counter_instance_types type_; +}; + +/* +{ + AgentBlockDimensionsMap = { + "gfx906":{}, + "gfx908":{ + "TCC": [dim_1, dim_2 ... dim_n] + "SQ": [dim_1, dim_2 ... dim_n] + "TCP": [dim_1, dim_2 ... dim_n] + } + } +} +*/ + +// // map block_name -> MetricDimension +// using BlockDimensionMap = std::unordered_map>; +// // map agent_name -> BlockDimensionMap +// using AgentBlockDimensionsMap = std::unordered_map; + +// // map dimension_id -> MetricDimension +// using DimensionIdMap = std::unordered_map; + +// // get the complete AgentBlockDimensionsMap +// const AgentBlockDimensionsMap& +// getAgentBlockDimensionsMap(); + +// // get specific dimensions for an agent, block_name +// const std::vector& +// getBlockDimension(const std::string& agent, +// std::string block_name, +// rocprofiler_profile_counter_instance_types dim); + +// get all dimensions for an agent, block_name +std::vector +getBlockDimensions(const std::string& agent, const counters::Metric&); + +// // get a specific dimension by id +// const MetricDimension& +// getDimensionById(uint64_t id); + +} // namespace counters +} // namespace rocprofiler \ No newline at end of file diff --git a/source/lib/rocprofiler/counters/evaluate_ast.cpp b/source/lib/rocprofiler/counters/evaluate_ast.cpp index 560baf5021..041c8311d5 100644 --- a/source/lib/rocprofiler/counters/evaluate_ast.cpp +++ b/source/lib/rocprofiler/counters/evaluate_ast.cpp @@ -1,15 +1,92 @@ #include "lib/rocprofiler/counters/evaluate_ast.hpp" +#include +#include #include +#include +#include #include "lib/common/synchronized.hpp" #include "lib/common/utility.hpp" +#include "lib/rocprofiler/counters/dimensions.hpp" #include "lib/rocprofiler/counters/parser/reader.hpp" namespace rocprofiler { namespace counters { +namespace +{ +ReduceOperation +get_reduce_op_type_from_string(const std::string& op) +{ + static const std::unordered_map reduce_op_string_to_type = { + {"min", REDUCE_MIN}, {"max", REDUCE_MAX}, {"sum", REDUCE_SUM}, {"avr", REDUCE_AVG}}; + + ReduceOperation type = REDUCE_NONE; + const auto* reduce_op_type = rocprofiler::common::get_val(reduce_op_string_to_type, op); + if(reduce_op_type) type = *reduce_op_type; + return type; +} + +std::vector* +perform_reduction(ReduceOperation reduce_op, std::vector* input_array) +{ + rocprofiler_record_counter_t result{.id = 0, .derived_counter = 0}; + if(input_array->empty()) return input_array; + switch(reduce_op) + { + case REDUCE_NONE: break; + case REDUCE_MIN: + { + result = + *std::min_element(input_array->begin(), input_array->end(), [](auto& a, auto& b) { + return a.derived_counter < b.derived_counter; + }); + break; + } + case REDUCE_MAX: + { + result = + *std::max_element(input_array->begin(), input_array->end(), [](auto& a, auto& b) { + return a.derived_counter > b.derived_counter; + }); + break; + } + case REDUCE_SUM: + { + result = std::accumulate( + input_array->begin(), + input_array->end(), + rocprofiler_record_counter_t{.id = 0, .derived_counter = 0}, + [](auto& a, auto& b) { + return rocprofiler_record_counter_t{ + .id = a.id, .derived_counter = a.derived_counter + b.derived_counter}; + }); + break; + } + case REDUCE_AVG: + { + result = std::accumulate( + input_array->begin(), + input_array->end(), + rocprofiler_record_counter_t{.id = 0, .derived_counter = 0}, + [](auto& a, auto& b) { + return rocprofiler_record_counter_t{ + .id = a.id, .derived_counter = a.derived_counter + b.derived_counter}; + }); + result.derived_counter /= input_array->size(); + break; + } + } + input_array->clear(); + input_array->push_back(result); + set_dim_in_rec(input_array->begin()->id, ROCPROFILER_DIMENSION_NONE, 0); + return input_array; +} + +} // namespace + const std::unordered_map& get_ast_map() { @@ -42,20 +119,35 @@ get_ast_map() } try { - eval_map.emplace(metric.name(), EvaluateAST(by_name, *ast)); - } catch(std::out_of_range& e) + auto& evaluate_ast_node = + eval_map.emplace(metric.name(), EvaluateAST(by_name, *ast, gfx)) + .first->second; + evaluate_ast_node.validate_raw_ast( + by_name); // TODO: refactor and consolidate internal post-construction + // logic as a Finish() method + } catch(std::exception& e) { + LOG(ERROR) << e.what(); throw std::runtime_error( - fmt::format("AST was not generated for {}:{}, Counter will be unavailable. " - "Likely cause is a base counter not being defined used in a " - "derrived counter.", - gfx, - metric.name())); + fmt::format("AST was not generated for {}:{}", gfx, metric.name())); } yy_delete_buffer(buf); delete ast; } + // Set dimensions after all ASTs loaded for arch. + for(auto& [name, ast] : eval_map) + { + try + { + ast.set_dimensions(); + } catch(std::exception& e) + { + LOG(ERROR) << "Could not set dimensions for " << name << " failed with " + << e.what(); + } + } } + return data; }(); return ast_map; @@ -75,5 +167,321 @@ get_required_hardware_counters(const std::string& agent, const Metric& metric) return required_counters; } +EvaluateAST::EvaluateAST(const std::unordered_map& metrics, + const RawAST& ast, + std::string agent) +: _type(ast.type) +, _reduce_op(get_reduce_op_type_from_string(ast.reduce_op)) +, _agent(std::move(agent)) +, _reduce_dimension_set(ast.reduce_dimension_set) +{ + if(_type == NodeType::REFERENCE_NODE) + { + try + { + _metric = metrics.at(std::get(ast.value)); + } catch(std::exception& e) + { + throw std::runtime_error( + fmt::format("Unable to lookup metric {}", std::get(ast.value))); + } + } + + if(_type == NodeType::NUMBER_NODE) + { + _raw_value = std::get(ast.value); + _static_value.push_back({.id = 0, .hw_counter = std::get(ast.value)}); + } + + for(const auto& nextAst : ast.counter_set) + { + _children.emplace_back(metrics, *nextAst, _agent); + } +} + +DimensionTypes +EvaluateAST::set_dimensions() +{ + if(_dimension_types != DIMENSION_LAST) + { + return _dimension_types; + } + + auto get_dim_types = [&](auto& metric) { + int dim_types = 0; + for(const auto& dim : getBlockDimensions(_agent, metric)) + { + dim_types |= (dim.type() != ROCPROFILER_DIMENSION_NONE) ? (0x1 << dim.type()) : 0; + } + return static_cast(dim_types); + }; + + switch(_type) + { + case NONE: + case RANGE_NODE: + case NUMBER_NODE: break; + case ADDITION_NODE: + case SUBTRACTION_NODE: + case MULTIPLY_NODE: + case DIVIDE_NODE: + { + if(_children[0].set_dimensions() != _children[1].set_dimensions() && + _children[0].type() != NUMBER_NODE && _children[1].type() != NUMBER_NODE) + throw std::runtime_error(fmt::format("Dimension mis-mismatch: {} and {}", + _children[0].metric(), + _children[1].metric())); + _dimension_types = (_children[0].type() != NUMBER_NODE) ? _children[0].set_dimensions() + : _children[1].set_dimensions(); + } + break; + case REFERENCE_NODE: + { + _dimension_types = get_dim_types(_metric); + } + break; + case REDUCE_NODE: + { + // There is only one child node in case of REDUCE_NODE and that + // child node denotes the expression on which the reduce is applied. + // The resulting dimension of REDUCE_NODE will be the child's dimension + // minus the dimensions specified in the reduce_dimension_set. + int original_dim = static_cast(_children[0].set_dimensions()); + int turn_off_dims = 0; + for(auto dim : _reduce_dimension_set) + { + turn_off_dims |= (dim != ROCPROFILER_DIMENSION_NONE) ? (0x1 << dim) : 1; + } + int final_dims = _reduce_dimension_set.empty() ? ROCPROFILER_DIMENSION_NONE + : (original_dim & ~turn_off_dims); + _dimension_types = static_cast(final_dims); + } + break; + case SELECT_NODE: + { + // TODO: future scope + } + break; + } + return _dimension_types; +} + +void +EvaluateAST::get_required_counters(const std::unordered_map& asts, + std::set& counters) const +{ + if(!_metric.empty() && children().empty() && _type != NodeType::NUMBER_NODE) + { + // Base counter + if(_metric.expression().empty()) + { + counters.insert(_metric); + return; + } + + // Derrived Counter + const auto* expr_ptr = rocprofiler::common::get_val(asts, _metric.name()); + if(!expr_ptr) throw std::runtime_error("could not find derived counter"); + expr_ptr->get_required_counters(asts, counters); + // TODO: Add guards against infinite recursion + return; + } + + for(const auto& child : children()) + { + child.get_required_counters(asts, counters); + } +} + +bool +EvaluateAST::validate_raw_ast(const std::unordered_map& metrics) +{ + bool ret = true; + + try + { + switch(_type) + { + case NONE: + case RANGE_NODE: + case NUMBER_NODE: break; + case ADDITION_NODE: + case SUBTRACTION_NODE: + case MULTIPLY_NODE: + case DIVIDE_NODE: + { + // For arithmetic operations '+' '-' '*' '/' check if + // dimensions of both operands are matching. (handled in set_dimensions()) + for(auto& child : _children) + { + child.validate_raw_ast(metrics); + } + } + break; + case REFERENCE_NODE: + { + // handled in constructor + } + break; + case REDUCE_NODE: + { + // Future TODO + // Check #1 : Should be applied on a base metric. Derived metric support will be + // added later. Check #2 : Operation should be a supported operation. Check #3 : + // Dimensions specified should be valid for this metric and GPU + + // validate the members of RawAST, not the members of this class + } + break; + case SELECT_NODE: + { + // Future TODO + // Check #1 : Should be applied on a base metric. Derived metric support will be + // added later. Check #2 : Operation should be a supported operation. Check #3 : + // Dimensions specified should be valid for this metric and GPU. Check #4 : + // Dimensionindex values should be within limits for this metric and GPU. + } + break; + } + } catch(std::exception& e) + { + throw; + } + + // Future TODO: + // check if there are cycles in the graph + + return ret; +} + +std::unordered_map> +EvaluateAST::read_pkt(const aql::AQLPacketConstruct* pkt_gen, hsa::AQLPacket& pkt) +{ + struct it_data + { + std::unordered_map>* data; + const aql::AQLPacketConstruct* pkt_gen; + }; + + std::unordered_map> ret; + it_data aql_data{.data = &ret, .pkt_gen = pkt_gen}; + + hsa_status_t status = hsa_ven_amd_aqlprofile_iterate_data( + &pkt.profile, + [](hsa_ven_amd_aqlprofile_info_type_t info_type, + hsa_ven_amd_aqlprofile_info_data_t* info_data, + void* data) { + CHECK(data); + auto& it = *static_cast(data); + if(info_type != HSA_VEN_AMD_AQLPROFILE_INFO_PMC_DATA) return HSA_STATUS_SUCCESS; + const auto* metric = it.pkt_gen->event_to_metric(info_data->pmc_data.event); + if(!metric) return HSA_STATUS_SUCCESS; + auto& vec = it.data->emplace(metric->id(), std::vector{}) + .first->second; + auto& next_rec = vec.emplace_back(); + set_counter_in_rec(next_rec.id, {.handle = metric->id()}); + // Actual dimension info needs to be used here in the future + set_dim_in_rec(next_rec.id, ROCPROFILER_DIMENSION_NONE, vec.size() - 1); + // Note: in the near future we need to use hw_counter here instead + next_rec.derived_counter = info_data->pmc_data.result; + return HSA_STATUS_SUCCESS; + }, + &aql_data); + CHECK(status == HSA_STATUS_SUCCESS); + return ret; +} + +// convert to buffer at some point +std::vector* +EvaluateAST::evaluate( + std::unordered_map>& results_map) +{ + auto perform_op = [&](auto&& op) { + auto* r1 = _children[0].evaluate(results_map); + auto* r2 = _children[1].evaluate(results_map); + + if(r1->size() < r2->size()) swap(r1, r2); + + CHECK(!r1->empty() && !r2->empty()); + + if(r2->size() == 1) + { + // Special operation on either a number node + // or special node. This is typically a multiple/divide + // or some other type of constant op. + for(auto& val : *r1) + { + val = op(val, *r2->begin()); + } + } + else if(r2->size() == r1->size()) + { + // Normal combination + std::transform(r1->begin(), r1->end(), r2->begin(), r1->begin(), op); + } + else + { + throw std::runtime_error( + fmt::format("Mismatched Sizes {}, {}", r1->size(), r2->size())); + } + return r1; + }; + + switch(_type) + { + case NONE: + case RANGE_NODE: break; + case NUMBER_NODE: return &_static_value; + case ADDITION_NODE: + return perform_op([](auto& a, auto& b) { + return rocprofiler_record_counter_t{ + .id = a.id, .derived_counter = a.derived_counter + b.derived_counter}; + }); + case SUBTRACTION_NODE: + return perform_op([](auto& a, auto& b) { + return rocprofiler_record_counter_t{ + .id = a.id, .derived_counter = a.derived_counter - b.derived_counter}; + }); + case MULTIPLY_NODE: + return perform_op([](auto& a, auto& b) { + return rocprofiler_record_counter_t{ + .id = a.id, .derived_counter = a.derived_counter * b.derived_counter}; + }); + case DIVIDE_NODE: + return perform_op([](auto& a, auto& b) { + return rocprofiler_record_counter_t{ + .id = a.id, + .derived_counter = + (b.derived_counter == 0 ? 0 : a.derived_counter / b.derived_counter)}; + }); + case REFERENCE_NODE: + { + auto* result = rocprofiler::common::get_val(results_map, _metric.id()); + if(!result) + throw std::runtime_error( + fmt::format("Unable to lookup results for metric {}", _metric.name())); + + return result; + } + break; + case REDUCE_NODE: + { + auto* result = rocprofiler::common::get_val(results_map, _children[0]._metric.id()); + if(!result) + throw std::runtime_error(fmt::format("Unable to lookup results for metric {}", + _children[0]._metric.name())); + + if(_reduce_op == REDUCE_NONE) + throw std::runtime_error(fmt::format("Invalid Second argument to reduce(): {}", + static_cast(_reduce_op))); + return perform_reduction(_reduce_op, result); + } + // Currently unsupported + case SELECT_NODE: break; + } + + return nullptr; +} + } // namespace counters } // namespace rocprofiler diff --git a/source/lib/rocprofiler/counters/evaluate_ast.hpp b/source/lib/rocprofiler/counters/evaluate_ast.hpp index 361ba35f46..1ed623e9a2 100644 --- a/source/lib/rocprofiler/counters/evaluate_ast.hpp +++ b/source/lib/rocprofiler/counters/evaluate_ast.hpp @@ -1,10 +1,13 @@ #pragma once +#include #include #include #include #include "lib/common/utility.hpp" +#include "lib/rocprofiler/aql/packet_construct.hpp" +#include "lib/rocprofiler/counters/dimensions.hpp" #include "lib/rocprofiler/counters/metrics.hpp" #include "lib/rocprofiler/counters/parser/raw_ast.hpp" @@ -12,66 +15,69 @@ namespace rocprofiler { namespace counters { +struct metric_result +{ + uint64_t metric_id; + std::vector sample_values; +}; + +enum DimensionTypes +{ + DIMENSION_NONE = 0, + DIMENSION_XCC = 1 << 0, + DIMENSION_SHADER_ENGINE = 1 << 1, + DIMENSION_AGENT = 1 << 2, + DIMENSION_PMC_CHANNEL = 1 << 3, + DIMENSION_CU = 1 << 4, + DIMENSION_LAST = 1 << 5, +}; + +enum ReduceOperation +{ + REDUCE_NONE, + REDUCE_MIN, + REDUCE_MAX, + REDUCE_SUM, + REDUCE_AVG, +}; + class EvaluateAST { public: - EvaluateAST(const std::unordered_map& metrics, const RawAST& ast) - : _type(ast.type) - , _op(ast.operation) - { - if(_type == NodeType::REFERENCE_NODE) - { - _metric = metrics.at(std::get(ast.value)); - // LOG(ERROR) << fmt::format("CHILD METRIC {}", _metric); - } + EvaluateAST(const std::unordered_map& metrics, + const RawAST& ast, + std::string agent); - if(_type == NodeType::NUMBER_NODE) - { - _raw_value = std::get(ast.value); - } + std::vector* evaluate( + std::unordered_map>& results_map); - for(const auto& nextAst : ast.counter_set) - { - _children.emplace_back(metrics, *nextAst); - } - } + DimensionTypes set_dimensions(); + + bool validate_raw_ast(const std::unordered_map& metrics); void get_required_counters(const std::unordered_map& asts, - std::set& counters) const - { - if(!_metric.empty() && children().empty() && _type != NodeType::NUMBER_NODE) - { - // Base counter - if(_metric.expression().empty()) - { - counters.insert(_metric); - return; - } + std::set& counters) const; - // Derrived Counter - const auto* expr_ptr = rocprofiler::common::get_val(asts, _metric.name()); - if(!expr_ptr) throw std::runtime_error("could not find derived counter"); - expr_ptr->get_required_counters(asts, counters); - return; - } - - for(const auto& child : children()) - { - child.get_required_counters(asts, counters); - } - } + static std::unordered_map> read_pkt( + const aql::AQLPacketConstruct* pkt_gen, + hsa::AQLPacket& pkt); NodeType type() const { return _type; } - NodeType op() const { return _op; } + ReduceOperation reduce_op() const { return _reduce_op; } const std::vector& children() const { return _children; } const Metric& metric() const { return _metric; } + DimensionTypes dimension_types() const { return _dimension_types; } private: - NodeType _type{NONE}; - NodeType _op{NONE}; - Metric _metric; - double _raw_value{0}; - std::vector _children; + NodeType _type{NONE}; + ReduceOperation _reduce_op{REDUCE_NONE}; + Metric _metric; + double _raw_value{0}; + std::vector _children; + std::string _agent; + DimensionTypes _dimension_types{DIMENSION_LAST}; + std::vector _static_value; + std::unordered_set _reduce_dimension_set; }; using EvaluateASTMap = std::unordered_map; @@ -91,3 +97,28 @@ std::optional> get_required_hardware_counters(const std::string& agent, const Metric& metric); } // namespace counters } // namespace rocprofiler + +namespace fmt +{ +template <> +struct formatter +{ + template + constexpr auto parse(ParseContext& ctx) + { + return ctx.begin(); + } + + template + auto format(rocprofiler_record_counter_t const& data, Ctx& ctx) const + { + return fmt::format_to(ctx.out(), + "(CounterId: {}, Dimension: {:x}, Value [D]: {}, Value [I]: {})", + rocprofiler::counters::rec_to_counter_id(data.id).handle, + rocprofiler::counters::rec_to_dim_pos( + data.id, rocprofiler::counters::ROCPROFILER_DIMENSION_NONE), + data.derived_counter, + data.hw_counter); + } +}; +} // namespace fmt \ No newline at end of file diff --git a/source/lib/rocprofiler/counters/id_decode.cpp b/source/lib/rocprofiler/counters/id_decode.cpp new file mode 100644 index 0000000000..2c9beb0759 --- /dev/null +++ b/source/lib/rocprofiler/counters/id_decode.cpp @@ -0,0 +1,27 @@ +#include "lib/rocprofiler/counters/id_decode.hpp" + +#include +#include + +#include "lib/common/utility.hpp" + +namespace rocprofiler +{ +namespace counters +{ +const std::unordered_map& +dimension_map() +{ + static std::unordered_map map = { + {ROCPROFILER_DIMENSION_NONE, "DIMENSION_NONE"}, + {ROCPROFILER_DIMENSION_XCC, "DIMENSION_XCC"}, + {ROCPROFILER_DIMENSION_SHADER_ENGINE, "DIMENSION_SHADER_ENGINE"}, + {ROCPROFILER_DIMENSION_AGENT, "DIMENSION_AGENT"}, + {ROCPROFILER_DIMENSION_PMC_CHANNEL, "DIMENSION_PMC_CHANNEL"}, + {ROCPROFILER_DIMENSION_CU, "DIMENSION_CU"}, + }; + return map; +} + +} // namespace counters +} // namespace rocprofiler \ No newline at end of file diff --git a/source/lib/rocprofiler/counters/id_decode.hpp b/source/lib/rocprofiler/counters/id_decode.hpp new file mode 100644 index 0000000000..1886b329a7 --- /dev/null +++ b/source/lib/rocprofiler/counters/id_decode.hpp @@ -0,0 +1,104 @@ +#pragma once + +#include + +#include + +#include + +namespace rocprofiler +{ +namespace counters +{ +constexpr uint64_t COUNTER_BIT_LENGTH = 16; +constexpr uint64_t DIM_BIT_LENGTH = 48; +constexpr uint64_t MAX_64 = std::numeric_limits::max(); +enum rocprofiler_profile_counter_instance_types +{ + ROCPROFILER_DIMENSION_NONE = 0, ///< No dimension data, returns/sets 48 bit value as is + ROCPROFILER_DIMENSION_XCC, ///< XCC dimension of result + ROCPROFILER_DIMENSION_SHADER_ENGINE, ///< SE dimension of result + ROCPROFILER_DIMENSION_AGENT, ///< Agent dimension + ROCPROFILER_DIMENSION_PMC_CHANNEL, ///< PMC Channel dimension of result + ROCPROFILER_DIMENSION_CU, ///< Number of compute units + ROCPROFILER_DIMENSION_LAST +}; + +const std::unordered_map& +dimension_map(); + +inline rocprofiler_counter_id_t +rec_to_counter_id(rocprofiler_counter_instance_id_t id); +inline void +set_dim_in_rec(rocprofiler_counter_instance_id_t& id, + rocprofiler_profile_counter_instance_types dim, + size_t value); +inline void +set_counter_in_rec(rocprofiler_counter_instance_id_t& id, rocprofiler_counter_id_t value); + +inline size_t +rec_to_dim_pos(rocprofiler_counter_instance_id_t id, + rocprofiler_profile_counter_instance_types dim); + +} // namespace counters +} // namespace rocprofiler + +inline rocprofiler_counter_id_t +rocprofiler::counters::rec_to_counter_id(rocprofiler_counter_instance_id_t id) +{ + return {.handle = id >> DIM_BIT_LENGTH}; +} + +inline void +rocprofiler::counters::set_dim_in_rec(rocprofiler_counter_instance_id_t& id, + rocprofiler_profile_counter_instance_types dim, + size_t value) +{ + size_t bit_length = DIM_BIT_LENGTH / ROCPROFILER_DIMENSION_LAST; + int64_t mask = (MAX_64 >> (64 - bit_length)) << ((dim - 1) * bit_length); + + if(dim == ROCPROFILER_DIMENSION_NONE) + { + // Set all 48 bits of dimension + id = (id & ~(MAX_64 >> COUNTER_BIT_LENGTH)) | value; + bit_length = DIM_BIT_LENGTH; + } + else + { + // Reset bits to 0 for dimension. Does so by getting the bit length as F's then + // shifiting that into the position of dim. Not's that value and then and's it + // with id. + id = (id & ~(mask)); + // Set the value for the dimenstion + id = id | (value << ((dim - 1) * bit_length)); + } + + CHECK(value <= (MAX_64 >> (64 - bit_length))) << "Dimension value exceeds max allowed"; +} + +inline void +rocprofiler::counters::set_counter_in_rec(rocprofiler_counter_instance_id_t& id, + rocprofiler_counter_id_t value) +{ + // Maximum counter value given the current setup. + CHECK(value.handle <= 0xffff) << "Counter id exceeds max allowed"; + // Reset bits to 0 for counter id + id = id & ~((MAX_64 >> (64 - DIM_BIT_LENGTH)) << (DIM_BIT_LENGTH)); + // Set the value for the dimenstion + id = id | (value.handle << (DIM_BIT_LENGTH)); +} + +inline size_t +rocprofiler::counters::rec_to_dim_pos(rocprofiler_counter_instance_id_t id, + rocprofiler_profile_counter_instance_types dim) +{ + if(dim == ROCPROFILER_DIMENSION_NONE) + { + // read all 48 bits of dimension + return id & (MAX_64 >> COUNTER_BIT_LENGTH); + } + + size_t bit_length = DIM_BIT_LENGTH / ROCPROFILER_DIMENSION_LAST; + id = id & ((MAX_64 >> (64 - bit_length)) << ((dim - 1) * bit_length)); + return id >> ((dim - 1) * bit_length); +} \ No newline at end of file diff --git a/source/lib/rocprofiler/counters/metrics.cpp b/source/lib/rocprofiler/counters/metrics.cpp index d27889778f..e9d39895d3 100644 --- a/source/lib/rocprofiler/counters/metrics.cpp +++ b/source/lib/rocprofiler/counters/metrics.cpp @@ -28,10 +28,12 @@ THE SOFTWARE. #include "lib/common/utility.hpp" #include "lib/common/xml.hpp" +#include "dimensions.hpp" #include "glog/logging.h" #include // for dladdr #include +#include #include #include #include @@ -42,6 +44,7 @@ namespace counters { namespace { +// Future TODO: inheritance? does it work for derived_counters.xml? MetricMap loadXml(const std::string& filename) { @@ -72,7 +75,8 @@ loadXml(const std::string& filename) .first->second; for(const auto& node : nodes) { - metricVec.emplace_back(node->opts["name"], + metricVec.emplace_back(gfx_name, + node->opts["name"], node->opts["block"], node->opts["event"], node->opts["descr"], diff --git a/source/lib/rocprofiler/counters/metrics.hpp b/source/lib/rocprofiler/counters/metrics.hpp index 0f77c40f4d..ba08ecda42 100644 --- a/source/lib/rocprofiler/counters/metrics.hpp +++ b/source/lib/rocprofiler/counters/metrics.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -19,7 +20,8 @@ class Metric { public: Metric() = default; - Metric(std::string name, + Metric(const std::string&, // Get rid of this... + std::string name, std::string block, std::string event, std::string dsc, diff --git a/source/lib/rocprofiler/counters/parser/parser.cpp b/source/lib/rocprofiler/counters/parser/parser.cpp index f5d944be7a..6c36e1b69d 100644 --- a/source/lib/rocprofiler/counters/parser/parser.cpp +++ b/source/lib/rocprofiler/counters/parser/parser.cpp @@ -1,8 +1,8 @@ -/* A Bison parser, made by GNU Bison 3.5.1. */ +/* A Bison parser, made by GNU Bison 3.8.2. */ /* Bison implementation for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation, + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see . */ + along with this program. If not, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work @@ -34,6 +34,10 @@ /* C LALR(1) parser skeleton written by Richard Stallman, by simplifying the original so-called "semantic" parser. */ +/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual, + especially those whose name start with YY_ or yy_. They are + private implementation details that can be changed or removed. */ + /* All symbols defined below should begin with yy or YY, to avoid infringing on user name space. This should be done even for local variables, as they might otherwise be expanded by user macros. @@ -41,14 +45,11 @@ define necessary library symbols; they are noted "INFRINGES ON USER NAME SPACE" below. */ -/* Undocumented macros, especially those whose name start with YY_, - are private implementation details. Do not rely on them. */ +/* Identify Bison output, and Bison version. */ +#define YYBISON 30802 -/* Identify Bison output. */ -#define YYBISON 1 - -/* Bison version. */ -#define YYBISON_VERSION "3.5.1" +/* Bison version string. */ +#define YYBISON_VERSION "3.8.2" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -83,7 +84,7 @@ yyerror(rocprofiler::counters::RawAST**, const char* s) LOG(ERROR) << s; } -#line 84 "parser.cpp" +#line 85 "parser.cpp" #ifndef YY_CAST # ifdef __cplusplus @@ -106,86 +107,43 @@ yyerror(rocprofiler::counters::RawAST**, const char* s) # endif #endif -/* Enabling verbose error messages. */ -#ifdef YYERROR_VERBOSE -# undef YYERROR_VERBOSE -# define YYERROR_VERBOSE 1 -#else -# define YYERROR_VERBOSE 0 -#endif - -/* Use api.header.include to #include this header - instead of duplicating it here. */ -#ifndef YY_YY_ROCPROFILER_SOURCE_LIB_ROCPROFILER_COUNTERS_PARSER_PARSER_H_INCLUDED -# define YY_YY_ROCPROFILER_SOURCE_LIB_ROCPROFILER_COUNTERS_PARSER_PARSER_H_INCLUDED -/* Debug traces. */ -# ifndef YYDEBUG -# define YYDEBUG 1 -# endif -# if YYDEBUG -extern int yydebug; -# endif -/* "%code requires" blocks. */ -# line 2 "parser.y" - -# include "raw_ast.hpp" -using namespace rocprofiler::counters; -# define YYDEBUG 1 - -# line 133 "parser.cpp" - -/* Token type. */ -# ifndef YYTOKENTYPE -# define YYTOKENTYPE -enum yytokentype +#include "parser.h" +/* Symbol kind. */ +enum yysymbol_kind_t { - ADD = 258, - SUB = 259, - MUL = 260, - DIV = 261, - ABS = 262, - EQUALS = 263, - OP = 264, - CP = 265, - O_SQ = 266, - C_SQ = 267, - COLON = 268, - EOL = 269, - UMINUS = 270, - CM = 271, - NUMBER = 272, - RANGE = 273, - NAME = 274, - REDUCE = 275, - SELECT = 276, - LOWER_THAN_ELSE = 277, - ELSE = 278 + YYSYMBOL_YYEMPTY = -2, + YYSYMBOL_YYEOF = 0, /* "end of file" */ + YYSYMBOL_YYerror = 1, /* error */ + YYSYMBOL_YYUNDEF = 2, /* "invalid token" */ + YYSYMBOL_ADD = 3, /* ADD */ + YYSYMBOL_SUB = 4, /* SUB */ + YYSYMBOL_MUL = 5, /* MUL */ + YYSYMBOL_DIV = 6, /* DIV */ + YYSYMBOL_ABS = 7, /* ABS */ + YYSYMBOL_EQUALS = 8, /* EQUALS */ + YYSYMBOL_OP = 9, /* OP */ + YYSYMBOL_CP = 10, /* CP */ + YYSYMBOL_O_SQ = 11, /* O_SQ */ + YYSYMBOL_C_SQ = 12, /* C_SQ */ + YYSYMBOL_COLON = 13, /* COLON */ + YYSYMBOL_EOL = 14, /* EOL */ + YYSYMBOL_15_ = 15, /* '|' */ + YYSYMBOL_UMINUS = 16, /* UMINUS */ + YYSYMBOL_CM = 17, /* CM */ + YYSYMBOL_NUMBER = 18, /* NUMBER */ + YYSYMBOL_RANGE = 19, /* RANGE */ + YYSYMBOL_NAME = 20, /* NAME */ + YYSYMBOL_REDUCE = 21, /* REDUCE */ + YYSYMBOL_SELECT = 22, /* SELECT */ + YYSYMBOL_LOWER_THAN_ELSE = 23, /* LOWER_THAN_ELSE */ + YYSYMBOL_ELSE = 24, /* ELSE */ + YYSYMBOL_YYACCEPT = 25, /* $accept */ + YYSYMBOL_top = 26, /* top */ + YYSYMBOL_exp = 27, /* exp */ + YYSYMBOL_reduce_dim_args = 28, /* reduce_dim_args */ + YYSYMBOL_select_dim_args = 29 /* select_dim_args */ }; -# endif - -/* Value type. */ -# if !defined YYSTYPE && !defined YYSTYPE_IS_DECLARED -union YYSTYPE -{ -# line 34 "parser.y" - - RawAST* a; /* For ast node */ - int64_t d; - char* s; - -# line 174 "parser.cpp" -}; -typedef union YYSTYPE YYSTYPE; -# define YYSTYPE_IS_TRIVIAL 1 -# define YYSTYPE_IS_DECLARED 1 -# endif - -extern YYSTYPE yylval; - -int -yyparse(RawAST** result); - -#endif /* !YY_YY_ROCPROFILER_SOURCE_LIB_ROCPROFILER_COUNTERS_PARSER_PARSER_H_INCLUDED */ +typedef enum yysymbol_kind_t yysymbol_kind_t; #ifdef short # undef short @@ -224,6 +182,18 @@ typedef int_least16_t yytype_int16; typedef short yytype_int16; #endif +/* Work around bug in HP-UX 11.23, which defines these macros + incorrectly for preprocessor constants. This workaround can likely + be removed in 2023, as HPE has promised support for HP-UX 11.23 + (aka HP-UX 11i v2) only through the end of 2022; see Table 2 of + . */ +#ifdef __hpux +# undef UINT_LEAST8_MAX +# undef UINT_LEAST16_MAX +# define UINT_LEAST8_MAX 255 +# define UINT_LEAST16_MAX 65535 +#endif + #if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__ typedef __UINT_LEAST8_TYPE__ yytype_uint8; #elif(!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H && UINT_LEAST8_MAX <= INT_MAX) @@ -316,16 +286,21 @@ typedef int yy_state_fast_t; /* Suppress unused-variable warnings by "using" E. */ #if !defined lint || defined __GNUC__ -# define YYUSE(E) ((void) (E)) +# define YY_USE(E) ((void) (E)) #else -# define YYUSE(E) /* empty */ +# define YY_USE(E) /* empty */ #endif -#if defined __GNUC__ && !defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ /* Suppress an incorrect diagnostic about yylval being uninitialized. */ -# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ - _Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignored \"-Wuninitialized\"") \ - _Pragma("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +#if defined __GNUC__ && !defined __ICC && 406 <= __GNUC__ * 100 + __GNUC_MINOR__ +# if __GNUC__ * 100 + __GNUC_MINOR__ < 407 +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignored \"-Wuninitialized\"") +# else +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignored \"-Wuninitialized\"") \ + _Pragma("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +# endif # define YY_IGNORE_MAYBE_UNINITIALIZED_END _Pragma("GCC diagnostic pop") #else # define YY_INITIAL_VALUE(Value) Value @@ -350,7 +325,7 @@ typedef int yy_state_fast_t; #define YY_ASSERT(E) ((void) (0 && (E))) -#if !defined yyoverflow || YYERROR_VERBOSE +#if !defined yyoverflow /* The parser invokes alloca or malloc; define the necessary symbols. */ @@ -419,7 +394,7 @@ free(void*); /* INFRINGES ON USER NAME SPACE */ # endif # endif # endif -#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ +#endif /* !defined yyoverflow */ #if(!defined yyoverflow && \ (!defined __cplusplus || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) @@ -478,25 +453,27 @@ union yyalloc #endif /* !YYCOPY_NEEDED */ /* YYFINAL -- State number of the termination state. */ -#define YYFINAL 14 +#define YYFINAL 11 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 84 +#define YYLAST 54 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 25 /* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 3 +#define YYNNTS 5 /* YYNRULES -- Number of rules. */ #define YYNRULES 16 /* YYNSTATES -- Number of states. */ #define YYNSTATES 44 -#define YYUNDEFTOK 2 -#define YYMAXUTOK 278 +/* YYMAXUTOK -- Last valid token kind. */ +#define YYMAXUTOK 278 /* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM as returned by yylex, with out-of-bounds checking. */ -#define YYTRANSLATE(YYX) (0 <= (YYX) && (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) +#define YYTRANSLATE(YYX) \ + (0 <= (YYX) && (YYX) <= YYMAXUTOK ? YY_CAST(yysymbol_kind_t, yytranslate[YYX]) \ + : YYSYMBOL_YYUNDEF) /* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM as returned by yylex. */ @@ -516,28 +493,60 @@ static const yytype_int8 yytranslate[] = { #if YYDEBUG /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_int8 yyrline[] = - {0, 55, 55, 66, 67, 68, 69, 70, 71, 72, 73, 76, 79, 82, 85, 88, 91}; + {0, 57, 57, 60, 61, 62, 63, 64, 65, 66, 69, 73, 77, 84, 87, 94, 97}; #endif -#if YYDEBUG || YYERROR_VERBOSE || 0 +/** Accessing symbol of state STATE. */ +#define YY_ACCESSING_SYMBOL(State) YY_CAST(yysymbol_kind_t, yystos[State]) + +#if YYDEBUG || 0 +/* The user-facing name of the symbol whose (internal) number is + YYSYMBOL. No bounds checking. */ +static const char* +yysymbol_name(yysymbol_kind_t yysymbol) YY_ATTRIBUTE_UNUSED; + /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at YYNTOKENS, nonterminals. */ -static const char* const yytname[] = { - "$end", "error", "$undefined", "ADD", "SUB", "MUL", "DIV", "ABS", - "EQUALS", "OP", "CP", "O_SQ", "C_SQ", "COLON", "EOL", "'|'", - "UMINUS", "CM", "NUMBER", "RANGE", "NAME", "REDUCE", "SELECT", "LOWER_THAN_ELSE", - "ELSE", "$accept", "top", "exp", YY_NULLPTR}; +static const char* const yytname[] = {"\"end of file\"", + "error", + "\"invalid token\"", + "ADD", + "SUB", + "MUL", + "DIV", + "ABS", + "EQUALS", + "OP", + "CP", + "O_SQ", + "C_SQ", + "COLON", + "EOL", + "'|'", + "UMINUS", + "CM", + "NUMBER", + "RANGE", + "NAME", + "REDUCE", + "SELECT", + "LOWER_THAN_ELSE", + "ELSE", + "$accept", + "top", + "exp", + "reduce_dim_args", + "select_dim_args", + YY_NULLPTR}; + +static const char* +yysymbol_name(yysymbol_kind_t yysymbol) +{ + return yytname[yysymbol]; +} #endif -#ifdef YYPRINT -/* YYTOKNUM[NUM] -- (External) token number corresponding to the - (internal) symbol number NUM (which must be that of a token). */ -static const yytype_int16 yytoknum[] = {0, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, 268, 269, 124, 270, 271, - 272, 273, 274, 275, 276, 277, 278}; -#endif - -#define YYPACT_NINF (-9) +#define YYPACT_NINF (-3) #define yypact_value_is_default(Yyn) ((Yyn) == YYPACT_NINF) @@ -547,59 +556,61 @@ static const yytype_int16 yytoknum[] = {0, 256, 257, 258, 259, 260, 261, 262, /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ -static const yytype_int8 yypact[] = {24, 24, 24, -9, -5, 4, 28, 8, 21, 58, 44, 24, 24, 24, -9, - 24, 24, 24, 24, -9, 24, 1, 17, 26, 34, 34, -9, -9, 48, 24, - 35, 36, -9, -9, -8, 49, -9, 24, -9, 24, 66, 74, -9, -9}; +static const yytype_int8 yypact[] = {11, 11, -3, -3, 1, 16, 7, 32, 18, 11, 11, -3, 11, 11, 11, + 11, -3, -2, 13, 0, 0, -3, -3, 6, 28, 17, 20, -3, 30, 34, + 31, 24, 27, 36, 33, 35, 37, -3, 24, 38, 20, -3, -3, -3}; /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. Performed when YYTABLE does not specify something else to do. Zero means the default is an error. */ -static const yytype_int8 yydefact[] = {0, 0, 0, 3, 10, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, - 0, 0, 0, 0, 8, 0, 11, 0, 0, 4, 5, 6, 7, 0, 0, - 0, 0, 9, 12, 0, 0, 13, 0, 15, 0, 0, 0, 14, 16}; +static const yytype_int8 yydefact[] = {0, 0, 3, 9, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, + 0, 8, 0, 0, 4, 5, 6, 7, 0, 0, 0, 0, 10, 0, 0, + 0, 0, 0, 0, 13, 0, 15, 12, 0, 0, 0, 14, 11, 16}; /* YYPGOTO[NTERM-NUM]. */ -static const yytype_int8 yypgoto[] = {-9, -9, -1}; +static const yytype_int8 yypgoto[] = {-3, -3, -1, 14, 9}; /* YYDEFGOTO[NTERM-NUM]. */ -static const yytype_int8 yydefgoto[] = {-1, 7, 8}; +static const yytype_int8 yydefgoto[] = {0, 6, 7, 35, 30}; /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule whose number is the opposite. If YYTABLE_NINF, syntax error. */ -static const yytype_int8 yytable[] = { - 9, 10, 36, 11, 15, 16, 17, 18, 14, 37, 21, 22, 23, 12, 24, 25, 26, 27, 29, 28, 15, 16, - 17, 18, 15, 16, 17, 18, 33, 15, 16, 17, 18, 1, 30, 2, 40, 13, 41, 17, 18, 0, 3, 31, - 4, 5, 6, 15, 16, 17, 18, 15, 16, 17, 18, 34, 35, 20, 0, 38, 32, 15, 16, 17, 18, 0, - 39, 0, 19, 15, 16, 17, 18, 0, 0, 0, 42, 15, 16, 17, 18, 0, 0, 0, 43}; +static const yytype_int8 yytable[] = {8, 12, 13, 14, 15, 14, 15, 11, 17, 18, 9, 19, 20, 21, + 22, 23, 12, 13, 14, 15, 1, 12, 13, 14, 15, 10, 25, 27, + 16, 2, 24, 3, 4, 5, 28, 12, 13, 14, 15, 26, 29, 31, + 32, 33, 34, 36, 37, 39, 42, 43, 38, 0, 41, 0, 40}; -static const yytype_int8 yycheck[] = { - 1, 2, 10, 8, 3, 4, 5, 6, 0, 17, 11, 12, 13, 9, 15, 16, 17, 18, 17, 20, 3, 4, - 5, 6, 3, 4, 5, 6, 29, 3, 4, 5, 6, 9, 17, 11, 37, 9, 39, 5, 6, -1, 18, 17, - 20, 21, 22, 3, 4, 5, 6, 3, 4, 5, 6, 20, 20, 13, -1, 10, 12, 3, 4, 5, 6, -1, - 17, -1, 10, 3, 4, 5, 6, -1, -1, -1, 10, 3, 4, 5, 6, -1, -1, -1, 10}; +static const yytype_int8 yycheck[] = {1, 3, 4, 5, 6, 5, 6, 0, 9, 10, 9, 12, 13, 14, + 15, 17, 3, 4, 5, 6, 9, 3, 4, 5, 6, 9, 20, 10, + 10, 18, 17, 20, 21, 22, 17, 3, 4, 5, 6, 11, 20, 11, + 8, 12, 20, 18, 10, 12, 10, 40, 17, -1, 38, -1, 17}; -/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing - symbol of state STATE-NUM. */ -static const yytype_int8 yystos[] = {0, 9, 11, 18, 20, 21, 22, 26, 27, 27, 27, 8, 9, 9, 0, - 3, 4, 5, 6, 10, 13, 27, 27, 27, 27, 27, 27, 27, 27, 17, - 17, 17, 12, 27, 20, 20, 10, 17, 10, 17, 27, 27, 10, 10}; +/* YYSTOS[STATE-NUM] -- The symbol kind of the accessing symbol of + state STATE-NUM. */ +static const yytype_int8 yystos[] = {0, 9, 18, 20, 21, 22, 26, 27, 27, 9, 9, 0, 3, 4, 5, + 6, 10, 27, 27, 27, 27, 27, 27, 17, 17, 20, 11, 10, 17, 20, + 29, 11, 8, 12, 20, 28, 18, 10, 17, 12, 17, 28, 10, 29}; -/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +/* YYR1[RULE-NUM] -- Symbol kind of the left-hand side of rule RULE-NUM. */ static const yytype_int8 yyr1[] = - {0, 25, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27}; + {0, 25, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 29, 29}; -/* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ -static const yytype_int8 yyr2[] = {0, 2, 1, 1, 3, 3, 3, 3, 3, 5, 1, 3, 5, 6, 8, 6, 8}; +/* YYR2[RULE-NUM] -- Number of symbols on the right-hand side of rule RULE-NUM. */ +static const yytype_int8 yyr2[] = {0, 2, 1, 1, 3, 3, 3, 3, 3, 1, 6, 10, 8, 1, 3, 3, 5}; + +enum +{ + YYENOMEM = -2 +}; #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) -#define YYEMPTY (-2) -#define YYEOF 0 #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab #define YYERROR goto yyerrorlab +#define YYNOMEM goto yyexhaustedlab #define YYRECOVERING() (!!yyerrstatus) @@ -620,9 +631,9 @@ static const yytype_int8 yyr2[] = {0, 2, 1, 1, 3, 3, 3, 3, 3, 5, 1, 3, 5, 6, 8, } \ while(0) -/* Error token number */ -#define YYTERROR 1 -#define YYERRCODE 256 +/* Backward compatibility with an undocumented macro. + Use YYerror or YYUNDEF. */ +#define YYERRCODE YYUNDEF /* Enable debugging if requested. */ #if YYDEBUG @@ -638,18 +649,13 @@ static const yytype_int8 yyr2[] = {0, 2, 1, 1, 3, 3, 3, 3, 3, 5, 1, 3, 5, 6, 8, if(yydebug) YYFPRINTF Args; \ } while(0) -/* This macro is provided for backward compatibility. */ -# ifndef YY_LOCATION_PRINT -# define YY_LOCATION_PRINT(File, Loc) ((void) 0) -# endif - -# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) \ do \ { \ if(yydebug) \ { \ YYFPRINTF(stderr, "%s ", Title); \ - yy_symbol_print(stderr, Type, Value, result); \ + yy_symbol_print(stderr, Kind, Value, result); \ YYFPRINTF(stderr, "\n"); \ } \ } while(0) @@ -659,17 +665,17 @@ static const yytype_int8 yyr2[] = {0, 2, 1, 1, 3, 3, 3, 3, 3, 5, 1, 3, 5, 6, 8, `-----------------------------------*/ static void -yy_symbol_value_print(FILE* yyo, int yytype, YYSTYPE const* const yyvaluep, RawAST** result) +yy_symbol_value_print(FILE* yyo, + yysymbol_kind_t yykind, + YYSTYPE const* const yyvaluep, + RawAST** result) { FILE* yyoutput = yyo; - YYUSE(yyoutput); - YYUSE(result); + YY_USE(yyoutput); + YY_USE(result); if(!yyvaluep) return; -# ifdef YYPRINT - if(yytype < YYNTOKENS) YYPRINT(yyo, yytoknum[yytype], *yyvaluep); -# endif YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - YYUSE(yytype); + YY_USE(yykind); YY_IGNORE_MAYBE_UNINITIALIZED_END } @@ -678,11 +684,11 @@ yy_symbol_value_print(FILE* yyo, int yytype, YYSTYPE const* const yyvaluep, RawA `---------------------------*/ static void -yy_symbol_print(FILE* yyo, int yytype, YYSTYPE const* const yyvaluep, RawAST** result) +yy_symbol_print(FILE* yyo, yysymbol_kind_t yykind, YYSTYPE const* const yyvaluep, RawAST** result) { - YYFPRINTF(yyo, "%s %s (", yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]); + YYFPRINTF(yyo, "%s %s (", yykind < YYNTOKENS ? "token" : "nterm", yysymbol_name(yykind)); - yy_symbol_value_print(yyo, yytype, yyvaluep, result); + yy_symbol_value_print(yyo, yykind, yyvaluep, result); YYFPRINTF(yyo, ")"); } @@ -724,8 +730,10 @@ yy_reduce_print(yy_state_t* yyssp, YYSTYPE* yyvsp, int yyrule, RawAST** result) for(yyi = 0; yyi < yynrhs; yyi++) { YYFPRINTF(stderr, " $%d = ", yyi + 1); - yy_symbol_print( - stderr, yystos[+yyssp[yyi + 1 - yynrhs]], &yyvsp[(yyi + 1) - (yynrhs)], result); + yy_symbol_print(stderr, + YY_ACCESSING_SYMBOL(+yyssp[yyi + 1 - yynrhs]), + &yyvsp[(yyi + 1) - (yynrhs)], + result); YYFPRINTF(stderr, "\n"); } } @@ -740,8 +748,8 @@ yy_reduce_print(yy_state_t* yyssp, YYSTYPE* yyvsp, int yyrule, RawAST** result) multiple parsers can coexist. */ int yydebug; #else /* !YYDEBUG */ -# define YYDPRINTF(Args) -# define YY_SYMBOL_PRINT(Title, Type, Value, Location) +# define YYDPRINTF(Args) ((void) 0) +# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) # define YY_STACK_PRINT(Bottom, Top) # define YY_REDUCE_PRINT(Rule) #endif /* !YYDEBUG */ @@ -762,251 +770,24 @@ int yydebug; # define YYMAXDEPTH 10000 #endif -#if YYERROR_VERBOSE - -# ifndef yystrlen -# if defined __GLIBC__ && defined _STRING_H -# define yystrlen(S) (YY_CAST(YYPTRDIFF_T, strlen(S))) -# else -/* Return the length of YYSTR. */ -static YYPTRDIFF_T -yystrlen(const char* yystr) -{ - YYPTRDIFF_T yylen; - for(yylen = 0; yystr[yylen]; yylen++) - continue; - return yylen; -} -# endif -# endif - -# ifndef yystpcpy -# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE -# define yystpcpy stpcpy -# else -/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in - YYDEST. */ -static char* -yystpcpy(char* yydest, const char* yysrc) -{ - char* yyd = yydest; - const char* yys = yysrc; - - while((*yyd++ = *yys++) != '\0') - continue; - - return yyd - 1; -} -# endif -# endif - -# ifndef yytnamerr -/* Copy to YYRES the contents of YYSTR after stripping away unnecessary - quotes and backslashes, so that it's suitable for yyerror. The - heuristic is that double-quoting is unnecessary unless the string - contains an apostrophe, a comma, or backslash (other than - backslash-backslash). YYSTR is taken from yytname. If YYRES is - null, do not copy; instead, return the length of what the result - would have been. */ -static YYPTRDIFF_T -yytnamerr(char* yyres, const char* yystr) -{ - if(*yystr == '"') - { - YYPTRDIFF_T yyn = 0; - char const* yyp = yystr; - - for(;;) - switch(*++yyp) - { - case '\'': - case ',': goto do_not_strip_quotes; - - case '\\': - if(*++yyp != '\\') - goto do_not_strip_quotes; - else - goto append; - - append: - default: - if(yyres) yyres[yyn] = *yyp; - yyn++; - break; - - case '"': - if(yyres) yyres[yyn] = '\0'; - return yyn; - } - do_not_strip_quotes:; - } - - if(yyres) - return yystpcpy(yyres, yystr) - yyres; - else - return yystrlen(yystr); -} -# endif - -/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message - about the unexpected token YYTOKEN for the state stack whose top is - YYSSP. - - Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is - not large enough to hold the message. In that case, also set - *YYMSG_ALLOC to the required number of bytes. Return 2 if the - required number of bytes is too large to store. */ -static int -yysyntax_error(YYPTRDIFF_T* yymsg_alloc, char** yymsg, yy_state_t* yyssp, int yytoken) -{ - enum - { - YYERROR_VERBOSE_ARGS_MAXIMUM = 5 - }; - /* Internationalized format string. */ - const char* yyformat = YY_NULLPTR; - /* Arguments of yyformat: reported tokens (one for the "unexpected", - one per "expected"). */ - char const* yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; - /* Actual size of YYARG. */ - int yycount = 0; - /* Cumulated lengths of YYARG. */ - YYPTRDIFF_T yysize = 0; - - /* There are many possibilities here to consider: - - If this state is a consistent state with a default action, then - the only way this function was invoked is if the default action - is an error action. In that case, don't check for expected - tokens because there are none. - - The only way there can be no lookahead present (in yychar) is if - this state is a consistent state with a default action. Thus, - detecting the absence of a lookahead is sufficient to determine - that there is no unexpected or expected token to report. In that - case, just report a simple "syntax error". - - Don't assume there isn't a lookahead just because this state is a - consistent state with a default action. There might have been a - previous inconsistent state, consistent state with a non-default - action, or user semantic action that manipulated yychar. - - Of course, the expected token list depends on states to have - correct lookahead information, and it depends on the parser not - to perform extra reductions after fetching a lookahead from the - scanner and before detecting a syntax error. Thus, state merging - (from LALR or IELR) and default reductions corrupt the expected - token list. However, the list is correct for canonical LR with - one exception: it will still contain any token that will not be - accepted due to an error action in a later state. - */ - if(yytoken != YYEMPTY) - { - int yyn = yypact[+*yyssp]; - YYPTRDIFF_T yysize0 = yytnamerr(YY_NULLPTR, yytname[yytoken]); - yysize = yysize0; - yyarg[yycount++] = yytname[yytoken]; - if(!yypact_value_is_default(yyn)) - { - /* Start YYX at -YYN if negative to avoid negative indexes in - YYCHECK. In other words, skip the first -YYN actions for - this state because they are default actions. */ - int yyxbegin = yyn < 0 ? -yyn : 0; - /* Stay within bounds of both yycheck and yytname. */ - int yychecklim = YYLAST - yyn + 1; - int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; - int yyx; - - for(yyx = yyxbegin; yyx < yyxend; ++yyx) - if(yycheck[yyx + yyn] == yyx && yyx != YYTERROR && - !yytable_value_is_error(yytable[yyx + yyn])) - { - if(yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) - { - yycount = 1; - yysize = yysize0; - break; - } - yyarg[yycount++] = yytname[yyx]; - { - YYPTRDIFF_T yysize1 = yysize + yytnamerr(YY_NULLPTR, yytname[yyx]); - if(yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM) - yysize = yysize1; - else - return 2; - } - } - } - } - - switch(yycount) - { -# define YYCASE_(N, S) \ - case N: yyformat = S; break - default: /* Avoid compiler warnings. */ - YYCASE_(0, YY_("syntax error")); - YYCASE_(1, YY_("syntax error, unexpected %s")); - YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); - YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); - YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); - YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); -# undef YYCASE_ - } - - { - /* Don't count the "%s"s in the final size, but reserve room for - the terminator. */ - YYPTRDIFF_T yysize1 = yysize + (yystrlen(yyformat) - 2 * yycount) + 1; - if(yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM) - yysize = yysize1; - else - return 2; - } - - if(*yymsg_alloc < yysize) - { - *yymsg_alloc = 2 * yysize; - if(!(yysize <= *yymsg_alloc && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) - *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; - return 1; - } - - /* Avoid sprintf, as that infringes on the user's name space. - Don't have undefined behavior even if the translation - produced a string with the wrong number of "%s"s. */ - { - char* yyp = *yymsg; - int yyi = 0; - while((*yyp = *yyformat) != '\0') - if(*yyp == '%' && yyformat[1] == 's' && yyi < yycount) - { - yyp += yytnamerr(yyp, yyarg[yyi++]); - yyformat += 2; - } - else - { - ++yyp; - ++yyformat; - } - } - return 0; -} -#endif /* YYERROR_VERBOSE */ - /*-----------------------------------------------. | Release the memory associated to this symbol. | `-----------------------------------------------*/ static void -yydestruct(const char* yymsg, int yytype, YYSTYPE* yyvaluep, RawAST** result) +yydestruct(const char* yymsg, yysymbol_kind_t yykind, YYSTYPE* yyvaluep, RawAST** result) { - YYUSE(yyvaluep); - YYUSE(result); + YY_USE(yyvaluep); + YY_USE(result); if(!yymsg) yymsg = "Deleting"; - YY_SYMBOL_PRINT(yymsg, yytype, yyvaluep, yylocationp); + YY_SYMBOL_PRINT(yymsg, yykind, yyvaluep, yylocationp); YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - YYUSE(yytype); + YY_USE(yykind); YY_IGNORE_MAYBE_UNINITIALIZED_END } -/* The lookahead symbol. */ +/* Lookahead token kind. */ int yychar; /* The semantic value of the lookahead symbol. */ @@ -1021,60 +802,45 @@ int yynerrs; int yyparse(RawAST** result) { - yy_state_fast_t yystate; + yy_state_fast_t yystate = 0; /* Number of tokens to shift before error messages enabled. */ - int yyerrstatus; + int yyerrstatus = 0; - /* The stacks and their tools: - 'yyss': related to states. - 'yyvs': related to semantic values. - - Refer to the stacks through separate pointers, to allow yyoverflow + /* Refer to the stacks through separate pointers, to allow yyoverflow to reallocate them elsewhere. */ - /* The state stack. */ + /* Their size. */ + YYPTRDIFF_T yystacksize = YYINITDEPTH; + + /* The state stack: array, bottom, top. */ yy_state_t yyssa[YYINITDEPTH]; - yy_state_t* yyss; - yy_state_t* yyssp; + yy_state_t* yyss = yyssa; + yy_state_t* yyssp = yyss; - /* The semantic value stack. */ + /* The semantic value stack: array, bottom, top. */ YYSTYPE yyvsa[YYINITDEPTH]; - YYSTYPE* yyvs; - YYSTYPE* yyvsp; - - YYPTRDIFF_T yystacksize; + YYSTYPE* yyvs = yyvsa; + YYSTYPE* yyvsp = yyvs; int yyn; + /* The return value of yyparse. */ int yyresult; - /* Lookahead token as an internal (translated) token number. */ - int yytoken = 0; + /* Lookahead symbol kind. */ + yysymbol_kind_t yytoken = YYSYMBOL_YYEMPTY; /* The variables used to return semantic value and location from the action routines. */ YYSTYPE yyval; -#if YYERROR_VERBOSE - /* Buffer for error messages, and its allocated size. */ - char yymsgbuf[128]; - char* yymsg = yymsgbuf; - YYPTRDIFF_T yymsg_alloc = sizeof yymsgbuf; -#endif - #define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) /* The number of symbols on the RHS of the reduced rule. Keep to zero when no symbol should be popped. */ int yylen = 0; - yyssp = yyss = yyssa; - yyvsp = yyvs = yyvsa; - yystacksize = YYINITDEPTH; - YYDPRINTF((stderr, "Starting parse\n")); - yystate = 0; - yyerrstatus = 0; - yynerrs = 0; - yychar = YYEMPTY; /* Cause a token to be read. */ + yychar = YYEMPTY; /* Cause a token to be read. */ + goto yysetstate; /*------------------------------------------------------------. @@ -1094,10 +860,11 @@ yysetstate: YY_IGNORE_USELESS_CAST_BEGIN *yyssp = YY_CAST(yy_state_t, yystate); YY_IGNORE_USELESS_CAST_END + YY_STACK_PRINT(yyss, yyssp); if(yyss + yystacksize - 1 <= yyssp) #if !defined yyoverflow && !defined YYSTACK_RELOCATE - goto yyexhaustedlab; + YYNOMEM; #else { /* Get the current used size of the three stacks, in elements. */ @@ -1126,7 +893,7 @@ yysetstate: } # else /* defined YYSTACK_RELOCATE */ /* Extend the stack our own way. */ - if(YYMAXDEPTH <= yystacksize) goto yyexhaustedlab; + if(YYMAXDEPTH <= yystacksize) YYNOMEM; yystacksize *= 2; if(YYMAXDEPTH < yystacksize) yystacksize = YYMAXDEPTH; @@ -1134,7 +901,7 @@ yysetstate: yy_state_t* yyss1 = yyss; union yyalloc* yyptr = YY_CAST( union yyalloc*, YYSTACK_ALLOC(YY_CAST(YYSIZE_T, YYSTACK_BYTES(yystacksize)))); - if(!yyptr) goto yyexhaustedlab; + if(!yyptr) YYNOMEM; YYSTACK_RELOCATE(yyss_alloc, yyss); YYSTACK_RELOCATE(yyvs_alloc, yyvs); # undef YYSTACK_RELOCATE @@ -1170,18 +937,29 @@ yybackup: /* Not known => get a lookahead token if don't already have one. */ - /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ + /* YYCHAR is either empty, or end-of-input, or a valid lookahead. */ if(yychar == YYEMPTY) { - YYDPRINTF((stderr, "Reading a token: ")); + YYDPRINTF((stderr, "Reading a token\n")); yychar = yylex(); } if(yychar <= YYEOF) { - yychar = yytoken = YYEOF; + yychar = YYEOF; + yytoken = YYSYMBOL_YYEOF; YYDPRINTF((stderr, "Now at end of input.\n")); } + else if(yychar == YYerror) + { + /* The scanner already issued an error message, process directly + to error recovery. But do not keep the error token as + lookahead, it is too special and may lead us to an endless + loop in error recovery. */ + yychar = YYUNDEF; + yytoken = YYSYMBOL_YYerror; + goto yyerrlab1; + } else { yytoken = YYTRANSLATE(yychar); @@ -1243,134 +1021,134 @@ yyreduce: YY_REDUCE_PRINT(yyn); switch(yyn) { - case 2: -#line 55 "parser.y" + case 2: /* top: exp */ +#line 57 "parser.y" { *result = (yyvsp[0].a); } -#line 1375 "parser.cpp" +#line 1119 "parser.cpp" break; - case 3: -#line 66 "parser.y" + case 3: /* exp: NUMBER */ +#line 60 "parser.y" { (yyval.a) = new RawAST(NUMBER_NODE, (yyvsp[0].d)); } -#line 1381 "parser.cpp" +#line 1125 "parser.cpp" break; - case 4: -#line 67 "parser.y" + case 4: /* exp: exp ADD exp */ +#line 61 "parser.y" { (yyval.a) = new RawAST(ADDITION_NODE, {(yyvsp[-2].a), (yyvsp[0].a)}); } -#line 1387 "parser.cpp" +#line 1131 "parser.cpp" break; - case 5: -#line 68 "parser.y" + case 5: /* exp: exp SUB exp */ +#line 62 "parser.y" { (yyval.a) = new RawAST(SUBTRACTION_NODE, {(yyvsp[-2].a), (yyvsp[0].a)}); } -#line 1393 "parser.cpp" +#line 1137 "parser.cpp" break; - case 6: -#line 69 "parser.y" + case 6: /* exp: exp MUL exp */ +#line 63 "parser.y" { (yyval.a) = new RawAST(MULTIPLY_NODE, {(yyvsp[-2].a), (yyvsp[0].a)}); } -#line 1399 "parser.cpp" +#line 1143 "parser.cpp" break; - case 7: -#line 70 "parser.y" + case 7: /* exp: exp DIV exp */ +#line 64 "parser.y" { (yyval.a) = new RawAST(DIVIDE_NODE, {(yyvsp[-2].a), (yyvsp[0].a)}); } -#line 1405 "parser.cpp" +#line 1149 "parser.cpp" break; - case 8: -#line 71 "parser.y" + case 8: /* exp: OP exp CP */ +#line 65 "parser.y" { (yyval.a) = (yyvsp[-1].a); } -#line 1411 "parser.cpp" +#line 1155 "parser.cpp" break; - case 9: -#line 72 "parser.y" - { - (yyval.a) = new RawAST(RANGE_NODE, {(yyvsp[-3].a), (yyvsp[-1].a)}); - } -#line 1417 "parser.cpp" - break; - - case 10: -#line 73 "parser.y" + case 9: /* exp: NAME */ +#line 66 "parser.y" { (yyval.a) = new RawAST(REFERENCE_NODE, (yyvsp[0].s)); free((yyvsp[0].s)); } -#line 1425 "parser.cpp" +#line 1163 "parser.cpp" break; - case 11: -#line 76 "parser.y" + case 10: /* exp: REDUCE OP exp CM NAME CP */ +#line 69 "parser.y" { - (yyval.a) = new RawAST(REFERENCE_SET, (yyvsp[-2].s), (yyvsp[0].a)); + (yyval.a) = new RawAST(REDUCE_NODE, (yyvsp[-3].a), (yyvsp[-1].s), NULL); + free((yyvsp[-1].s)); + } +#line 1172 "parser.cpp" + break; + + case 11: /* exp: REDUCE OP exp CM NAME CM O_SQ reduce_dim_args C_SQ CP */ +#line 73 "parser.y" + { + (yyval.a) = new RawAST(REDUCE_NODE, (yyvsp[-7].a), (yyvsp[-5].s), (yyvsp[-2].ll)); + free((yyvsp[-5].s)); + } +#line 1181 "parser.cpp" + break; + + case 12: /* exp: SELECT OP exp CM O_SQ select_dim_args C_SQ CP */ +#line 77 "parser.y" + { + (yyval.a) = new RawAST(SELECT_NODE, (yyvsp[-5].a), (yyvsp[-2].ll)); + } +#line 1189 "parser.cpp" + break; + + case 13: /* reduce_dim_args: NAME */ +#line 84 "parser.y" + { + (yyval.ll) = new LinkedList((yyvsp[0].s), NULL); + free((yyvsp[0].s)); + } +#line 1197 "parser.cpp" + break; + + case 14: /* reduce_dim_args: NAME CM reduce_dim_args */ +#line 87 "parser.y" + { + (yyval.ll) = new LinkedList((yyvsp[-2].s), (yyvsp[0].ll)); free((yyvsp[-2].s)); } -#line 1433 "parser.cpp" +#line 1205 "parser.cpp" break; - case 12: -#line 79 "parser.y" + case 15: /* select_dim_args: NAME EQUALS NUMBER */ +#line 94 "parser.y" { - (yyval.a) = new RawAST(REFERENCE_SET, (yyvsp[-4].s), (yyvsp[-2].a), (yyvsp[0].a)); + (yyval.ll) = new LinkedList((yyvsp[-2].s), (yyvsp[0].d), NULL); + free((yyvsp[-2].s)); + } +#line 1213 "parser.cpp" + break; + + case 16: /* select_dim_args: NAME EQUALS NUMBER CM select_dim_args */ +#line 97 "parser.y" + { + (yyval.ll) = new LinkedList((yyvsp[-4].s), (yyvsp[-2].d), (yyvsp[0].ll)); free((yyvsp[-4].s)); } -#line 1441 "parser.cpp" +#line 1221 "parser.cpp" break; - case 13: -#line 82 "parser.y" - { - (yyval.a) = new RawAST(REDUCE_NODE, (yyvsp[-3].a), (yyvsp[-1].s)); - free((yyvsp[-1].s)); - } -#line 1449 "parser.cpp" - break; - - case 14: -#line 85 "parser.y" - { - (yyval.a) = new RawAST(REDUCE_NODE, (yyvsp[-5].a), (yyvsp[-3].s), (yyvsp[-1].a)); - free((yyvsp[-3].s)); - } -#line 1457 "parser.cpp" - break; - - case 15: -#line 88 "parser.y" - { - (yyval.a) = new RawAST(SELECT_NODE, (yyvsp[-3].a), (yyvsp[-1].s)); - free((yyvsp[-1].s)); - } -#line 1465 "parser.cpp" - break; - - case 16: -#line 91 "parser.y" - { - (yyval.a) = new RawAST(SELECT_NODE, (yyvsp[-5].a), (yyvsp[-3].s), (yyvsp[-1].a)); - free((yyvsp[-3].s)); - } -#line 1473 "parser.cpp" - break; - -#line 1477 "parser.cpp" +#line 1225 "parser.cpp" default: break; } @@ -1385,11 +1163,10 @@ yyreduce: case of YYERROR or YYBACKUP, subsequent parser actions might lead to an incorrect destructor call or verbose syntax error message before the lookahead is translated. */ - YY_SYMBOL_PRINT("-> $$ =", yyr1[yyn], &yyval, &yyloc); + YY_SYMBOL_PRINT("-> $$ =", YY_CAST(yysymbol_kind_t, yyr1[yyn]), &yyval, &yyloc); YYPOPSTACK(yylen); yylen = 0; - YY_STACK_PRINT(yyss, yyssp); *++yyvsp = yyval; @@ -1411,43 +1188,12 @@ yyreduce: yyerrlab: /* Make sure we have latest lookahead translation. See comments at user semantic actions for why this is necessary. */ - yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE(yychar); - + yytoken = yychar == YYEMPTY ? YYSYMBOL_YYEMPTY : YYTRANSLATE(yychar); /* If not already recovering from an error, report this error. */ if(!yyerrstatus) { ++yynerrs; -#if !YYERROR_VERBOSE yyerror(result, YY_("syntax error")); -#else -# define YYSYNTAX_ERROR yysyntax_error(&yymsg_alloc, &yymsg, yyssp, yytoken) - { - char const* yymsgp = YY_("syntax error"); - int yysyntax_error_status; - yysyntax_error_status = YYSYNTAX_ERROR; - if(yysyntax_error_status == 0) - yymsgp = yymsg; - else if(yysyntax_error_status == 1) - { - if(yymsg != yymsgbuf) YYSTACK_FREE(yymsg); - yymsg = YY_CAST(char*, YYSTACK_ALLOC(YY_CAST(YYSIZE_T, yymsg_alloc))); - if(!yymsg) - { - yymsg = yymsgbuf; - yymsg_alloc = sizeof yymsgbuf; - yysyntax_error_status = 2; - } - else - { - yysyntax_error_status = YYSYNTAX_ERROR; - yymsgp = yymsg; - } - } - yyerror(result, yymsgp); - if(yysyntax_error_status == 2) goto yyexhaustedlab; - } -# undef YYSYNTAX_ERROR -#endif } if(yyerrstatus == 3) @@ -1478,6 +1224,7 @@ yyerrorlab: /* Pacify compilers when the user code never invokes YYERROR and the label yyerrorlab therefore never appears in user code. */ if(0) YYERROR; + ++yynerrs; /* Do not reclaim the symbols of the rule whose action triggered this YYERROR. */ @@ -1493,13 +1240,14 @@ yyerrorlab: yyerrlab1: yyerrstatus = 3; /* Each real token shifted decrements this. */ + /* Pop stack until we find a state that shifts the error token. */ for(;;) { yyn = yypact[yystate]; if(!yypact_value_is_default(yyn)) { - yyn += YYTERROR; - if(0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + yyn += YYSYMBOL_YYerror; + if(0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYSYMBOL_YYerror) { yyn = yytable[yyn]; if(0 < yyn) break; @@ -1509,7 +1257,7 @@ yyerrlab1: /* Pop the current state because it cannot handle the error token. */ if(yyssp == yyss) YYABORT; - yydestruct("Error: popping", yystos[yystate], yyvsp, result); + yydestruct("Error: popping", YY_ACCESSING_SYMBOL(yystate), yyvsp, result); YYPOPSTACK(1); yystate = *yyssp; YY_STACK_PRINT(yyss, yyssp); @@ -1520,7 +1268,7 @@ yyerrlab1: YY_IGNORE_MAYBE_UNINITIALIZED_END /* Shift the error token. */ - YY_SYMBOL_PRINT("Shifting", yystos[yyn], yyvsp, yylsp); + YY_SYMBOL_PRINT("Shifting", YY_ACCESSING_SYMBOL(yyn), yyvsp, yylsp); yystate = yyn; goto yynewstate; @@ -1530,29 +1278,27 @@ yyerrlab1: `-------------------------------------*/ yyacceptlab: yyresult = 0; - goto yyreturn; + goto yyreturnlab; /*-----------------------------------. | yyabortlab -- YYABORT comes here. | `-----------------------------------*/ yyabortlab: yyresult = 1; - goto yyreturn; + goto yyreturnlab; -#if !defined yyoverflow || YYERROR_VERBOSE -/*-------------------------------------------------. -| yyexhaustedlab -- memory exhaustion comes here. | -`-------------------------------------------------*/ +/*-----------------------------------------------------------. +| yyexhaustedlab -- YYNOMEM (memory exhaustion) comes here. | +`-----------------------------------------------------------*/ yyexhaustedlab: yyerror(result, YY_("memory exhausted")); yyresult = 2; - /* Fall through. */ -#endif + goto yyreturnlab; -/*-----------------------------------------------------. -| yyreturn -- parsing is finished, return the result. | -`-----------------------------------------------------*/ -yyreturn: +/*----------------------------------------------------------. +| yyreturnlab -- parsing is finished, clean up and return. | +`----------------------------------------------------------*/ +yyreturnlab: if(yychar != YYEMPTY) { /* Make sure we have latest lookahead translation. See comments at @@ -1566,20 +1312,14 @@ yyreturn: YY_STACK_PRINT(yyss, yyssp); while(yyssp != yyss) { - yydestruct("Cleanup: popping", yystos[+*yyssp], yyvsp, result); + yydestruct("Cleanup: popping", YY_ACCESSING_SYMBOL(+*yyssp), yyvsp, result); YYPOPSTACK(1); } #ifndef yyoverflow if(yyss != yyssa) YYSTACK_FREE(yyss); #endif -#if YYERROR_VERBOSE - if(yymsg != yymsgbuf) YYSTACK_FREE(yymsg); -#endif + return yyresult; } -#line 98 "parser.y" -// void yyerror(char const *s) -// { -// fprintf(stderr, "check error saurabh: %s\n", s); -// } +#line 103 "parser.y" diff --git a/source/lib/rocprofiler/counters/parser/parser.h b/source/lib/rocprofiler/counters/parser/parser.h index 0fe37fd999..355f02ffd2 100644 --- a/source/lib/rocprofiler/counters/parser/parser.h +++ b/source/lib/rocprofiler/counters/parser/parser.h @@ -1,8 +1,8 @@ -/* A Bison parser, made by GNU Bison 3.5.1. */ +/* A Bison parser, made by GNU Bison 3.8.2. */ /* Bison interface for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation, + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see . */ + along with this program. If not, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work @@ -31,8 +31,9 @@ This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ -/* Undocumented macros, especially those whose name start with YY_, - are private implementation details. Do not rely on them. */ +/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual, + especially those whose name start with YY_ or yy_. They are + private implementation details that can be changed or removed. */ #ifndef YY_YY_ROCPROFILER_SOURCE_LIB_ROCPROFILER_COUNTERS_PARSER_PARSER_H_INCLUDED #define YY_YY_ROCPROFILER_SOURCE_LIB_ROCPROFILER_COUNTERS_PARSER_PARSER_H_INCLUDED @@ -50,35 +51,40 @@ extern int yydebug; using namespace rocprofiler::counters; #define YYDEBUG 1 -#line 54 "parser.h" +#line 55 "parser.h" -/* Token type. */ +/* Token kinds. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE enum yytokentype { - ADD = 258, - SUB = 259, - MUL = 260, - DIV = 261, - ABS = 262, - EQUALS = 263, - OP = 264, - CP = 265, - O_SQ = 266, - C_SQ = 267, - COLON = 268, - EOL = 269, - UMINUS = 270, - CM = 271, - NUMBER = 272, - RANGE = 273, - NAME = 274, - REDUCE = 275, - SELECT = 276, - LOWER_THAN_ELSE = 277, - ELSE = 278 + YYEMPTY = -2, + YYEOF = 0, /* "end of file" */ + YYerror = 256, /* error */ + YYUNDEF = 257, /* "invalid token" */ + ADD = 258, /* ADD */ + SUB = 259, /* SUB */ + MUL = 260, /* MUL */ + DIV = 261, /* DIV */ + ABS = 262, /* ABS */ + EQUALS = 263, /* EQUALS */ + OP = 264, /* OP */ + CP = 265, /* CP */ + O_SQ = 266, /* O_SQ */ + C_SQ = 267, /* C_SQ */ + COLON = 268, /* COLON */ + EOL = 269, /* EOL */ + UMINUS = 270, /* UMINUS */ + CM = 271, /* CM */ + NUMBER = 272, /* NUMBER */ + RANGE = 273, /* RANGE */ + NAME = 274, /* NAME */ + REDUCE = 275, /* REDUCE */ + SELECT = 276, /* SELECT */ + LOWER_THAN_ELSE = 277, /* LOWER_THAN_ELSE */ + ELSE = 278 /* ELSE */ }; +typedef enum yytokentype yytoken_kind_t; #endif /* Value type. */ @@ -87,11 +93,12 @@ union YYSTYPE { # line 34 "parser.y" - RawAST* a; /* For ast node */ - int64_t d; - char* s; + RawAST* a; /* For ast node */ + LinkedList* ll; /* For linked list node */ + int64_t d; + char* s; -# line 95 "parser.h" +# line 102 "parser.h" }; typedef union YYSTYPE YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 diff --git a/source/lib/rocprofiler/counters/parser/parser.y b/source/lib/rocprofiler/counters/parser/parser.y index e16dc03663..12d24274e7 100644 --- a/source/lib/rocprofiler/counters/parser/parser.y +++ b/source/lib/rocprofiler/counters/parser/parser.y @@ -33,6 +33,7 @@ void yyerror(rocprofiler::counters::RawAST**, const char *s) { LOG(ERROR) << s; /*declare data types*/ %union { RawAST* a; /* For ast node */ + LinkedList* ll; /* For linked list node */ int64_t d; char* s; } @@ -43,6 +44,7 @@ void yyerror(rocprofiler::counters::RawAST**, const char *s) { LOG(ERROR) << s; %type exp /* set data type for expressions */ %type NAME %type NUMBER +%type reduce_dim_args select_dim_args %nonassoc LOWER_THAN_ELSE %nonassoc ELSE @@ -54,14 +56,6 @@ void yyerror(rocprofiler::counters::RawAST**, const char *s) { LOG(ERROR) << s; top: exp { *result = $1;}; -// line: /* nothing */ -// | line exp EOL { -// // TODO -// //printf("= %g\n", eval($2)); //evaluate and print the AST -// //printf("> "); -// } -// | line EOL { printf("> "); } /* blank line or a comment */ -// ; exp: NUMBER { $$ = new RawAST(NUMBER_NODE, $1); } | exp ADD exp { $$ = new RawAST(ADDITION_NODE, {$1, $3}); } @@ -69,35 +63,41 @@ exp: NUMBER { $$ = new RawAST(NUMBER_NODE, $1); } | exp MUL exp { $$ = new RawAST(MULTIPLY_NODE, {$1, $3}); } | exp DIV exp { $$ = new RawAST(DIVIDE_NODE, {$1, $3}); } | OP exp CP { $$ = $2; } - | O_SQ exp COLON exp C_SQ { $$ = new RawAST(RANGE_NODE, {$2, $4}); } | NAME { $$ = new RawAST(REFERENCE_NODE, $1); free($1); } - | NAME EQUALS exp { $$ = new RawAST(REFERENCE_SET, $1, $3); - free($1); - } - | NAME EQUALS exp CM exp { $$ = new RawAST(REFERENCE_SET, $1, $3, $5); - free($1); - } - | REDUCE OP exp CM NAME CP { $$ = new RawAST(REDUCE_NODE, $3, $5); + | REDUCE OP exp CM NAME CP { + $$ = new RawAST(REDUCE_NODE, $3, $5, NULL); free($5); } - | REDUCE OP exp CM NAME CM exp CP { $$ = new RawAST(REDUCE_NODE, $3, $5, $7); + | REDUCE OP exp CM NAME CM O_SQ reduce_dim_args C_SQ CP { + $$ = new RawAST(REDUCE_NODE, $3, $5, $8); free($5); } - | SELECT OP exp CM NAME CP { $$ = new RawAST(SELECT_NODE, $3, $5); - free($5); + | SELECT OP exp CM O_SQ select_dim_args C_SQ CP { + $$ = new RawAST(SELECT_NODE, $3, $6); } - | SELECT OP exp CM NAME CM exp CP { $$ = new RawAST(SELECT_NODE, $3, $5, $7); - free($5); - } - // | NAME O_SQ POS_INTEGER C_SQ { $$ = create_index_access_node($1, $3); } ; -%% -// void yyerror(char const *s) -// { -// fprintf(stderr, "check error saurabh: %s\n", s); -// } +reduce_dim_args: NAME { $$ = new LinkedList($1, NULL); + free($1); + } + | NAME CM reduce_dim_args { $$ = new LinkedList($1, $3); + free($1); + } + ; + + + +select_dim_args: NAME EQUALS NUMBER { $$ = new LinkedList($1, $3, NULL); + free($1); + } + | NAME EQUALS NUMBER CM select_dim_args { $$ = new LinkedList($1, $3, $5); + free($1); + } + ; + + +%% diff --git a/source/lib/rocprofiler/counters/parser/raw_ast.hpp b/source/lib/rocprofiler/counters/parser/raw_ast.hpp index 8c90f7186d..fb4a8480db 100644 --- a/source/lib/rocprofiler/counters/parser/raw_ast.hpp +++ b/source/lib/rocprofiler/counters/parser/raw_ast.hpp @@ -3,6 +3,8 @@ #include #include #include +#include +#include #include #include #include @@ -11,6 +13,9 @@ #include #include +#include "lib/common/utility.hpp" +#include "lib/rocprofiler/counters/id_decode.hpp" + namespace rocprofiler { namespace counters @@ -25,16 +30,31 @@ enum NodeType RANGE_NODE, REDUCE_NODE, REFERENCE_NODE, - REFERENCE_SET, SELECT_NODE, SUBTRACTION_NODE, }; +struct LinkedList +{ + std::string name; + int data{-1}; + LinkedList* next{nullptr}; + LinkedList(const char* v, LinkedList* next_node) + : name(std::string{CHECK_NOTNULL(v)}) + , next(next_node) + {} + LinkedList(const char* v, int d, LinkedList* next_node) + : name(std::string{CHECK_NOTNULL(v)}) + , data(d) + , next(next_node) + {} +}; + struct RawAST { // Node type - NodeType type{NONE}; // Operation to perform on the counter set - NodeType operation{NONE}; + NodeType type{NONE}; // Operation to perform on the counter set + std::string reduce_op; // Stores either the name or digit dependening on whether this // is a name or number @@ -44,10 +64,12 @@ struct RawAST // Operation is applied to all counters in this set. std::vector counter_set; - // Reference set to remove dimensions (such as shader) - // from the result. This is a future looking change and - // will be unsupported in 6.0. - std::vector reference_set; + // Dimension set to remove dimensions (such as shader engine) + // from the result. + std::unordered_set reduce_dimension_set; + + // Dimension set to select certain dimensions from the result + std::unordered_map select_dimension_set; // Range restriction on this node RawAST* range{nullptr}; @@ -61,7 +83,6 @@ struct RawAST } }; - deleteVec(reference_set); deleteVec(counter_set); delete range; } @@ -77,47 +98,86 @@ struct RawAST , value(v) {} - // Reduce/Select operation constructor. Counter is the counter AST - // to use for the reduce/select op, op is how to reduce (i.e. SUM,AVG,etc), - // refs is the reference set AST. This reference set is copied to flatten - // the AST. - RawAST(NodeType t, RawAST* counter, const char* op, RawAST* refs = nullptr) + static const auto& get_dim_map() + { + static const auto dim_map = []() { + std::map out; + const auto& dims = dimension_map(); + for(const auto& [id, name] : dims) + { + out.emplace(name, id); + } + return out; + }(); + return dim_map; + } + + // Reduce operation constructor. Counter is the counter AST + // to use for the reduce op, op is how to reduce (i.e. SUM,AVG,etc), + // dimensions contains the set of dimensions which we want to keep + // in the result. Dimensions not specified are all reduced according to op + RawAST(NodeType t, RawAST* counter, const char* op, LinkedList* dimensions) : type(t) - , value(std::string{CHECK_NOTNULL(op)}) + , reduce_op(CHECK_NOTNULL(op)) , counter_set({counter}) { - copy_reference_set(refs); + if(dimensions) + { + while(dimensions) + { + const rocprofiler_profile_counter_instance_types* dim = + rocprofiler::common::get_val(get_dim_map(), std::string{dimensions->name}); + if(!dim) + { + throw std::runtime_error( + fmt::format("Unknown Dimension - {}", dimensions->name)); + } + + reduce_dimension_set.insert(*dim); + LinkedList* current = dimensions; + dimensions = dimensions->next; + delete current; + } + } + } + + // Select operation constructor. Counter is the counter AST + // to use for the reduce op, refs is the reference set AST. + // dimensions contains the mapping for selecting dimensions + // (XCC=1,SE=2,...) + RawAST(NodeType t, RawAST* counter, LinkedList* dimensions) + : type(t) + , counter_set({counter}) + { + if(dimensions) + { + LinkedList* ptr = dimensions; + while(ptr) + { + const rocprofiler_profile_counter_instance_types* dim = + rocprofiler::common::get_val(get_dim_map(), dimensions->name); + if(!dim) + { + throw std::runtime_error( + fmt::format("Unknown Dimension - {}", dimensions->name)); + } + + select_dimension_set.insert({*dim, ptr->data}); + LinkedList* current = ptr; + ptr = ptr->next; + delete current; + } + } + else + { + LOG(ERROR) << "select_dimension_set creation failed."; + } } RawAST(NodeType t, std::vector c) : type(t) , counter_set(std::move(c)) {} - - // Following two calls are for future reference set settings - // for select/reduce ops. - - // Referene set constructor, refs is a pointer to an existing - // reference set when multiple references are given (i.e. - // shader=X,anotherRef=Y,....). - RawAST(NodeType t, const char* v, RawAST* r, RawAST* refs = nullptr) - : type(t) - , value(std::string{CHECK_NOTNULL(v)}) - , range(r) - { - LOG(ERROR) << "BUilding bad ast"; - copy_reference_set(refs); - } - - // Flattens reference set tree into this node. - void copy_reference_set(RawAST* ast) - { - if(!ast) return; - reference_set.push_back(ast); - reference_set.insert( - reference_set.end(), ast->reference_set.begin(), ast->reference_set.end()); - ast->reference_set.clear(); - } }; } // namespace counters } // namespace rocprofiler @@ -146,15 +206,14 @@ struct formatter {rocprofiler::counters::RANGE_NODE, "RANGE_NODE"}, {rocprofiler::counters::REDUCE_NODE, "REDUCE_NODE"}, {rocprofiler::counters::REFERENCE_NODE, "REFERENCE_NODE"}, - {rocprofiler::counters::REFERENCE_SET, "REFERENCE_SET"}, {rocprofiler::counters::SELECT_NODE, "SELECT_NODE"}, {rocprofiler::counters::SUBTRACTION_NODE, "SUBTRACTION_NODE"}, }; auto out = fmt::format_to(ctx.out(), - "{{\"Type\":\"{}\", \"Operation\":\"{}\",", + "{{\"Type\":\"{}\", \"REDUCE_OP\":\"{}\",", NodeTypeToString.at(ast.type), - NodeTypeToString.at(ast.operation)); + ast.reduce_op); if(const auto* string_val = std::get_if(&ast.value)) { @@ -170,19 +229,34 @@ struct formatter out = fmt::format_to(out, " \"Range\":{},", *ast.range); } - out = fmt::format_to(out, "\"ReferenceSet\":["); - for(const auto& ref : ast.reference_set) - { - out = fmt::format_to( - out, "{}{}", *CHECK_NOTNULL(ref), ref == ast.reference_set.back() ? "" : ","); - } - - out = fmt::format_to(out, "], \"CounterSet\":["); + out = fmt::format_to(out, " \"Counter_Set\":["); for(const auto& ref : ast.counter_set) { out = fmt::format_to( out, "{}{}", *CHECK_NOTNULL(ref), ref == ast.counter_set.back() ? "" : ","); } + + out = fmt::format_to(out, "], \"Reduce_Dimension_Set\":["); + size_t ReduceSetIndex = 0; + for(const auto& ref : ast.reduce_dimension_set) + { + out = fmt::format_to(out, + "\"{}\"{}", + static_cast(ref), + ++ReduceSetIndex == ast.reduce_dimension_set.size() ? "" : ","); + } + + out = fmt::format_to(out, "], \"Select_Dimension_Set\":["); + size_t SelectSetIndex = 0; + for(const auto& [type, val] : ast.select_dimension_set) + { + out = fmt::format_to(out, + "\"{},{}\"{}", + static_cast(type), + val, + ++SelectSetIndex == ast.select_dimension_set.size() ? "" : ","); + } + return fmt::format_to(out, "]}}"); } }; diff --git a/source/lib/rocprofiler/counters/parser/tests/parser_test.cpp b/source/lib/rocprofiler/counters/parser/tests/parser_test.cpp index d6eba18535..9a81b9f566 100644 --- a/source/lib/rocprofiler/counters/parser/tests/parser_test.cpp +++ b/source/lib/rocprofiler/counters/parser/tests/parser_test.cpp @@ -1,5 +1,6 @@ #include #include +#include #include @@ -9,26 +10,38 @@ TEST(parser, base_ops) { std::map expressionToExpected = { - {"AB + BA", - "{\"Type\":\"ADDITION_NODE\", \"Operation\":\"NONE\",\"ReferenceSet\":[], " - "\"CounterSet\":[{\"Type\":\"REFERENCE_NODE\", \"Operation\":\"NONE\", " - "\"Value\":\"AB\",\"ReferenceSet\":[], \"CounterSet\":[]},{\"Type\":\"REFERENCE_NODE\", " - "\"Operation\":\"NONE\", \"Value\":\"BA\",\"ReferenceSet\":[], \"CounterSet\":[]}]}"}, - {"CD - ZX", - "{\"Type\":\"SUBTRACTION_NODE\", \"Operation\":\"NONE\",\"ReferenceSet\":[], " - "\"CounterSet\":[{\"Type\":\"REFERENCE_NODE\", \"Operation\":\"NONE\", " - "\"Value\":\"CD\",\"ReferenceSet\":[], \"CounterSet\":[]},{\"Type\":\"REFERENCE_NODE\", " - "\"Operation\":\"NONE\", \"Value\":\"ZX\",\"ReferenceSet\":[], \"CounterSet\":[]}]}"}, - {"NM / DB", - "{\"Type\":\"DIVIDE_NODE\", \"Operation\":\"NONE\",\"ReferenceSet\":[], " - "\"CounterSet\":[{\"Type\":\"REFERENCE_NODE\", \"Operation\":\"NONE\", " - "\"Value\":\"NM\",\"ReferenceSet\":[], \"CounterSet\":[]},{\"Type\":\"REFERENCE_NODE\", " - "\"Operation\":\"NONE\", \"Value\":\"DB\",\"ReferenceSet\":[], \"CounterSet\":[]}]}"}, {"AB * BA", - "{\"Type\":\"MULTIPLY_NODE\", \"Operation\":\"NONE\",\"ReferenceSet\":[], " - "\"CounterSet\":[{\"Type\":\"REFERENCE_NODE\", \"Operation\":\"NONE\", " - "\"Value\":\"AB\",\"ReferenceSet\":[], \"CounterSet\":[]},{\"Type\":\"REFERENCE_NODE\", " - "\"Operation\":\"NONE\", \"Value\":\"BA\",\"ReferenceSet\":[], \"CounterSet\":[]}]}"}}; + "{\"Type\":\"MULTIPLY_NODE\", \"REDUCE_OP\":\"\", " + "\"Counter_Set\":[{\"Type\":\"REFERENCE_NODE\", \"REDUCE_OP\":\"\", \"Value\":\"AB\", " + "\"Counter_Set\":[], \"Reduce_Dimension_Set\":[], " + "\"Select_Dimension_Set\":[]},{\"Type\":\"REFERENCE_NODE\", \"REDUCE_OP\":\"\", " + "\"Value\":\"BA\", \"Counter_Set\":[], \"Reduce_Dimension_Set\":[], " + "\"Select_Dimension_Set\":[]}], \"Reduce_Dimension_Set\":[], " + "\"Select_Dimension_Set\":[]}"}, + {"AB + BA", + "{\"Type\":\"ADDITION_NODE\", \"REDUCE_OP\":\"\", " + "\"Counter_Set\":[{\"Type\":\"REFERENCE_NODE\", \"REDUCE_OP\":\"\", \"Value\":\"AB\", " + "\"Counter_Set\":[], \"Reduce_Dimension_Set\":[], " + "\"Select_Dimension_Set\":[]},{\"Type\":\"REFERENCE_NODE\", \"REDUCE_OP\":\"\", " + "\"Value\":\"BA\", \"Counter_Set\":[], \"Reduce_Dimension_Set\":[], " + "\"Select_Dimension_Set\":[]}], \"Reduce_Dimension_Set\":[], " + "\"Select_Dimension_Set\":[]}"}, + {"CD - ZX", + "{\"Type\":\"SUBTRACTION_NODE\", \"REDUCE_OP\":\"\", " + "\"Counter_Set\":[{\"Type\":\"REFERENCE_NODE\", \"REDUCE_OP\":\"\", \"Value\":\"CD\", " + "\"Counter_Set\":[], \"Reduce_Dimension_Set\":[], " + "\"Select_Dimension_Set\":[]},{\"Type\":\"REFERENCE_NODE\", \"REDUCE_OP\":\"\", " + "\"Value\":\"ZX\", \"Counter_Set\":[], \"Reduce_Dimension_Set\":[], " + "\"Select_Dimension_Set\":[]}], \"Reduce_Dimension_Set\":[], " + "\"Select_Dimension_Set\":[]}"}, + {"NM / DB", + "{\"Type\":\"DIVIDE_NODE\", \"REDUCE_OP\":\"\", " + "\"Counter_Set\":[{\"Type\":\"REFERENCE_NODE\", \"REDUCE_OP\":\"\", \"Value\":\"NM\", " + "\"Counter_Set\":[], \"Reduce_Dimension_Set\":[], " + "\"Select_Dimension_Set\":[]},{\"Type\":\"REFERENCE_NODE\", \"REDUCE_OP\":\"\", " + "\"Value\":\"DB\", \"Counter_Set\":[], \"Reduce_Dimension_Set\":[], " + "\"Select_Dimension_Set\":[]}], \"Reduce_Dimension_Set\":[], " + "\"Select_Dimension_Set\":[]}"}}; for(auto [op, expected] : expressionToExpected) { @@ -46,37 +59,53 @@ TEST(parser, order_of_ops) { std::map expressionToExpected = { {"(AB + BA) / CD", - "{\"Type\":\"DIVIDE_NODE\", \"Operation\":\"NONE\",\"ReferenceSet\":[], " - "\"CounterSet\":[{\"Type\":\"ADDITION_NODE\", \"Operation\":\"NONE\",\"ReferenceSet\":[], " - "\"CounterSet\":[{\"Type\":\"REFERENCE_NODE\", \"Operation\":\"NONE\", " - "\"Value\":\"AB\",\"ReferenceSet\":[], \"CounterSet\":[]},{\"Type\":\"REFERENCE_NODE\", " - "\"Operation\":\"NONE\", \"Value\":\"BA\",\"ReferenceSet\":[], " - "\"CounterSet\":[]}]},{\"Type\":\"REFERENCE_NODE\", \"Operation\":\"NONE\", " - "\"Value\":\"CD\",\"ReferenceSet\":[], \"CounterSet\":[]}]}"}, - {"AD / (CD - ZX)", - "{\"Type\":\"DIVIDE_NODE\", \"Operation\":\"NONE\",\"ReferenceSet\":[], " - "\"CounterSet\":[{\"Type\":\"REFERENCE_NODE\", \"Operation\":\"NONE\", " - "\"Value\":\"AD\",\"ReferenceSet\":[], \"CounterSet\":[]},{\"Type\":\"SUBTRACTION_NODE\", " - "\"Operation\":\"NONE\",\"ReferenceSet\":[], " - "\"CounterSet\":[{\"Type\":\"REFERENCE_NODE\", \"Operation\":\"NONE\", " - "\"Value\":\"CD\",\"ReferenceSet\":[], \"CounterSet\":[]},{\"Type\":\"REFERENCE_NODE\", " - "\"Operation\":\"NONE\", \"Value\":\"ZX\",\"ReferenceSet\":[], \"CounterSet\":[]}]}]}"}, - {"MN * (NM / DB)", - "{\"Type\":\"MULTIPLY_NODE\", \"Operation\":\"NONE\",\"ReferenceSet\":[], " - "\"CounterSet\":[{\"Type\":\"REFERENCE_NODE\", \"Operation\":\"NONE\", " - "\"Value\":\"MN\",\"ReferenceSet\":[], \"CounterSet\":[]},{\"Type\":\"DIVIDE_NODE\", " - "\"Operation\":\"NONE\",\"ReferenceSet\":[], " - "\"CounterSet\":[{\"Type\":\"REFERENCE_NODE\", \"Operation\":\"NONE\", " - "\"Value\":\"NM\",\"ReferenceSet\":[], \"CounterSet\":[]},{\"Type\":\"REFERENCE_NODE\", " - "\"Operation\":\"NONE\", \"Value\":\"DB\",\"ReferenceSet\":[], \"CounterSet\":[]}]}]}"}, + "{\"Type\":\"DIVIDE_NODE\", \"REDUCE_OP\":\"\", " + "\"Counter_Set\":[{\"Type\":\"ADDITION_NODE\", \"REDUCE_OP\":\"\", " + "\"Counter_Set\":[{\"Type\":\"REFERENCE_NODE\", \"REDUCE_OP\":\"\", \"Value\":\"AB\", " + "\"Counter_Set\":[], \"Reduce_Dimension_Set\":[], " + "\"Select_Dimension_Set\":[]},{\"Type\":\"REFERENCE_NODE\", \"REDUCE_OP\":\"\", " + "\"Value\":\"BA\", \"Counter_Set\":[], \"Reduce_Dimension_Set\":[], " + "\"Select_Dimension_Set\":[]}], \"Reduce_Dimension_Set\":[], " + "\"Select_Dimension_Set\":[]},{\"Type\":\"REFERENCE_NODE\", \"REDUCE_OP\":\"\", " + "\"Value\":\"CD\", \"Counter_Set\":[], \"Reduce_Dimension_Set\":[], " + "\"Select_Dimension_Set\":[]}], \"Reduce_Dimension_Set\":[], " + "\"Select_Dimension_Set\":[]}"}, {"(AB / BA) - BN", - "{\"Type\":\"SUBTRACTION_NODE\", \"Operation\":\"NONE\",\"ReferenceSet\":[], " - "\"CounterSet\":[{\"Type\":\"DIVIDE_NODE\", \"Operation\":\"NONE\",\"ReferenceSet\":[], " - "\"CounterSet\":[{\"Type\":\"REFERENCE_NODE\", \"Operation\":\"NONE\", " - "\"Value\":\"AB\",\"ReferenceSet\":[], \"CounterSet\":[]},{\"Type\":\"REFERENCE_NODE\", " - "\"Operation\":\"NONE\", \"Value\":\"BA\",\"ReferenceSet\":[], " - "\"CounterSet\":[]}]},{\"Type\":\"REFERENCE_NODE\", \"Operation\":\"NONE\", " - "\"Value\":\"BN\",\"ReferenceSet\":[], \"CounterSet\":[]}]}"}}; + "{\"Type\":\"SUBTRACTION_NODE\", \"REDUCE_OP\":\"\", " + "\"Counter_Set\":[{\"Type\":\"DIVIDE_NODE\", \"REDUCE_OP\":\"\", " + "\"Counter_Set\":[{\"Type\":\"REFERENCE_NODE\", \"REDUCE_OP\":\"\", \"Value\":\"AB\", " + "\"Counter_Set\":[], \"Reduce_Dimension_Set\":[], " + "\"Select_Dimension_Set\":[]},{\"Type\":\"REFERENCE_NODE\", \"REDUCE_OP\":\"\", " + "\"Value\":\"BA\", \"Counter_Set\":[], \"Reduce_Dimension_Set\":[], " + "\"Select_Dimension_Set\":[]}], \"Reduce_Dimension_Set\":[], " + "\"Select_Dimension_Set\":[]},{\"Type\":\"REFERENCE_NODE\", \"REDUCE_OP\":\"\", " + "\"Value\":\"BN\", \"Counter_Set\":[], \"Reduce_Dimension_Set\":[], " + "\"Select_Dimension_Set\":[]}], \"Reduce_Dimension_Set\":[], " + "\"Select_Dimension_Set\":[]}"}, + {"AD / (CD - ZX)", + "{\"Type\":\"DIVIDE_NODE\", \"REDUCE_OP\":\"\", " + "\"Counter_Set\":[{\"Type\":\"REFERENCE_NODE\", \"REDUCE_OP\":\"\", \"Value\":\"AD\", " + "\"Counter_Set\":[], \"Reduce_Dimension_Set\":[], " + "\"Select_Dimension_Set\":[]},{\"Type\":\"SUBTRACTION_NODE\", \"REDUCE_OP\":\"\", " + "\"Counter_Set\":[{\"Type\":\"REFERENCE_NODE\", \"REDUCE_OP\":\"\", \"Value\":\"CD\", " + "\"Counter_Set\":[], \"Reduce_Dimension_Set\":[], " + "\"Select_Dimension_Set\":[]},{\"Type\":\"REFERENCE_NODE\", \"REDUCE_OP\":\"\", " + "\"Value\":\"ZX\", \"Counter_Set\":[], \"Reduce_Dimension_Set\":[], " + "\"Select_Dimension_Set\":[]}], \"Reduce_Dimension_Set\":[], " + "\"Select_Dimension_Set\":[]}], \"Reduce_Dimension_Set\":[], " + "\"Select_Dimension_Set\":[]}"}, + {"MN * (NM / DB)", + "{\"Type\":\"MULTIPLY_NODE\", \"REDUCE_OP\":\"\", " + "\"Counter_Set\":[{\"Type\":\"REFERENCE_NODE\", \"REDUCE_OP\":\"\", \"Value\":\"MN\", " + "\"Counter_Set\":[], \"Reduce_Dimension_Set\":[], " + "\"Select_Dimension_Set\":[]},{\"Type\":\"DIVIDE_NODE\", \"REDUCE_OP\":\"\", " + "\"Counter_Set\":[{\"Type\":\"REFERENCE_NODE\", \"REDUCE_OP\":\"\", \"Value\":\"NM\", " + "\"Counter_Set\":[], \"Reduce_Dimension_Set\":[], " + "\"Select_Dimension_Set\":[]},{\"Type\":\"REFERENCE_NODE\", \"REDUCE_OP\":\"\", " + "\"Value\":\"DB\", \"Counter_Set\":[], \"Reduce_Dimension_Set\":[], " + "\"Select_Dimension_Set\":[]}], \"Reduce_Dimension_Set\":[], " + "\"Select_Dimension_Set\":[]}], \"Reduce_Dimension_Set\":[], " + "\"Select_Dimension_Set\":[]}"}}; for(auto [op, expected] : expressionToExpected) { @@ -92,32 +121,34 @@ TEST(parser, order_of_ops) TEST(parser, reduction) { - std::map expressionToExpected = { - {"reduce(AB, SUM)", - "{\"Type\":\"REDUCE_NODE\", \"Operation\":\"NONE\", " - "\"Value\":\"SUM\",\"ReferenceSet\":[], \"CounterSet\":[{\"Type\":\"REFERENCE_NODE\", " - "\"Operation\":\"NONE\", \"Value\":\"AB\",\"ReferenceSet\":[], \"CounterSet\":[]}]}"}, - {"reduce(AB+CD, SUM)", - "{\"Type\":\"REDUCE_NODE\", \"Operation\":\"NONE\", " - "\"Value\":\"SUM\",\"ReferenceSet\":[], \"CounterSet\":[{\"Type\":\"ADDITION_NODE\", " - "\"Operation\":\"NONE\",\"ReferenceSet\":[], " - "\"CounterSet\":[{\"Type\":\"REFERENCE_NODE\", \"Operation\":\"NONE\", " - "\"Value\":\"AB\",\"ReferenceSet\":[], \"CounterSet\":[]},{\"Type\":\"REFERENCE_NODE\", " - "\"Operation\":\"NONE\", \"Value\":\"CD\",\"ReferenceSet\":[], \"CounterSet\":[]}]}]}"}, - {"reduce(AB,DIV)+reduce(DC,SUM)", - "{\"Type\":\"ADDITION_NODE\", \"Operation\":\"NONE\",\"ReferenceSet\":[], " - "\"CounterSet\":[{\"Type\":\"REDUCE_NODE\", \"Operation\":\"NONE\", " - "\"Value\":\"DIV\",\"ReferenceSet\":[], \"CounterSet\":[{\"Type\":\"REFERENCE_NODE\", " - "\"Operation\":\"NONE\", \"Value\":\"AB\",\"ReferenceSet\":[], " - "\"CounterSet\":[]}]},{\"Type\":\"REDUCE_NODE\", \"Operation\":\"NONE\", " - "\"Value\":\"SUM\",\"ReferenceSet\":[], \"CounterSet\":[{\"Type\":\"REFERENCE_NODE\", " - "\"Operation\":\"NONE\", \"Value\":\"DC\",\"ReferenceSet\":[], \"CounterSet\":[]}]}]}"}, - {"reduce(AB, SUM, shader)", - "{\"Type\":\"REDUCE_NODE\", \"Operation\":\"NONE\", " - "\"Value\":\"SUM\",\"ReferenceSet\":[{\"Type\":\"REFERENCE_NODE\", " - "\"Operation\":\"NONE\", \"Value\":\"shader\",\"ReferenceSet\":[], \"CounterSet\":[]}], " - "\"CounterSet\":[{\"Type\":\"REFERENCE_NODE\", \"Operation\":\"NONE\", " - "\"Value\":\"AB\",\"ReferenceSet\":[], \"CounterSet\":[]}]}"}}; + std::vector> expressionToExpected = { + {"reduce(AB, SUM, [DIMENSION_XCC,DIMENSION_SHADER_ENGINE])", + "{\"Type\":\"REDUCE_NODE\", \"REDUCE_OP\":\"SUM\", " + "\"Counter_Set\":[{\"Type\":\"REFERENCE_NODE\", \"REDUCE_OP\":\"\", \"Value\":\"AB\", " + "\"Counter_Set\":[], \"Reduce_Dimension_Set\":[], \"Select_Dimension_Set\":[]}], " + "\"Reduce_Dimension_Set\":[\"2\",\"1\"], \"Select_Dimension_Set\":[]}"}, + {"reduce(AB+CD, SUM, [DIMENSION_XCC,DIMENSION_SHADER_ENGINE])", + "{\"Type\":\"REDUCE_NODE\", \"REDUCE_OP\":\"SUM\", " + "\"Counter_Set\":[{\"Type\":\"ADDITION_NODE\", \"REDUCE_OP\":\"\", " + "\"Counter_Set\":[{\"Type\":\"REFERENCE_NODE\", \"REDUCE_OP\":\"\", \"Value\":\"AB\", " + "\"Counter_Set\":[], \"Reduce_Dimension_Set\":[], " + "\"Select_Dimension_Set\":[]},{\"Type\":\"REFERENCE_NODE\", \"REDUCE_OP\":\"\", " + "\"Value\":\"CD\", \"Counter_Set\":[], \"Reduce_Dimension_Set\":[], " + "\"Select_Dimension_Set\":[]}], \"Reduce_Dimension_Set\":[], " + "\"Select_Dimension_Set\":[]}], \"Reduce_Dimension_Set\":[\"2\",\"1\"], " + "\"Select_Dimension_Set\":[]}"}, + {"reduce(AB,DIV, [DIMENSION_XCC,DIMENSION_SHADER_ENGINE])+reduce(DC,SUM, " + "[DIMENSION_XCC,DIMENSION_SHADER_ENGINE])", + "{\"Type\":\"ADDITION_NODE\", \"REDUCE_OP\":\"\", " + "\"Counter_Set\":[{\"Type\":\"REDUCE_NODE\", \"REDUCE_OP\":\"DIV\", " + "\"Counter_Set\":[{\"Type\":\"REFERENCE_NODE\", \"REDUCE_OP\":\"\", \"Value\":\"AB\", " + "\"Counter_Set\":[], \"Reduce_Dimension_Set\":[], \"Select_Dimension_Set\":[]}], " + "\"Reduce_Dimension_Set\":[\"2\",\"1\"], " + "\"Select_Dimension_Set\":[]},{\"Type\":\"REDUCE_NODE\", \"REDUCE_OP\":\"SUM\", " + "\"Counter_Set\":[{\"Type\":\"REFERENCE_NODE\", \"REDUCE_OP\":\"\", \"Value\":\"DC\", " + "\"Counter_Set\":[], \"Reduce_Dimension_Set\":[], \"Select_Dimension_Set\":[]}], " + "\"Reduce_Dimension_Set\":[\"2\",\"1\"], \"Select_Dimension_Set\":[]}], " + "\"Reduce_Dimension_Set\":[], \"Select_Dimension_Set\":[]}"}}; for(auto [op, expected] : expressionToExpected) { @@ -131,34 +162,31 @@ TEST(parser, reduction) } } -TEST(parser, selection) +TEST(parser, DISABLED_selection) { std::map expressionToExpected = { - {"select(AB, SUM)", - "{\"Type\":\"SELECT_NODE\", \"Operation\":\"NONE\", " - "\"Value\":\"SUM\",\"ReferenceSet\":[], \"CounterSet\":[{\"Type\":\"REFERENCE_NODE\", " - "\"Operation\":\"NONE\", \"Value\":\"AB\",\"ReferenceSet\":[], \"CounterSet\":[]}]}"}, - {"select(AB+CD, SUM)", - "{\"Type\":\"SELECT_NODE\", \"Operation\":\"NONE\", " - "\"Value\":\"SUM\",\"ReferenceSet\":[], \"CounterSet\":[{\"Type\":\"ADDITION_NODE\", " - "\"Operation\":\"NONE\",\"ReferenceSet\":[], " - "\"CounterSet\":[{\"Type\":\"REFERENCE_NODE\", \"Operation\":\"NONE\", " - "\"Value\":\"AB\",\"ReferenceSet\":[], \"CounterSet\":[]},{\"Type\":\"REFERENCE_NODE\", " - "\"Operation\":\"NONE\", \"Value\":\"CD\",\"ReferenceSet\":[], \"CounterSet\":[]}]}]}"}, - {"select(AB,DIV)+select(DC,SUM)", - "{\"Type\":\"ADDITION_NODE\", \"Operation\":\"NONE\",\"ReferenceSet\":[], " - "\"CounterSet\":[{\"Type\":\"SELECT_NODE\", \"Operation\":\"NONE\", " - "\"Value\":\"DIV\",\"ReferenceSet\":[], \"CounterSet\":[{\"Type\":\"REFERENCE_NODE\", " - "\"Operation\":\"NONE\", \"Value\":\"AB\",\"ReferenceSet\":[], " - "\"CounterSet\":[]}]},{\"Type\":\"SELECT_NODE\", \"Operation\":\"NONE\", " - "\"Value\":\"SUM\",\"ReferenceSet\":[], \"CounterSet\":[{\"Type\":\"REFERENCE_NODE\", " - "\"Operation\":\"NONE\", \"Value\":\"DC\",\"ReferenceSet\":[], \"CounterSet\":[]}]}]}"}, - {"select(AB, SUM, shader)", - "{\"Type\":\"SELECT_NODE\", \"Operation\":\"NONE\", " - "\"Value\":\"SUM\",\"ReferenceSet\":[{\"Type\":\"REFERENCE_NODE\", " - "\"Operation\":\"NONE\", \"Value\":\"shader\",\"ReferenceSet\":[], \"CounterSet\":[]}], " - "\"CounterSet\":[{\"Type\":\"REFERENCE_NODE\", \"Operation\":\"NONE\", " - "\"Value\":\"AB\",\"ReferenceSet\":[], \"CounterSet\":[]}]}"}}; + {"select(AB, [SE=1,XCC=0])+select(DC,[SE=2])", + "{\"Type\":\"ADDITION_NODE\", \"REDUCE_OP\":\"\", " + "\"Counter_Set\":[{\"Type\":\"SELECT_NODE\", \"REDUCE_OP\":\"\", " + "\"Counter_Set\":[{\"Type\":\"REFERENCE_NODE\", \"REDUCE_OP\":\"\", \"Value\":\"AB\", " + "\"Counter_Set\":[], \"Reduce_Dimension_Set\":[], \"Select_Dimension_Set\":[]}], " + "\"Reduce_Dimension_Set\":[], \"Select_Dimension_Set\":[\"(\"XCC\", 0)\",\"(\"SE\", " + "1)\"]},{\"Type\":\"SELECT_NODE\", \"REDUCE_OP\":\"\", " + "\"Counter_Set\":[{\"Type\":\"REFERENCE_NODE\", \"REDUCE_OP\":\"\", \"Value\":\"DC\", " + "\"Counter_Set\":[], \"Reduce_Dimension_Set\":[], \"Select_Dimension_Set\":[]}], " + "\"Reduce_Dimension_Set\":[], \"Select_Dimension_Set\":[\"(\"SE\", 2)\"]}], " + "\"Reduce_Dimension_Set\":[], \"Select_Dimension_Set\":[]}"}, + {"select(AB, [SE=2,XCC=1,WGP=3])", + "{\"Type\":\"SELECT_NODE\", \"REDUCE_OP\":\"\", " + "\"Counter_Set\":[{\"Type\":\"REFERENCE_NODE\", \"REDUCE_OP\":\"\", \"Value\":\"AB\", " + "\"Counter_Set\":[], \"Reduce_Dimension_Set\":[], \"Select_Dimension_Set\":[]}], " + "\"Reduce_Dimension_Set\":[], \"Select_Dimension_Set\":[\"(\"WGP\", 3)\",\"(\"XCC\", " + "1)\",\"(\"SE\", 2)\"]}"}, + {"select(AB, [XCC=0])", + "{\"Type\":\"SELECT_NODE\", \"REDUCE_OP\":\"\", " + "\"Counter_Set\":[{\"Type\":\"REFERENCE_NODE\", \"REDUCE_OP\":\"\", \"Value\":\"AB\", " + "\"Counter_Set\":[], \"Reduce_Dimension_Set\":[], \"Select_Dimension_Set\":[]}], " + "\"Reduce_Dimension_Set\":[], \"Select_Dimension_Set\":[\"(\"XCC\", 0)\"]}"}}; for(auto [op, expected] : expressionToExpected) { diff --git a/source/lib/rocprofiler/counters/tests/CMakeLists.txt b/source/lib/rocprofiler/counters/tests/CMakeLists.txt index a8cf10d8cb..617873b2ea 100644 --- a/source/lib/rocprofiler/counters/tests/CMakeLists.txt +++ b/source/lib/rocprofiler/counters/tests/CMakeLists.txt @@ -2,7 +2,8 @@ rocprofiler_deactivate_clang_tidy() include(GoogleTest) -set(ROCPROFILER_LIB_COUNTER_TEST_SOURCES metrics_test.cpp evaluate_ast_test.cpp) +set(ROCPROFILER_LIB_COUNTER_TEST_SOURCES metrics_test.cpp evaluate_ast_test.cpp + dimension.cpp) add_executable(counter-test) diff --git a/source/lib/rocprofiler/counters/tests/dimension.cpp b/source/lib/rocprofiler/counters/tests/dimension.cpp new file mode 100644 index 0000000000..a42ddc4277 --- /dev/null +++ b/source/lib/rocprofiler/counters/tests/dimension.cpp @@ -0,0 +1,82 @@ +#include + +#include "lib/common/utility.hpp" +#include "lib/rocprofiler/counters/id_decode.hpp" + +TEST(dimension, set_get) +{ + using namespace rocprofiler::counters; + int64_t max_counter_val = (std::numeric_limits::max() >> + (64 - (DIM_BIT_LENGTH / ROCPROFILER_DIMENSION_LAST))); + rocprofiler_counter_instance_id_t test_id = 0; + rocprofiler_counter_id_t test_counter{.handle = 123}; + + set_counter_in_rec(test_id, test_counter); + // 0x007B000000000000 = decimal counter id 123 << DIM_BIT_LENGTH + EXPECT_EQ(test_id, 0x007B000000000000); + + test_counter.handle = 321; + set_counter_in_rec(test_id, test_counter); + // 0x0141000000000000 = decimal counter id 321 << DIM_BIT_LENGTH + EXPECT_EQ(test_id, 0x0141000000000000); + EXPECT_EQ(rec_to_counter_id(test_id).handle, 321); + + // Test multiples of i, setting/getting those values across all + // dimensions + for(size_t multi_factor = 1; multi_factor < 7; multi_factor++) + { + for(size_t i = 1; i < static_cast(ROCPROFILER_DIMENSION_LAST); i++) + { + auto dim = static_cast(i); + set_dim_in_rec(test_id, dim, i); + EXPECT_EQ(rec_to_dim_pos(test_id, dim), i); + set_dim_in_rec(test_id, dim, i * multi_factor); + for(size_t j = 1; j < static_cast(ROCPROFILER_DIMENSION_LAST); j++) + { + if(i == j) continue; + set_dim_in_rec(test_id, + static_cast(j), + max_counter_val); + EXPECT_EQ(rec_to_dim_pos( + test_id, static_cast(j)), + max_counter_val); + EXPECT_EQ(rec_to_dim_pos(test_id, dim), i * multi_factor); + } + + for(size_t j = static_cast(ROCPROFILER_DIMENSION_LAST - 1); j > 0; j--) + { + if(i == j) continue; + set_dim_in_rec(test_id, + static_cast(j), + max_counter_val); + EXPECT_EQ(rec_to_dim_pos(test_id, (rocprofiler_profile_counter_instance_types) j), + max_counter_val); + EXPECT_EQ(rec_to_dim_pos(test_id, dim), i * multi_factor); + } + + // Check that name exists + EXPECT_TRUE(rocprofiler::common::get_val( + rocprofiler::counters::dimension_map(), + static_cast(i))); + } + } + + for(size_t i = static_cast(ROCPROFILER_DIMENSION_LAST - 1); i > 0; i--) + { + auto dim = static_cast(i); + set_dim_in_rec(test_id, dim, i * 5); + EXPECT_EQ(rec_to_dim_pos(test_id, dim), i * 5); + set_dim_in_rec(test_id, dim, i * 3); + EXPECT_EQ(rec_to_dim_pos(test_id, dim), i * 3); + } + + test_counter.handle = 123; + set_counter_in_rec(test_id, test_counter); + EXPECT_EQ(rec_to_counter_id(test_id).handle, 123); + + // Test that all bits can be set/fetched for dims, 0xFAFBFCFDFEFF is a random + // collection of 48 bits. + set_dim_in_rec(test_id, ROCPROFILER_DIMENSION_NONE, 0xFAFBFCFDFEFF); + EXPECT_EQ(rec_to_dim_pos(test_id, ROCPROFILER_DIMENSION_NONE), 0xFAFBFCFDFEFF); + EXPECT_EQ(rec_to_counter_id(test_id).handle, 123); +} \ No newline at end of file diff --git a/source/lib/rocprofiler/counters/tests/evaluate_ast_test.cpp b/source/lib/rocprofiler/counters/tests/evaluate_ast_test.cpp index c29ad4c5f8..652cc075ad 100644 --- a/source/lib/rocprofiler/counters/tests/evaluate_ast_test.cpp +++ b/source/lib/rocprofiler/counters/tests/evaluate_ast_test.cpp @@ -1,17 +1,32 @@ +#include #include +#include #include -#include "lib/rocprofiler/counters/evaluate_ast.hpp" +#include "evaluate_ast_test.hpp" #include "lib/rocprofiler/counters/parser/reader.hpp" namespace { +ReduceOperation +get_reduce_op_type_from_string(const std::string& op) +{ + static const std::unordered_map reduce_op_string_to_type = { + {"min", REDUCE_MIN}, {"max", REDUCE_MAX}, {"sum", REDUCE_SUM}, {"avr", REDUCE_AVG}}; + + ReduceOperation type = REDUCE_NONE; + const auto* reduce_op_type = rocprofiler::common::get_val(reduce_op_string_to_type, op); + if(reduce_op_type) type = *reduce_op_type; + return type; +} + bool isIdentical(const EvaluateAST& eval_ast, const RawAST& raw_ast) { if(raw_ast.counter_set.size() != eval_ast.children().size() || - raw_ast.type != eval_ast.type() || raw_ast.operation != eval_ast.op()) + raw_ast.type != eval_ast.type() || + get_reduce_op_type_from_string(raw_ast.reduce_op) != eval_ast.reduce_op()) { return false; } @@ -30,15 +45,15 @@ isIdentical(const EvaluateAST& eval_ast, const RawAST& raw_ast) TEST(evaluate_ast, basic_copy) { std::unordered_map metrics = { - {"SQ_WAVES", Metric("a", "a", "a", "a", "a", "", 0)}, - {"TCC_HIT", Metric("b", "b", "b", "b", "b", "", 1)}}; + {"SQ_WAVES", Metric("gfx9", "a", "a", "a", "a", "a", "", 0)}, + {"TCC_HIT", Metric("gfx9", "b", "b", "b", "b", "b", "", 1)}}; RawAST* ast = nullptr; auto* buf = yy_scan_string("SQ_WAVES + TCC_HIT"); yyparse(&ast); ASSERT_TRUE(ast); - auto eval_ast = EvaluateAST(metrics, *ast); + auto eval_ast = EvaluateAST(metrics, *ast, "gfx9"); EXPECT_TRUE(isIdentical(eval_ast, *ast)); yy_delete_buffer(buf); @@ -48,9 +63,10 @@ TEST(evaluate_ast, basic_copy) TEST(evaluate_ast, counter_expansion) { std::unordered_map metrics = { - {"SQ_WAVES", Metric("SQ_WAVES", "a", "a", "a", "", "", 0)}, - {"TCC_HIT", Metric("TCC_HIT", "b", "b", "b", "", "", 1)}, - {"TEST_DERRIVED", Metric("TEST_DERRIVED", "C", "C", "C", "SQ_WAVES+TCC_HIT", "", 2)}}; + {"SQ_WAVES", Metric("gfx9", "SQ_WAVES", "a", "a", "a", "", "", 0)}, + {"TCC_HIT", Metric("gfx9", "TCC_HIT", "b", "b", "b", "", "", 1)}, + {"TEST_DERRIVED", + Metric("gfx9", "TEST_DERRIVED", "C", "C", "C", "SQ_WAVES+TCC_HIT", "", 2)}}; std::unordered_map asts; for(auto [val, metric] : metrics) @@ -60,7 +76,7 @@ TEST(evaluate_ast, counter_expansion) : metric.expression().c_str()); yyparse(&ast); ASSERT_TRUE(ast); - asts.emplace(val, std::move(EvaluateAST(metrics, *ast))); + asts.emplace(val, std::move(EvaluateAST(metrics, *ast, "gfx9"))); yy_delete_buffer(buf); delete ast; } @@ -68,8 +84,8 @@ TEST(evaluate_ast, counter_expansion) std::set required_counters; asts.at("TEST_DERRIVED").get_required_counters(asts, required_counters); EXPECT_EQ(required_counters.size(), 2); - auto expected = std::set{{Metric("TCC_HIT", "b", "b", "b", "", "", 1), - Metric("SQ_WAVES", "a", "a", "a", "", "", 0)}}; + auto expected = std::set{{Metric("gfx9", "TCC_HIT", "b", "b", "b", "", "", 1), + Metric("gfx9", "SQ_WAVES", "a", "a", "a", "", "", 0)}}; for(auto& counter_found : required_counters) { @@ -80,11 +96,12 @@ TEST(evaluate_ast, counter_expansion) TEST(evaluate_ast, counter_expansion_multi_derived) { std::unordered_map metrics = { - {"SQ_WAVES", Metric("SQ_WAVES", "a", "a", "a", "", "", 0)}, - {"TCC_HIT", Metric("TCC_HIT", "b", "b", "b", "", "", 1)}, - {"TEST_DERRIVED", Metric("TEST_DERRIVED", "C", "C", "C", "SQ_WAVES+TCC_HIT", "", 2)}, + {"SQ_WAVES", Metric("gfx9", "SQ_WAVES", "a", "a", "a", "", "", 0)}, + {"TCC_HIT", Metric("gfx9", "TCC_HIT", "b", "b", "b", "", "", 1)}, + {"TEST_DERRIVED", + Metric("gfx9", "TEST_DERRIVED", "C", "C", "C", "SQ_WAVES+TCC_HIT", "", 2)}, {"TEST_DERRIVED3", - Metric("TEST_DERRIVED3", "C", "C", "C", "TEST_DERRIVED+SQ_WAVES+TCC_HIT", "", 3)}}; + Metric("gfx9", "TEST_DERRIVED3", "C", "C", "C", "TEST_DERRIVED+SQ_WAVES+TCC_HIT", "", 3)}}; std::unordered_map asts; for(auto [val, metric] : metrics) @@ -94,7 +111,7 @@ TEST(evaluate_ast, counter_expansion_multi_derived) : metric.expression().c_str()); yyparse(&ast); ASSERT_TRUE(ast); - asts.emplace(val, std::move(EvaluateAST(metrics, *ast))); + asts.emplace(val, std::move(EvaluateAST(metrics, *ast, "gfx9"))); yy_delete_buffer(buf); delete ast; } @@ -102,8 +119,8 @@ TEST(evaluate_ast, counter_expansion_multi_derived) std::set required_counters; asts.at("TEST_DERRIVED3").get_required_counters(asts, required_counters); EXPECT_EQ(required_counters.size(), 2); - auto expected = std::set{{Metric("TCC_HIT", "b", "b", "b", "", "", 1), - Metric("SQ_WAVES", "a", "a", "a", "", "", 0)}}; + auto expected = std::set{{Metric("gfx9", "TCC_HIT", "b", "b", "b", "", "", 1), + Metric("gfx9", "SQ_WAVES", "a", "a", "a", "", "", 0)}}; for(auto& counter_found : required_counters) { @@ -114,12 +131,12 @@ TEST(evaluate_ast, counter_expansion_multi_derived) TEST(evaluate_ast, counter_expansion_order) { std::unordered_map metrics = { - {"SQ_WAVES", Metric("SQ_WAVES", "a", "a", "a", "", "", 0)}, - {"TCC_HIT", Metric("TCC_HIT", "b", "b", "b", "", "", 1)}, - {"VLL", Metric("VLL", "b", "b", "b", "", "", 4)}, - {"TEST_DERRIVED", Metric("TEST_DERRIVED", "C", "C", "C", "SQ_WAVES+VLL", "", 2)}, + {"SQ_WAVES", Metric("gfx9", "SQ_WAVES", "a", "a", "a", "", "", 0)}, + {"TCC_HIT", Metric("gfx9", "TCC_HIT", "b", "b", "b", "", "", 1)}, + {"VLL", Metric("gfx9", "VLL", "b", "b", "b", "", "", 4)}, + {"TEST_DERRIVED", Metric("gfx9", "TEST_DERRIVED", "C", "C", "C", "SQ_WAVES+VLL", "", 2)}, {"TEST_DERRIVED3", - Metric("TEST_DERRIVED3", "C", "C", "C", "TEST_DERRIVED+SQ_WAVES+TCC_HIT", "", 3)}}; + Metric("gfx9", "TEST_DERRIVED3", "C", "C", "C", "TEST_DERRIVED+SQ_WAVES+TCC_HIT", "", 3)}}; std::unordered_map asts; for(auto [val, metric] : metrics) @@ -129,7 +146,7 @@ TEST(evaluate_ast, counter_expansion_order) : metric.expression().c_str()); yyparse(&ast); ASSERT_TRUE(ast); - asts.emplace(val, std::move(EvaluateAST(metrics, *ast))); + asts.emplace(val, std::move(EvaluateAST(metrics, *ast, "gfx9"))); yy_delete_buffer(buf); delete ast; } @@ -137,9 +154,9 @@ TEST(evaluate_ast, counter_expansion_order) std::set required_counters; asts.at("TEST_DERRIVED3").get_required_counters(asts, required_counters); EXPECT_EQ(required_counters.size(), 3); - auto expected = std::set{{Metric("VLL", "b", "b", "b", "", "", 4), - Metric("TCC_HIT", "b", "b", "b", "", "", 1), - Metric("SQ_WAVES", "a", "a", "a", "", "", 0)}}; + auto expected = std::set{{Metric("gfx9", "VLL", "b", "b", "b", "", "", 4), + Metric("gfx9", "TCC_HIT", "b", "b", "b", "", "", 1), + Metric("gfx9", "SQ_WAVES", "a", "a", "a", "", "", 0)}}; for(auto& counter_found : required_counters) { @@ -147,44 +164,100 @@ TEST(evaluate_ast, counter_expansion_order) } } -TEST(evaluate_ast, counter_expansion_function) -{ - std::unordered_map metrics = { - {"SQ_WAVES", Metric("SQ_WAVES", "a", "a", "a", "", "", 0)}, - {"TCC_HIT", Metric("TCC_HIT", "b", "b", "b", "", "", 1)}, - {"VLL", Metric("VLL", "b", "b", "b", "", "", 4)}, - {"TEST_DERRIVED", Metric("TEST_DERRIVED", "C", "C", "C", "SQ_WAVES+VLL", "", 2)}, - {"TEST_DERRIVED3", - Metric("TEST_DERRIVED3", - "C", - "C", - "C", - "reduce(TEST_DERRIVED,max)+SQ_WAVES+TCC_HIT", - "", - 3)}}; +// TEST(evaluate_ast, counter_expansion_function) +// { +// std::unordered_map metrics = { +// {"SQ_WAVES", Metric("gfx9", "SQ_WAVES", "a", "a", "a", "", "", 0)}, +// {"TCC_HIT", Metric("gfx9", "TCC_HIT", "b", "b", "b", "", "", 1)}, +// {"VLL", Metric("gfx9", "VLL", "b", "b", "b", "", "", 4)}, +// {"TEST_DERRIVED", Metric("gfx9", "TEST_DERRIVED", "C", "C", "C", "SQ_WAVES+VLL", "", +// 2)}}; - std::unordered_map asts; - for(auto [val, metric] : metrics) - { - RawAST* ast = nullptr; - auto buf = yy_scan_string(metric.expression().empty() ? metric.name().c_str() - : metric.expression().c_str()); - yyparse(&ast); - ASSERT_TRUE(ast); - asts.emplace(val, std::move(EvaluateAST(metrics, *ast))); - yy_delete_buffer(buf); - delete ast; - } +// std::unordered_map asts; +// for(auto [val, metric] : metrics) +// { +// RawAST* ast = nullptr; +// auto buf = yy_scan_string(metric.expression().empty() ? metric.name().c_str() +// : metric.expression().c_str()); +// yyparse(&ast); +// ASSERT_TRUE(ast) << metric.expression() << " " << metric.name(); +// asts.emplace(val, std::move(EvaluateAST(metrics, *ast, "gfx9"))); +// yy_delete_buffer(buf); +// delete ast; +// } +// } - std::set required_counters; - asts.at("TEST_DERRIVED3").get_required_counters(asts, required_counters); - EXPECT_EQ(required_counters.size(), 3); - auto expected = std::set{{Metric("VLL", "b", "b", "b", "", "", 4), - Metric("TCC_HIT", "b", "b", "b", "", "", 1), - Metric("SQ_WAVES", "a", "a", "a", "", "", 0)}}; +// TEST(evaluate_ast, evaluate_simple_math) +// { +// std::unordered_map metrics; +// std::unordered_map results_map; +// std::unordered_map> expected_values; - for(auto& counter_found : required_counters) - { - EXPECT_NE(expected.find(counter_found), expected.end()); - } -} +// uint64_t id = 0; +// for(auto& data : test_data_evaluate_simple_math) +// { +// metrics.emplace( +// data.name, Metric("gfx9", data.name, "Block", "0", "", data.expr, "", id)); +// metric_result res = {id, data.sample_values}; +// results_map.emplace(id, res); +// expected_values.emplace(id, data.expected_values); +// ++id; +// } + +// std::unordered_map asts; +// for(auto [val, metric] : metrics) +// { +// RawAST* ast = nullptr; +// auto buf = yy_scan_string(metric.expression().empty() ? metric.name().c_str() +// : metric.expression().c_str()); +// yyparse(&ast); +// ASSERT_TRUE(ast); +// asts.emplace(val, std::move(EvaluateAST(metrics, *ast, "gfx9"))); +// yy_delete_buffer(buf); +// delete ast; +// } + +// for(auto [metric_name, ast] : asts) +// { +// double value = ast.evaluate(results_map); +// uint64_t metric_id = metrics.at(metric_name).id(); +// EXPECT_EQ(value, expected_values.at(metric_id)[0]); +// } +// } + +// TEST(evaluate_ast, evaluate_evaluate_simple_reduce) +// { +// std::unordered_map metrics; +// std::unordered_map results_map; +// std::unordered_map> expected_values; + +// uint64_t id = 0; +// for(auto& data : test_data_evaluate_simple_reduce) +// { +// metrics.emplace( +// data.name, Metric("gfx9", data.name, "Block", "0", "", data.expr, "", id)); +// metric_result res = {id, data.sample_values}; +// results_map.emplace(id, res); +// expected_values.emplace(id, data.expected_values); +// ++id; +// } + +// std::unordered_map asts; +// for(auto [val, metric] : metrics) +// { +// RawAST* ast = nullptr; +// auto buf = yy_scan_string(metric.expression().empty() ? metric.name().c_str() +// : metric.expression().c_str()); +// yyparse(&ast); +// ASSERT_TRUE(ast); +// asts.emplace(val, EvaluateAST(metrics, *ast, "gfx9")); +// yy_delete_buffer(buf); +// delete ast; +// } + +// for(auto [metric_name, ast]: asts){ +// double value = ast.evaluate(results_map); +// uint64_t metric_id = metrics.at(metric_name).id(); +// EXPECT_EQ(value, expected_values.at(metric_id)[0]); +// } +// } diff --git a/source/lib/rocprofiler/counters/tests/evaluate_ast_test.hpp b/source/lib/rocprofiler/counters/tests/evaluate_ast_test.hpp new file mode 100644 index 0000000000..a630ba8fc7 --- /dev/null +++ b/source/lib/rocprofiler/counters/tests/evaluate_ast_test.hpp @@ -0,0 +1,44 @@ +#pragma once + +#include +#include +#include +#include "lib/rocprofiler/counters/evaluate_ast.hpp" + +struct test_data +{ + std::string name; + std::string expr; + std::vector sample_values; + std::vector expected_values; +}; + +static const std::vector test_data_evaluate_simple_math = { + {"SQ_WAVES", "", {10, 20, 30}, {60}}, + {"TCC_HIT", "", {1, 2, 3, 4, 5}, {15}}, + {"SQ_INSTS_VALU", "", {2, 4, 6, 8}, {20}}, + + /* Add/Subtract/Multiply/Divide */ + {"Metric_1", "SQ_WAVES+TCC_HIT", {}, {75}}, + {"Metric_2", "SQ_WAVES-TCC_HIT", {}, {45}}, + {"Metric_3", "SQ_WAVES*TCC_HIT", {}, {900}}, + {"Metric_4", "SQ_WAVES/TCC_HIT", {}, {4}}, + + /* Order of Ops */ + {"Metric_5", "(SQ_WAVES+TCC_HIT)/SQ_INSTS_VALU", {}, {3.75}}, + {"Metric_6", "(SQ_WAVES/TCC_HIT)-SQ_INSTS_VALU", {}, {-16}}, + {"Metric_7", "SQ_WAVES/(TCC_HIT-SQ_INSTS_VALU)", {}, {-12}}, + {"Metric_8", "SQ_WAVES*(TCC_HIT/SQ_INSTS_VALU)", {}, {45}}}; + +static const std::vector test_data_evaluate_simple_reduce = { + {"SQ_WAVES", "", {10, 20, 30}, {60}}, + {"TCC_HIT", "", {1, 2, 3}, {6}}, + + /* Simple reduce operations */ + {"Metric_1", "reduce(SQ_WAVES, sum)", {}, {60}}, + {"Metric_2", "reduce(SQ_WAVES, sum, [DIMENSION_XCC])", {}, {60}}, + {"Metric_3", "reduce(SQ_WAVES, min, [DIMENSION_XCC])", {}, {10}}, + {"Metric_4", "reduce(SQ_WAVES, max, [DIMENSION_XCC])", {}, {30}}, + {"Metric_5", "reduce(SQ_WAVES, avr, [DIMENSION_XCC])", {}, {20}}, + {"Metric_6", "reduce(SQ_WAVES, sum) + reduce(SQ_WAVES, avr)", {}, {80}}, + {"Metric_7", "reduce(SQ_WAVES, max) - reduce(TCC_HIT, min)", {}, {29}}}; diff --git a/source/lib/rocprofiler/counters/tests/metrics_test.cpp b/source/lib/rocprofiler/counters/tests/metrics_test.cpp index 5d34ade974..9a81b845d7 100644 --- a/source/lib/rocprofiler/counters/tests/metrics_test.cpp +++ b/source/lib/rocprofiler/counters/tests/metrics_test.cpp @@ -1,5 +1,6 @@ #include "metrics_test.h" +#include #include #include "lib/rocprofiler/counters/metrics.hpp" @@ -17,7 +18,8 @@ loadTestData(const std::unordered_map{}).first->second; for(const auto& data_vec : dataMap) { - metric_vec.emplace_back(data_vec.at(0), + metric_vec.emplace_back("gfx9", + data_vec.at(0), data_vec.at(1), data_vec.at(2), data_vec.at(4), @@ -34,6 +36,7 @@ TEST(metrics, base_load) { auto rocp_data = counters::getBaseHardwareMetrics(); auto test_data = loadTestData(basic_gfx908); + ASSERT_EQ(rocp_data.count("gfx908"), 1); ASSERT_EQ(test_data.count("gfx908"), 1); auto rocp_data_v = rocp_data.at("gfx908"); @@ -41,7 +44,10 @@ TEST(metrics, base_load) EXPECT_EQ(rocp_data_v.size(), test_data_v.size()); auto find = [&rocp_data_v](const auto& v) -> std::optional { for(const auto& ditr : rocp_data_v) + { + LOG(ERROR) << fmt::format("{}", ditr); if(ditr.name() == v.name()) return ditr; + } return std::nullopt; }; auto equal = [](const auto& lhs, const auto& rhs) { diff --git a/source/lib/rocprofiler/counters/xml/basic_counters.xml b/source/lib/rocprofiler/counters/xml/basic_counters.xml index 9de1aef1c0..72e3569634 100755 --- a/source/lib/rocprofiler/counters/xml/basic_counters.xml +++ b/source/lib/rocprofiler/counters/xml/basic_counters.xml @@ -1,9 +1,9 @@ - - - + + + @@ -40,9 +40,9 @@ - - - + + + @@ -82,9 +82,9 @@ # EA1 - - - + + + @@ -120,9 +120,9 @@ - - - + + + @@ -388,9 +388,9 @@ - - - + + + @@ -661,9 +661,9 @@ - - - + + + @@ -726,9 +726,9 @@ - - - + + + diff --git a/source/lib/rocprofiler/counters/xml/derived_counters.xml b/source/lib/rocprofiler/counters/xml/derived_counters.xml index d9a47743b4..bbe3281c05 100755 --- a/source/lib/rocprofiler/counters/xml/derived_counters.xml +++ b/source/lib/rocprofiler/counters/xml/derived_counters.xml @@ -249,21 +249,21 @@ - + ## Local Data Share (LDS) Metrics - + ## L1I and sL1D Cache Metrics ## vL1D Cache Metrics - + diff --git a/source/lib/rocprofiler/profile_config.cpp b/source/lib/rocprofiler/profile_config.cpp index 8233633431..00c60a0ba0 100644 --- a/source/lib/rocprofiler/profile_config.cpp +++ b/source/lib/rocprofiler/profile_config.cpp @@ -34,19 +34,6 @@ rocprofiler_create_profile_config(rocprofiler_agent_t agent, const auto* metric_ptr = rocprofiler::common::get_val(id_map, counter_id.handle); if(!metric_ptr) return ROCPROFILER_STATUS_ERROR_COUNTER_NOT_FOUND; config.metrics.push_back(*metric_ptr); - - auto agent_name = std::string(agent.name); - auto req_counters = - rocprofiler::counters::get_required_hardware_counters(agent_name, *metric_ptr); - if(!req_counters) return ROCPROFILER_STATUS_ERROR_COUNTER_NOT_FOUND; - config.reqired_hw_counters.insert(req_counters->begin(), req_counters->end()); - - const auto& asts = rocprofiler::counters::get_ast_map(); - const auto* agent_map = rocprofiler::common::get_val(asts, agent_name); - if(!agent_map) return ROCPROFILER_STATUS_ERROR_COUNTER_NOT_FOUND; - const auto* counter_ast = rocprofiler::common::get_val(*agent_map, metric_ptr->name()); - if(!counter_ast) return ROCPROFILER_STATUS_ERROR_COUNTER_NOT_FOUND; - config.asts.push_back(*counter_ast); } config.agent = agent;