// Unit test for tlm_generic_payload update_original_from() method #include #define SC_INCLUDE_DYNAMIC_PROCESSES #include "systemc" using namespace sc_core; using namespace sc_dt; using namespace std; #include "tlm.h" #include "tlm_utils/simple_initiator_socket.h" #include "tlm_utils/simple_target_socket.h" #include "mm.h" struct my_extension: tlm::tlm_extension { my_extension() {} virtual tlm_extension_base* clone() const { my_extension* ext = new my_extension; ext->len = len; ext->bel = bel; ext->ptr = ptr; ext->byt = byt; return ext; } virtual void copy_from(tlm_extension_base const &ext) { len = static_cast(ext).len; bel = static_cast(ext).bel; ptr = static_cast(ext).ptr; byt = static_cast(ext).byt; } unsigned int len; unsigned int bel; unsigned char* ptr; unsigned char* byt; }; struct Initiator: sc_module { tlm_utils::simple_initiator_socket socket; typedef unsigned char uchar; SC_CTOR(Initiator) : socket("socket") { SC_THREAD(thread_process); data = new uchar[32]; byte_enable = new uchar[32]; } void thread_process() { tlm::tlm_generic_payload* trans; sc_time delay = SC_ZERO_TIME; for (int i = 0; i < 1000000; i++) { int addr = 0; tlm::tlm_command cmd = static_cast(rand() % 2); unsigned int len = rand() % 33; unsigned int bel = rand() % (len + 1); // Fix sizes when performing a speed test //cmd = tlm::TLM_READ_COMMAND; //len = 32; //bel = 8; for (unsigned int i = 0; i < len; i++) if (cmd == tlm::TLM_WRITE_COMMAND) { data[i] = rand() % 256; } else data[i] = 0x99; trans = m_mm.allocate(); trans->acquire(); trans->set_command( cmd ); trans->set_address( addr ); trans->set_data_ptr( data ); trans->set_data_length( len ); trans->set_streaming_width( len ); trans->set_byte_enable_length( bel ); for (unsigned int i = 0; i < bel; i++) { byte_enable[i] = (rand() % 2) ? 0xff : 0; } if (bel) trans->set_byte_enable_ptr( byte_enable ); else trans->set_byte_enable_ptr( 0 ); trans->set_dmi_allowed( false ); trans->set_response_status( tlm::TLM_INCOMPLETE_RESPONSE ); // Add sticky extension diagnostics my_extension* ext; trans->get_extension(ext); if (!ext) { ext = new my_extension; trans->set_extension(ext); } ext->len = len; ext->bel = bel; ext->ptr = data; ext->byt = byte_enable; socket->b_transport( *trans, delay ); // Blocking transport call if ( trans->is_response_error() ) SC_REPORT_ERROR("TLM-2", "Response error from b_transport"); //cout << "cmd = " << cmd << ", len = " << len << ", bel = " << bel << endl; //cout << hex << setw(2) << setfill('0') << (unsigned int)data[i]; if (cmd == tlm::TLM_READ_COMMAND) { for (unsigned int i = 0; i < len; i++) if (bel) if (byte_enable[i % bel]) sc_assert( data[i] == ext->ptr[i] ); else sc_assert( data[i] == 0x99 ); else sc_assert( data[i] == ext->ptr[i] ); } trans->release(); } } mm m_mm; // Memory manager unsigned char* data; // 32 bytes unsigned char* byte_enable; }; struct Interconnect: sc_module { tlm_utils::simple_target_socket targ_socket; tlm_utils::simple_initiator_socket init_socket; SC_CTOR(Interconnect) : targ_socket("targ_socket") , init_socket("init_socket") { targ_socket.register_b_transport(this, &Interconnect::b_transport); } virtual void b_transport( tlm::tlm_generic_payload& trans, sc_time& delay ) { unsigned int bel = trans.get_byte_enable_length(); trans2.set_data_ptr( data ); if (bel) trans2.set_byte_enable_ptr( byte_enable ); trans2.deep_copy_from(trans); init_socket->b_transport( trans2, delay ); trans.update_original_from( trans2 ); } tlm::tlm_generic_payload trans2; unsigned char data[32]; unsigned char byte_enable[32]; }; struct Target: sc_module { tlm_utils::simple_target_socket socket; SC_CTOR(Target) : socket("socket") { socket.register_b_transport(this, &Target ::b_transport); typedef unsigned char uchar; data = new uchar[32]; } virtual void b_transport( tlm::tlm_generic_payload& trans, sc_time& delay ) { tlm::tlm_command cmd = trans.get_command(); unsigned char* ptr = trans.get_data_ptr(); unsigned int len = trans.get_data_length(); unsigned char* byt = trans.get_byte_enable_ptr(); unsigned int bel = trans.get_byte_enable_length(); my_extension* ext; trans.get_extension(ext); sc_assert( ext ); sc_assert( len == ext->len ); sc_assert( bel == ext->bel ); for (unsigned int i = 0; i < bel; i++) sc_assert( byt[i] == ext->byt[i] ); for (unsigned int i = 0; i < len; i++) sc_assert( ptr[i] == ext->ptr[i] ); if (cmd == tlm::TLM_READ_COMMAND) { for (unsigned int i = 0; i < len; i++) { data[i] = rand() % 256; ptr[i] = data[i]; } ext->ptr = data; } trans.set_dmi_allowed( true ); trans.set_response_status( tlm::TLM_OK_RESPONSE ); } unsigned char* data; // 32 bytes }; SC_MODULE(Top) { Initiator *initiator; Interconnect *interconnect; Target *target; SC_CTOR(Top) { // Instantiate components initiator = new Initiator ("initiator"); interconnect = new Interconnect("interconnect"); target = new Target ("target"); // One initiator is bound directly to one target with no intervening bus // Bind initiator socket to target socket initiator ->socket .bind( interconnect->targ_socket ); interconnect ->init_socket.bind( target ->socket ); } }; int sc_main(int argc, char* argv[]) { cout << "Unit test for update_original_from(). Should remain silent\n"; Top top("top"); sc_start(); return 0; }