tlm_sync_enum Accelerator::nb_transport_fw(tlm_generic_payload& payload, tlm_phase& phase, sc_time& delay) { if(do_logging & LOG_ACC) cout << sc_time_stamp()<<" "<<name() << " received request." << endl; // update params if (payload.is_write()) // data amount that has been written determines the delay delay += (int)((payload.get_data_length()+bus_width-1)/bus_width)*CLK_CYCLE_BUS; else delay += CLK_CYCLE_BUS; // one cycle delay to acknowledge request to the bus transaction_queue.notify(payload, delay); phase = END_REQ; // end of request phase if(do_logging & LOG_ACC) cout << "\t"<<name()<<": trans " << &payload << "received, phase " << report::print( phase) << (payload.is_write()?" Read":" Write") <<", delay " << delay << std::endl; return TLM_UPDATED; // parameters modified but transaction not yet finished }
void b_transport(tlm_generic_payload& trans, sc_time& delay){ tlm_command cmd = trans.get_command(); sc_dt::uint64 adr = trans.get_address(); unsigned char* ptr = trans.get_data_ptr(); unsigned int len = trans.get_data_length(); unsigned char* byt = trans.get_byte_enable_ptr(); unsigned int wid = trans.get_streaming_width(); #ifdef DEBUGMODE cerr << sc_time_stamp() << ": " << name() << " - Transaction " << trans.is_write() << " for Address " << adr << " with "; cerr << "data length " << len << " and streaming width " << wid << endl; // ofstream outFile("cache.txt", ios::app); // outFile << sc_time_stamp() << " " << trans.get_address() << " " << trans.get_data_length() << " " << trans.is_write() << endl; #endif unsigned int words = len / sizeof(BUSWIDTH); if (len%sizeof(BUSWIDTH) != 0) words++; if(this->scratchpadEn && adr >= this->scratchStart && adr + len <= (this->scratchStart + this->scratchSize)) { //Using local scratchpad if(this->scratchMemory == NULL){ THROW_EXCEPTION(__PRETTY_FUNCTION__ << ": Trying to access a NULL scratchpad"); } if(cmd == TLM_READ_COMMAND) memcpy(ptr, &scratchMemory[adr - this->scratchStart], len); else if(cmd == TLM_WRITE_COMMAND) memcpy(&scratchMemory[adr - this->scratchStart], ptr, len); else THROW_EXCEPTION(__PRETTY_FUNCTION__ << ": Undefined TLM command"); this->numScratchAcc++; wait(words*this->scratchLatency); trans.set_response_status(TLM_OK_RESPONSE); return; } else if (adr > cacheLimit){ this->initSocket->b_transport(trans,delay); } else { if (cmd == TLM_READ_COMMAND) { this->readFromCache(adr, ptr, len); trans.set_response_status(TLM_OK_RESPONSE); } else if (cmd == TLM_WRITE_COMMAND) { this->writeToCache(adr, ptr, len); if (writePolicy == THROUGH || writePolicy == THROUGH_ALL) { this->initSocket->b_transport(trans,delay); } else trans.set_response_status(TLM_OK_RESPONSE); } else THROW_EXCEPTION(__PRETTY_FUNCTION__ << ": Undefined TLM command"); this->numAccesses++; } #ifdef DEBUGMODE cerr << sc_time_stamp() << ": " << name() << " - Transaction " << trans.is_write() << " for Address " << adr << " completed with data "; if (trans.get_data_length() == 4) cerr << (unsigned int) (*trans.get_data_ptr()) << endl; else cerr << "ND" << endl; #endif trans.set_dmi_allowed(false); // Disables DMI in order to insert the cache latency for each transaction }
/** * \brief Receives a transaction from the bus and transform the interface to read/write * * \param trans The transaction packet * \param delay Transaction delay (actually ignored) */ void UC_master_slave_base::b_transport(tlm_generic_payload &trans, sc_time &delay) { unsigned int addr = trans.get_address(); DATA data = trans.get_data_ptr(); unsigned int size = trans.get_data_length(); int bytes; if (trans.is_read() == true) { add_read_access (size); bytes = this->read(addr, data, size); } else if (trans.is_write() == true) { add_write_access (size); bytes = this->write(addr, data, size); } else { cout << "HW error: TLM command unrecognized" << endl; bytes = -3; } switch (bytes) { case 0: trans.set_response_status(TLM_INCOMPLETE_RESPONSE); break; case -1: trans.set_response_status(TLM_GENERIC_ERROR_RESPONSE); break; case -2: trans.set_response_status(TLM_ADDRESS_ERROR_RESPONSE); break; case -3: trans.set_response_status(TLM_COMMAND_ERROR_RESPONSE); break; default: trans.set_response_status(TLM_OK_RESPONSE); break; } }
// TLM-2 debug transaction method // It is unuseful to work with caches for DBG methods, since there is no time concept // This method simply forwards the request to the memory unsigned int transport_dbg(tlm_generic_payload& trans){ tlm_command cmd = trans.get_command(); sc_dt::uint64 adr = trans.get_address(); unsigned char* ptr = trans.get_data_ptr(); unsigned int len = trans.get_data_length(); #ifdef DEBUGMODE cerr << sc_time_stamp() << ": " << name() << " - DBG Transaction " << trans.is_write() << " for Address " << adr << " with "; cerr << "data length " << len << endl; #endif // Declaring some support variables... sc_dt::uint64 tag; tlm_generic_payload message; deque<CacheBlock*>::iterator tagIter; bool hit; CacheBlock *curBlock; sc_dt::uint64 curBaseAddress; int cachePointerModifier; unsigned int partLen; unsigned int remLen = len; unsigned char *dataPointer = ptr; if(this->scratchpadEn && adr >= this->scratchStart && adr + len <= (this->scratchStart + this->scratchSize)) { //Using local scratchpad if(this->scratchMemory == NULL){ THROW_EXCEPTION(__PRETTY_FUNCTION__ << ": Trying to access a NULL scratchpad"); } if(cmd == TLM_READ_COMMAND) memcpy(ptr, &scratchMemory[adr - this->scratchStart], len); else if(cmd == TLM_WRITE_COMMAND) memcpy(&scratchMemory[adr - this->scratchStart], ptr, len); else THROW_EXCEPTION(__PRETTY_FUNCTION__ << ": Undefined TLM command"); trans.set_response_status(TLM_OK_RESPONSE); return len; } else if (adr > cacheLimit){ return this->initSocket->transport_dbg(trans); } // else ... // For each block containing part of the requested data... for (curBaseAddress = adr - (adr % this->blockSize); curBaseAddress < adr+len; curBaseAddress += this->blockSize) { // Calculating the TAG associated to the required memory position tag = GET_TAG(curBaseAddress); hit = false; // For each block cached... // N.B. If no blocks are currently cached, cache[tag] is an ampty queue! for (tagIter = this->cache[tag].begin(); tagIter != this->cache[tag].end(); tagIter++) { // If the required block is cached... if ((*tagIter)->base_address == curBaseAddress) { // We have a HIT! #ifdef DEBUGMODE cerr << sc_time_stamp() << ": " << name() << " - DBG Hit! @" << curBaseAddress << endl; #endif hit = true; // We save the current block... curBlock = *(tagIter); // And we upgrade the queue order if we use an LRU policy if (this->removePolicy==LRU) { this->cache[tag].erase(tagIter); this->cache[tag].push_front(curBlock); } break; } } if (!hit) { // We have a MISS... #ifdef DEBUGMODE cerr << sc_time_stamp() << ": " << name() << " - DBG Miss! @ " << curBaseAddress << endl; #endif // We load the block from memory... curBlock = new CacheBlock(); curBlock->block = (unsigned char*) malloc (blockSize*sizeof(unsigned char)); curBlock->base_address = curBaseAddress; message.set_data_length(blockSize); message.set_data_ptr(curBlock->block); message.set_read(); message.set_address(curBlock->base_address); message.set_response_status(TLM_INCOMPLETE_RESPONSE); this->initSocket->transport_dbg(message); if (message.get_response_status() != TLM_OK_RESPONSE) THROW_EXCEPTION(__PRETTY_FUNCTION__ << ": Error while reading from main memory"); } // Finally, we can actually read/write the required data from/to the block... // We calculate the displacement of the data in the cache block... cachePointerModifier = adr - curBlock->base_address; if (cachePointerModifier < 0) cachePointerModifier = 0; // And the length of the data to be read/written partLen = remLen; if (partLen + cachePointerModifier > this->blockSize) partLen = this->blockSize - cachePointerModifier; // We perform the effective read/write... if(cmd == TLM_READ_COMMAND) memcpy(dataPointer, curBlock->block + cachePointerModifier, partLen*sizeof(unsigned char)); else if(cmd == TLM_WRITE_COMMAND) { memcpy(curBlock->block + cachePointerModifier, dataPointer, partLen*sizeof(unsigned char)); message.set_data_length(blockSize); message.set_data_ptr(curBlock->block); message.set_write(); message.set_address(curBlock->base_address); message.set_response_status(TLM_INCOMPLETE_RESPONSE); this->initSocket->transport_dbg(message); if (message.get_response_status() != TLM_OK_RESPONSE) THROW_EXCEPTION(__PRETTY_FUNCTION__ << ": Error while reading from main memory"); } else THROW_EXCEPTION(__PRETTY_FUNCTION__ << ": Undefined TLM command"); if (!hit) delete curBlock; // And we update the pointer to the required data for eventual subsequent reads remLen -= partLen; dataPointer += partLen; } trans.set_response_status(TLM_OK_RESPONSE); #ifdef DEBUGMODE cerr << sc_time_stamp() << ": " << name() << " - DBG Transaction " << trans.is_write() << " for Address " << adr << " completed with data "; if (trans.get_data_length() == 4) cerr << (unsigned int) (*trans.get_data_ptr()) << endl; else cerr << "ND" << endl; #endif return len; }