power: add parsing of Vector2d stats for power eq
Adding parsing of Vector2d stats (such as issue queue instruction class
counts in O3) to the equation parser. This is a little tedious as
* Vector2d (or rather the associated Info class) does not allow access
to the actual data; instead, one has to pretend printing the stat and
the data is copied over into an accessible array (cvec)
* the parsing of the 2d stat names, because well.. parsing :)
Added a cache for Vector2d name to fully parsed out stat + index so that
we don't have to run through the parsing code every time we print stats.
Change-Id: I8eb821c05ee60b53a869bbd73164e91dba53400b
Signed-off-by: Stephan Diestelhorst <stephan.diestelhorst@arm.com>
diff --git a/src/sim/mathexpr.cc b/src/sim/mathexpr.cc
index 10d6cb7..75e9f50 100644
--- a/src/sim/mathexpr.cc
+++ b/src/sim/mathexpr.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016 ARM Limited
+ * Copyright (c) 2016,2019 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -71,7 +71,7 @@
* It will look for operators in priority order to recursively build the
* tree, respecting parenthesization.
* Constants can be expressed in any format accepted by std::stod, whereas
- * variables are essentially [A-Za-z0-9\.$\\]+
+ * variables are essentially [A-Za-z0-9\.$:\\]+
*/
MathExpr::Node *
MathExpr::parse(std::string expr) {
@@ -135,7 +135,7 @@
!( (c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') ||
(c >= '0' && c <= '9') ||
- c == '$' || c == '\\' || c == '.' || c == '_');
+ c == '$' || c == '\\' || c == '.' || c == '_' || c == ':');
if (!contains_non_alpha) {
Node * n = new Node();
@@ -145,6 +145,8 @@
}
}
+ warn("Expression parser could not parse %s", expr.c_str());
+
return NULL;
}
diff --git a/src/sim/power/mathexpr_powermodel.cc b/src/sim/power/mathexpr_powermodel.cc
index ab48720..0e132ed 100644
--- a/src/sim/power/mathexpr_powermodel.cc
+++ b/src/sim/power/mathexpr_powermodel.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017 ARM Limited
+ * Copyright (c) 2016-2017,2019 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -39,6 +39,8 @@
#include "sim/power/mathexpr_powermodel.hh"
+#include <algorithm>
+#include <regex>
#include <string>
#include "base/statistics.hh"
@@ -116,7 +118,74 @@
return value;
}
+#define ALL(x) x.cbegin(), x.cend()
+static int
+getVecStatIdx(const std::vector<std::string>& names, const std::string &tag)
+{
+ auto is_empty =[](const std::string &s) {return s.empty();};
+ bool empty = names.empty() ||
+ std::all_of(ALL(names), is_empty);
+ // Indices can either be tags or numerical; the stats system uses the tags
+ // if they exist
+ if (empty)
+ return std::stoi(tag);
+
+ auto pos = find(ALL(names), tag);
+ if (pos == names.cend()) {
+ warn("Could not find %s in vector stats", tag);
+ return -1;
+ }
+ return pos - names.cbegin();
+}
+#undef ALL
+
+struct V2D_Cache {
+ Stats::Vector2dInfo *info;
+ int idx;
+};
+
+bool MathExprPowerModel::parseVec2dStat(std::string name, Stats::Vector2dInfo
+ **out_v2di, int *out_idx) const {
+ using namespace Stats;
+
+ // Prune the name for vector stats, they look like this:
+ // iq.FU_type_0::Alu, really meaning iq.FU_type[0][Alu]
+ std::regex split("([._[:alnum:]]*)_(\\w*)::(\\w*)");
+ std::smatch results;
+
+ bool matched = regex_match(name, results, split);
+ panic_if(!matched, "Could not match stat name %s", name.c_str());
+
+ auto bname = results[1];
+ auto xtag = results[2];
+ auto ytag = results[3];
+
+ auto it = stats_map.find(bname);
+ if (it == stats_map.cend()) {
+ warn("Failed to find stat '%s'\n", name);
+ failed = true;
+ return false;
+ }
+ Info *info = it->second;
+ auto v2di = dynamic_cast<Vector2dInfo *>(info);
+ if (!v2di)
+ return false;
+
+ int xidx = getVecStatIdx(v2di->subnames, xtag);
+ int yidx = getVecStatIdx(v2di->y_subnames, ytag);
+
+ if (xidx == -1 || yidx == -1)
+ return false;
+
+ assert (0 <= xidx && xidx < v2di->x);
+ assert (0 <= yidx && yidx < v2di->y);
+ int idx = xidx * v2di->y + yidx;
+
+ *out_idx = idx;
+ *out_v2di = v2di;
+ return true;
+}
double
MathExprPowerModel::getStatValue(const std::string &name) const
{
@@ -129,6 +198,27 @@
return clocked_object->voltage();
}
+ // Check for a Vector 2D stat; first in cache
+ static std::unordered_map<std::string, V2D_Cache> v2d_cache;
+ auto v2d = v2d_cache.find(name);
+ if (v2d != v2d_cache.end()) {
+ // Found, pull out the data
+ auto v2di = v2d->second.info;
+ // cvec data is only initialised in prepare()
+ v2di->prepare();
+ return v2di->cvec[v2d->second.idx];
+ } else if (name.find("::") != name.npos) {
+ // Not found, but looks like a Vector 2D stat -> parse and add
+ Vector2dInfo *v2di;
+ int idx;
+ if (parseVec2dStat(name, &v2di, &idx)) {
+ // Add to cache
+ v2d_cache.emplace(name, V2D_Cache {v2di, idx});
+ v2di->prepare();
+ return v2di->cvec[idx];
+ }
+ }
+
// Try to cast the stat, only these are supported right now
const auto it = stats_map.find(name);
if (it == stats_map.cend()) {
diff --git a/src/sim/power/mathexpr_powermodel.hh b/src/sim/power/mathexpr_powermodel.hh
index b4d0254..e15d6e7 100644
--- a/src/sim/power/mathexpr_powermodel.hh
+++ b/src/sim/power/mathexpr_powermodel.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017 ARM Limited
+ * Copyright (c) 2016-2017,2019 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -107,6 +107,9 @@
*/
double tryEval(const MathExpr &expr) const;
+ bool parseVec2dStat(std::string name, Stats::Vector2dInfo **out_v2di,
+ int *out_idx) const;
+
// Math expressions for dynamic and static power
MathExpr dyn_expr, st_expr;