DMASequencer.cc revision 11346:64e862d3758f
112854Sgabeblack@google.com/* 212854Sgabeblack@google.com * Copyright (c) 2008 Mark D. Hill and David A. Wood 312854Sgabeblack@google.com * All rights reserved. 412854Sgabeblack@google.com * 512854Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without 612854Sgabeblack@google.com * modification, are permitted provided that the following conditions are 712854Sgabeblack@google.com * met: redistributions of source code must retain the above copyright 812854Sgabeblack@google.com * notice, this list of conditions and the following disclaimer; 912854Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright 1012854Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the 1112854Sgabeblack@google.com * documentation and/or other materials provided with the distribution; 1212854Sgabeblack@google.com * neither the name of the copyright holders nor the names of its 1312854Sgabeblack@google.com * contributors may be used to endorse or promote products derived from 1412854Sgabeblack@google.com * this software without specific prior written permission. 1512854Sgabeblack@google.com * 1612854Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1712854Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1812854Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1912854Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2012854Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2112854Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2212854Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2312854Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2412854Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2512854Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2612854Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2712854Sgabeblack@google.com */ 2812854Sgabeblack@google.com 2912854Sgabeblack@google.com#include <memory> 3012854Sgabeblack@google.com 3112854Sgabeblack@google.com#include "debug/RubyDma.hh" 3212854Sgabeblack@google.com#include "debug/RubyStats.hh" 3312854Sgabeblack@google.com#include "mem/protocol/SequencerMsg.hh" 3412854Sgabeblack@google.com#include "mem/protocol/SequencerRequestType.hh" 3512854Sgabeblack@google.com#include "mem/ruby/system/DMASequencer.hh" 3612854Sgabeblack@google.com#include "mem/ruby/system/RubySystem.hh" 3712854Sgabeblack@google.com 3812854Sgabeblack@google.comDMASequencer::DMASequencer(const Params *p) 3912854Sgabeblack@google.com : RubyPort(p) 4012854Sgabeblack@google.com{ 4112854Sgabeblack@google.com} 4212854Sgabeblack@google.com 4312854Sgabeblack@google.comvoid 4412854Sgabeblack@google.comDMASequencer::init() 4512854Sgabeblack@google.com{ 4612854Sgabeblack@google.com RubyPort::init(); 4712854Sgabeblack@google.com m_is_busy = false; 4812854Sgabeblack@google.com m_data_block_mask = ~ (~0 << RubySystem::getBlockSizeBits()); 4912854Sgabeblack@google.com 5012854Sgabeblack@google.com for (const auto &s_port : slave_ports) 5112854Sgabeblack@google.com s_port->sendRangeChange(); 5212854Sgabeblack@google.com} 5312854Sgabeblack@google.com 5412854Sgabeblack@google.comRequestStatus 5512854Sgabeblack@google.comDMASequencer::makeRequest(PacketPtr pkt) 5612854Sgabeblack@google.com{ 5712854Sgabeblack@google.com if (m_is_busy) { 5812854Sgabeblack@google.com return RequestStatus_BufferFull; 5912854Sgabeblack@google.com } 6012854Sgabeblack@google.com 6112854Sgabeblack@google.com Addr paddr = pkt->getAddr(); 6212854Sgabeblack@google.com uint8_t* data = pkt->getPtr<uint8_t>(); 6312854Sgabeblack@google.com int len = pkt->getSize(); 6412854Sgabeblack@google.com bool write = pkt->isWrite(); 6512854Sgabeblack@google.com 6612854Sgabeblack@google.com assert(!m_is_busy); // only support one outstanding DMA request 6712854Sgabeblack@google.com m_is_busy = true; 6812854Sgabeblack@google.com 6912854Sgabeblack@google.com active_request.start_paddr = paddr; 7012854Sgabeblack@google.com active_request.write = write; 7112854Sgabeblack@google.com active_request.data = data; 7212854Sgabeblack@google.com active_request.len = len; 7312854Sgabeblack@google.com active_request.bytes_completed = 0; 7412854Sgabeblack@google.com active_request.bytes_issued = 0; 7512854Sgabeblack@google.com active_request.pkt = pkt; 7612854Sgabeblack@google.com 7712854Sgabeblack@google.com std::shared_ptr<SequencerMsg> msg = 7812854Sgabeblack@google.com std::make_shared<SequencerMsg>(clockEdge()); 7912854Sgabeblack@google.com msg->getPhysicalAddress() = paddr; 8012854Sgabeblack@google.com msg->getLineAddress() = makeLineAddress(msg->getPhysicalAddress()); 8112854Sgabeblack@google.com msg->getType() = write ? SequencerRequestType_ST : SequencerRequestType_LD; 8212854Sgabeblack@google.com int offset = paddr & m_data_block_mask; 8312854Sgabeblack@google.com 8412854Sgabeblack@google.com msg->getLen() = (offset + len) <= RubySystem::getBlockSizeBytes() ? 8512854Sgabeblack@google.com len : RubySystem::getBlockSizeBytes() - offset; 8612854Sgabeblack@google.com 8712854Sgabeblack@google.com if (write && (data != NULL)) { 8812854Sgabeblack@google.com if (active_request.data != NULL) { 8912854Sgabeblack@google.com msg->getDataBlk().setData(data, offset, msg->getLen()); 9012854Sgabeblack@google.com } 9112854Sgabeblack@google.com } 9212854Sgabeblack@google.com 9312854Sgabeblack@google.com assert(m_mandatory_q_ptr != NULL); 9412854Sgabeblack@google.com m_mandatory_q_ptr->enqueue(msg, clockEdge(), cyclesToTicks(Cycles(1))); 9512854Sgabeblack@google.com active_request.bytes_issued += msg->getLen(); 9612854Sgabeblack@google.com 9712854Sgabeblack@google.com return RequestStatus_Issued; 9812854Sgabeblack@google.com} 9912854Sgabeblack@google.com 10012854Sgabeblack@google.comvoid 10112854Sgabeblack@google.comDMASequencer::issueNext() 10212854Sgabeblack@google.com{ 10312854Sgabeblack@google.com assert(m_is_busy); 10412854Sgabeblack@google.com active_request.bytes_completed = active_request.bytes_issued; 10512854Sgabeblack@google.com if (active_request.len == active_request.bytes_completed) { 10612854Sgabeblack@google.com // 10712854Sgabeblack@google.com // Must unset the busy flag before calling back the dma port because 10812854Sgabeblack@google.com // the callback may cause a previously nacked request to be reissued 10912854Sgabeblack@google.com // 11012854Sgabeblack@google.com DPRINTF(RubyDma, "DMA request completed\n"); 11112854Sgabeblack@google.com m_is_busy = false; 11212854Sgabeblack@google.com ruby_hit_callback(active_request.pkt); 11312854Sgabeblack@google.com return; 11412854Sgabeblack@google.com } 11512854Sgabeblack@google.com 11612854Sgabeblack@google.com std::shared_ptr<SequencerMsg> msg = 11712854Sgabeblack@google.com std::make_shared<SequencerMsg>(clockEdge()); 11812854Sgabeblack@google.com msg->getPhysicalAddress() = active_request.start_paddr + 11912854Sgabeblack@google.com active_request.bytes_completed; 12012854Sgabeblack@google.com 12112854Sgabeblack@google.com assert((msg->getPhysicalAddress() & m_data_block_mask) == 0); 12212854Sgabeblack@google.com msg->getLineAddress() = makeLineAddress(msg->getPhysicalAddress()); 12312854Sgabeblack@google.com 12412854Sgabeblack@google.com msg->getType() = (active_request.write ? SequencerRequestType_ST : 12512854Sgabeblack@google.com SequencerRequestType_LD); 12612854Sgabeblack@google.com 12712854Sgabeblack@google.com msg->getLen() = 12812854Sgabeblack@google.com (active_request.len - 12912854Sgabeblack@google.com active_request.bytes_completed < RubySystem::getBlockSizeBytes() ? 13012854Sgabeblack@google.com active_request.len - active_request.bytes_completed : 13112854Sgabeblack@google.com RubySystem::getBlockSizeBytes()); 13212854Sgabeblack@google.com 13312854Sgabeblack@google.com if (active_request.write) { 13412854Sgabeblack@google.com msg->getDataBlk(). 13512854Sgabeblack@google.com setData(&active_request.data[active_request.bytes_completed], 13612854Sgabeblack@google.com 0, msg->getLen()); 13712854Sgabeblack@google.com } 13812854Sgabeblack@google.com 13912854Sgabeblack@google.com assert(m_mandatory_q_ptr != NULL); 14012854Sgabeblack@google.com m_mandatory_q_ptr->enqueue(msg, clockEdge(), cyclesToTicks(Cycles(1))); 14112854Sgabeblack@google.com active_request.bytes_issued += msg->getLen(); 14212854Sgabeblack@google.com DPRINTF(RubyDma, 14312854Sgabeblack@google.com "DMA request bytes issued %d, bytes completed %d, total len %d\n", 14412854Sgabeblack@google.com active_request.bytes_issued, active_request.bytes_completed, 14512854Sgabeblack@google.com active_request.len); 14612854Sgabeblack@google.com} 14712854Sgabeblack@google.com 14812854Sgabeblack@google.comvoid 14912854Sgabeblack@google.comDMASequencer::dataCallback(const DataBlock & dblk) 15013197Sgabeblack@google.com{ 15112854Sgabeblack@google.com assert(m_is_busy); 15212854Sgabeblack@google.com int len = active_request.bytes_issued - active_request.bytes_completed; 15312854Sgabeblack@google.com int offset = 0; 15412854Sgabeblack@google.com if (active_request.bytes_completed == 0) 15512854Sgabeblack@google.com offset = active_request.start_paddr & m_data_block_mask; 15612854Sgabeblack@google.com assert(!active_request.write); 15712854Sgabeblack@google.com if (active_request.data != NULL) { 15812854Sgabeblack@google.com memcpy(&active_request.data[active_request.bytes_completed], 15912854Sgabeblack@google.com dblk.getData(offset, len), len); 16012854Sgabeblack@google.com } 16112854Sgabeblack@google.com issueNext(); 16212854Sgabeblack@google.com} 16312854Sgabeblack@google.com 16412854Sgabeblack@google.comvoid 16512854Sgabeblack@google.comDMASequencer::ackCallback() 16612854Sgabeblack@google.com{ 16712854Sgabeblack@google.com issueNext(); 16812854Sgabeblack@google.com} 16912854Sgabeblack@google.com 17012854Sgabeblack@google.comvoid 17112854Sgabeblack@google.comDMASequencer::recordRequestType(DMASequencerRequestType requestType) 17212854Sgabeblack@google.com{ 17312854Sgabeblack@google.com DPRINTF(RubyStats, "Recorded statistic: %s\n", 17413197Sgabeblack@google.com DMASequencerRequestType_to_string(requestType)); 17512854Sgabeblack@google.com} 17612854Sgabeblack@google.com 17712854Sgabeblack@google.comDMASequencer * 17812854Sgabeblack@google.comDMASequencerParams::create() 17912854Sgabeblack@google.com{ 18012854Sgabeblack@google.com return new DMASequencer(this); 18112854Sgabeblack@google.com} 18212854Sgabeblack@google.com