112855Sgabeblack@google.com/***************************************************************************** 212855Sgabeblack@google.com 312855Sgabeblack@google.com Licensed to Accellera Systems Initiative Inc. (Accellera) under one or 412855Sgabeblack@google.com more contributor license agreements. See the NOTICE file distributed 512855Sgabeblack@google.com with this work for additional information regarding copyright ownership. 612855Sgabeblack@google.com Accellera licenses this file to you under the Apache License, Version 2.0 712855Sgabeblack@google.com (the "License"); you may not use this file except in compliance with the 812855Sgabeblack@google.com License. You may obtain a copy of the License at 912855Sgabeblack@google.com 1012855Sgabeblack@google.com http://www.apache.org/licenses/LICENSE-2.0 1112855Sgabeblack@google.com 1212855Sgabeblack@google.com Unless required by applicable law or agreed to in writing, software 1312855Sgabeblack@google.com distributed under the License is distributed on an "AS IS" BASIS, 1412855Sgabeblack@google.com WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 1512855Sgabeblack@google.com implied. See the License for the specific language governing 1612855Sgabeblack@google.com permissions and limitations under the License. 1712855Sgabeblack@google.com 1812855Sgabeblack@google.com *****************************************************************************/ 1912855Sgabeblack@google.com 2012855Sgabeblack@google.com 2112855Sgabeblack@google.com/* 2212855Sgabeblack@google.comThis C++ programme runs single transactions through a single 2312855Sgabeblack@google.comendianness conversion function, then through a simple memory model, 2412855Sgabeblack@google.comthen converts it back. 2512855Sgabeblack@google.comTakes the initial memory state as input and provides the final 2612855Sgabeblack@google.commemory state as output. 2712855Sgabeblack@google.com*/ 2812855Sgabeblack@google.com 2912855Sgabeblack@google.com 3012855Sgabeblack@google.com#define BUFFER_SIZE 2048 3112855Sgabeblack@google.com 3212855Sgabeblack@google.com#include<systemc> 3312855Sgabeblack@google.com#include "tlm.h" 3412855Sgabeblack@google.com#include<iostream> 3512855Sgabeblack@google.com#include<time.h> 3612855Sgabeblack@google.com#include <fstream> 3712855Sgabeblack@google.com 3812855Sgabeblack@google.comusing namespace std; 3912855Sgabeblack@google.comusing namespace tlm; 4012855Sgabeblack@google.comusing namespace sc_dt; 4112855Sgabeblack@google.com 4212855Sgabeblack@google.com 4312855Sgabeblack@google.com// simple set of types with known sizeof(), for testing // 4412855Sgabeblack@google.comtemplate<int SIZE> class dt { 4512855Sgabeblack@google.com char content[SIZE]; 4612855Sgabeblack@google.com}; 4712855Sgabeblack@google.com 4812855Sgabeblack@google.com 4912855Sgabeblack@google.com#define convert(function) \ 5012855Sgabeblack@google.com switch(data_width) { \ 5112855Sgabeblack@google.com case 1: function<dt<1> >(&txn,bus_width); break; \ 5212855Sgabeblack@google.com case 2: function<dt<2> >(&txn,bus_width); break; \ 5312855Sgabeblack@google.com case 4: function<dt<4> >(&txn,bus_width); break; \ 5412855Sgabeblack@google.com case 8: function<dt<8> >(&txn,bus_width); break; \ 5512855Sgabeblack@google.com case 16: function<dt<16> >(&txn,bus_width); break; \ 5612855Sgabeblack@google.com case 32: function<dt<32> >(&txn,bus_width); break; \ 5712855Sgabeblack@google.com default: cout << "bad data width\n"; \ 5812855Sgabeblack@google.com exit(1); \ 5912855Sgabeblack@google.com } 6012855Sgabeblack@google.com 6112855Sgabeblack@google.com 6212855Sgabeblack@google.com// forward declarations - see below 6312855Sgabeblack@google.comtemplate<class DATAWORD> inline void 6412855Sgabeblack@google.comlocal_single_tohe(tlm_generic_payload *txn, unsigned int sizeof_databus); 6512855Sgabeblack@google.comtemplate<class DATAWORD> inline void 6612855Sgabeblack@google.comlocal_single_fromhe(tlm_generic_payload *txn, unsigned int sizeof_databus); 6712855Sgabeblack@google.com 6812855Sgabeblack@google.com 6912855Sgabeblack@google.comvoid test_a_conversion(char cmd, tlm_generic_payload &txn, std::ifstream & fin) { 7012855Sgabeblack@google.com 7112855Sgabeblack@google.com if(cmd == 'R') txn.set_read(); 7212855Sgabeblack@google.com else txn.set_write(); 7312855Sgabeblack@google.com 7412855Sgabeblack@google.com fin.ignore(10000,'='); 7512855Sgabeblack@google.com uint64 a; 7612855Sgabeblack@google.com fin >> a; 7712855Sgabeblack@google.com txn.set_address(a); 7812855Sgabeblack@google.com 7912855Sgabeblack@google.com fin.ignore(10000,'='); 8012855Sgabeblack@google.com int l; 8112855Sgabeblack@google.com fin >> l; 8212855Sgabeblack@google.com txn.set_data_length(l); 8312855Sgabeblack@google.com 8412855Sgabeblack@google.com int bus_width; 8512855Sgabeblack@google.com fin.ignore(10000,'='); fin >> bus_width; 8612855Sgabeblack@google.com 8712855Sgabeblack@google.com int data_width; 8812855Sgabeblack@google.com fin.ignore(10000,'='); fin >> data_width; 8912855Sgabeblack@google.com 9012855Sgabeblack@google.com int initiator_offset; 9112855Sgabeblack@google.com fin.ignore(10000,'='); fin >> initiator_offset; 9212855Sgabeblack@google.com 9312855Sgabeblack@google.com unsigned char *original_byte_enable = 0; 9412855Sgabeblack@google.com unsigned char *byte_enable_legible = 9512855Sgabeblack@google.com new unsigned char[txn.get_data_length() + 1]; 9612855Sgabeblack@google.com memset(byte_enable_legible, 0, txn.get_data_length() + 1); 9712855Sgabeblack@google.com fin.ignore(10000,'='); 9812855Sgabeblack@google.com for(unsigned b=0; b<txn.get_data_length(); b++) { 9912855Sgabeblack@google.com char tmp; fin >> tmp; 10012855Sgabeblack@google.com if((tmp=='0')||(tmp=='1')||(tmp=='x')) byte_enable_legible[b]=tmp; 10112855Sgabeblack@google.com else break; 10212855Sgabeblack@google.com } 10312855Sgabeblack@google.com if((byte_enable_legible[0] == '1') || (byte_enable_legible[0] == '0')) { 10412855Sgabeblack@google.com txn.set_byte_enable_ptr(new unsigned char[txn.get_data_length()]); 10512855Sgabeblack@google.com txn.set_byte_enable_length(txn.get_data_length()); 10612855Sgabeblack@google.com original_byte_enable = txn.get_byte_enable_ptr(); 10712855Sgabeblack@google.com for(unsigned int i=0; i<txn.get_data_length(); i++) { 10812855Sgabeblack@google.com if(byte_enable_legible[i] == '0') { 10912855Sgabeblack@google.com txn.get_byte_enable_ptr()[i] = TLM_BYTE_DISABLED; 11012855Sgabeblack@google.com } else if(byte_enable_legible[i] == '1') { 11112855Sgabeblack@google.com txn.get_byte_enable_ptr()[i] = TLM_BYTE_ENABLED; 11212855Sgabeblack@google.com } else { 11312855Sgabeblack@google.com // not enough byte enables 11412855Sgabeblack@google.com txn.set_byte_enable_length(i); 11512855Sgabeblack@google.com break; 11612855Sgabeblack@google.com } 11712855Sgabeblack@google.com } 11812855Sgabeblack@google.com } else { 11912855Sgabeblack@google.com txn.set_byte_enable_ptr(0); 12012855Sgabeblack@google.com txn.set_byte_enable_length(0); 12112855Sgabeblack@google.com } 12212855Sgabeblack@google.com 12312855Sgabeblack@google.com int stream_width; 12412855Sgabeblack@google.com fin.ignore(10000,'='); fin >> stream_width; 12512855Sgabeblack@google.com txn.set_streaming_width(stream_width); 12612855Sgabeblack@google.com 12712855Sgabeblack@google.com cout << "enter initiator memory state = ("<< BUFFER_SIZE << " characters)\n"; 12812855Sgabeblack@google.com unsigned char initiator_mem[BUFFER_SIZE+1]; 12912855Sgabeblack@google.com memset(initiator_mem, 0, BUFFER_SIZE+1); 13012855Sgabeblack@google.com fin.ignore(10000,'='); fin >> initiator_mem; 13112855Sgabeblack@google.com 13212855Sgabeblack@google.com txn.set_data_ptr(initiator_mem + initiator_offset); 13312855Sgabeblack@google.com 13412855Sgabeblack@google.com cout << "enter target memory state = ("<< BUFFER_SIZE << " characters)\n"; 13512855Sgabeblack@google.com unsigned char target_mem[BUFFER_SIZE+1]; 13612855Sgabeblack@google.com memset(target_mem, 0, BUFFER_SIZE+1); 13712855Sgabeblack@google.com fin.ignore(10000,'='); fin >> target_mem; 13812855Sgabeblack@google.com 13912855Sgabeblack@google.com cout << "enter converter choice = (0 => generic, 1 => word, 2 => aligned, 3 => single)\n"; 14012855Sgabeblack@google.com int converter; 14112855Sgabeblack@google.com fin.ignore(10000,'='); fin >> converter; 14212855Sgabeblack@google.com 14312855Sgabeblack@google.com cout << "Initiator Intent\n"; 14412855Sgabeblack@google.com cout << " Cmd = " << cmd << endl; 14512855Sgabeblack@google.com cout << " Addr = " << txn.get_address() << endl; 14612855Sgabeblack@google.com cout << " Len = " << txn.get_data_length() << endl; 14712855Sgabeblack@google.com cout << " Bus Width = " << bus_width << endl; 14812855Sgabeblack@google.com cout << " Data Word = " << data_width << endl; 14912855Sgabeblack@google.com#ifdef VERBOSE 15012855Sgabeblack@google.com cout << " Initiator offset and txn data pointer = " << initiator_offset << ", " << int(txn.get_data_ptr()) << endl; 15112855Sgabeblack@google.com cout << " Byte enables and byte enable pointer = " << byte_enable_legible << ", " << int(txn.get_byte_enable_ptr()) << endl; 15212855Sgabeblack@google.com#else 15312855Sgabeblack@google.com cout << " Initiator offset = " << initiator_offset << endl; 15412855Sgabeblack@google.com cout << " Byte enables = " << byte_enable_legible << endl; 15512855Sgabeblack@google.com#endif 15612855Sgabeblack@google.com cout << " Byte enable length = " << txn.get_byte_enable_length() << endl; 15712855Sgabeblack@google.com cout << " Streaming width = " << txn.get_streaming_width() << endl; 15812855Sgabeblack@google.com cout << " Initiator memory = " << initiator_mem << endl; 15912855Sgabeblack@google.com cout << " Target memory = " << target_mem << endl; 16012855Sgabeblack@google.com cout << " Converter = " << converter << endl << endl; 16112855Sgabeblack@google.com 16212855Sgabeblack@google.com // initiator // 16312855Sgabeblack@google.com switch(converter) { 16412855Sgabeblack@google.com case 0: convert(tlm_to_hostendian_generic); break; 16512855Sgabeblack@google.com case 1: convert(tlm_to_hostendian_word); break; 16612855Sgabeblack@google.com case 2: convert(tlm_to_hostendian_aligned); break; 16712855Sgabeblack@google.com case 3: convert(tlm_to_hostendian_single); break; 16812855Sgabeblack@google.com case 4: convert(local_single_tohe); break; 16912855Sgabeblack@google.com default: cout << "no such converter as " << converter << endl; 17012855Sgabeblack@google.com exit(1); 17112855Sgabeblack@google.com } 17212855Sgabeblack@google.com 17312855Sgabeblack@google.com cout << "Converted Transaction\n"; 17412855Sgabeblack@google.com cout << " Addr = " << txn.get_address() << endl; 17512855Sgabeblack@google.com cout << " Len = " << txn.get_data_length() << endl; 17612855Sgabeblack@google.com#ifdef VERBOSE 17712855Sgabeblack@google.com cout << " Txn data pointer = " << int(txn.get_data_ptr()) << endl; 17812855Sgabeblack@google.com if(txn.get_byte_enable_ptr() != 0) { 17912855Sgabeblack@google.com cout << " Byte enables and byte enable pointer = "; 18012855Sgabeblack@google.com for(unsigned int i=0; i<txn.get_data_length(); i++) 18112855Sgabeblack@google.com cout << (txn.get_byte_enable_ptr()[i] ? '1' : '0'); 18212855Sgabeblack@google.com cout << ", " << int(txn.get_byte_enable_ptr()) << endl; 18312855Sgabeblack@google.com } 18412855Sgabeblack@google.com#else 18512855Sgabeblack@google.com cout << " Txn data pointer = " << 18612855Sgabeblack@google.com (txn.get_data_ptr() == initiator_mem+initiator_offset ? "unchanged" : "changed") << endl; 18712855Sgabeblack@google.com if(txn.get_byte_enable_ptr() != 0) { 18812855Sgabeblack@google.com cout << " Byte enables and byte enable pointer = "; 18912855Sgabeblack@google.com for(unsigned int i=0; i<txn.get_data_length(); i++) 19012855Sgabeblack@google.com cout << (txn.get_byte_enable_ptr()[i] ? '1' : '0'); 19112855Sgabeblack@google.com cout << ", " << 19212855Sgabeblack@google.com (txn.get_byte_enable_ptr() == original_byte_enable ? "unchanged" : "changed") << endl; 19312855Sgabeblack@google.com } 19412855Sgabeblack@google.com#endif 19512855Sgabeblack@google.com cout << " Byte enable length = " << txn.get_byte_enable_length() << endl; 19612855Sgabeblack@google.com cout << " Streaming width = " << txn.get_streaming_width() << endl; 19712855Sgabeblack@google.com cout << endl; 19812855Sgabeblack@google.com 19912855Sgabeblack@google.com // target // 20012855Sgabeblack@google.com int sw = txn.get_streaming_width(); 20112855Sgabeblack@google.com if((txn.get_data_length()/sw)*sw != txn.get_data_length()) { 20212855Sgabeblack@google.com cout << "ERROR: Data length not a multiple of streaming width\n"; 20312855Sgabeblack@google.com exit(1); 20412855Sgabeblack@google.com } 20512855Sgabeblack@google.com for(unsigned int ss = 0; ss < txn.get_data_length(); ss += sw) { 20612855Sgabeblack@google.com if(txn.get_byte_enable_ptr() == 0) { 20712855Sgabeblack@google.com // simple transaction can be processed by mem-copy 20812855Sgabeblack@google.com if(txn.is_read()) 20912855Sgabeblack@google.com memcpy(ss+txn.get_data_ptr(), target_mem+txn.get_address(), sw); 21012855Sgabeblack@google.com else 21112855Sgabeblack@google.com memcpy(target_mem+txn.get_address(), ss+txn.get_data_ptr(), sw); 21212855Sgabeblack@google.com } else { 21312855Sgabeblack@google.com // complex transaction, byte enables, maybe shorter than data 21412855Sgabeblack@google.com int bel = txn.get_byte_enable_length(); 21512855Sgabeblack@google.com if(txn.is_read()) { 21612855Sgabeblack@google.com for(int j=0; j<sw; j++) { 21712855Sgabeblack@google.com if(txn.get_byte_enable_ptr()[(ss+j) % bel]) 21812855Sgabeblack@google.com (txn.get_data_ptr())[ss+j] = target_mem[j+txn.get_address()]; 21912855Sgabeblack@google.com } 22012855Sgabeblack@google.com } else { 22112855Sgabeblack@google.com for(int j=0; j<sw; j++) { 22212855Sgabeblack@google.com if(txn.get_byte_enable_ptr()[(ss+j) % bel]) 22312855Sgabeblack@google.com target_mem[j+txn.get_address()] = (txn.get_data_ptr())[ss+j]; 22412855Sgabeblack@google.com } 22512855Sgabeblack@google.com } 22612855Sgabeblack@google.com } 22712855Sgabeblack@google.com } 22812855Sgabeblack@google.com 22912855Sgabeblack@google.com // initiator again // 23012855Sgabeblack@google.com if((rand() & 0x100) && (converter < 4)) { 23112855Sgabeblack@google.com#ifdef VERBOSE 23212855Sgabeblack@google.com cout << "using single entry point for response\n"; 23312855Sgabeblack@google.com#endif 23412855Sgabeblack@google.com tlm_from_hostendian(&txn); 23512855Sgabeblack@google.com } else { 23612855Sgabeblack@google.com#ifdef VERBOSE 23712855Sgabeblack@google.com cout << "using specific entry point for response\n"; 23812855Sgabeblack@google.com#endif 23912855Sgabeblack@google.com switch(converter) { 24012855Sgabeblack@google.com case 0: convert(tlm_from_hostendian_generic); break; 24112855Sgabeblack@google.com case 1: convert(tlm_from_hostendian_word); break; 24212855Sgabeblack@google.com case 2: convert(tlm_from_hostendian_aligned); break; 24312855Sgabeblack@google.com case 3: convert(tlm_from_hostendian_single); break; 24412855Sgabeblack@google.com case 4: convert(local_single_fromhe); break; 24512855Sgabeblack@google.com default: cout << "no such converter as " << converter << endl; 24612855Sgabeblack@google.com exit(1); 24712855Sgabeblack@google.com } 24812855Sgabeblack@google.com } 24912855Sgabeblack@google.com 25012855Sgabeblack@google.com // print the results // 25112855Sgabeblack@google.com cout << "Memory States after Transaction\n"; 25212855Sgabeblack@google.com cout << " initiator = " << initiator_mem << endl; 25312855Sgabeblack@google.com cout << " target = " << target_mem << endl << endl; 25412855Sgabeblack@google.com 25512855Sgabeblack@google.com // clean up 25612855Sgabeblack@google.com delete [] byte_enable_legible; 25712855Sgabeblack@google.com if(original_byte_enable != 0) delete [] original_byte_enable; 25812855Sgabeblack@google.com} 25912855Sgabeblack@google.com 26012855Sgabeblack@google.com 26112855Sgabeblack@google.comvoid pool_status() { 26212855Sgabeblack@google.com cout << "Pool status: "; 26312855Sgabeblack@google.com tlm_endian_context *f = global_tlm_endian_context_pool.first; 26412855Sgabeblack@google.com while(f!=0) { 26512855Sgabeblack@google.com cout << "(" << f->dbuf_size << "," << f->bebuf_size << ") "; 26612855Sgabeblack@google.com f = f->next; 26712855Sgabeblack@google.com } 26812855Sgabeblack@google.com cout << endl; 26912855Sgabeblack@google.com} 27012855Sgabeblack@google.com 27112855Sgabeblack@google.com 27212855Sgabeblack@google.comint sc_main(int argc, char **argv) { 27312855Sgabeblack@google.com 27412855Sgabeblack@google.com #include <string> 27512855Sgabeblack@google.com 27612855Sgabeblack@google.com // no command line parameters // 27712855Sgabeblack@google.com // get everything from stdin and build transaction object // 27812855Sgabeblack@google.com cout << "\nTLM-2 Endianness Conversion Helper Functions Tester\n"; 27912855Sgabeblack@google.com cout << "March 2008\n"; 28012855Sgabeblack@google.com cout << "January 2012 Updated to read from endian_conv/input.txt\n\n"; 28112855Sgabeblack@google.com 28212855Sgabeblack@google.com std::string filename; 28312855Sgabeblack@google.com std::ifstream fin; 28412855Sgabeblack@google.com 28512855Sgabeblack@google.com if (1 == argc) 28612855Sgabeblack@google.com filename = "endian_conv/input.txt"; 28712855Sgabeblack@google.com else if (2 == argc) 28812855Sgabeblack@google.com filename = argv[1]; 28912855Sgabeblack@google.com else { 29012855Sgabeblack@google.com std::cerr << "Too many input arguments" << std::endl; 29112855Sgabeblack@google.com return 1; 29212855Sgabeblack@google.com } 29312855Sgabeblack@google.com 29412855Sgabeblack@google.com 29512855Sgabeblack@google.com fin.open(filename.c_str(), ios_base::in); 29612855Sgabeblack@google.com if (!fin) { 29712855Sgabeblack@google.com std::cerr << "Could not open input filename " << filename << std::endl; 29812855Sgabeblack@google.com return 1; 29912855Sgabeblack@google.com } 30012855Sgabeblack@google.com 30112855Sgabeblack@google.com srand(time(NULL)); 30212855Sgabeblack@google.com const int nr_txns_in_pool = 7; 30312855Sgabeblack@google.com const int txn_to_cycle = 4; 30412855Sgabeblack@google.com tlm_generic_payload *txns[nr_txns_in_pool]; 30512855Sgabeblack@google.com for(int i=0; i < nr_txns_in_pool; i++) txns[i] = new tlm_generic_payload; 30612855Sgabeblack@google.com 30712855Sgabeblack@google.com for(int i=0; true; i = ((i+1) % nr_txns_in_pool)) { 30812855Sgabeblack@google.com cout << i << " enter {R|W}, addr=a, len=l, bus width=b, word width=w, initiator offset=i, be={x|01}, stream width=s\n"; 30912855Sgabeblack@google.com pool_status(); 31012855Sgabeblack@google.com char command; 31112855Sgabeblack@google.com fin >> command; 31212855Sgabeblack@google.com if(fin.eof()) break; 31312855Sgabeblack@google.com if((command != 'R') && (command != 'W')) break; 31412855Sgabeblack@google.com if(i==txn_to_cycle) { 31512855Sgabeblack@google.com // should cause 2 extensions to get pushed to the pool once they've been used 31612855Sgabeblack@google.com delete txns[i]; 31712855Sgabeblack@google.com pool_status(); 31812855Sgabeblack@google.com delete txns[i-1]; 31912855Sgabeblack@google.com pool_status(); 32012855Sgabeblack@google.com // and popped back later when these new ones establish contexts 32112855Sgabeblack@google.com txns[i] = new tlm_generic_payload; 32212855Sgabeblack@google.com txns[i-1] = new tlm_generic_payload; 32312855Sgabeblack@google.com pool_status(); 32412855Sgabeblack@google.com } 32512855Sgabeblack@google.com test_a_conversion(command, *txns[i], fin); 32612855Sgabeblack@google.com } 32712855Sgabeblack@google.com 32812855Sgabeblack@google.com for(int i=0; i < nr_txns_in_pool; i++) { 32912855Sgabeblack@google.com delete txns[i]; 33012855Sgabeblack@google.com pool_status(); 33112855Sgabeblack@google.com } 33212855Sgabeblack@google.com return 0; 33312855Sgabeblack@google.com} 33412855Sgabeblack@google.com 33512855Sgabeblack@google.com 33612855Sgabeblack@google.com// converter functions for non-aligned single transactions 33712855Sgabeblack@google.com// included here for validation only. not designed for general use. 33812855Sgabeblack@google.com 33912855Sgabeblack@google.comunsigned char *original_dptr; 34012855Sgabeblack@google.comsc_dt::uint64 original_addr; 34112855Sgabeblack@google.com 34212855Sgabeblack@google.comtemplate<class DATAWORD> inline void 34312855Sgabeblack@google.comlocal_single_tohe(tlm_generic_payload *txn, unsigned int sizeof_databus) { 34412855Sgabeblack@google.com if(txn->get_data_length() != sizeof(DATAWORD)) { 34512855Sgabeblack@google.com cout << "Error: local_single_tohe() wrongly called\n"; 34612855Sgabeblack@google.com exit(1); 34712855Sgabeblack@google.com } 34812855Sgabeblack@google.com 34912855Sgabeblack@google.com sc_dt::uint64 mask = sizeof_databus - 1; 35012855Sgabeblack@google.com 35112855Sgabeblack@google.com // set up new buffers, length and address 35212855Sgabeblack@google.com if(sizeof(DATAWORD) > sizeof_databus) 35312855Sgabeblack@google.com txn->set_data_length(sizeof_databus + sizeof(DATAWORD)); 35412855Sgabeblack@google.com else 35512855Sgabeblack@google.com txn->set_data_length(2 * sizeof_databus); 35612855Sgabeblack@google.com txn->set_streaming_width(txn->get_data_length()); 35712855Sgabeblack@google.com unsigned char *new_data = new unsigned char[txn->get_data_length()]; 35812855Sgabeblack@google.com unsigned char *new_be = new unsigned char[txn->get_data_length()]; 35912855Sgabeblack@google.com // drive all BEs to zero initially 36012855Sgabeblack@google.com for(unsigned int i=0; i<txn->get_data_length(); i++) new_be[i] = 0; 36112855Sgabeblack@google.com sc_dt::uint64 new_addr = txn->get_address() & ~mask; 36212855Sgabeblack@google.com 36312855Sgabeblack@google.com // Comments assume arithmetic mode big endian initiator modelled on little 36412855Sgabeblack@google.com // endian host (but the functionality is the same for LE initiator on BE host) 36512855Sgabeblack@google.com 36612855Sgabeblack@google.com // iterate over the initiator word byte by byte, MSB first 36712855Sgabeblack@google.com unsigned char *curr_d = txn->get_data_ptr() + sizeof(DATAWORD) - 1; 36812855Sgabeblack@google.com unsigned char *curr_b = txn->get_byte_enable_ptr() + sizeof(DATAWORD) - 1; 36912855Sgabeblack@google.com 37012855Sgabeblack@google.com // initiator intent is to put the MSB at the address given in the transaction 37112855Sgabeblack@google.com sc_dt::uint64 curr_a = txn->get_address(); 37212855Sgabeblack@google.com 37312855Sgabeblack@google.com // iterate copying data and byte enables 37412855Sgabeblack@google.com for( ; curr_d >= txn->get_data_ptr(); curr_d--, curr_b--, curr_a++) { 37512855Sgabeblack@google.com // work out the address in the TLM interpretation of the initiator's intent 37612855Sgabeblack@google.com sc_dt::uint64 he_addr = curr_a ^ mask; 37712855Sgabeblack@google.com int idx = he_addr - new_addr; 37812855Sgabeblack@google.com if(txn->is_write()) new_data[idx] = *curr_d; 37912855Sgabeblack@google.com if(txn->get_byte_enable_ptr() == 0) new_be[idx] = 1; 38012855Sgabeblack@google.com else new_be[idx] = *curr_b; 38112855Sgabeblack@google.com } 38212855Sgabeblack@google.com 38312855Sgabeblack@google.com // replace the pointers 38412855Sgabeblack@google.com original_dptr = txn->get_data_ptr(); 38512855Sgabeblack@google.com txn->set_data_ptr(new_data); 38612855Sgabeblack@google.com txn->set_byte_enable_ptr(new_be); 38712855Sgabeblack@google.com txn->set_byte_enable_length(txn->get_data_length()); 38812855Sgabeblack@google.com original_addr = txn->get_address(); 38912855Sgabeblack@google.com txn->set_address(new_addr); 39012855Sgabeblack@google.com} 39112855Sgabeblack@google.com 39212855Sgabeblack@google.com 39312855Sgabeblack@google.comtemplate<class DATAWORD> inline void 39412855Sgabeblack@google.comlocal_single_fromhe(tlm_generic_payload *txn, unsigned int sizeof_databus) { 39512855Sgabeblack@google.com sc_dt::uint64 mask = sizeof_databus - 1; 39612855Sgabeblack@google.com 39712855Sgabeblack@google.com // Comments assume arithmetic mode big endian initiator modelled on little 39812855Sgabeblack@google.com // endian host (but the functionality is the same for LE initiator on BE host) 39912855Sgabeblack@google.com 40012855Sgabeblack@google.com // iterate over the initiator word byte by byte, MSB first 40112855Sgabeblack@google.com unsigned char *curr_d = original_dptr + sizeof(DATAWORD) - 1; 40212855Sgabeblack@google.com 40312855Sgabeblack@google.com // initiator intent is to put the MSB at the address given in the transaction 40412855Sgabeblack@google.com sc_dt::uint64 curr_a = original_addr; 40512855Sgabeblack@google.com 40612855Sgabeblack@google.com // iterate copying data and byte enables 40712855Sgabeblack@google.com for( ; curr_d >= original_dptr; curr_d--, curr_a++) { 40812855Sgabeblack@google.com // work out the address in the TLM interpretation of the initiator's intent 40912855Sgabeblack@google.com sc_dt::uint64 he_addr = curr_a ^ mask; 41012855Sgabeblack@google.com int idx = he_addr - txn->get_address(); 41112855Sgabeblack@google.com if((txn->is_read()) && (txn->get_byte_enable_ptr()[idx] != 0)) 41212855Sgabeblack@google.com *curr_d = txn->get_data_ptr()[idx]; 41312855Sgabeblack@google.com } 41412855Sgabeblack@google.com 41512855Sgabeblack@google.com // clean up 41612855Sgabeblack@google.com delete [] txn->get_data_ptr(); 41712855Sgabeblack@google.com delete [] txn->get_byte_enable_ptr(); 41812855Sgabeblack@google.com} 41912855Sgabeblack@google.com 420