/*
 * Copyright (c) 2001-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * 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.
 */

#ifndef __SAT_COUNTER_HH__
#define __SAT_COUNTER_HH__

#include <string>

#include "base/predictor.hh"

#include "base/statistics.hh"
#include "sim/stats.hh"

//
//
//  A simple saturating counter predictor
//
//
class SaturatingCounterPred : public GenericPredictor
{
  private:
    std::string   pred_name;
    std::string   zero_name;
    std::string   one_name;

    unsigned index_bits;
    unsigned counter_bits;
    unsigned zero_change;
    unsigned one_change;
    unsigned thresh;
    unsigned init_value;

    unsigned max_value;       // maximum counter value

    unsigned long max_index;  // also the index mask value
    unsigned *table;

    //  Statistics
    Stats::Scalar<> predicted_one;      // Total predictions of one, preds_one
    Stats::Scalar<> predicted_zero;     // Total predictions of zero, preds_zero
    Stats::Scalar<> correct_pred_one;   // Total correct predictions of one, correct_one
    Stats::Scalar<> correct_pred_zero;  // Total correct predictions of zero, correct_zero

    Stats::Scalar<> record_zero;        //updates_zero
    Stats::Scalar<> record_one;         //updates_one

    Stats::Formula preds_total;
    Stats::Formula pred_frac_zero;
    Stats::Formula pred_frac_one;
    Stats::Formula correct_total;
    Stats::Formula updates_total;
    Stats::Formula pred_rate;
    Stats::Formula frac_correct_zero;
    Stats::Formula frac_correct_one;
    Stats::Formula coverage_zero;
    Stats::Formula coverage_one;

  private:
    bool pred_one(unsigned &counter)  { return counter >  thresh; }
    bool pred_zero(unsigned &counter) { return counter <= thresh; }

    void update_one(unsigned &counter) {

        if (one_change)
            counter += one_change;
        else
            counter = 0;

        // check for wrap
        if (counter > max_value)
            counter = max_value;
    }

    void update_zero(unsigned &counter) {
        if (zero_change) {
            // check for wrap
            if (counter < zero_change)
                counter = 0;
            else
                counter -= zero_change;
        } else
            counter = 0;
    }


  public:

    SaturatingCounterPred(std::string p_name,
                          std::string z_name, std::string o_name,
                          unsigned _index_bits, unsigned _counter_bits = 2,
                          unsigned _zero_change = 1, unsigned _one_change = 1,
                          unsigned _thresh = 1, unsigned _init_value = 0);

    void clear() {
        for (int i = 0; i <= max_index; ++i)
            table[i] = init_value;
    }

    //  Record the ACTUAL result... and indicate whether the prediction
    //  corresponding to this event was correct
    void record(unsigned long _index, unsigned _val, unsigned _predicted,
                unsigned _pdata)
    {
        record(_index, _val, _predicted);
    }

    void record(unsigned long _index, unsigned _val, unsigned _predicted) {
        unsigned long index = _index & max_index;

        if (_val) {
            update_one(table[index]);
            ++record_one;

            if (_predicted)
                ++correct_pred_one;
        } else {
            update_zero(table[index]);
            ++record_zero;

            if (!_predicted)
                ++correct_pred_zero;
        }
    }

    unsigned value(unsigned long _index) {
        unsigned long index = _index & max_index;

        return table[index];
    }


    unsigned predict(unsigned long _index, unsigned &pdata) {
        return predict(_index);
    }

    unsigned predict(unsigned long _index) {
        unsigned long index = _index & max_index;

        if (pred_one(table[index])) {
            ++predicted_one;
            return 1;
        }

        ++predicted_zero;
        return 0;
    }

    //  No internal state is changed here
    unsigned peek(unsigned long _index) {
        unsigned long index = _index & max_index;

        if (pred_one(table[index]))
            return 1;

        return 0;
    }


    //=======================================================
    void regStats();
    void regFormulas();
};


#endif // __SAT_COUNTER_HH__
