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 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); }
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; }