packet.cc revision 4040:eb894f3fc168
16313Sgblack@eecs.umich.edu/*
26313Sgblack@eecs.umich.edu * Copyright (c) 2006 The Regents of The University of Michigan
36313Sgblack@eecs.umich.edu * All rights reserved.
46313Sgblack@eecs.umich.edu *
56313Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
66313Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are
76313Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright
86313Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
96313Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
106313Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
116313Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution;
126313Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
136313Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
146313Sgblack@eecs.umich.edu * this software without specific prior written permission.
156313Sgblack@eecs.umich.edu *
166313Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
176313Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
186313Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
196313Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
206313Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
216313Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
226313Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
236313Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
246313Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
256313Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
266313Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
276313Sgblack@eecs.umich.edu *
286313Sgblack@eecs.umich.edu * Authors: Ali Saidi
296313Sgblack@eecs.umich.edu *          Steve Reinhardt
306313Sgblack@eecs.umich.edu */
316313Sgblack@eecs.umich.edu
328229Snate@binkert.org/**
336334Sgblack@eecs.umich.edu * @file
346334Sgblack@eecs.umich.edu * Definition of the Packet Class, a packet is a transaction occuring
356334Sgblack@eecs.umich.edu * between a single level of the memory heirarchy (ie L1->L2).
366334Sgblack@eecs.umich.edu */
376313Sgblack@eecs.umich.edu
388232Snate@binkert.org#include <iostream>
399384SAndreas.Sandberg@arm.com#include <cstring>
406313Sgblack@eecs.umich.edu#include "base/misc.hh"
416313Sgblack@eecs.umich.edu#include "base/trace.hh"
426313Sgblack@eecs.umich.edu#include "mem/packet.hh"
436313Sgblack@eecs.umich.edu
446334Sgblack@eecs.umich.edu// The one downside to bitsets is that static initializers can get ugly.
456334Sgblack@eecs.umich.edu#define SET1(a1)                     (1 << (a1))
466334Sgblack@eecs.umich.edu#define SET2(a1, a2)                 (SET1(a1) | SET1(a2))
476334Sgblack@eecs.umich.edu#define SET3(a1, a2, a3)             (SET2(a1, a2) | SET1(a3))
486334Sgblack@eecs.umich.edu#define SET4(a1, a2, a3, a4)         (SET3(a1, a2, a3) | SET1(a4))
496334Sgblack@eecs.umich.edu#define SET5(a1, a2, a3, a4, a5)     (SET4(a1, a2, a3, a4) | SET1(a5))
506334Sgblack@eecs.umich.edu#define SET6(a1, a2, a3, a4, a5, a6) (SET5(a1, a2, a3, a4, a5) | SET1(a6))
516334Sgblack@eecs.umich.edu
526334Sgblack@eecs.umich.educonst MemCmd::CommandInfo
536334Sgblack@eecs.umich.eduMemCmd::commandInfo[] =
546334Sgblack@eecs.umich.edu{
556334Sgblack@eecs.umich.edu    /* InvalidCmd */
566334Sgblack@eecs.umich.edu    { 0, InvalidCmd, "InvalidCmd" },
576334Sgblack@eecs.umich.edu    /* ReadReq */
586334Sgblack@eecs.umich.edu    { SET3(IsRead, IsRequest, NeedsResponse), ReadResp, "ReadReq" },
596334Sgblack@eecs.umich.edu    /* WriteReq */
606334Sgblack@eecs.umich.edu    { SET4(IsWrite, IsRequest, NeedsResponse, HasData),
616334Sgblack@eecs.umich.edu            WriteResp, "WriteReq" },
626334Sgblack@eecs.umich.edu    /* WriteReqNoAck */
636334Sgblack@eecs.umich.edu    { SET3(IsWrite, IsRequest, HasData), InvalidCmd, "WriteReqNoAck" },
646334Sgblack@eecs.umich.edu    /* ReadResp */
656334Sgblack@eecs.umich.edu    { SET3(IsRead, IsResponse, HasData), InvalidCmd, "ReadResp" },
666334Sgblack@eecs.umich.edu    /* WriteResp */
676334Sgblack@eecs.umich.edu    { SET2(IsWrite, IsResponse), InvalidCmd, "WriteResp" },
686334Sgblack@eecs.umich.edu    /* Writeback */
696334Sgblack@eecs.umich.edu    { SET3(IsWrite, IsRequest, HasData), InvalidCmd, "Writeback" },
706334Sgblack@eecs.umich.edu    /* SoftPFReq */
716334Sgblack@eecs.umich.edu    { SET4(IsRead, IsRequest, IsSWPrefetch, NeedsResponse),
726334Sgblack@eecs.umich.edu            SoftPFResp, "SoftPFReq" },
736334Sgblack@eecs.umich.edu    /* HardPFReq */
746334Sgblack@eecs.umich.edu    { SET4(IsRead, IsRequest, IsHWPrefetch, NeedsResponse),
756334Sgblack@eecs.umich.edu            HardPFResp, "HardPFReq" },
766334Sgblack@eecs.umich.edu    /* SoftPFResp */
776334Sgblack@eecs.umich.edu    { SET4(IsRead, IsResponse, IsSWPrefetch, HasData),
786334Sgblack@eecs.umich.edu            InvalidCmd, "SoftPFResp" },
796334Sgblack@eecs.umich.edu    /* HardPFResp */
806334Sgblack@eecs.umich.edu    { SET4(IsRead, IsResponse, IsHWPrefetch, HasData),
816334Sgblack@eecs.umich.edu            InvalidCmd, "HardPFResp" },
826334Sgblack@eecs.umich.edu    /* InvalidateReq */
836334Sgblack@eecs.umich.edu    { SET2(IsInvalidate, IsRequest), InvalidCmd, "InvalidateReq" },
846334Sgblack@eecs.umich.edu    /* WriteInvalidateReq */
856334Sgblack@eecs.umich.edu    { SET5(IsWrite, IsInvalidate, IsRequest, HasData, NeedsResponse),
866334Sgblack@eecs.umich.edu            WriteInvalidateResp, "WriteInvalidateReq" },
876334Sgblack@eecs.umich.edu    /* WriteInvalidateResp */
886334Sgblack@eecs.umich.edu    { SET5(IsWrite, IsInvalidate, IsRequest, NeedsResponse, IsResponse),
896334Sgblack@eecs.umich.edu            InvalidCmd, "WriteInvalidateResp" },
906334Sgblack@eecs.umich.edu    /* UpgradeReq */
919384SAndreas.Sandberg@arm.com    { SET3(IsInvalidate, IsRequest, IsUpgrade), InvalidCmd, "UpgradeReq" },
9210033SAli.Saidi@ARM.com    /* ReadExReq */
936334Sgblack@eecs.umich.edu    { SET4(IsRead, IsInvalidate, IsRequest, NeedsResponse),
946334Sgblack@eecs.umich.edu            ReadExResp, "ReadExReq" },
956334Sgblack@eecs.umich.edu    /* ReadExResp */
966334Sgblack@eecs.umich.edu    { SET4(IsRead, IsInvalidate, IsResponse, HasData),
976334Sgblack@eecs.umich.edu            InvalidCmd, "ReadExResp" },
986334Sgblack@eecs.umich.edu    /* SwapReq -- for Swap ldstub type operations */
996334Sgblack@eecs.umich.edu    { SET4(IsReadWrite, IsRequest, HasData, NeedsResponse),
1006334Sgblack@eecs.umich.edu        SwapResp, "SwapReq" },
1016334Sgblack@eecs.umich.edu    /* SwapResp -- for Swap ldstub type operations */
1026334Sgblack@eecs.umich.edu    { SET3(IsReadWrite, IsResponse, HasData),
1036334Sgblack@eecs.umich.edu        InvalidCmd, "SwapResp" }
1046376Sgblack@eecs.umich.edu};
1056376Sgblack@eecs.umich.edu
1066334Sgblack@eecs.umich.edu
1076334Sgblack@eecs.umich.edu/** delete the data pointed to in the data pointer. Ok to call to matter how
1086334Sgblack@eecs.umich.edu * data was allocted. */
1096383Sgblack@eecs.umich.eduvoid
1106383Sgblack@eecs.umich.eduPacket::deleteData()
1116383Sgblack@eecs.umich.edu{
1126383Sgblack@eecs.umich.edu    assert(staticData || dynamicData);
1136383Sgblack@eecs.umich.edu    if (staticData)
1146383Sgblack@eecs.umich.edu        return;
1156383Sgblack@eecs.umich.edu
1166383Sgblack@eecs.umich.edu    if (arrayData)
1176334Sgblack@eecs.umich.edu        delete [] data;
1186334Sgblack@eecs.umich.edu    else
1196334Sgblack@eecs.umich.edu        delete data;
1208181Sksewell@umich.edu}
1218181Sksewell@umich.edu
1226334Sgblack@eecs.umich.edu/** If there isn't data in the packet, allocate some. */
1236334Sgblack@eecs.umich.eduvoid
1246334Sgblack@eecs.umich.eduPacket::allocate()
1256334Sgblack@eecs.umich.edu{
1266334Sgblack@eecs.umich.edu    if (data)
1276383Sgblack@eecs.umich.edu        return;
1286383Sgblack@eecs.umich.edu    assert(!staticData);
1296383Sgblack@eecs.umich.edu    dynamicData = true;
1306383Sgblack@eecs.umich.edu    arrayData = true;
1316383Sgblack@eecs.umich.edu    data = new uint8_t[getSize()];
1326383Sgblack@eecs.umich.edu}
1336334Sgblack@eecs.umich.edu
1346334Sgblack@eecs.umich.edu/** Do the packet modify the same addresses. */
1356334Sgblack@eecs.umich.edubool
1366334Sgblack@eecs.umich.eduPacket::intersect(PacketPtr p)
1378181Sksewell@umich.edu{
1386334Sgblack@eecs.umich.edu    Addr s1 = getAddr();
1396334Sgblack@eecs.umich.edu    Addr e1 = getAddr() + getSize() - 1;
1406334Sgblack@eecs.umich.edu    Addr s2 = p->getAddr();
1418181Sksewell@umich.edu    Addr e2 = p->getAddr() + p->getSize() - 1;
1426334Sgblack@eecs.umich.edu
1436334Sgblack@eecs.umich.edu    return !(s1 > e2 || e1 < s2);
1449384SAndreas.Sandberg@arm.com}
1459384SAndreas.Sandberg@arm.com
1469384SAndreas.Sandberg@arm.combool
1479384SAndreas.Sandberg@arm.comfixDelayedResponsePacket(PacketPtr func, PacketPtr timing)
1489384SAndreas.Sandberg@arm.com{
1499384SAndreas.Sandberg@arm.com    bool result;
1506334Sgblack@eecs.umich.edu
1518181Sksewell@umich.edu    if (timing->isRead() || timing->isWrite()) {
1528181Sksewell@umich.edu        // Ugly hack to deal with the fact that we queue the requests
1538181Sksewell@umich.edu        // and don't convert them to responses until we issue them on
1548181Sksewell@umich.edu        // the bus.  I tried to avoid this by converting packets to
1558181Sksewell@umich.edu        // responses right away, but this breaks during snoops where a
1568181Sksewell@umich.edu        // responder may do the conversion before other caches have
1578181Sksewell@umich.edu        // done the snoop.  Would work if we copied the packet instead
1588181Sksewell@umich.edu        // of just hanging on to a pointer.
1598181Sksewell@umich.edu        MemCmd oldCmd = timing->cmd;
1608181Sksewell@umich.edu        timing->cmd = timing->cmd.responseCommand();
1618181Sksewell@umich.edu        result = fixPacket(func, timing);
1628181Sksewell@umich.edu        timing->cmd = oldCmd;
1638181Sksewell@umich.edu    }
1648181Sksewell@umich.edu    else {
1656334Sgblack@eecs.umich.edu        //Don't toggle if it isn't a read/write response
1666334Sgblack@eecs.umich.edu        result = fixPacket(func, timing);
1678181Sksewell@umich.edu    }
1686334Sgblack@eecs.umich.edu
1698181Sksewell@umich.edu    return result;
1708181Sksewell@umich.edu}
1716334Sgblack@eecs.umich.edu
1726334Sgblack@eecs.umich.edubool
1736334Sgblack@eecs.umich.edufixPacket(PacketPtr func, PacketPtr timing)
1746334Sgblack@eecs.umich.edu{
1756334Sgblack@eecs.umich.edu    Addr funcStart      = func->getAddr();
1766334Sgblack@eecs.umich.edu    Addr funcEnd        = func->getAddr() + func->getSize() - 1;
1776334Sgblack@eecs.umich.edu    Addr timingStart    = timing->getAddr();
1786334Sgblack@eecs.umich.edu    Addr timingEnd      = timing->getAddr() + timing->getSize() - 1;
1796383Sgblack@eecs.umich.edu
1806376Sgblack@eecs.umich.edu    assert(!(funcStart > timingEnd || timingStart > funcEnd));
1816376Sgblack@eecs.umich.edu
1826376Sgblack@eecs.umich.edu    // this packet can't solve our problem, continue on
1836376Sgblack@eecs.umich.edu    if (!timing->hasData())
1846383Sgblack@eecs.umich.edu        return true;
1856376Sgblack@eecs.umich.edu
1866334Sgblack@eecs.umich.edu    if (func->isRead()) {
1876383Sgblack@eecs.umich.edu        if (funcStart >= timingStart && funcEnd <= timingEnd) {
1886383Sgblack@eecs.umich.edu            func->allocate();
1896383Sgblack@eecs.umich.edu            std::memcpy(func->getPtr<uint8_t>(), timing->getPtr<uint8_t>() +
1906334Sgblack@eecs.umich.edu                    funcStart - timingStart, func->getSize());
1916334Sgblack@eecs.umich.edu            func->result = Packet::Success;
1926383Sgblack@eecs.umich.edu            func->flags |= SATISFIED;
1936376Sgblack@eecs.umich.edu            return false;
1946376Sgblack@eecs.umich.edu        } else {
1956376Sgblack@eecs.umich.edu            // In this case the timing packet only partially satisfies the
1966376Sgblack@eecs.umich.edu            // requset, so we would need more information to make this work.
1976376Sgblack@eecs.umich.edu            // Like bytes valid in the packet or something, so the request could
1986376Sgblack@eecs.umich.edu            // continue and get this bit of possibly newer data along with the
1996383Sgblack@eecs.umich.edu            // older data not written to yet.
2006334Sgblack@eecs.umich.edu            panic("Timing packet only partially satisfies the functional"
2016334Sgblack@eecs.umich.edu                    "request. Now what?");
2026376Sgblack@eecs.umich.edu        }
2036383Sgblack@eecs.umich.edu    } else if (func->isWrite()) {
2046334Sgblack@eecs.umich.edu        if (funcStart >= timingStart) {
2056334Sgblack@eecs.umich.edu            std::memcpy(timing->getPtr<uint8_t>() + (funcStart - timingStart),
2066383Sgblack@eecs.umich.edu                   func->getPtr<uint8_t>(),
2076376Sgblack@eecs.umich.edu                   (std::min(funcEnd, timingEnd) - funcStart) + 1);
2086376Sgblack@eecs.umich.edu        } else { // timingStart > funcStart
2096376Sgblack@eecs.umich.edu            std::memcpy(timing->getPtr<uint8_t>(),
2106376Sgblack@eecs.umich.edu                   func->getPtr<uint8_t>() + (timingStart - funcStart),
2116376Sgblack@eecs.umich.edu                   (std::min(funcEnd, timingEnd) - timingStart) + 1);
2126376Sgblack@eecs.umich.edu        }
2136376Sgblack@eecs.umich.edu        // we always want to keep going with a write
2146376Sgblack@eecs.umich.edu        return true;
2156376Sgblack@eecs.umich.edu    } else
2166376Sgblack@eecs.umich.edu        panic("Don't know how to handle command type %#x\n",
2176376Sgblack@eecs.umich.edu                func->cmdToIndex());
2186376Sgblack@eecs.umich.edu
2196376Sgblack@eecs.umich.edu}
2206376Sgblack@eecs.umich.edu
2216383Sgblack@eecs.umich.edu
2226334Sgblack@eecs.umich.edustd::ostream &
2236334Sgblack@eecs.umich.eduoperator<<(std::ostream &o, const Packet &p)
2246376Sgblack@eecs.umich.edu{
2256383Sgblack@eecs.umich.edu
2266334Sgblack@eecs.umich.edu    o << "[0x";
2276334Sgblack@eecs.umich.edu    o.setf(std::ios_base::hex, std::ios_base::showbase);
2286383Sgblack@eecs.umich.edu    o <<  p.getAddr();
2296376Sgblack@eecs.umich.edu    o.unsetf(std::ios_base::hex| std::ios_base::showbase);
2306376Sgblack@eecs.umich.edu    o <<  ":";
2316376Sgblack@eecs.umich.edu    o.setf(std::ios_base::hex, std::ios_base::showbase);
2326376Sgblack@eecs.umich.edu    o <<  p.getAddr() + p.getSize() - 1 << "] ";
2336376Sgblack@eecs.umich.edu    o.unsetf(std::ios_base::hex| std::ios_base::showbase);
2346376Sgblack@eecs.umich.edu
2356376Sgblack@eecs.umich.edu    if (p.result == Packet::Success)
2366376Sgblack@eecs.umich.edu        o << "Successful ";
2376376Sgblack@eecs.umich.edu    if (p.result == Packet::BadAddress)
2386383Sgblack@eecs.umich.edu        o << "BadAddress ";
2396334Sgblack@eecs.umich.edu    if (p.result == Packet::Nacked)
2406334Sgblack@eecs.umich.edu        o << "Nacked ";
2416376Sgblack@eecs.umich.edu    if (p.result == Packet::Unknown)
2426383Sgblack@eecs.umich.edu        o << "Inflight ";
2436334Sgblack@eecs.umich.edu
2446334Sgblack@eecs.umich.edu    if (p.isRead())
2456383Sgblack@eecs.umich.edu        o << "Read ";
2466376Sgblack@eecs.umich.edu    if (p.isWrite())
2476376Sgblack@eecs.umich.edu        o << "Write ";
2486376Sgblack@eecs.umich.edu    if (p.isReadWrite())
2496376Sgblack@eecs.umich.edu        o << "Read/Write ";
2506376Sgblack@eecs.umich.edu    if (p.isInvalidate())
2516376Sgblack@eecs.umich.edu        o << "Invalidate ";
2526376Sgblack@eecs.umich.edu    if (p.isRequest())
2536376Sgblack@eecs.umich.edu        o << "Request ";
2546383Sgblack@eecs.umich.edu    if (p.isResponse())
2556334Sgblack@eecs.umich.edu        o << "Response ";
2566334Sgblack@eecs.umich.edu    if (p.hasData())
2576376Sgblack@eecs.umich.edu        o << "w/Data ";
2586383Sgblack@eecs.umich.edu
2596334Sgblack@eecs.umich.edu    o << std::endl;
2606334Sgblack@eecs.umich.edu    return o;
2616383Sgblack@eecs.umich.edu}
2626376Sgblack@eecs.umich.edu
2636376Sgblack@eecs.umich.edu