DMASequencer.cc revision 7915
14120Sgblack@eecs.umich.edu/* 24120Sgblack@eecs.umich.edu * Copyright (c) 2008 Mark D. Hill and David A. Wood 34120Sgblack@eecs.umich.edu * All rights reserved. 44120Sgblack@eecs.umich.edu * 54120Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 64120Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 74120Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 84120Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 94120Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 104120Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 114120Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 124120Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 134120Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 144120Sgblack@eecs.umich.edu * this software without specific prior written permission. 154120Sgblack@eecs.umich.edu * 164120Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 174120Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 184120Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 194120Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 204120Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 214120Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 224120Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 234120Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 244120Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 254120Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 264120Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 274120Sgblack@eecs.umich.edu */ 284120Sgblack@eecs.umich.edu 294120Sgblack@eecs.umich.edu#include "mem/protocol/SequencerMsg.hh" 304120Sgblack@eecs.umich.edu#include "mem/protocol/SequencerRequestType.hh" 314120Sgblack@eecs.umich.edu#include "mem/ruby/buffers/MessageBuffer.hh" 324120Sgblack@eecs.umich.edu#include "mem/ruby/slicc_interface/AbstractController.hh" 334120Sgblack@eecs.umich.edu#include "mem/ruby/system/DMASequencer.hh" 344120Sgblack@eecs.umich.edu#include "mem/ruby/system/System.hh" 354120Sgblack@eecs.umich.edu 364120Sgblack@eecs.umich.eduDMASequencer::DMASequencer(const Params *p) 374120Sgblack@eecs.umich.edu : RubyPort(p) 384120Sgblack@eecs.umich.edu{ 394120Sgblack@eecs.umich.edu} 404120Sgblack@eecs.umich.edu 414120Sgblack@eecs.umich.eduvoid 424120Sgblack@eecs.umich.eduDMASequencer::init() 434120Sgblack@eecs.umich.edu{ 444120Sgblack@eecs.umich.edu RubyPort::init(); 454120Sgblack@eecs.umich.edu m_is_busy = false; 464120Sgblack@eecs.umich.edu m_data_block_mask = ~ (~0 << RubySystem::getBlockSizeBits()); 474120Sgblack@eecs.umich.edu} 484120Sgblack@eecs.umich.edu 494120Sgblack@eecs.umich.eduRequestStatus 504120Sgblack@eecs.umich.eduDMASequencer::makeRequest(const RubyRequest &request) 514120Sgblack@eecs.umich.edu{ 524120Sgblack@eecs.umich.edu if (m_is_busy) { 534120Sgblack@eecs.umich.edu return RequestStatus_BufferFull; 544120Sgblack@eecs.umich.edu } 554120Sgblack@eecs.umich.edu 564120Sgblack@eecs.umich.edu uint64_t paddr = request.paddr; 574120Sgblack@eecs.umich.edu uint8_t* data = request.data; 584120Sgblack@eecs.umich.edu int len = request.len; 594120Sgblack@eecs.umich.edu bool write = false; 604120Sgblack@eecs.umich.edu switch(request.type) { 614148Sgblack@eecs.umich.edu case RubyRequestType_LD: 624182Sgblack@eecs.umich.edu write = false; 634148Sgblack@eecs.umich.edu break; 645135Sgblack@eecs.umich.edu case RubyRequestType_ST: 654241Sgblack@eecs.umich.edu write = true; 664154Sgblack@eecs.umich.edu break; 674148Sgblack@eecs.umich.edu case RubyRequestType_NULL: 684148Sgblack@eecs.umich.edu case RubyRequestType_IFETCH: 694120Sgblack@eecs.umich.edu case RubyRequestType_Load_Linked: 704182Sgblack@eecs.umich.edu case RubyRequestType_Store_Conditional: 714182Sgblack@eecs.umich.edu case RubyRequestType_RMW_Read: 724182Sgblack@eecs.umich.edu case RubyRequestType_RMW_Write: 734182Sgblack@eecs.umich.edu case RubyRequestType_Locked_RMW_Read: 744334Sgblack@eecs.umich.edu case RubyRequestType_Locked_RMW_Write: 754334Sgblack@eecs.umich.edu case RubyRequestType_NUM: 764334Sgblack@eecs.umich.edu panic("DMASequencer::makeRequest does not support RubyRequestType"); 774334Sgblack@eecs.umich.edu return RequestStatus_NULL; 784334Sgblack@eecs.umich.edu } 794334Sgblack@eecs.umich.edu 804334Sgblack@eecs.umich.edu assert(!m_is_busy); // only support one outstanding DMA request 814334Sgblack@eecs.umich.edu m_is_busy = true; 824342Sgblack@eecs.umich.edu 834587Sgblack@eecs.umich.edu active_request.start_paddr = paddr; 844587Sgblack@eecs.umich.edu active_request.write = write; 854182Sgblack@eecs.umich.edu active_request.data = data; 864182Sgblack@eecs.umich.edu active_request.len = len; 874182Sgblack@eecs.umich.edu active_request.bytes_completed = 0; 884182Sgblack@eecs.umich.edu active_request.bytes_issued = 0; 894120Sgblack@eecs.umich.edu active_request.pkt = request.pkt; 904120Sgblack@eecs.umich.edu 915086Sgblack@eecs.umich.edu SequencerMsg *msg = new SequencerMsg; 925086Sgblack@eecs.umich.edu msg->getPhysicalAddress() = Address(paddr); 934148Sgblack@eecs.umich.edu msg->getLineAddress() = line_address(msg->getPhysicalAddress()); 944148Sgblack@eecs.umich.edu msg->getType() = write ? SequencerRequestType_ST : SequencerRequestType_LD; 954148Sgblack@eecs.umich.edu int offset = paddr & m_data_block_mask; 964148Sgblack@eecs.umich.edu 974148Sgblack@eecs.umich.edu msg->getLen() = (offset + len) <= RubySystem::getBlockSizeBytes() ? 984148Sgblack@eecs.umich.edu len : RubySystem::getBlockSizeBytes() - offset; 994148Sgblack@eecs.umich.edu 1004148Sgblack@eecs.umich.edu if (write && (data != NULL)) { 1014148Sgblack@eecs.umich.edu if (active_request.data != NULL) { 1024148Sgblack@eecs.umich.edu msg->getDataBlk().setData(data, offset, msg->getLen()); 1034148Sgblack@eecs.umich.edu } 1044148Sgblack@eecs.umich.edu } 1054148Sgblack@eecs.umich.edu 1064148Sgblack@eecs.umich.edu assert(m_mandatory_q_ptr != NULL); 1074148Sgblack@eecs.umich.edu m_mandatory_q_ptr->enqueue(msg); 1084148Sgblack@eecs.umich.edu active_request.bytes_issued += msg->getLen(); 1094148Sgblack@eecs.umich.edu 1104148Sgblack@eecs.umich.edu return RequestStatus_Issued; 1114148Sgblack@eecs.umich.edu} 1124148Sgblack@eecs.umich.edu 1134148Sgblack@eecs.umich.eduvoid 1144148Sgblack@eecs.umich.eduDMASequencer::issueNext() 1154148Sgblack@eecs.umich.edu{ 1164148Sgblack@eecs.umich.edu assert(m_is_busy == true); 1174148Sgblack@eecs.umich.edu active_request.bytes_completed = active_request.bytes_issued; 1184148Sgblack@eecs.umich.edu if (active_request.len == active_request.bytes_completed) { 1194148Sgblack@eecs.umich.edu DPRINTF(RubyDma, "DMA request completed\n"); 1204148Sgblack@eecs.umich.edu ruby_hit_callback(active_request.pkt); 1214148Sgblack@eecs.umich.edu m_is_busy = false; 1224148Sgblack@eecs.umich.edu return; 1234148Sgblack@eecs.umich.edu } 1244148Sgblack@eecs.umich.edu 1254148Sgblack@eecs.umich.edu SequencerMsg *msg = new SequencerMsg; 1264148Sgblack@eecs.umich.edu msg->getPhysicalAddress() = Address(active_request.start_paddr + 1274148Sgblack@eecs.umich.edu active_request.bytes_completed); 1284148Sgblack@eecs.umich.edu 1294148Sgblack@eecs.umich.edu assert((msg->getPhysicalAddress().getAddress() & m_data_block_mask) == 0); 1304148Sgblack@eecs.umich.edu msg->getLineAddress() = line_address(msg->getPhysicalAddress()); 1314148Sgblack@eecs.umich.edu 1324148Sgblack@eecs.umich.edu msg->getType() = (active_request.write ? SequencerRequestType_ST : 1334148Sgblack@eecs.umich.edu SequencerRequestType_LD); 1344148Sgblack@eecs.umich.edu 1354148Sgblack@eecs.umich.edu msg->getLen() = 1364148Sgblack@eecs.umich.edu (active_request.len - 1374148Sgblack@eecs.umich.edu active_request.bytes_completed < RubySystem::getBlockSizeBytes() ? 1384148Sgblack@eecs.umich.edu active_request.len - active_request.bytes_completed : 1394148Sgblack@eecs.umich.edu RubySystem::getBlockSizeBytes()); 1404148Sgblack@eecs.umich.edu 1414148Sgblack@eecs.umich.edu if (active_request.write) { 1424148Sgblack@eecs.umich.edu msg->getDataBlk(). 1434148Sgblack@eecs.umich.edu setData(&active_request.data[active_request.bytes_completed], 1445135Sgblack@eecs.umich.edu 0, msg->getLen()); 1454194Ssaidi@eecs.umich.edu msg->getType() = SequencerRequestType_ST; 1465135Sgblack@eecs.umich.edu } else { 1475135Sgblack@eecs.umich.edu msg->getType() = SequencerRequestType_LD; 1485135Sgblack@eecs.umich.edu } 1495135Sgblack@eecs.umich.edu 1505135Sgblack@eecs.umich.edu assert(m_mandatory_q_ptr != NULL); 1514120Sgblack@eecs.umich.edu m_mandatory_q_ptr->enqueue(msg); 1524120Sgblack@eecs.umich.edu active_request.bytes_issued += msg->getLen(); 1534120Sgblack@eecs.umich.edu DPRINTF(RubyDma, "Next DMA segment issued to the DMA cntrl\n"); 154} 155 156void 157DMASequencer::dataCallback(const DataBlock & dblk) 158{ 159 assert(m_is_busy == true); 160 int len = active_request.bytes_issued - active_request.bytes_completed; 161 int offset = 0; 162 if (active_request.bytes_completed == 0) 163 offset = active_request.start_paddr & m_data_block_mask; 164 assert(active_request.write == false); 165 if (active_request.data != NULL) { 166 memcpy(&active_request.data[active_request.bytes_completed], 167 dblk.getData(offset, len), len); 168 } 169 issueNext(); 170} 171 172void 173DMASequencer::ackCallback() 174{ 175 issueNext(); 176} 177 178void 179DMASequencer::printConfig(std::ostream & out) 180{ 181} 182 183DMASequencer * 184DMASequencerParams::create() 185{ 186 return new DMASequencer(this); 187} 188