summaryrefslogtreecommitdiff
path: root/src/cpu/timing_expr.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/cpu/timing_expr.cc')
-rw-r--r--src/cpu/timing_expr.cc248
1 files changed, 248 insertions, 0 deletions
diff --git a/src/cpu/timing_expr.cc b/src/cpu/timing_expr.cc
new file mode 100644
index 000000000..d6d904956
--- /dev/null
+++ b/src/cpu/timing_expr.cc
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 2013-2014 ARM Limited
+ * All rights reserved.
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Andrew Bardsley
+ */
+
+#include "base/intmath.hh"
+#include "cpu/timing_expr.hh"
+
+TimingExprEvalContext::TimingExprEvalContext (StaticInstPtr inst_,
+ ThreadContext *thread_,
+ TimingExprLet *let_) :
+ inst(inst_), thread(thread_), let(let_)
+{
+ /* Reserve space to hold the results of evaluating the
+ * let expressions */
+ if (let) {
+ unsigned int num_defns = let->defns.size();
+
+ results.resize(num_defns, 0);
+ resultAvailable.resize(num_defns, false);
+ }
+}
+
+uint64_t TimingExprSrcReg::eval(TimingExprEvalContext &context)
+{
+ return context.inst->srcRegIdx(index);
+}
+
+uint64_t TimingExprReadIntReg::eval(TimingExprEvalContext &context)
+{
+ return context.thread->readIntReg(reg->eval(context));
+}
+
+uint64_t TimingExprLet::eval(TimingExprEvalContext &context)
+{
+ TimingExprEvalContext new_context(context.inst,
+ context.thread, this);
+
+ return expr->eval(new_context);
+}
+
+uint64_t TimingExprRef::eval(TimingExprEvalContext &context)
+{
+ /* Lookup the result, evaluating if necessary. @todo, this
+ * should have more error checking */
+ if (!context.resultAvailable[index]) {
+ context.results[index] = context.let->defns[index]->eval(context);
+ context.resultAvailable[index] = true;
+ }
+
+ return context.results[index];
+}
+
+uint64_t TimingExprUn::eval(TimingExprEvalContext &context)
+{
+ uint64_t arg_value = arg->eval(context);
+ uint64_t ret = 0;
+
+ switch (op) {
+ case Enums::timingExprSizeInBits:
+ if (arg_value == 0)
+ ret = 0;
+ else
+ ret = ceilLog2(arg_value);
+ break;
+ case Enums::timingExprNot:
+ ret = arg_value != 0;
+ break;
+ case Enums::timingExprInvert:
+ ret = ~arg_value;
+ break;
+ case Enums::timingExprSignExtend32To64:
+ ret = static_cast<int64_t>(
+ static_cast<int32_t>(arg_value));
+ break;
+ case Enums::timingExprAbs:
+ if (static_cast<int64_t>(arg_value) < 0)
+ ret = -arg_value;
+ else
+ ret = arg_value;
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+uint64_t TimingExprBin::eval(TimingExprEvalContext &context)
+{
+ uint64_t left_value = left->eval(context);
+ uint64_t right_value = right->eval(context);
+ uint64_t ret = 0;
+
+ switch (op) {
+ case Enums::timingExprAdd:
+ ret = left_value + right_value;
+ break;
+ case Enums::timingExprSub:
+ ret = left_value - right_value;
+ break;
+ case Enums::timingExprUMul:
+ ret = left_value * right_value;
+ break;
+ case Enums::timingExprUDiv:
+ if (right_value != 0) {
+ ret = left_value / right_value;
+ }
+ break;
+ case Enums::timingExprUCeilDiv:
+ if (right_value != 0) {
+ ret = (left_value + (right_value - 1)) / right_value;
+ }
+ break;
+ case Enums::timingExprSMul:
+ ret = static_cast<int64_t>(left_value) *
+ static_cast<int64_t>(right_value);
+ break;
+ case Enums::timingExprSDiv:
+ if (right_value != 0) {
+ ret = static_cast<int64_t>(left_value) /
+ static_cast<int64_t>(right_value);
+ }
+ break;
+ case Enums::timingExprEqual:
+ ret = left_value == right_value;
+ break;
+ case Enums::timingExprNotEqual:
+ ret = left_value != right_value;
+ break;
+ case Enums::timingExprULessThan:
+ ret = left_value < right_value;
+ break;
+ case Enums::timingExprUGreaterThan:
+ ret = left_value > right_value;
+ break;
+ case Enums::timingExprSLessThan:
+ ret = static_cast<int64_t>(left_value) <
+ static_cast<int64_t>(right_value);
+ break;
+ case Enums::timingExprSGreaterThan:
+ ret = static_cast<int64_t>(left_value) >
+ static_cast<int64_t>(right_value);
+ break;
+ case Enums::timingExprAnd:
+ ret = (left_value != 0) && (right_value != 0);
+ break;
+ case Enums::timingExprOr:
+ ret = (left_value != 0) || (right_value != 0);
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+uint64_t TimingExprIf::eval(TimingExprEvalContext &context)
+{
+ uint64_t cond_value = cond->eval(context);
+
+ if (cond_value != 0)
+ return trueExpr->eval(context);
+ else
+ return falseExpr->eval(context);
+}
+
+TimingExprLiteral *
+TimingExprLiteralParams::create()
+{
+ return new TimingExprLiteral(this);
+}
+
+TimingExprSrcReg *
+TimingExprSrcRegParams::create()
+{
+ return new TimingExprSrcReg(this);
+}
+
+TimingExprReadIntReg *
+TimingExprReadIntRegParams::create()
+{
+ return new TimingExprReadIntReg(this);
+}
+
+TimingExprLet *
+TimingExprLetParams::create()
+{
+ return new TimingExprLet(this);
+}
+
+TimingExprRef *
+TimingExprRefParams::create()
+{
+ return new TimingExprRef(this);
+}
+
+TimingExprUn *
+TimingExprUnParams::create()
+{
+ return new TimingExprUn(this);
+}
+
+TimingExprBin *
+TimingExprBinParams::create()
+{
+ return new TimingExprBin(this);
+}
+
+TimingExprIf *
+TimingExprIfParams::create()
+{
+ return new TimingExprIf(this);
+}