power: Add error checking to MathExprPowerModel

MathExprPower model currently doesn't print any useful error messages
if an expression fails to evaluate. To add insult to injury, the model
only detects a failure when dumping stats and not at
initialization. This change adds a verification step in startup() that
ensures that all of the referenced stats actually exist.

Change-Id: I8f71c73341578d5882c8d93e482f5383fbda5f1d
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
Reviewed-by: Sascha Bischoff <sascha.bischoff@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/2661
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Maintainer: Jason Lowe-Power <jason@lowepower.com>
This commit is contained in:
Andreas Sandberg
2017-04-05 16:38:00 +01:00
parent 01bc2ea80d
commit 0b223f4001
2 changed files with 78 additions and 18 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016 ARM Limited
* Copyright (c) 2016-2017 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -46,7 +46,7 @@
#include "sim/sim_object.hh"
MathExprPowerModel::MathExprPowerModel(const Params *p)
: PowerModelState(p), dyn_expr(p->dyn), st_expr(p->st)
: PowerModelState(p), dyn_expr(p->dyn), st_expr(p->st), failed(false)
{
// Calculate the name of the object we belong to
std::vector<std::string> path;
@@ -65,8 +65,50 @@ MathExprPowerModel::startup()
for (auto & i: Stats::statsList())
if (i->name.find(basename) == 0)
stats_map[i->name.substr(basename.size())] = i;
tryEval(st_expr);
const bool st_failed = failed;
tryEval(dyn_expr);
const bool dyn_failed = failed;
if (st_failed || dyn_failed) {
const auto *p = dynamic_cast<const Params *>(params());
assert(p);
fatal("Failed to evaluate power expressions:\n%s%s%s\n",
st_failed ? p->st : "",
st_failed && dyn_failed ? "\n" : "",
dyn_failed ? p->dyn : "");
}
}
double
MathExprPowerModel::eval(const MathExpr &expr) const
{
const double value = tryEval(expr);
// This shouldn't happen unless something went wrong the equations
// were verified in startup().
panic_if(failed, "Failed to evaluate power expression '%s'\n",
expr.toStr());
return value;
}
double
MathExprPowerModel::tryEval(const MathExpr &expr) const
{
failed = false;
const double value = expr.eval(
std::bind(&MathExprPowerModel::getStatValue,
this, std::placeholders::_1)
);
return value;
}
double
MathExprPowerModel::getStatValue(const std::string &name) const
{
@@ -77,12 +119,19 @@ MathExprPowerModel::getStatValue(const std::string &name) const
return _temp;
// Try to cast the stat, only these are supported right now
Info *info = stats_map.at(name);
const auto it = stats_map.find(name);
if (it == stats_map.cend()) {
warn("Failed to find stat '%s'\n", name);
failed = true;
return 0;
}
ScalarInfo *si = dynamic_cast<ScalarInfo*>(info);
const Info *info = it->second;
auto si = dynamic_cast<const ScalarInfo *>(info);
if (si)
return si->value();
FormulaInfo *fi = dynamic_cast<FormulaInfo*>(info);
auto fi = dynamic_cast<const FormulaInfo *>(info);
if (fi)
return fi->total();

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016 ARM Limited
* Copyright (c) 2016-2017 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -66,24 +66,14 @@ class MathExprPowerModel : public PowerModelState
*
* @return Power (Watts) consumed by this object (dynamic component)
*/
double getDynamicPower() const {
return dyn_expr.eval(
std::bind(&MathExprPowerModel::getStatValue,
this, std::placeholders::_1)
);
}
double getDynamicPower() const { return eval(dyn_expr); }
/**
* Get the static power consumption.
*
* @return Power (Watts) consumed by this object (static component)
*/
double getStaticPower() const {
return st_expr.eval(
std::bind(&MathExprPowerModel::getStatValue,
this, std::placeholders::_1)
);
}
double getStaticPower() const { return eval(st_expr); }
/**
* Get the value for a variable (maps to a stat)
@@ -99,6 +89,23 @@ class MathExprPowerModel : public PowerModelState
void regStats();
private:
/**
* Evaluate an expression in the context of this object, fatal if
* evaluation fails.
*
* @param expr Expression to evaluate
* @return Value of expression.
*/
double eval(const MathExpr &expr) const;
/**
* Evaluate an expression in the context of this object, set
* failed if evaluation failed.
*
* @param expr Expression to evaluate
* @return Value of expression.
*/
double tryEval(const MathExpr &expr) const;
// Math expressions for dynamic and static power
MathExpr dyn_expr, st_expr;
@@ -108,6 +115,10 @@ class MathExprPowerModel : public PowerModelState
// Map that contains relevant stats for this power model
std::unordered_map<std::string, Stats::Info*> stats_map;
// Did the expression fail to evaluate (e.g., because a stat value
// can't be resolved)
mutable bool failed;
};
#endif