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 }
void Or1ksimJtagSC::jtagHandler(tlm_generic_payload & inpPayload, sc_time & inpDelay) { // Retrieve the extension. JtagExtensionSC * localJtagExtension; inpPayload.get_extension(localJtagExtension); // Check if the extension exists. Set up the access type and bit size as // appropriate. JtagExtensionSC::AccessType localAccessType; int localBitSize; if(NULL == localJtagExtension) { unsigned int addr = static_cast<unsigned int>(inpPayload.get_address()); localAccessType = ((ADDR_SHIFT_IR == addr) ? JtagExtensionSC::SHIFT_IR : (ADDR_SHIFT_DR == addr) ? JtagExtensionSC::SHIFT_DR : JtagExtensionSC::RESET); localBitSize = 8 * static_cast<int>(inpPayload.get_data_length()); } else { localAccessType = localJtagExtension->getType(); localBitSize = localJtagExtension->getBitSize(); } // Behavior depends on the type switch (localAccessType) { case JtagExtensionSC::RESET: myOr1ksimMutex.lock(); inpDelay += sc_time(or1ksim_jtag_reset(), SC_SEC); myOr1ksimMutex.unlock(); inpPayload.set_response_status(tlm::TLM_OK_RESPONSE); return; case JtagExtensionSC::SHIFT_IR: myOr1ksimMutex.lock(); inpDelay += sc_time (or1ksim_jtag_shift_ir(inpPayload. get_data_ptr(), localBitSize), SC_SEC); myOr1ksimMutex.unlock(); inpPayload.set_response_status(tlm::TLM_OK_RESPONSE); return; case JtagExtensionSC::SHIFT_DR: myOr1ksimMutex.lock (); inpDelay += sc_time(or1ksim_jtag_shift_dr( inpPayload.get_data_ptr(), localBitSize), SC_SEC); myOr1ksimMutex.unlock (); inpPayload.set_response_status (tlm::TLM_OK_RESPONSE); return; default: cerr << "ERROR: Unrecognized JTAG transaction type." << endl; inpPayload.set_response_status(tlm::TLM_GENERIC_ERROR_RESPONSE); return; } }
/* ------------------------------------------------------------------------- */ void Slave::my_b_transport(tlm_generic_payload &trans, sc_time &local_time) { sc_assert((BUS_WIDTH % 32) == 0); unsigned int length = trans.get_data_length(); unsigned int address = trans.get_address(); //some checks and error responses to unsupported features if (trans.get_byte_enable_ptr()){ // not supporting byte enable trans.set_response_status(TLM_BYTE_ENABLE_ERROR_RESPONSE); } else if (trans.get_streaming_width() < length) { // not supporting streaming trans.set_response_status(TLM_BURST_ERROR_RESPONSE); } else if ((length%bus_width_in_bytes) || (address%bus_width_in_bytes)){ // not supporting unaligned access trans.set_response_status(TLM_ADDRESS_ERROR_RESPONSE); } else { trans.set_response_status(TLM_OK_RESPONSE); if (trans.is_read()) { // only allow reading from result register if (address == REG_RESULT && (length == bus_width_in_bytes)) { unsigned int *data_ptr = (unsigned int *) trans.get_data_ptr(); *data_ptr= sum_; } else { trans.set_response_status(TLM_ADDRESS_ERROR_RESPONSE); } local_time += (SLAVE_READ_DELAY+(length/bus_width_in_bytes)) * bus_clock_period; } else { // write // only on the terms, burst access is taken into account if ((address == REG_START) && (length == bus_width_in_bytes)) { run_event_.notify(local_time+SLAVE_WRITE_DELAY*bus_clock_period); } else if ((address < REG_OFFSET_TERMS) || (address >= REG_OFFSET_TERMS+sizeof(int)*NR_TERMS)) { trans.set_response_status(TLM_ADDRESS_ERROR_RESPONSE); } else { unsigned int index = (address - REG_OFFSET_TERMS)/sizeof(int); unsigned int remaining = (NR_TERMS-index)*sizeof(int); const void *data_ptr = (const void *) trans.get_data_ptr(); if (length<= remaining) { memcpy((void *) &terms_[index], data_ptr, length); } else { memcpy((void *) &terms_[index], data_ptr, remaining); } } local_time += (SLAVE_WRITE_DELAY+(length/bus_width_in_bytes)) * bus_clock_period; } } }
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(); if(cmd == TLM_WRITE_COMMAND){ status++; std::cout << name() << " status: " << status << "/" << numOfMessages << std::endl; if(status>=numOfMessages) sc_stop(); } else { THROW_EXCEPTION("unknown command"); } //wait(this->latency); trans.set_response_status(TLM_OK_RESPONSE); }
/** * \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; } }
void test_a_conversion(char cmd, tlm_generic_payload &txn, std::ifstream & fin) { if(cmd == 'R') txn.set_read(); else txn.set_write(); fin.ignore(10000,'='); uint64 a; fin >> a; txn.set_address(a); fin.ignore(10000,'='); int l; fin >> l; txn.set_data_length(l); int bus_width; fin.ignore(10000,'='); fin >> bus_width; int data_width; fin.ignore(10000,'='); fin >> data_width; int initiator_offset; fin.ignore(10000,'='); fin >> initiator_offset; unsigned char *original_byte_enable = 0; unsigned char *byte_enable_legible = new unsigned char[txn.get_data_length() + 1]; memset(byte_enable_legible, 0, txn.get_data_length() + 1); fin.ignore(10000,'='); for(unsigned b=0; b<txn.get_data_length(); b++) { char tmp; fin >> tmp; if((tmp=='0')||(tmp=='1')||(tmp=='x')) byte_enable_legible[b]=tmp; else break; } if((byte_enable_legible[0] == '1') || (byte_enable_legible[0] == '0')) { txn.set_byte_enable_ptr(new unsigned char[txn.get_data_length()]); txn.set_byte_enable_length(txn.get_data_length()); original_byte_enable = txn.get_byte_enable_ptr(); for(unsigned int i=0; i<txn.get_data_length(); i++) { if(byte_enable_legible[i] == '0') { txn.get_byte_enable_ptr()[i] = TLM_BYTE_DISABLED; } else if(byte_enable_legible[i] == '1') { txn.get_byte_enable_ptr()[i] = TLM_BYTE_ENABLED; } else { // not enough byte enables txn.set_byte_enable_length(i); break; } } } else { txn.set_byte_enable_ptr(0); txn.set_byte_enable_length(0); } int stream_width; fin.ignore(10000,'='); fin >> stream_width; txn.set_streaming_width(stream_width); cout << "enter initiator memory state = ("<< BUFFER_SIZE << " characters)\n"; unsigned char initiator_mem[BUFFER_SIZE+1]; memset(initiator_mem, 0, BUFFER_SIZE+1); fin.ignore(10000,'='); fin >> initiator_mem; txn.set_data_ptr(initiator_mem + initiator_offset); cout << "enter target memory state = ("<< BUFFER_SIZE << " characters)\n"; unsigned char target_mem[BUFFER_SIZE+1]; memset(target_mem, 0, BUFFER_SIZE+1); fin.ignore(10000,'='); fin >> target_mem; cout << "enter converter choice = (0 => generic, 1 => word, 2 => aligned, 3 => single)\n"; int converter; fin.ignore(10000,'='); fin >> converter; cout << "Initiator Intent\n"; cout << " Cmd = " << cmd << endl; cout << " Addr = " << txn.get_address() << endl; cout << " Len = " << txn.get_data_length() << endl; cout << " Bus Width = " << bus_width << endl; cout << " Data Word = " << data_width << endl; #ifdef VERBOSE cout << " Initiator offset and txn data pointer = " << initiator_offset << ", " << int(txn.get_data_ptr()) << endl; cout << " Byte enables and byte enable pointer = " << byte_enable_legible << ", " << int(txn.get_byte_enable_ptr()) << endl; #else cout << " Initiator offset = " << initiator_offset << endl; cout << " Byte enables = " << byte_enable_legible << endl; #endif cout << " Byte enable length = " << txn.get_byte_enable_length() << endl; cout << " Streaming width = " << txn.get_streaming_width() << endl; cout << " Initiator memory = " << initiator_mem << endl; cout << " Target memory = " << target_mem << endl; cout << " Converter = " << converter << endl << endl; // initiator // switch(converter) { case 0: convert(tlm_to_hostendian_generic); break; case 1: convert(tlm_to_hostendian_word); break; case 2: convert(tlm_to_hostendian_aligned); break; case 3: convert(tlm_to_hostendian_single); break; case 4: convert(local_single_tohe); break; default: cout << "no such converter as " << converter << endl; exit(1); } cout << "Converted Transaction\n"; cout << " Addr = " << txn.get_address() << endl; cout << " Len = " << txn.get_data_length() << endl; #ifdef VERBOSE cout << " Txn data pointer = " << int(txn.get_data_ptr()) << endl; if(txn.get_byte_enable_ptr() != 0) { cout << " Byte enables and byte enable pointer = "; for(unsigned int i=0; i<txn.get_data_length(); i++) cout << (txn.get_byte_enable_ptr()[i] ? '1' : '0'); cout << ", " << int(txn.get_byte_enable_ptr()) << endl; } #else cout << " Txn data pointer = " << (txn.get_data_ptr() == initiator_mem+initiator_offset ? "unchanged" : "changed") << endl; if(txn.get_byte_enable_ptr() != 0) { cout << " Byte enables and byte enable pointer = "; for(unsigned int i=0; i<txn.get_data_length(); i++) cout << (txn.get_byte_enable_ptr()[i] ? '1' : '0'); cout << ", " << (txn.get_byte_enable_ptr() == original_byte_enable ? "unchanged" : "changed") << endl; } #endif cout << " Byte enable length = " << txn.get_byte_enable_length() << endl; cout << " Streaming width = " << txn.get_streaming_width() << endl; cout << endl; // target // int sw = txn.get_streaming_width(); if((txn.get_data_length()/sw)*sw != txn.get_data_length()) { cout << "ERROR: Data length not a multiple of streaming width\n"; exit(1); } for(unsigned int ss = 0; ss < txn.get_data_length(); ss += sw) { if(txn.get_byte_enable_ptr() == 0) { // simple transaction can be processed by mem-copy if(txn.is_read()) memcpy(ss+txn.get_data_ptr(), target_mem+txn.get_address(), sw); else memcpy(target_mem+txn.get_address(), ss+txn.get_data_ptr(), sw); } else { // complex transaction, byte enables, maybe shorter than data int bel = txn.get_byte_enable_length(); if(txn.is_read()) { for(int j=0; j<sw; j++) { if(txn.get_byte_enable_ptr()[(ss+j) % bel]) (txn.get_data_ptr())[ss+j] = target_mem[j+txn.get_address()]; } } else { for(int j=0; j<sw; j++) { if(txn.get_byte_enable_ptr()[(ss+j) % bel]) target_mem[j+txn.get_address()] = (txn.get_data_ptr())[ss+j]; } } } } // initiator again // if((rand() & 0x100) && (converter < 4)) { #ifdef VERBOSE cout << "using single entry point for response\n"; #endif tlm_from_hostendian(&txn); } else { #ifdef VERBOSE cout << "using specific entry point for response\n"; #endif switch(converter) { case 0: convert(tlm_from_hostendian_generic); break; case 1: convert(tlm_from_hostendian_word); break; case 2: convert(tlm_from_hostendian_aligned); break; case 3: convert(tlm_from_hostendian_single); break; case 4: convert(local_single_fromhe); break; default: cout << "no such converter as " << converter << endl; exit(1); } } // print the results // cout << "Memory States after Transaction\n"; cout << " initiator = " << initiator_mem << endl; cout << " target = " << target_mem << endl << endl; // clean up delete [] byte_enable_legible; if(original_byte_enable != 0) delete [] original_byte_enable; }
void ahb_slave_if::b_transport(tlm_generic_payload& payload, sc_time& delay) { tlm_command cmd = payload.get_command(); uint32_t addr = (uint32_t)payload.get_address(); uint32_t* data_ptr = (uint32_t*)payload.get_data_ptr(); unsigned int length = payload.get_data_length(); int burst_length = payload.get_streaming_width(); /* if(addr & get_address_mask() >= 0) { payload.set_response_status(TLM_ADDRESS_ERROR_RESPONSE); } else*/ if(length > 4) { std::cout << "length error" << endl; payload.set_response_status(TLM_BURST_ERROR_RESPONSE); } else { bool success; uint32_t data; if(cmd == TLM_READ_COMMAND) { success = local_access(false, addr, data, length, burst_length); printf("read from 0x%X: 0x%X\n", addr, data); if(success) { *data_ptr = data; payload.set_response_status(TLM_OK_RESPONSE); } else { std::cout << "read error" << endl; payload.set_response_status(TLM_GENERIC_ERROR_RESPONSE); } //memcpy(ptr, &mem[adr], len); } else if(cmd == TLM_WRITE_COMMAND) { data = *data_ptr; success = local_access(true, addr, data, length, burst_length); printf("write to 0x%X: 0x%X\n", addr, data); if(success) { payload.set_response_status(TLM_OK_RESPONSE); } else { std::cout << "write error" << endl; payload.set_response_status(TLM_GENERIC_ERROR_RESPONSE); } //memcpy(&mem[adr], ptr, len); } else { std::cout << "no such command" << endl; payload.set_response_status(TLM_COMMAND_ERROR_RESPONSE); } } }
// 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; }