/* ------------------------------------------------------------------------- */ 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; } } }
/** * \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; }