/*
 * Copyright (c) 2020 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.
 *
 * Authors: Wendy Elsasser
 */

#include "cpu/testers/traffic_gen/hybrid_gen.hh"

#include <algorithm>

#include "base/random.hh"
#include "base/trace.hh"
#include "debug/TrafficGen.hh"
#include "enums/AddrMap.hh"

using namespace std;

HybridGen::HybridGen(SimObject &obj,
               MasterID master_id, Tick _duration,
               Addr start_addr_dram, Addr end_addr_dram,
               Addr blocksize_dram,
               Addr start_addr_nvm, Addr end_addr_nvm,
               Addr blocksize_nvm,
               Addr cacheline_size,
               Tick min_period, Tick max_period,
               uint8_t read_percent, Addr data_limit,
               unsigned int num_seq_pkts_dram, unsigned int page_size_dram,
               unsigned int nbr_of_banks_dram,
               unsigned int nbr_of_banks_util_dram,
               unsigned int num_seq_pkts_nvm, unsigned int buffer_size_nvm,
               unsigned int nbr_of_banks_nvm,
               unsigned int nbr_of_banks_util_nvm,
               Enums::AddrMap addr_mapping,
               unsigned int nbr_of_ranks_dram,
               unsigned int nbr_of_ranks_nvm,
               uint8_t nvm_percent)
       : BaseGen(obj, master_id, _duration),
         startAddrDram(start_addr_dram),
         endAddrDram(end_addr_dram),
         blocksizeDram(blocksize_dram),
         startAddrNvm(start_addr_nvm),
         endAddrNvm(end_addr_nvm),
         blocksizeNvm(blocksize_nvm),
         cacheLineSize(cacheline_size),
         minPeriod(min_period), maxPeriod(max_period),
         readPercent(read_percent), dataLimit(data_limit),
         numSeqPktsDram(num_seq_pkts_dram),
         numSeqPktsNvm(num_seq_pkts_nvm),
         countNumSeqPkts(0), addr(0),
         pageSizeDram(page_size_dram),
         pageBitsDram(floorLog2(pageSizeDram / blocksizeDram)),
         bankBitsDram(floorLog2(nbr_of_banks_dram)),
         blockBitsDram(floorLog2(blocksizeDram)),
         nbrOfBanksDram(nbr_of_banks_dram),
         nbrOfBanksUtilDram(nbr_of_banks_util_dram),
         bufferSizeNvm(buffer_size_nvm),
         pageBitsNvm(floorLog2(bufferSizeNvm / blocksizeNvm)),
         bankBitsNvm(floorLog2(nbr_of_banks_nvm)),
         blockBitsNvm(floorLog2(blocksizeNvm)),
         nbrOfBanksNvm(nbr_of_banks_nvm),
         nbrOfBanksUtilNvm(nbr_of_banks_util_nvm),
         addrMapping(addr_mapping),
         nbrOfRanksDram(nbr_of_ranks_dram),
         rankBitsDram(floorLog2(nbrOfRanksDram)),
         nbrOfRanksNvm(nbr_of_ranks_nvm),
         rankBitsNvm(floorLog2(nbrOfRanksNvm)),
         nvmPercent(nvm_percent),
         isRead(true),
         isNvm(false),
         dataManipulated(0)
{
    if (blocksizeDram > cacheLineSize)
        fatal("TrafficGen %s Dram block size (%d) is larger than "
              "cache line size (%d)\n", name(),
              blocksizeDram, cacheLineSize);

    if (blocksizeNvm > cacheLineSize)
        fatal("TrafficGen %s Nvm block size (%d) is larger than "
              "cache line size (%d)\n", name(),
              blocksizeNvm, cacheLineSize);

    if (readPercent > 100)
        fatal("%s cannot have more than 100% reads", name());

    if (minPeriod > maxPeriod)
        fatal("%s cannot have min_period > max_period", name());

    if (nbrOfBanksUtilDram > nbrOfBanksDram)
        fatal("Attempting to use more Dram banks (%d) than "
              "what is available (%d)\n",
              nbrOfBanksUtilDram, nbrOfBanksDram);

    if (nbrOfBanksUtilNvm > nbrOfBanksNvm)
        fatal("Attempting to use more Nvm banks (%d) than "
              "what is available (%d)\n",
              nbrOfBanksUtilNvm, nbrOfBanksNvm);
}

void
HybridGen::enter()
{
    // reset the counter to zero
    dataManipulated = 0;
}

