/*
 * Copyright (c) 2012-2013, 2016-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 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: Thomas Grass
 *          Andreas Hansson
 *          Sascha Bischoff
 */
#include "cpu/testers/traffic_gen/base.hh"

#include <sstream>

#include "base/intmath.hh"
#include "base/random.hh"
#include "config/have_protobuf.hh"
#include "cpu/testers/traffic_gen/base_gen.hh"
#include "cpu/testers/traffic_gen/dram_gen.hh"
#include "cpu/testers/traffic_gen/dram_rot_gen.hh"
#include "cpu/testers/traffic_gen/exit_gen.hh"
#include "cpu/testers/traffic_gen/idle_gen.hh"
#include "cpu/testers/traffic_gen/linear_gen.hh"
#include "cpu/testers/traffic_gen/random_gen.hh"
#include "cpu/testers/traffic_gen/stream_gen.hh"
#include "debug/Checkpoint.hh"
#include "debug/TrafficGen.hh"
#include "params/BaseTrafficGen.hh"
#include "sim/sim_exit.hh"
#include "sim/stats.hh"
#include "sim/system.hh"

#if HAVE_PROTOBUF
#include "cpu/testers/traffic_gen/trace_gen.hh"
#endif


using namespace std;

BaseTrafficGen::BaseTrafficGen(const BaseTrafficGenParams* p)
    : MemObject(p),
      system(p->system),
      elasticReq(p->elastic_req),
      progressCheck(p->progress_check),
      noProgressEvent([this]{ noProgress(); }, name()),
      nextTransitionTick(0),
      nextPacketTick(0),
      port(name() + ".port", *this),
      retryPkt(NULL),
      retryPktTick(0),
      updateEvent([this]{ update(); }, name()),
      masterID(system->getMasterId(this)),
      streamGenerator(StreamGen::create(p))
{
}

BaseTrafficGen::~BaseTrafficGen()
{
}

BaseMasterPort&
BaseTrafficGen::getMasterPort(const string& if_name, PortID idx)
{
    if (if_name == "port") {
        return port;
    } else {
        return MemObject::getMasterPort(if_name, idx);
    }
}

void
BaseTrafficGen::init()
{
    MemObject::init();

    if (!port.isConnected())
        fatal("The port of %s is not connected!\n", name());
}

DrainState
BaseTrafficGen::drain()
{
    if (!updateEvent.scheduled()) {
        // no event has been scheduled yet (e.g. switched from atomic mode)
        return DrainState::Drained;
    }

    if (retryPkt == NULL) {
        // shut things down
        nextPacketTick = MaxTick;
        nextTransitionTick = MaxTick;
        deschedule(updateEvent);
        return DrainState::Drained;
    } else {
        return DrainState::Draining;
    }
}

void
BaseTrafficGen::serialize(CheckpointOut &cp) const
{
    warn("%s serialization does not keep all traffic generator"
         " internal state\n", name());

    DPRINTF(Checkpoint, "Serializing BaseTrafficGen\n");

    // save ticks of the graph event if it is scheduled
    Tick nextEvent = updateEvent.scheduled() ? updateEvent.when() : 0;

    DPRINTF(TrafficGen, "Saving nextEvent=%llu\n", nextEvent);

    SERIALIZE_SCALAR(nextEvent);

    SERIALIZE_SCALAR(nextTransitionTick);

    SERIALIZE_SCALAR(nextPacketTick);
}

void
BaseTrafficGen::unserialize(CheckpointIn &cp)
{
    warn("%s serialization does not restore all traffic generator"
         " internal state\n", name());

    // restore scheduled events
    Tick nextEvent;
    UNSERIALIZE_SCALAR(nextEvent);
    if (nextEvent != 0)
        schedule(updateEvent, nextEvent);

    UNSERIALIZE_SCALAR(nextTransitionTick);

    UNSERIALIZE_SCALAR(nextPacketTick);
}

