/*
 * Copyright (c) 2018 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 here under.  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.
 */

/**
 * @file
 * Declaration of the Stream generator for issuing memory requests
 * with variable/fixed stream and substream IDs.
 */

#ifndef __CPU_TRAFFIC_GEN_STREAM_GEN_HH__
#define __CPU_TRAFFIC_GEN_STREAM_GEN_HH__

#include "params/BaseTrafficGen.hh"

namespace gem5
{

class StreamGen
{
  protected:
    StreamGen(const BaseTrafficGenParams &p)
      : streamIds(p.sids), substreamIds(p.ssids)
    {
        // A non empty vector of StreamIDs must be provided.
        // SubstreamIDs are not mandatory hence having an empty
        // vector means that they are not used and no configuration
        // error must be thrown
        fatal_if(streamIds.empty(),
            "Must provide a vector of StreamIDs");
    }

  public:
    virtual ~StreamGen() {};

    virtual uint32_t pickStreamID() = 0;
    virtual uint32_t pickSubstreamID() = 0;

    /**
     * Factory method for constructing a Stream generator.
     * The Stream generator type is selected by the
     * StreamGenType enum parameter.
     *
     * @params p pointer to BaseTrafficGenParams struct where
     *           the stream generator type is stored.
     * @return a pointer to the newly alocated StremGen
     */
    static StreamGen* create(const BaseTrafficGenParams &p);

    /**
     * Returns true if the substreamID generation is valid
     * and hence should be taken into account.
     * It is valid if the set of substreamIDs passed as a
     * parameter to the TrafficGenerator is a non empty list.
     *
     * @return true if ssid is valid, false otherwise
     */
    bool ssidValid() const { return !substreamIds.empty(); }

  protected:
    /**
     * Store preset Stream and Substream IDs to use for requests
     * This is the set of available streamIDs the generator can
     * pick. The actual ID being picked for a specific memory
     * request is selected by the pickStreamID and pickSubstreamID
     * methods.
     */
    std::vector<uint32_t> streamIds;
    std::vector<uint32_t> substreamIds;
};

class FixedStreamGen : public StreamGen
{
  public:
    FixedStreamGen(const BaseTrafficGenParams &p)
      : StreamGen(p)
    {
        // For a fixed stream generator only one sid must be provided. The
        // ssid can have either 0 (not used) or 1 value.
        fatal_if(streamIds.size() != 1 || substreamIds.size() > 1,
                 "Invalid sids/ssids configuration");
    }

    uint32_t pickStreamID() override
    { return streamIds[0]; }

    uint32_t pickSubstreamID() override
    { return substreamIds[0]; }
};

class RandomStreamGen : public StreamGen
{
  public:
    RandomStreamGen(const BaseTrafficGenParams &p)
      : StreamGen(p)
    {}

    uint32_t pickStreamID() override
    { return randomPick(streamIds); }

    uint32_t pickSubstreamID() override
    { return randomPick(substreamIds); }

  protected:
    /** Function to pick one of the preset Stream or Substream ID */
    uint32_t randomPick(const std::vector<uint32_t> &svec);
};

} // namespace gem5

#endif // __CPU_TRAFFIC_GEN_STREAM_GEN_HH__