PacketPtr
HybridGen::getNextPacket()
{
    // if this is the first of the packets in series to be generated,
    // start counting again
    if (countNumSeqPkts == 0) {
        isNvm = nvmPercent != 0 &&
            (nvmPercent == 100 || random_mt.random(0, 100) < nvmPercent);

        // choose if we generate a read or a write here
        isRead = readPercent != 0 &&
            (readPercent == 100 || random_mt.random(0, 100) < readPercent);

        assert((readPercent == 0 && !isRead) ||
               (readPercent == 100 && isRead) ||
               readPercent != 100);

        if (isNvm) {
            // Select the appropriate parameters for this interface
            numSeqPkts = numSeqPktsNvm;
            startAddr = startAddrNvm;
            endAddr = endAddrNvm;
            blocksize = blocksizeNvm;
            pageSize = bufferSizeNvm;
            pageBits = pageBitsNvm;
            bankBits = bankBitsNvm;
            blockBits = blockBitsNvm;
            nbrOfBanks = nbrOfBanksNvm;
            nbrOfBanksUtil = nbrOfBanksUtilNvm;
            nbrOfRanks = nbrOfRanksNvm;
            rankBits = rankBitsNvm;
        } else {
            // Select the appropriate parameters for this interface
            numSeqPkts = numSeqPktsDram;
            startAddr = startAddrDram;
            endAddr = endAddrDram;
            blocksize = blocksizeDram;
            pageSize = pageSizeDram;
            pageBits = pageBitsDram;
            bankBits = bankBitsDram;
            blockBits = blockBitsDram;
            nbrOfBanks = nbrOfBanksDram;
            nbrOfBanksUtil = nbrOfBanksUtilDram;
            nbrOfRanks = nbrOfRanksDram;
            rankBits = rankBitsDram;
        }

        countNumSeqPkts = numSeqPkts;

        // pick a random bank
        unsigned int new_bank =
            random_mt.random<unsigned int>(0, nbrOfBanksUtil - 1);

        // pick a random rank
        unsigned int new_rank =
            random_mt.random<unsigned int>(0, nbrOfRanks - 1);

        // Generate the start address of the command series
        // routine will update addr variable with bank, rank, and col
        // bits updated for random traffic mode
        genStartAddr(new_bank, new_rank);


    } else {
        // increment the column by one
        if (addrMapping == Enums::RoRaBaCoCh ||
            addrMapping == Enums::RoRaBaChCo)
            // Simply increment addr by blocksize to increment
            // the column by one
            addr += blocksize;

        else if (addrMapping == Enums::RoCoRaBaCh) {
            // Explicity increment the column bits
            unsigned int new_col = ((addr / blocksize /
                                       nbrOfBanks / nbrOfRanks) %
                                   (pageSize / blocksize)) + 1;
            replaceBits(addr, blockBits + bankBits + rankBits + pageBits - 1,
                        blockBits + bankBits + rankBits, new_col);
        }
    }

    DPRINTF(TrafficGen, "HybridGen::getNextPacket: %c to addr %x, "
            "size %d, countNumSeqPkts: %d, numSeqPkts: %d\n",
            isRead ? 'r' : 'w', addr, blocksize, countNumSeqPkts, numSeqPkts);

    // create a new request packet
    PacketPtr pkt = getPacket(addr, blocksize,
                              isRead ? MemCmd::ReadReq : MemCmd::WriteReq);

    // add the amount of data manipulated to the total
    dataManipulated += blocksize;

    // subtract the number of packets remained to be generated
    --countNumSeqPkts;

    // return the generated packet
    return pkt;
}

void
HybridGen::genStartAddr(unsigned int new_bank, unsigned int new_rank)
{
    // start by picking a random address in the range
    addr = random_mt.random<Addr>(startAddr, endAddr - 1);

    // round down to start address of a block, i.e. a DRAM burst
    addr -= addr % blocksize;

    // insert the bank bits at the right spot, and align the
    // address to achieve the required hit length, this involves
    // finding the appropriate start address such that all
    // sequential packets target successive columns in the same
    // page

    // for example, if we have a stride size of 192B, which means
    // for LPDDR3 where burstsize = 32B we have numSeqPkts = 6,
    // the address generated previously can be such that these
    // 192B cross the page boundary, hence it needs to be aligned
    // so that they all belong to the same page for page hit
    unsigned int burst_per_page = pageSize / blocksize;

    // pick a random column, but ensure that there is room for
    // numSeqPkts sequential columns in the same page
    unsigned int new_col =
        random_mt.random<unsigned int>(0, burst_per_page - numSeqPkts);

    if (addrMapping == Enums::RoRaBaCoCh ||
        addrMapping == Enums::RoRaBaChCo) {
        // Block bits, then page bits, then bank bits, then rank bits
        replaceBits(addr, blockBits + pageBits + bankBits - 1,
                    blockBits + pageBits, new_bank);
        replaceBits(addr, blockBits + pageBits - 1, blockBits, new_col);
        if (rankBits != 0) {
            replaceBits(addr, blockBits + pageBits + bankBits +rankBits - 1,
                        blockBits + pageBits + bankBits, new_rank);
        }
    } else if (addrMapping == Enums::RoCoRaBaCh) {
        // Block bits, then bank bits, then rank bits, then page bits
        replaceBits(addr, blockBits + bankBits - 1, blockBits, new_bank);
        replaceBits(addr, blockBits + bankBits + rankBits + pageBits - 1,
                    blockBits + bankBits + rankBits, new_col);
        if (rankBits != 0) {
            replaceBits(addr, blockBits + bankBits + rankBits - 1,
                        blockBits + bankBits, new_rank);
        }
    }
}

Tick
HybridGen::nextPacketTick(bool elastic, Tick delay) const
{
    // Check to see if we have reached the data limit. If dataLimit is
    // zero we do not have a data limit and therefore we will keep
    // generating requests for the entire residency in this state.
    if (dataLimit && dataManipulated >= dataLimit)
    {
        DPRINTF(TrafficGen, "Data limit for RandomGen reached.\n");
        // No more requests. Return MaxTick.
        return MaxTick;
    } else {
        // return the time when the next request should take place
        Tick wait = random_mt.random(minPeriod, maxPeriod);

        // compensate for the delay experienced to not be elastic, by
        // default the value we generate is from the time we are
        // asked, so the elasticity happens automatically
        if (!elastic) {
            if (wait < delay)
                wait = 0;
            else
                wait -= delay;
        }

        return curTick() + wait;
    }
}
