packet.cc revision 11793
11689SN/A/*
22329SN/A * Copyright (c) 2011-2016 ARM Limited
31689SN/A * All rights reserved
41689SN/A *
51689SN/A * The license below extends only to copyright in the software and shall
61689SN/A * not be construed as granting a license to any other intellectual
71689SN/A * property including but not limited to intellectual property relating
81689SN/A * to a hardware implementation of the functionality of the software
91689SN/A * licensed hereunder.  You may use the software subject to the license
101689SN/A * terms below provided that you ensure that this notice is replicated
111689SN/A * unmodified and in its entirety in all distributions of the software,
121689SN/A * modified or unmodified, in source code or in binary form.
131689SN/A *
141689SN/A * Copyright (c) 2006 The Regents of The University of Michigan
151689SN/A * Copyright (c) 2010,2015 Advanced Micro Devices, Inc.
161689SN/A * All rights reserved.
171689SN/A *
181689SN/A * Redistribution and use in source and binary forms, with or without
191689SN/A * modification, are permitted provided that the following conditions are
201689SN/A * met: redistributions of source code must retain the above copyright
211689SN/A * notice, this list of conditions and the following disclaimer;
221689SN/A * redistributions in binary form must reproduce the above copyright
231689SN/A * notice, this list of conditions and the following disclaimer in the
241689SN/A * documentation and/or other materials provided with the distribution;
251689SN/A * neither the name of the copyright holders nor the names of its
261689SN/A * contributors may be used to endorse or promote products derived from
272665Ssaidi@eecs.umich.edu * this software without specific prior written permission.
282665Ssaidi@eecs.umich.edu *
291689SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
301689SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
311060SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
321060SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
331858SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
341717SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
351060SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
362292SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
372292SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
381061SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
392292SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
402292SN/A *
412292SN/A * Authors: Ali Saidi
422292SN/A *          Steve Reinhardt
432292SN/A */
442292SN/A
452292SN/A/**
461060SN/A * @file
472292SN/A * Definition of the Packet Class, a packet is a transaction occuring
482292SN/A * between a single level of the memory heirarchy (ie L1->L2).
492292SN/A */
502292SN/A
512292SN/A#include "mem/packet.hh"
522292SN/A
532292SN/A#include <cstring>
542292SN/A#include <iostream>
552292SN/A
562292SN/A#include "base/cprintf.hh"
572292SN/A#include "base/misc.hh"
582301SN/A#include "base/trace.hh"
592292SN/A
602292SN/Ausing namespace std;
612292SN/A
622292SN/A// The one downside to bitsets is that static initializers can get ugly.
632292SN/A#define SET1(a1)                     (1 << (a1))
642292SN/A#define SET2(a1, a2)                 (SET1(a1) | SET1(a2))
652292SN/A#define SET3(a1, a2, a3)             (SET2(a1, a2) | SET1(a3))
662292SN/A#define SET4(a1, a2, a3, a4)         (SET3(a1, a2, a3) | SET1(a4))
672292SN/A#define SET5(a1, a2, a3, a4, a5)     (SET4(a1, a2, a3, a4) | SET1(a5))
682292SN/A#define SET6(a1, a2, a3, a4, a5, a6) (SET5(a1, a2, a3, a4, a5) | SET1(a6))
692292SN/A#define SET7(a1, a2, a3, a4, a5, a6, a7) (SET6(a1, a2, a3, a4, a5, a6) | \
702292SN/A                                          SET1(a7))
712292SN/A
722292SN/Aconst MemCmd::CommandInfo
732292SN/AMemCmd::commandInfo[] =
742292SN/A{
752292SN/A    /* InvalidCmd */
761060SN/A    { 0, InvalidCmd, "InvalidCmd" },
771060SN/A    /* ReadReq - Read issued by a non-caching agent such as a CPU or
781061SN/A     * device, with no restrictions on alignment. */
791060SN/A    { SET3(IsRead, IsRequest, NeedsResponse), ReadResp, "ReadReq" },
802292SN/A    /* ReadResp */
811062SN/A    { SET3(IsRead, IsResponse, HasData), InvalidCmd, "ReadResp" },
821062SN/A    /* ReadRespWithInvalidate */
832301SN/A    { SET4(IsRead, IsResponse, HasData, IsInvalidate),
841062SN/A            InvalidCmd, "ReadRespWithInvalidate" },
851062SN/A    /* WriteReq */
861062SN/A    { SET5(IsWrite, NeedsWritable, IsRequest, NeedsResponse, HasData),
872301SN/A            WriteResp, "WriteReq" },
881062SN/A    /* WriteResp */
891062SN/A    { SET2(IsWrite, IsResponse), InvalidCmd, "WriteResp" },
901062SN/A    /* WritebackDirty */
912301SN/A    { SET5(IsWrite, IsRequest, IsEviction, HasData, FromCache),
921062SN/A            InvalidCmd, "WritebackDirty" },
931062SN/A    /* WritebackClean - This allows the upstream cache to writeback a
942301SN/A     * line to the downstream cache without it being considered
952301SN/A     * dirty. */
962301SN/A    { SET5(IsWrite, IsRequest, IsEviction, HasData, FromCache),
972301SN/A            InvalidCmd, "WritebackClean" },
982292SN/A    /* CleanEvict */
992301SN/A    { SET3(IsRequest, IsEviction, FromCache), InvalidCmd, "CleanEvict" },
1002292SN/A    /* SoftPFReq */
1012292SN/A    { SET4(IsRead, IsRequest, IsSWPrefetch, NeedsResponse),
1021062SN/A            SoftPFResp, "SoftPFReq" },
1032301SN/A    /* HardPFReq */
1041062SN/A    { SET5(IsRead, IsRequest, IsHWPrefetch, NeedsResponse, FromCache),
1051062SN/A            HardPFResp, "HardPFReq" },
1061062SN/A    /* SoftPFResp */
1072301SN/A    { SET4(IsRead, IsResponse, IsSWPrefetch, HasData),
1081062SN/A            InvalidCmd, "SoftPFResp" },
1091062SN/A    /* HardPFResp */
1101062SN/A    { SET4(IsRead, IsResponse, IsHWPrefetch, HasData),
1112301SN/A            InvalidCmd, "HardPFResp" },
1121062SN/A    /* WriteLineReq */
1131062SN/A    { SET5(IsWrite, NeedsWritable, IsRequest, NeedsResponse, HasData),
1141062SN/A            WriteResp, "WriteLineReq" },
1152301SN/A    /* UpgradeReq */
1162292SN/A    { SET6(IsInvalidate, NeedsWritable, IsUpgrade, IsRequest, NeedsResponse,
1171062SN/A            FromCache),
1181062SN/A            UpgradeResp, "UpgradeReq" },
1192301SN/A    /* SCUpgradeReq: response could be UpgradeResp or UpgradeFailResp */
1202292SN/A    { SET7(IsInvalidate, NeedsWritable, IsUpgrade, IsLlsc,
1211062SN/A           IsRequest, NeedsResponse, FromCache),
1222292SN/A            UpgradeResp, "SCUpgradeReq" },
1232301SN/A    /* UpgradeResp */
1242292SN/A    { SET2(IsUpgrade, IsResponse),
1252292SN/A            InvalidCmd, "UpgradeResp" },
1261062SN/A    /* SCUpgradeFailReq: generates UpgradeFailResp but still gets the data */
1272301SN/A    { SET7(IsRead, NeedsWritable, IsInvalidate,
1281062SN/A           IsLlsc, IsRequest, NeedsResponse, FromCache),
1291062SN/A            UpgradeFailResp, "SCUpgradeFailReq" },
1301062SN/A    /* UpgradeFailResp - Behaves like a ReadExReq, but notifies an SC
1312301SN/A     * that it has failed, acquires line as Dirty*/
1321062SN/A    { SET3(IsRead, IsResponse, HasData),
1331062SN/A            InvalidCmd, "UpgradeFailResp" },
1341062SN/A    /* ReadExReq - Read issues by a cache, always cache-line aligned,
1352301SN/A     * and the response is guaranteed to be writeable (exclusive or
1361062SN/A     * even modified) */
1371062SN/A    { SET6(IsRead, NeedsWritable, IsInvalidate, IsRequest, NeedsResponse,
1381062SN/A            FromCache),
1392301SN/A            ReadExResp, "ReadExReq" },
1401062SN/A    /* ReadExResp - Response matching a read exclusive, as we check
1411062SN/A     * the need for exclusive also on responses */
1421062SN/A    { SET3(IsRead, IsResponse, HasData),
1432301SN/A            InvalidCmd, "ReadExResp" },
1441062SN/A    /* ReadCleanReq - Read issued by a cache, always cache-line
1451062SN/A     * aligned, and the response is guaranteed to not contain dirty data
1462301SN/A     * (exclusive or shared).*/
1472301SN/A    { SET4(IsRead, IsRequest, NeedsResponse, FromCache),
1482301SN/A            ReadResp, "ReadCleanReq" },
1492301SN/A    /* ReadSharedReq - Read issued by a cache, always cache-line
1502301SN/A     * aligned, response is shared, possibly exclusive, owned or even
1512301SN/A     * modified. */
1522301SN/A    { SET4(IsRead, IsRequest, NeedsResponse, FromCache),
1532301SN/A            ReadResp, "ReadSharedReq" },
1542301SN/A    /* LoadLockedReq: note that we use plain ReadResp as response, so that
1552301SN/A     *                we can also use ReadRespWithInvalidate when needed */
1562307SN/A    { SET4(IsRead, IsLlsc, IsRequest, NeedsResponse),
1572307SN/A            ReadResp, "LoadLockedReq" },
1582307SN/A    /* StoreCondReq */
1592307SN/A    { SET6(IsWrite, NeedsWritable, IsLlsc,
1602307SN/A           IsRequest, NeedsResponse, HasData),
1611062SN/A            StoreCondResp, "StoreCondReq" },
1621062SN/A    /* StoreCondFailReq: generates failing StoreCondResp */
1631062SN/A    { SET6(IsWrite, NeedsWritable, IsLlsc,
1641062SN/A           IsRequest, NeedsResponse, HasData),
1652733Sktlim@umich.edu            StoreCondResp, "StoreCondFailReq" },
1661060SN/A    /* StoreCondResp */
1672292SN/A    { SET3(IsWrite, IsLlsc, IsResponse),
1681060SN/A            InvalidCmd, "StoreCondResp" },
1691060SN/A    /* SwapReq -- for Swap ldstub type operations */
1701060SN/A    { SET6(IsRead, IsWrite, NeedsWritable, IsRequest, HasData, NeedsResponse),
1711061SN/A        SwapResp, "SwapReq" },
1721060SN/A    /* SwapResp -- for Swap ldstub type operations */
1732292SN/A    { SET4(IsRead, IsWrite, IsResponse, HasData),
1741060SN/A            InvalidCmd, "SwapResp" },
1752292SN/A    /* IntReq -- for interrupts */
1761060SN/A    { SET4(IsWrite, IsRequest, NeedsResponse, HasData),
1771060SN/A        MessageResp, "MessageReq" },
1781060SN/A    /* IntResp -- for interrupts */
1791060SN/A    { SET2(IsWrite, IsResponse), InvalidCmd, "MessageResp" },
1801060SN/A    /* MemFenceReq -- for synchronization requests */
1811060SN/A    {SET2(IsRequest, NeedsResponse), MemFenceResp, "MemFenceReq"},
1821060SN/A    /* MemFenceResp -- for synchronization responses */
1831060SN/A    {SET1(IsResponse), InvalidCmd, "MemFenceResp"},
1841060SN/A    /* InvalidDestError  -- packet dest field invalid */
1851060SN/A    { SET2(IsResponse, IsError), InvalidCmd, "InvalidDestError" },
1861060SN/A    /* BadAddressError   -- memory address invalid */
1871060SN/A    { SET2(IsResponse, IsError), InvalidCmd, "BadAddressError" },
1881061SN/A    /* FunctionalReadError */
1891060SN/A    { SET3(IsRead, IsResponse, IsError), InvalidCmd, "FunctionalReadError" },
1902292SN/A    /* FunctionalWriteError */
1911060SN/A    { SET3(IsWrite, IsResponse, IsError), InvalidCmd, "FunctionalWriteError" },
1922292SN/A    /* PrintReq */
1931060SN/A    { SET2(IsRequest, IsPrint), InvalidCmd, "PrintReq" },
1941060SN/A    /* Flush Request */
1951060SN/A    { SET3(IsRequest, IsFlush, NeedsWritable), InvalidCmd, "FlushReq" },
1961060SN/A    /* Invalidation Request */
1971060SN/A    { SET5(IsInvalidate, IsRequest, NeedsWritable, NeedsResponse, FromCache),
1981060SN/A      InvalidateResp, "InvalidateReq" },
1991061SN/A    /* Invalidation Response */
2001060SN/A    { SET2(IsInvalidate, IsResponse),
2012292SN/A      InvalidCmd, "InvalidateResp" }
2021060SN/A};
2032292SN/A
2041060SN/Abool
2051060SN/APacket::checkFunctional(Printable *obj, Addr addr, bool is_secure, int size,
2061060SN/A                        uint8_t *_data)
2071060SN/A{
2081060SN/A    Addr func_start = getAddr();
2091060SN/A    Addr func_end   = getAddr() + getSize() - 1;
2101061SN/A    Addr val_start  = addr;
2111060SN/A    Addr val_end    = val_start + size - 1;
2122292SN/A
2131060SN/A    if (is_secure != _isSecure || func_start > val_end ||
2142329SN/A        val_start > func_end) {
2152292SN/A        // no intersection
2162292SN/A        return false;
2172292SN/A    }
2182292SN/A
2192292SN/A    // check print first since it doesn't require data
2202292SN/A    if (isPrint()) {
2211060SN/A        assert(!_data);
2221060SN/A        safe_cast<PrintReqState*>(senderState)->printObj(obj);
2232292SN/A        return false;
2242292SN/A    }
2252292SN/A
2262292SN/A    // we allow the caller to pass NULL to signify the other packet
2272292SN/A    // has no data
2282292SN/A    if (!_data) {
2292292SN/A        return false;
2302292SN/A    }
2312292SN/A
2321061SN/A    // offset of functional request into supplied value (could be
2331060SN/A    // negative if partial overlap)
2342292SN/A    int offset = func_start - val_start;
2351060SN/A
2362292SN/A    if (isRead()) {
2371060SN/A        if (func_start >= val_start && func_end <= val_end) {
2382292SN/A            memcpy(getPtr<uint8_t>(), _data + offset, getSize());
2392292SN/A            if (bytesValid.empty())
2401060SN/A                bytesValid.resize(getSize(), true);
2411060SN/A            // complete overlap, and as the current packet is a read
2421060SN/A            // we are done
2431061SN/A            return true;
2441060SN/A        } else {
2452292SN/A            // Offsets and sizes to copy in case of partial overlap
2461060SN/A            int func_offset;
2472292SN/A            int val_offset;
2482292SN/A            int overlap_size;
2492292SN/A
2501060SN/A            // calculate offsets and copy sizes for the two byte arrays
2512292SN/A            if (val_start < func_start && val_end <= func_end) {
2522292SN/A                // the one we are checking against starts before and
2532292SN/A                // ends before or the same
2542292SN/A                val_offset = func_start - val_start;
2552292SN/A                func_offset = 0;
2562292SN/A                overlap_size = val_end - func_start;
2571060SN/A            } else if (val_start >= func_start && val_end > func_end) {
2581060SN/A                // the one we are checking against starts after or the
2591061SN/A                // same, and ends after
2602863Sktlim@umich.edu                val_offset = 0;
2612843Sktlim@umich.edu                func_offset = val_start - func_start;
2621060SN/A                overlap_size = func_end - val_start;
2632348SN/A            } else if (val_start >= func_start && val_end <= func_end) {
2642843Sktlim@umich.edu                // the one we are checking against is completely
2652863Sktlim@umich.edu                // subsumed in the current packet, possibly starting
2662316SN/A                // and ending at the same address
2671060SN/A                val_offset = 0;
2682316SN/A                func_offset = val_start - func_start;
2692316SN/A                overlap_size = size;
2702843Sktlim@umich.edu            } else if (val_start < func_start && val_end > func_end) {
2712316SN/A                // the current packet is completely subsumed in the
2722348SN/A                // one we are checking against
2732307SN/A                val_offset = func_start - val_start;
2742307SN/A                func_offset = 0;
2752307SN/A                overlap_size = func_end - func_start;
2762307SN/A            } else {
2772307SN/A                panic("Missed a case for checkFunctional with "
2782307SN/A                      " %s 0x%x size %d, against 0x%x size %d\n",
2792307SN/A                      cmdString(), getAddr(), getSize(), addr, size);
2802307SN/A            }
2812307SN/A
2822307SN/A            // copy partial data into the packet's data array
2832307SN/A            uint8_t *dest = getPtr<uint8_t>() + func_offset;
2842307SN/A            uint8_t *src = _data + val_offset;
2852307SN/A            memcpy(dest, src, overlap_size);
2862307SN/A
2872307SN/A            // initialise the tracking of valid bytes if we have not
2882307SN/A            // used it already
2892307SN/A            if (bytesValid.empty())
2902307SN/A                bytesValid.resize(getSize(), false);
2912307SN/A
2922307SN/A            // track if we are done filling the functional access
2931060SN/A            bool all_bytes_valid = true;
2941060SN/A
2951060SN/A            int i = 0;
2961061SN/A
2971060SN/A            // check up to func_offset
2982307SN/A            for (; all_bytes_valid && i < func_offset; ++i)
2991060SN/A                all_bytes_valid &= bytesValid[i];
3002307SN/A
3012307SN/A            // update the valid bytes
3021060SN/A            for (i = func_offset; i < func_offset + overlap_size; ++i)
3032329SN/A                bytesValid[i] = true;
3042307SN/A
3052307SN/A            // check the bit after the update we just made
3061060SN/A            for (; all_bytes_valid && i < getSize(); ++i)
3072307SN/A                all_bytes_valid &= bytesValid[i];
3082307SN/A
3092307SN/A            return all_bytes_valid;
3102307SN/A        }
3112307SN/A    } else if (isWrite()) {
3122307SN/A        if (offset >= 0) {
3132307SN/A            memcpy(_data + offset, getConstPtr<uint8_t>(),
3142307SN/A                   (min(func_end, val_end) - func_start) + 1);
3152307SN/A        } else {
3162307SN/A            // val_start > func_start
3172307SN/A            memcpy(_data, getConstPtr<uint8_t>() - offset,
3182307SN/A                   (min(func_end, val_end) - val_start) + 1);
3192307SN/A        }
3202307SN/A    } else {
3212292SN/A        panic("Don't know how to handle command %s\n", cmdString());
3221858SN/A    }
3232292SN/A
3241858SN/A    // keep going with request by default
3252292SN/A    return false;
3262292SN/A}
3272292SN/A
3282292SN/Avoid
3292292SN/APacket::pushSenderState(Packet::SenderState *sender_state)
3302301SN/A{
3312698Sktlim@umich.edu    assert(sender_state != NULL);
3322292SN/A    sender_state->predecessor = senderState;
3332698Sktlim@umich.edu    senderState = sender_state;
3342301SN/A}
3352292SN/A
3362292SN/APacket::SenderState *
3372292SN/APacket::popSenderState()
3382292SN/A{
3392292SN/A    assert(senderState != NULL);
3402329SN/A    SenderState *sender_state = senderState;
3412292SN/A    senderState = sender_state->predecessor;
3422292SN/A    sender_state->predecessor = NULL;
3432292SN/A    return sender_state;
3442292SN/A}
3452731Sktlim@umich.edu
3462292SN/Avoid
3472292SN/APacket::print(ostream &o, const int verbosity, const string &prefix) const
3482292SN/A{
3492292SN/A    ccprintf(o, "%s%s [%x:%x]%s%s%s%s", prefix, cmdString(),
3502292SN/A             getAddr(), getAddr() + getSize() - 1,
3512292SN/A             req->isSecure() ? " (s)" : "",
3522292SN/A             req->isInstFetch() ? " IF" : "",
3532292SN/A             req->isUncacheable() ? " UC" : "",
3542292SN/A             isExpressSnoop() ? " ES" : "");
3552292SN/A}
3562292SN/A
3572292SN/Astd::string
3582292SN/APacket::print() const {
3592292SN/A    ostringstream str;
3602292SN/A    print(str);
3612292SN/A    return str.str();
3622292SN/A}
3632292SN/A
3642292SN/APacket::PrintReqState::PrintReqState(ostream &_os, int _verbosity)
3652292SN/A    : curPrefixPtr(new string("")), os(_os), verbosity(_verbosity)
3662292SN/A{
3672292SN/A    labelStack.push_back(LabelStackEntry("", curPrefixPtr));
3682292SN/A}
3692292SN/A
3702292SN/APacket::PrintReqState::~PrintReqState()
3712292SN/A{
3722292SN/A    labelStack.pop_back();
3732292SN/A    assert(labelStack.empty());
3742292SN/A    delete curPrefixPtr;
3752292SN/A}
3762292SN/A
3772292SN/APacket::PrintReqState::
3782292SN/ALabelStackEntry::LabelStackEntry(const string &_label, string *_prefix)
3792292SN/A    : label(_label), prefix(_prefix), labelPrinted(false)
3802292SN/A{
3812292SN/A}
3822292SN/A
3832292SN/Avoid
3842292SN/APacket::PrintReqState::pushLabel(const string &lbl, const string &prefix)
3852292SN/A{
3862292SN/A    labelStack.push_back(LabelStackEntry(lbl, curPrefixPtr));
3872292SN/A    curPrefixPtr = new string(*curPrefixPtr);
3882292SN/A    *curPrefixPtr += prefix;
3892292SN/A}
3902292SN/A
3912292SN/Avoid
3922292SN/APacket::PrintReqState::popLabel()
3932292SN/A{
3942292SN/A    delete curPrefixPtr;
3952292SN/A    curPrefixPtr = labelStack.back().prefix;
3962292SN/A    labelStack.pop_back();
3972292SN/A    assert(!labelStack.empty());
3982292SN/A}
3992292SN/A
4002292SN/Avoid
4012292SN/APacket::PrintReqState::printLabels()
4022292SN/A{
4032292SN/A    if (!labelStack.back().labelPrinted) {
4042292SN/A        LabelStack::iterator i = labelStack.begin();
4052292SN/A        LabelStack::iterator end = labelStack.end();
4062292SN/A        while (i != end) {
4072292SN/A            if (!i->labelPrinted) {
4082292SN/A                ccprintf(os, "%s%s\n", *(i->prefix), i->label);
4092292SN/A                i->labelPrinted = true;
4102292SN/A            }
4112292SN/A            i++;
4122292SN/A        }
4132292SN/A    }
4142292SN/A}
4152292SN/A
4162292SN/A
4172292SN/Avoid
4182292SN/APacket::PrintReqState::printObj(Printable *obj)
4192292SN/A{
4202292SN/A    printLabels();
4212292SN/A    obj->print(os, verbosity, curPrefix());
4222292SN/A}
4232292SN/A