Received: by 2002:a05:6a10:16a7:0:0:0:0 with SMTP id gp39csp3872152pxb; Tue, 10 Nov 2020 02:09:27 -0800 (PST) X-Google-Smtp-Source: ABdhPJy6OR+emFnBXhlsJYsS0CLifhPAfMPJVXnDk24As2kJG/YPemsykGHmAX1+jnrkYkGjNS7Y X-Received: by 2002:a17:906:4803:: with SMTP id w3mr18874667ejq.406.1605002967471; Tue, 10 Nov 2020 02:09:27 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1605002967; cv=none; d=google.com; s=arc-20160816; b=nuqxmRoVu1xtZ8/EFzZ22GFlOSF9dkE/2EYPkwpD32e87RJmvz2sUx9bsjnXsy/afM uwD3CL9/YTcSPM2umEEd398LHAOAm9euBWgi6au/IptnvtAIn6x0QIWeh8moKXWxYWSr jQFfwXM5/WuO68D98Tu9ENbQ38dTR8lod3tcVOb7HOoKmJM4lkhNhAssdMpm82ZKKdvR dgHoK3hkGEcAYIf5coxAVz7s8z0fRukafKz1PudXTPHbizv0OaGr1tDbjjS8BgUQSWR0 PTJ1lqYNrm2+Zqw4wyY8JFso2pC7vNbxAV/xAjr7luWpZ+ZMoBbPUb6MAZhSaBL1kfBs c3Ag== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:from:subject:references:mime-version :message-id:in-reply-to:date:sender:dkim-signature; bh=ksJMouSMDrfRXUNPlh4s9tAvLXsLzLqL9fqc/spB93U=; b=1FBMOruApl2dhC4Ae6iQO2U8QqAS4vn5zliLBgX8stG+vLKcybako0ma9Hbz2NAcdQ nzTAjYy15v33QqMu1pV5fG9GhfXb0h1mSG6cDhti2IBFajxYbyb7cmx2qZd+9ATiWa3B wGuzwbGbXMJjzIsiT4TvacPF7qN0XuiELslG6D2r0ihCaixxsa51WDMHXb83tfB9Eiza ffkFeQzUchvWxxFsogMnuHC+cX5usd5CX0XYVZPzr63pbivAL0AOySWrgH8rIhtqWaBE zTgMv6hFhtNgDqoHvsdCwucWBciMnS85xIZV5tnSH2nWuepnhAXXkT3Dl+a92WRmXwl2 6e9A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=XA8orP6Z; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id r7si8893688ejc.705.2020.11.10.02.09.04; Tue, 10 Nov 2020 02:09:27 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=XA8orP6Z; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731738AbgKJKER (ORCPT + 99 others); Tue, 10 Nov 2020 05:04:17 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47430 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731275AbgKJKEO (ORCPT ); Tue, 10 Nov 2020 05:04:14 -0500 Received: from mail-qv1-xf49.google.com (mail-qv1-xf49.google.com [IPv6:2607:f8b0:4864:20::f49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E8F35C0613CF for ; Tue, 10 Nov 2020 02:04:11 -0800 (PST) Received: by mail-qv1-xf49.google.com with SMTP id t13so7705233qvm.14 for ; Tue, 10 Nov 2020 02:04:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=sender:date:in-reply-to:message-id:mime-version:references:subject :from:to:cc; bh=ksJMouSMDrfRXUNPlh4s9tAvLXsLzLqL9fqc/spB93U=; b=XA8orP6ZKP+sdOPpU5pX0UJd3kUcoe/LAqdg19LkQSbqw9wOenGMGPHvHmmnv8J95s 3BwsAsJRvTj+nF6lAvh7lkoMz++ExTXe5oN7l/FRBeg6B5fqawRwWpD4ht6UcQ+Amb0J 3LaO9ACuxDbS9RCekU5YD4JVHI5q71gh8hW0hiuwRwoh8qK8KuglYKJvqlPAcyIg4bXz aX4cVo8yimyHu9BkG8yHSVibRZlVDE0maJw6AvyO2opzvuT1FGBOTEplgOKeMSzrLtZF aCeHxiM8VKZrh44Txts7pyLfYmKKrQoc4fODJpyc6vEHjLnA8k/c425wrlL2wwSOTzdu kTnA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=ksJMouSMDrfRXUNPlh4s9tAvLXsLzLqL9fqc/spB93U=; b=M/F4xqKkZfLmejPL/a3CMPEMTqR4QwCEb994N4NvxiBacMijR58TmW4kYGdLeXBacy BVt/3jGpo5ks5bduurb9rwmadIr+qBNRhQ7t16EcW8DF4Tzr8PJNAZM+HmTKZrIfB1Ds DzaJ0Y9u0hVIVM5381O4dzD6fsLMzua/PnyJ9cFBb0QzyiphsgX5j+Ek9i2r3unQJziD WLObZCTELdvd9Nx4zBawQvC/PWRc7rFScAuGnAvoU5A+CCjpccnHFT3Ie/Eh05ZeYA3N geerd2EHLgjun9BT0hbkPZox0psmmxwBD0GczHIG0veUtrYRG01/2yD6GjKfOCZsJuVT YW6Q== X-Gm-Message-State: AOAM530wddDTnh+q4A5nehacxVqd3ICBGU8ffkxjHSzIuD/xqksq3MlF tYK0fER8Lx44qe7nDTlBTqeM75i4xpsw Sender: "irogers via sendgmr" X-Received: from irogers.svl.corp.google.com ([2620:15c:2cd:2:f693:9fff:fef4:4583]) (user=irogers job=sendgmr) by 2002:a0c:eccb:: with SMTP id o11mr7004222qvq.0.1605002651100; Tue, 10 Nov 2020 02:04:11 -0800 (PST) Date: Tue, 10 Nov 2020 02:03:41 -0800 In-Reply-To: <20201110100346.2527031-1-irogers@google.com> Message-Id: <20201110100346.2527031-8-irogers@google.com> Mime-Version: 1.0 References: <20201110100346.2527031-1-irogers@google.com> X-Mailer: git-send-email 2.29.2.222.g5d2a92d10f8-goog Subject: [RFC PATCH 07/12] perf topdown-parser: Metric expression parser. From: Ian Rogers To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , linux-kernel@vger.kernel.org, Andi Kleen , Jin Yao , John Garry , Paul Clarke , kajoljain Cc: Stephane Eranian , Sandeep Dasgupta , linux-perf-users@vger.kernel.org, Ian Rogers Content-Type: text/plain; charset="UTF-8" Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Sandeep Dasgupta A parser capable of processing metrics found in TMA_Metrics.csv. Co-authored-by: Ian Rogers Signed-off-by: Ian Rogers Signed-off-by: Sandeep Dasgupta --- .../pmu-events/topdown-parser/expr_parser.y | 224 ++++++++++++++++++ 1 file changed, 224 insertions(+) create mode 100644 tools/perf/pmu-events/topdown-parser/expr_parser.y diff --git a/tools/perf/pmu-events/topdown-parser/expr_parser.y b/tools/perf/pmu-events/topdown-parser/expr_parser.y new file mode 100644 index 000000000000..ddf635a6470c --- /dev/null +++ b/tools/perf/pmu-events/topdown-parser/expr_parser.y @@ -0,0 +1,224 @@ +/* + * Copyright 2020 Google LLC. + * SPDX-License-Identifier: GPL-2.0 + */ + +/* Topdown expression parser */ +%language "c++" +%define api.value.type variant + +%code requires { +#include +} + +/* Increase error verbosity. */ +%define parse.trace +%define parse.error verbose +/* Semantic value printer. */ +%printer { yyo << $$; } <*>; + + +/* Inputs for the parser and yylex. */ +%param { const std::string &input } +%param { size_t *cursor } +/* Inputs/output for the parser. */ +%parse-param { bool convert_if_stmt } +%parse-param { bool remove_false_branch } +%parse-param { bool wrap_div_in_function } +%parse-param { std::string *final_val } + +/* Tokens returned by yylex. */ +%define api.token.prefix {TOK_} +%token + MIN + MAX + IF + ELSE + MODEL + IN + NEG + EOF 0 +%token ID_OR_NUM + +/* Type of non-terminal expressions. */ +%type expr if_expr IDS + +/* Presidence and associativity. */ +%left MIN MAX MODEL IN +%right ELSE +%right IF +%left '=' +%left '<' '>' +%left '-' '+' +%left '*' '/' '%' +%left NEG + +%code { +static int yylex(yy::parser::semantic_type *res, + const std::string &input, + size_t *cursor); + +void yy::parser::error (const std::string& m) +{ +// ERROR(m << '\n' << "Input:\n" << input << "\nCursor: " << *cursor); +} + +} + +%% +%start all_expr; +all_expr: expr EOF { *final_val = $1; } ; + +IDS: +'\'' ID_OR_NUM '\'' { $$ = std::string(" ") + $2 + " "; } +| +IDS '\'' ID_OR_NUM '\'' { $$ = $1 + " " + $3 + " "; } +; + +if_expr: +expr IF expr ELSE expr +{ + if (convert_if_stmt) + $$ = $3 + " ? " + $1 + " : " + $5; + else + $$ = $1 + " if " + $3 + " else " + $5; + + if (remove_false_branch) { + if (std::string::npos != $3.find("0.000", 0)) + $$ = $5; + else if (std::string::npos != $3.find("1.000", 0)) + $$ = $1; + } +} +| +expr IF MODEL IN '[' IDS ']' ELSE expr +{ + $$ = std::string("#Model in [ ") + $6 + " ] ? " + $1 + " : " + $9; +} +; + +expr: +ID_OR_NUM { $$ = $1; } +| +expr '+' expr { $$ = $1 + " + " + $3; } +| +expr '-' expr { $$ = $1 + " - " + $3; } +| +expr '*' expr { $$ = $1 + " * " + $3; } +| +expr '>' expr { $$ = $1 + " > " + $3; } +| +expr '<' expr { $$ = $1 + " < " + $3; } +| +expr '%' expr { $$ = $1 + " % " + $3; } +| +'(' expr ')' { $$ = std::string("( ") + $2 + " )"; } +| +expr '=' '=' expr { $$ = $1 + " == " + $4; } +| +'-' expr %prec NEG { $$ = std::string(" - ") + $2; } +| +expr '/' expr +{ + if (wrap_div_in_function) + $$ = std::string("d_ratio ( ") + $1 + " , " + $3 + " )"; + else + $$ = $1 + " / " + $3; +} +| +MIN '(' expr ',' expr ')' +{ + $$ = std::string("min ( ") + $3 + " , " + $5 + " )"; +} +| +MAX '(' expr ',' expr ')' +{ + $$ = std::string("max ( ") + $3 + " , " + $5 + " )"; +} +| +if_expr +{ + if (convert_if_stmt) + $$ = std::string("( ") + $1 + " )"; + else + $$ = $1; +} +; + +%% +static int expr__symbol(yy::parser::semantic_type *res, + size_t p, + const std::string &input, + size_t *cursor) +{ + std::string dst; + + if (input[p] == '#') + dst += input[p++]; + + while (p < input.size() && + (isalnum(input[p]) || + input[p] == '_' || + input[p] == '.' || + input[p] == ':' || + input[p] == '@' || + input[p] == '\\' || + input[p] == '=') + ) { + if(input[p] == '\\') { + // Consume 2 consequitive '\\' and the escaped char. + dst += input[p++]; + if (p >= input.size()) + break; + dst += input[p++]; + if (p >= input.size()) + break; + } + dst += input[p++]; + } + *cursor = p; + if (p >= input.size() && dst.empty()) + return yy::parser::token::TOK_EOF; + if (dst == "min") return yy::parser::token::TOK_MIN; + if (dst == "max") return yy::parser::token::TOK_MAX; + if (dst == "if") return yy::parser::token::TOK_IF; + if (dst == "in") return yy::parser::token::TOK_IN; + if (dst == "else") return yy::parser::token::TOK_ELSE; + if (dst == "#Model") return yy::parser::token::TOK_MODEL; + res->emplace(dst); + return yy::parser::token::TOK_ID_OR_NUM; +} + +static int yylex(yy::parser::semantic_type *res, + const std::string &input, + size_t *cursor) +{ + size_t p = *cursor; + + // Skip spaces. + while (p < input.size() && isspace(input[p])) + p++; + + if (p >= input.size()) { + *cursor = p; + return yy::parser::token::TOK_EOF; + } + switch (input[p]) { + case '#': + case 'a' ... 'z': + case 'A' ... 'Z': + return expr__symbol(res, p, input, cursor); + case '0' ... '9': case '.': { + // Read the number and regularize numbers starting + // with '.' adjusting the cursor to after the number. + const size_t s = p; + res->emplace( + std::to_string(std::stod(input.substr(p), &p))); + *cursor = p + s; + return yy::parser::token::TOK_ID_OR_NUM; + } + default: + *cursor = p + 1; + return input[p]; + } +} -- 2.29.2.222.g5d2a92d10f8-goog