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