DMASequencer.cc revision 11339:c45bfadcd51b
110037SARM gem5 Developers/*
210037SARM gem5 Developers * Copyright (c) 2008 Mark D. Hill and David A. Wood
310037SARM gem5 Developers * All rights reserved.
410037SARM gem5 Developers *
510037SARM gem5 Developers * Redistribution and use in source and binary forms, with or without
610037SARM gem5 Developers * modification, are permitted provided that the following conditions are
710037SARM gem5 Developers * met: redistributions of source code must retain the above copyright
810037SARM gem5 Developers * notice, this list of conditions and the following disclaimer;
910037SARM gem5 Developers * redistributions in binary form must reproduce the above copyright
1010037SARM gem5 Developers * notice, this list of conditions and the following disclaimer in the
1110037SARM gem5 Developers * documentation and/or other materials provided with the distribution;
1210037SARM gem5 Developers * neither the name of the copyright holders nor the names of its
1310037SARM gem5 Developers * contributors may be used to endorse or promote products derived from
1410037SARM gem5 Developers * this software without specific prior written permission.
1510037SARM gem5 Developers *
1610037SARM gem5 Developers * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1710037SARM gem5 Developers * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1810037SARM gem5 Developers * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1910037SARM gem5 Developers * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2010037SARM gem5 Developers * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2110037SARM gem5 Developers * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2210037SARM gem5 Developers * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2310037SARM gem5 Developers * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2410037SARM gem5 Developers * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2510037SARM gem5 Developers * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2610037SARM gem5 Developers * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2710037SARM gem5 Developers */
2810037SARM gem5 Developers
2910037SARM gem5 Developers#include <memory>
3010037SARM gem5 Developers
3110037SARM gem5 Developers#include "debug/RubyDma.hh"
3210037SARM gem5 Developers#include "debug/RubyStats.hh"
3310037SARM gem5 Developers#include "mem/protocol/SequencerMsg.hh"
3410037SARM gem5 Developers#include "mem/protocol/SequencerRequestType.hh"
3510037SARM gem5 Developers#include "mem/ruby/system/DMASequencer.hh"
3610037SARM gem5 Developers#include "mem/ruby/system/RubySystem.hh"
3710037SARM gem5 Developers
3810037SARM gem5 DevelopersDMASequencer::DMASequencer(const Params *p)
3910037SARM gem5 Developers    : RubyPort(p)
4010037SARM gem5 Developers{
4110037SARM gem5 Developers}
4210037SARM gem5 Developers
4310037SARM gem5 Developersvoid
4410037SARM gem5 DevelopersDMASequencer::init()
4510037SARM gem5 Developers{
4610037SARM gem5 Developers    RubyPort::init();
4710037SARM gem5 Developers    m_is_busy = false;
4810037SARM gem5 Developers    m_data_block_mask = ~ (~0 << RubySystem::getBlockSizeBits());
4910037SARM gem5 Developers}
5010037SARM gem5 Developers
5110037SARM gem5 DevelopersRequestStatus
5210037SARM gem5 DevelopersDMASequencer::makeRequest(PacketPtr pkt)
5310037SARM gem5 Developers{
5410037SARM gem5 Developers    if (m_is_busy) {
5510037SARM gem5 Developers        return RequestStatus_BufferFull;
5610037SARM gem5 Developers    }
5710037SARM gem5 Developers
5810037SARM gem5 Developers    Addr paddr = pkt->getAddr();
5910037SARM gem5 Developers    uint8_t* data =  pkt->getPtr<uint8_t>();
6010037SARM gem5 Developers    int len = pkt->getSize();
6110037SARM gem5 Developers    bool write = pkt->isWrite();
6210037SARM gem5 Developers
6310037SARM gem5 Developers    assert(!m_is_busy);  // only support one outstanding DMA request
6410037SARM gem5 Developers    m_is_busy = true;
6510037SARM gem5 Developers
6610037SARM gem5 Developers    active_request.start_paddr = paddr;
6710037SARM gem5 Developers    active_request.write = write;
6810037SARM gem5 Developers    active_request.data = data;
6910037SARM gem5 Developers    active_request.len = len;
7010037SARM gem5 Developers    active_request.bytes_completed = 0;
7110037SARM gem5 Developers    active_request.bytes_issued = 0;
7210037SARM gem5 Developers    active_request.pkt = pkt;
7310037SARM gem5 Developers
7410037SARM gem5 Developers    std::shared_ptr<SequencerMsg> msg =
7510037SARM gem5 Developers        std::make_shared<SequencerMsg>(clockEdge());
7610037SARM gem5 Developers    msg->getPhysicalAddress() = paddr;
7710037SARM gem5 Developers    msg->getLineAddress() = makeLineAddress(msg->getPhysicalAddress());
7810037SARM gem5 Developers    msg->getType() = write ? SequencerRequestType_ST : SequencerRequestType_LD;
7910037SARM gem5 Developers    int offset = paddr & m_data_block_mask;
8010037SARM gem5 Developers
8110037SARM gem5 Developers    msg->getLen() = (offset + len) <= RubySystem::getBlockSizeBytes() ?
8210037SARM gem5 Developers        len : RubySystem::getBlockSizeBytes() - offset;
8310037SARM gem5 Developers
8410037SARM gem5 Developers    if (write && (data != NULL)) {
8510037SARM gem5 Developers        if (active_request.data != NULL) {
8610037SARM gem5 Developers            msg->getDataBlk().setData(data, offset, msg->getLen());
8710037SARM gem5 Developers        }
8810037SARM gem5 Developers    }
8910037SARM gem5 Developers
9010037SARM gem5 Developers    assert(m_mandatory_q_ptr != NULL);
9110037SARM gem5 Developers    m_mandatory_q_ptr->enqueue(msg, clockEdge(), cyclesToTicks(Cycles(1)));
9210037SARM gem5 Developers    active_request.bytes_issued += msg->getLen();
9310037SARM gem5 Developers
9410037SARM gem5 Developers    return RequestStatus_Issued;
9510037SARM gem5 Developers}
9610037SARM gem5 Developers
9710037SARM gem5 Developersvoid
9810037SARM gem5 DevelopersDMASequencer::issueNext()
9910037SARM gem5 Developers{
10010037SARM gem5 Developers    assert(m_is_busy);
10110037SARM gem5 Developers    active_request.bytes_completed = active_request.bytes_issued;
10210037SARM gem5 Developers    if (active_request.len == active_request.bytes_completed) {
10310037SARM gem5 Developers        //
10410037SARM gem5 Developers        // Must unset the busy flag before calling back the dma port because
10510037SARM gem5 Developers        // the callback may cause a previously nacked request to be reissued
10610037SARM gem5 Developers        //
10710037SARM gem5 Developers        DPRINTF(RubyDma, "DMA request completed\n");
10810037SARM gem5 Developers        m_is_busy = false;
10910037SARM gem5 Developers        ruby_hit_callback(active_request.pkt);
11010037SARM gem5 Developers        return;
11110037SARM gem5 Developers    }
11210037SARM gem5 Developers
11310037SARM gem5 Developers    std::shared_ptr<SequencerMsg> msg =
11410037SARM gem5 Developers        std::make_shared<SequencerMsg>(clockEdge());
11510037SARM gem5 Developers    msg->getPhysicalAddress() = active_request.start_paddr +
11610037SARM gem5 Developers                                active_request.bytes_completed;
11710037SARM gem5 Developers
11810037SARM gem5 Developers    assert((msg->getPhysicalAddress() & m_data_block_mask) == 0);
11910037SARM gem5 Developers    msg->getLineAddress() = makeLineAddress(msg->getPhysicalAddress());
12010037SARM gem5 Developers
12110037SARM gem5 Developers    msg->getType() = (active_request.write ? SequencerRequestType_ST :
12210037SARM gem5 Developers                     SequencerRequestType_LD);
12310037SARM gem5 Developers
12410037SARM gem5 Developers    msg->getLen() =
12510037SARM gem5 Developers        (active_request.len -
12610037SARM gem5 Developers         active_request.bytes_completed < RubySystem::getBlockSizeBytes() ?
12710037SARM gem5 Developers         active_request.len - active_request.bytes_completed :
12810037SARM gem5 Developers         RubySystem::getBlockSizeBytes());
12910037SARM gem5 Developers
13010037SARM gem5 Developers    if (active_request.write) {
13110037SARM gem5 Developers        msg->getDataBlk().
13210037SARM gem5 Developers            setData(&active_request.data[active_request.bytes_completed],
13310037SARM gem5 Developers                    0, msg->getLen());
13410037SARM gem5 Developers    }
13510037SARM gem5 Developers
13610037SARM gem5 Developers    assert(m_mandatory_q_ptr != NULL);
13710037SARM gem5 Developers    m_mandatory_q_ptr->enqueue(msg, clockEdge(), cyclesToTicks(Cycles(1)));
13810037SARM gem5 Developers    active_request.bytes_issued += msg->getLen();
13910037SARM gem5 Developers    DPRINTF(RubyDma,
14010037SARM gem5 Developers            "DMA request bytes issued %d, bytes completed %d, total len %d\n",
14110037SARM gem5 Developers            active_request.bytes_issued, active_request.bytes_completed,
14210037SARM gem5 Developers            active_request.len);
14310037SARM gem5 Developers}
14410037SARM gem5 Developers
14510037SARM gem5 Developersvoid
14610037SARM gem5 DevelopersDMASequencer::dataCallback(const DataBlock & dblk)
14710037SARM gem5 Developers{
14810037SARM gem5 Developers    assert(m_is_busy);
14910037SARM gem5 Developers    int len = active_request.bytes_issued - active_request.bytes_completed;
15010037SARM gem5 Developers    int offset = 0;
15110037SARM gem5 Developers    if (active_request.bytes_completed == 0)
15210037SARM gem5 Developers        offset = active_request.start_paddr & m_data_block_mask;
15310037SARM gem5 Developers    assert(!active_request.write);
15410037SARM gem5 Developers    if (active_request.data != NULL) {
15510037SARM gem5 Developers        memcpy(&active_request.data[active_request.bytes_completed],
15610037SARM gem5 Developers               dblk.getData(offset, len), len);
15710037SARM gem5 Developers    }
15810037SARM gem5 Developers    issueNext();
15910037SARM gem5 Developers}
16010037SARM gem5 Developers
16110037SARM gem5 Developersvoid
16210037SARM gem5 DevelopersDMASequencer::ackCallback()
16310037SARM gem5 Developers{
16410037SARM gem5 Developers    issueNext();
16510037SARM gem5 Developers}
16610037SARM gem5 Developers
16710037SARM gem5 Developersvoid
16810037SARM gem5 DevelopersDMASequencer::recordRequestType(DMASequencerRequestType requestType)
16910037SARM gem5 Developers{
17010196SCurtis.Dunham@arm.com    DPRINTF(RubyStats, "Recorded statistic: %s\n",
17110037SARM gem5 Developers            DMASequencerRequestType_to_string(requestType));
17210037SARM gem5 Developers}
17310037SARM gem5 Developers
17410037SARM gem5 DevelopersDMASequencer *
17510196SCurtis.Dunham@arm.comDMASequencerParams::create()
17610037SARM gem5 Developers{
17710037SARM gem5 Developers    return new DMASequencer(this);
17810037SARM gem5 Developers}
17910037SARM gem5 Developers