void
BaseTrafficGen::update()
{
    // shift our progress-tracking event forward
    reschedule(noProgressEvent, curTick() + progressCheck, true);

    // if we have reached the time for the next state transition, then
    // perform the transition
    if (curTick() >= nextTransitionTick) {
        transition();
    } else {
        assert(curTick() >= nextPacketTick);
        // get the next packet and try to send it
        PacketPtr pkt = activeGenerator->getNextPacket();

        // If generating stream/substream IDs are enabled,
        // try to pick and assign them to the new packet
        if (streamGenerator) {
            auto sid = streamGenerator->pickStreamID();
            auto ssid = streamGenerator->pickSubStreamID();

            pkt->req->setStreamId(sid);

            if (streamGenerator->ssidValid()) {
                pkt->req->setSubStreamId(ssid);
            }
        }

        // suppress packets that are not destined for a memory, such as
        // device accesses that could be part of a trace
        if (pkt && system->isMemAddr(pkt->getAddr())) {
            numPackets++;
            if (!port.sendTimingReq(pkt)) {
                retryPkt = pkt;
                retryPktTick = curTick();
            }
        } else if (pkt) {
            DPRINTF(TrafficGen, "Suppressed packet %s 0x%x\n",
                    pkt->cmdString(), pkt->getAddr());

            ++numSuppressed;
            if (!(static_cast<int>(numSuppressed.value()) % 10000))
                warn("%s suppressed %d packets with non-memory addresses\n",
                     name(), numSuppressed.value());

            delete pkt;
            pkt = nullptr;
        }
    }

    // if we are waiting for a retry, do not schedule any further
    // events, in the case of a transition or a successful send, go
    // ahead and determine when the next update should take place
    if (retryPkt == NULL) {
        nextPacketTick = activeGenerator->nextPacketTick(elasticReq, 0);
        scheduleUpdate();
    }
}

void
BaseTrafficGen::transition()
{
    if (activeGenerator)
        activeGenerator->exit();

    activeGenerator = nextGenerator();

    if (activeGenerator) {
        const Tick duration = activeGenerator->duration;
        if (duration != MaxTick && duration != 0) {
            // we could have been delayed and not transitioned on the
            // exact tick when we were supposed to (due to back
            // pressure when sending a packet)
            nextTransitionTick = curTick() + duration;
        } else {
            nextTransitionTick = MaxTick;
        }

        activeGenerator->enter();
        nextPacketTick = activeGenerator->nextPacketTick(elasticReq, 0);
    } else {
        nextPacketTick = MaxTick;
        nextTransitionTick = MaxTick;
        assert(!updateEvent.scheduled());
    }
}

void
BaseTrafficGen::scheduleUpdate()
{
    // Has the generator run out of work? In that case, force a
    // transition if a transition period hasn't been configured.
    while (activeGenerator &&
           nextPacketTick == MaxTick && nextTransitionTick == MaxTick) {
        transition();
    }

    if (!activeGenerator)
        return;

    // schedule next update event based on either the next execute
    // tick or the next transition, which ever comes first
    const Tick nextEventTick = std::min(nextPacketTick, nextTransitionTick);

    DPRINTF(TrafficGen, "Next event scheduled at %lld\n", nextEventTick);

    // The next transition tick may be in the past if there was a
    // retry, so ensure that we don't schedule anything in the past.
    schedule(updateEvent, std::max(curTick(), nextEventTick));
}

void
BaseTrafficGen::start()
{
    transition();
    scheduleUpdate();
}

void
BaseTrafficGen::recvReqRetry()
{
    assert(retryPkt != NULL);

    DPRINTF(TrafficGen, "Received retry\n");
    numRetries++;
    // attempt to send the packet, and if we are successful start up
    // the machinery again
    if (port.sendTimingReq(retryPkt)) {
        retryPkt = NULL;
        // remember how much delay was incurred due to back-pressure
        // when sending the request, we also use this to derive
        // the tick for the next packet
        Tick delay = curTick() - retryPktTick;
        retryPktTick = 0;
        retryTicks += delay;

        if (drainState() != DrainState::Draining) {
            // packet is sent, so find out when the next one is due
            nextPacketTick = activeGenerator->nextPacketTick(elasticReq,
                                                             delay);
            scheduleUpdate();
        } else {
            // shut things down
            nextPacketTick = MaxTick;
            nextTransitionTick = MaxTick;
            signalDrainDone();
        }
    }
}

void
BaseTrafficGen::noProgress()
{
    fatal("BaseTrafficGen %s spent %llu ticks without making progress",
          name(), progressCheck);
}

