DMASequencer.cc revision 7908:4e83ebb67794
12810SN/A/*
22810SN/A * Copyright (c) 2008 Mark D. Hill and David A. Wood
32810SN/A * All rights reserved.
42810SN/A *
52810SN/A * Redistribution and use in source and binary forms, with or without
62810SN/A * modification, are permitted provided that the following conditions are
72810SN/A * met: redistributions of source code must retain the above copyright
82810SN/A * notice, this list of conditions and the following disclaimer;
92810SN/A * redistributions in binary form must reproduce the above copyright
102810SN/A * notice, this list of conditions and the following disclaimer in the
112810SN/A * documentation and/or other materials provided with the distribution;
122810SN/A * neither the name of the copyright holders nor the names of its
132810SN/A * contributors may be used to endorse or promote products derived from
142810SN/A * this software without specific prior written permission.
152810SN/A *
162810SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172810SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182810SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192810SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202810SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212810SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222810SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232810SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242810SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252810SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262810SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272810SN/A */
282810SN/A
294458SN/A#include "mem/protocol/SequencerMsg.hh"
304458SN/A#include "mem/protocol/SequencerRequestType.hh"
312810SN/A#include "mem/ruby/buffers/MessageBuffer.hh"
322810SN/A#include "mem/ruby/slicc_interface/AbstractController.hh"
332810SN/A#include "mem/ruby/system/DMASequencer.hh"
342810SN/A#include "mem/ruby/system/System.hh"
352810SN/A
362810SN/ADMASequencer::DMASequencer(const Params *p)
372810SN/A    : RubyPort(p)
382810SN/A{
392810SN/A}
402810SN/A
412810SN/Avoid
422810SN/ADMASequencer::init()
432810SN/A{
444666SN/A    RubyPort::init();
452810SN/A    m_is_busy = false;
462825SN/A    m_data_block_mask = ~ (~0 << RubySystem::getBlockSizeBits());
472810SN/A}
482810SN/A
496215Snate@binkert.orgRequestStatus
505338Sstever@gmail.comDMASequencer::makeRequest(const RubyRequest &request)
512810SN/A{
522810SN/A    if (m_is_busy) {
534626SN/A        return RequestStatus_BufferFull;
542810SN/A    }
555034SN/A
562811SN/A    uint64_t paddr = request.paddr;
574626SN/A    uint8_t* data = request.data;
582810SN/A    int len = request.len;
593194SN/A    bool write = false;
602810SN/A    switch(request.type) {
612810SN/A      case RubyRequestType_LD:
622810SN/A        write = false;
632810SN/A        break;
642810SN/A      case RubyRequestType_ST:
654628SN/A        write = true;
664628SN/A        break;
674628SN/A      case RubyRequestType_NULL:
684628SN/A      case RubyRequestType_IFETCH:
694628SN/A      case RubyRequestType_Load_Linked:
704628SN/A      case RubyRequestType_Store_Conditional:
714628SN/A      case RubyRequestType_RMW_Read:
724628SN/A      case RubyRequestType_RMW_Write:
734628SN/A      case RubyRequestType_Locked_RMW_Read:
744628SN/A      case RubyRequestType_Locked_RMW_Write:
754628SN/A      case RubyRequestType_NUM:
764628SN/A        panic("DMASequencer::makeRequest does not support RubyRequestType");
774628SN/A        return RequestStatus_NULL;
784628SN/A    }
794628SN/A
804628SN/A    assert(!m_is_busy);  // only support one outstanding DMA request
814628SN/A    m_is_busy = true;
824628SN/A
834628SN/A    active_request.start_paddr = paddr;
844628SN/A    active_request.write = write;
854628SN/A    active_request.data = data;
864628SN/A    active_request.len = len;
874628SN/A    active_request.bytes_completed = 0;
884628SN/A    active_request.bytes_issued = 0;
894628SN/A    active_request.pkt = request.pkt;
904628SN/A
914628SN/A    SequencerMsg *msg = new SequencerMsg;
924628SN/A    msg->getPhysicalAddress() = Address(paddr);
934628SN/A    msg->getLineAddress() = line_address(msg->getPhysicalAddress());
944628SN/A    msg->getType() = write ? SequencerRequestType_ST : SequencerRequestType_LD;
954628SN/A    int offset = paddr & m_data_block_mask;
964626SN/A
972810SN/A    msg->getLen() = (offset + len) <= RubySystem::getBlockSizeBytes() ?
982844SN/A        len : RubySystem::getBlockSizeBytes() - offset;
992810SN/A
1002810SN/A    if (write) {
1013738SN/A        msg->getDataBlk().setData(data, offset, msg->getLen());
1024965SN/A    }
1036122SSteve.Reinhardt@amd.com
1044458SN/A    assert(m_mandatory_q_ptr != NULL);
1052810SN/A    m_mandatory_q_ptr->enqueue(msg);
1062810SN/A    active_request.bytes_issued += msg->getLen();
1076227Snate@binkert.org
1082810SN/A    return RequestStatus_Issued;
1094458SN/A}
1103013SN/A
1114666SN/Avoid
1124666SN/ADMASequencer::issueNext()
1134666SN/A{
1145314SN/A    assert(m_is_busy == true);
1155314SN/A    active_request.bytes_completed = active_request.bytes_issued;
1162811SN/A    if (active_request.len == active_request.bytes_completed) {
1174458SN/A        DPRINTF(RubyDma, "DMA request completed\n");
1184458SN/A        ruby_hit_callback(active_request.pkt);
1192810SN/A        m_is_busy = false;
1202810SN/A        return;
1212810SN/A    }
1222810SN/A
1235314SN/A    SequencerMsg *msg = new SequencerMsg;
1243606SN/A    msg->getPhysicalAddress() = Address(active_request.start_paddr +
1254458SN/A                                       active_request.bytes_completed);
1264458SN/A
1272810SN/A    assert((msg->getPhysicalAddress().getAddress() & m_data_block_mask) == 0);
1282810SN/A    msg->getLineAddress() = line_address(msg->getPhysicalAddress());
1292897SN/A
1302897SN/A    msg->getType() = (active_request.write ? SequencerRequestType_ST :
1314458SN/A                     SequencerRequestType_LD);
1324458SN/A
1334888SN/A    msg->getLen() =
1344666SN/A        (active_request.len -
1354666SN/A         active_request.bytes_completed < RubySystem::getBlockSizeBytes() ?
1364458SN/A         active_request.len - active_request.bytes_completed :
1374458SN/A         RubySystem::getBlockSizeBytes());
1384458SN/A
1394626SN/A    if (active_request.write) {
1404626SN/A        msg->getDataBlk().
1414626SN/A            setData(&active_request.data[active_request.bytes_completed],
1422811SN/A                    0, msg->getLen());
1432810SN/A        msg->getType() = SequencerRequestType_ST;
1443338SN/A    } else {
1453338SN/A        msg->getType() = SequencerRequestType_LD;
1463738SN/A    }
1473338SN/A
1484626SN/A    assert(m_mandatory_q_ptr != NULL);
1494626SN/A    m_mandatory_q_ptr->enqueue(msg);
1504626SN/A    active_request.bytes_issued += msg->getLen();
1514626SN/A    DPRINTF(RubyDma, "Next DMA segment issued to the DMA cntrl\n");
1524626SN/A}
1534626SN/A
1544626SN/Avoid
1554626SN/ADMASequencer::dataCallback(const DataBlock & dblk)
1564628SN/A{
1574628SN/A    assert(m_is_busy == true);
1584628SN/A    int len = active_request.bytes_issued - active_request.bytes_completed;
1594666SN/A    int offset = 0;
1604628SN/A    if (active_request.bytes_completed == 0)
1614628SN/A        offset = active_request.start_paddr & m_data_block_mask;
1624628SN/A    assert(active_request.write == false);
1634628SN/A    memcpy(&active_request.data[active_request.bytes_completed],
1644628SN/A           dblk.getData(offset, len), len);
1654628SN/A    issueNext();
1664628SN/A}
1674628SN/A
1684628SN/Avoid
1694628SN/ADMASequencer::ackCallback()
1704628SN/A{
1714628SN/A    issueNext();
1724628SN/A}
1734628SN/A
1744628SN/Avoid
1754628SN/ADMASequencer::printConfig(std::ostream & out)
1764628SN/A{
1774628SN/A}
1784628SN/A
1794628SN/ADMASequencer *
1804628SN/ADMASequencerParams::create()
1814628SN/A{
1824626SN/A    return new DMASequencer(this);
1836227Snate@binkert.org}
1844626SN/A