void
BaseTrafficGen::regStats()
{
    ClockedObject::regStats();

    // Initialise all the stats
    using namespace Stats;

    numPackets
        .name(name() + ".numPackets")
        .desc("Number of packets generated");

    numSuppressed
        .name(name() + ".numSuppressed")
        .desc("Number of suppressed packets to non-memory space");

    numRetries
        .name(name() + ".numRetries")
        .desc("Number of retries");

    retryTicks
        .name(name() + ".retryTicks")
        .desc("Time spent waiting due to back-pressure (ticks)");
}

std::shared_ptr<BaseGen>
BaseTrafficGen::createIdle(Tick duration)
{
    return std::shared_ptr<BaseGen>(new IdleGen(*this, masterID, duration));
}

std::shared_ptr<BaseGen>
BaseTrafficGen::createExit(Tick duration)
{
    return std::shared_ptr<BaseGen>(new ExitGen(*this, masterID, duration));
}

std::shared_ptr<BaseGen>
BaseTrafficGen::createLinear(Tick duration,
                             Addr start_addr, Addr end_addr, Addr blocksize,
                             Tick min_period, Tick max_period,
                             uint8_t read_percent, Addr data_limit)
{
    return std::shared_ptr<BaseGen>(new LinearGen(*this, masterID,
                                                  duration, start_addr,
                                                  end_addr, blocksize,
                                                  system->cacheLineSize(),
                                                  min_period, max_period,
                                                  read_percent, data_limit));
}

std::shared_ptr<BaseGen>
BaseTrafficGen::createRandom(Tick duration,
                             Addr start_addr, Addr end_addr, Addr blocksize,
                             Tick min_period, Tick max_period,
                             uint8_t read_percent, Addr data_limit)
{
    return std::shared_ptr<BaseGen>(new RandomGen(*this, masterID,
                                                  duration, start_addr,
                                                  end_addr, blocksize,
                                                  system->cacheLineSize(),
                                                  min_period, max_period,
                                                  read_percent, data_limit));
}

std::shared_ptr<BaseGen>
BaseTrafficGen::createDram(Tick duration,
                           Addr start_addr, Addr end_addr, Addr blocksize,
                           Tick min_period, Tick max_period,
                           uint8_t read_percent, Addr data_limit,
                           unsigned int num_seq_pkts, unsigned int page_size,
                           unsigned int nbr_of_banks_DRAM,
                           unsigned int nbr_of_banks_util,
                           unsigned int addr_mapping,
                           unsigned int nbr_of_ranks)
{
    return std::shared_ptr<BaseGen>(new DramGen(*this, masterID,
                                                duration, start_addr,
                                                end_addr, blocksize,
                                                system->cacheLineSize(),
                                                min_period, max_period,
                                                read_percent, data_limit,
                                                num_seq_pkts, page_size,
                                                nbr_of_banks_DRAM,
                                                nbr_of_banks_util,
                                                addr_mapping,
                                                nbr_of_ranks));
}

std::shared_ptr<BaseGen>
BaseTrafficGen::createDramRot(Tick duration,
                              Addr start_addr, Addr end_addr, Addr blocksize,
                              Tick min_period, Tick max_period,
                              uint8_t read_percent, Addr data_limit,
                              unsigned int num_seq_pkts,
                              unsigned int page_size,
                              unsigned int nbr_of_banks_DRAM,
                              unsigned int nbr_of_banks_util,
                              unsigned int addr_mapping,
                              unsigned int nbr_of_ranks,
                              unsigned int max_seq_count_per_rank)
{
    return std::shared_ptr<BaseGen>(new DramRotGen(*this, masterID,
                                                   duration, start_addr,
                                                   end_addr, blocksize,
                                                   system->cacheLineSize(),
                                                   min_period, max_period,
                                                   read_percent, data_limit,
                                                   num_seq_pkts, page_size,
                                                   nbr_of_banks_DRAM,
                                                   nbr_of_banks_util,
                                                   addr_mapping,
                                                   nbr_of_ranks,
                                                   max_seq_count_per_rank));
}

std::shared_ptr<BaseGen>
BaseTrafficGen::createTrace(Tick duration,
                            const std::string& trace_file, Addr addr_offset)
{
#if HAVE_PROTOBUF
    return std::shared_ptr<BaseGen>(
        new TraceGen(*this, masterID, duration, trace_file, addr_offset));
#else
    panic("Can't instantiate trace generation without Protobuf support!\n");
#endif
}

bool
BaseTrafficGen::TrafficGenPort::recvTimingResp(PacketPtr pkt)
{
    delete pkt;

    return true;
}
