void thread_process() { // TLM-2 generic payload transaction tlm::tlm_generic_payload* trans = new tlm::tlm_generic_payload; sc_time delay = sc_time(10, SC_NS); // Generate a random sequence of reads and writes for (int i = 0; i < 128; i += 4) { int data; tlm::tlm_command cmd = static_cast<tlm::tlm_command> (rand() % 2); if (cmd == tlm::TLM_WRITE_COMMAND) data = 0xFF000000 | i; trans->set_command(cmd); //address is set randomly within the address range trans->set_address(rand() % N_INIT); trans->set_data_ptr(reinterpret_cast<unsigned char*> (&data)); trans->set_data_length(4); trans->set_streaming_width(4); // = data_length to indicate no streaming trans->set_byte_enable_ptr(0); // 0 indicates unused trans->set_dmi_allowed(false); // Mandatory initial value trans->set_response_status(tlm::TLM_INCOMPLETE_RESPONSE); // Mandatory initial value // Blocking transport call socket->b_transport(*trans, delay); // Initiator obliged to check response status if (trans->is_response_error()) { // ********************* // Print response string // ********************* char txt[100]; sprintf(txt, "Error from b_transport, response status = %s", trans->get_response_string().c_str()); SC_REPORT_ERROR("TLM-2", txt); } cout << sc_time_stamp() << " @ " << " trans = { " << (cmd ? 'W' : 'R') << ", " << hex << i << " } , data = " << hex << data << " at time " << sc_time_stamp() << " delay = " << delay << endl; } // ******************************************************** // Use debug transaction interface to dump memory contents, // reusing same transaction object // ******************************************************** trans->set_command(tlm::TLM_READ_COMMAND); trans->set_address(0); trans->set_read(); trans->set_data_length(128); unsigned char* data = new unsigned char[128]; trans->set_data_ptr(data); unsigned int n_bytes = socket->transport_dbg(*trans); for (unsigned int i = 0; i < n_bytes; i += 4) { cout << "mem[" << i << "] = " << *(reinterpret_cast<unsigned int*> (&data[i])) << endl; } }
void peq_cb(tlm::tlm_generic_payload& trans, const tlm::tlm_phase& phase) { #ifdef DEBUG if (phase == tlm::END_REQ) fout << hex << trans.get_address() << " " << name() << " END_REQ at " << sc_time_stamp() << endl; else if (phase == tlm::BEGIN_RESP) fout << hex << trans.get_address() << " " << name() << " BEGIN_RESP at " << sc_time_stamp() << endl; #endif if (phase == tlm::END_REQ || (&trans == request_in_progress && phase == tlm::BEGIN_RESP)) { // The end of the BEGIN_REQ phase request_in_progress = 0; end_request_event.notify(); } else if (phase == tlm::BEGIN_REQ || phase == tlm::END_RESP) SC_REPORT_FATAL("TLM-2", "Illegal transaction phase received by initiator"); if (phase == tlm::BEGIN_RESP) { check_transaction( trans ); // Send final phase transition to target tlm::tlm_phase fw_phase = tlm::END_RESP; sc_time delay = sc_time(rand_ps(), SC_PS); socket->nb_transport_fw( trans, fw_phase, delay ); // Ignore return value } }
void dump() { unsigned char buffer[64]; // Use debug transaction interface to dump memory contents cout << "\nDump memories at time " << sc_time_stamp() << "\n"; for (unsigned int k = 0; k < 4; k++) { tlm::tlm_generic_payload dbg; sc_dt::uint64 A = 64 * k; dbg.set_address(A); dbg.set_read(); dbg.set_data_length(64); dbg.set_data_ptr(buffer); unsigned int n_bytes = socket->transport_dbg( dbg ); for (unsigned int i = 0; i < n_bytes; i += 4) { cout << "mem[" << hex << (A + i) << "] = " << *(reinterpret_cast<unsigned int*>( &buffer[i] )) << endl; } } cout << "\n"; }
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 ); }
void thread_process() { tlm::tlm_generic_payload* trans; sc_time delay; // Reset the local quantum keeper m_qk.reset(); wait(1, SC_US); for (int i = 0; i < RUN_LENGTH; i += 4) { // Grab a new transaction from the memory manager trans = m_mm.allocate(); trans->acquire(); data = i; trans->set_command( tlm::TLM_READ_COMMAND ); trans->set_address( i ); trans->set_data_ptr( reinterpret_cast<unsigned char*>(&data) ); trans->set_data_length( 4 ); trans->set_streaming_width( 4 ); // = data_length to indicate no streaming trans->set_byte_enable_ptr( 0 ); // 0 indicates unused trans->set_dmi_allowed( false ); // Mandatory initial value trans->set_response_status( tlm::TLM_INCOMPLETE_RESPONSE ); // Mandatory initial value delay = m_qk.get_local_time(); socket->b_transport( *trans, delay ); // Initiator obliged to check response status if (trans->is_response_error()) SC_REPORT_ERROR("TLM-2", trans->get_response_string().c_str()); if (data != i) SC_REPORT_ERROR("TLM-2", "Mismatch in initiator when reading back data"); cout << "READ addr = " << hex << i << ", data = " << data << " at " << sc_time_stamp() << " delay = " << delay << "\n"; trans->release(); // Accumulate local time and synchronize when quantum is reached m_qk.set( delay ); m_qk.inc( sc_time(100, SC_NS) );// Model time used for additional processing if (m_qk.need_sync()) m_qk.sync(); } }
void thread_process() { // TLM-2 generic payload transaction, reused across calls to b_transport tlm::tlm_generic_payload* trans = new tlm::tlm_generic_payload; sc_time delay = sc_time(10, SC_NS); // Generate a random sequence of reads and writes for (int i = 32; i < 96; i += 4) { tlm::tlm_command cmd = static_cast<tlm::tlm_command>(rand() % 2); if (cmd == tlm::TLM_WRITE_COMMAND) data = 0xFF000000 | i; // Initialize 8 out of the 10 attributes, byte_enable_length and extensions being unused trans->set_command( cmd ); trans->set_address( i ); trans->set_data_ptr( reinterpret_cast<unsigned char*>(&data) ); trans->set_data_length( 4 ); trans->set_streaming_width( 4 ); // = data_length to indicate no streaming trans->set_byte_enable_ptr( 0 ); // 0 indicates unused trans->set_dmi_allowed( false ); // Mandatory initial value trans->set_response_status( tlm::TLM_INCOMPLETE_RESPONSE ); // Mandatory initial value socket->b_transport( *trans, delay ); // Blocking transport call // Initiator obliged to check response status and delay if ( trans->is_response_error() ) SC_REPORT_ERROR("TLM-2", "Response error from b_transport"); cout << "trans = { " << (cmd ? 'W' : 'R') << ", " << hex << i << " } , data = " << hex << data << " at time " << sc_time_stamp() << " delay = " << delay << endl; // Realize the delay annotated onto the transport call wait(delay); } }
void thread_process() { tlm::tlm_generic_payload* trans; tlm::tlm_phase phase; sc_time delay; // Generate a sequence of random transactions for (int i = 0; i < 1000; i++) { int adr = rand(); tlm::tlm_command cmd = static_cast<tlm::tlm_command>(rand() % 2); if (cmd == tlm::TLM_WRITE_COMMAND) data[i % 16] = rand(); // Grab a new transaction from the memory manager trans = m_mm.allocate(); trans->acquire(); // Set all attributes except byte_enable_length and extensions (unused) trans->set_command( cmd ); trans->set_address( adr ); trans->set_data_ptr( reinterpret_cast<unsigned char*>(&data[i % 16]) ); trans->set_data_length( 4 ); trans->set_streaming_width( 4 ); // = data_length to indicate no streaming trans->set_byte_enable_ptr( 0 ); // 0 indicates unused trans->set_dmi_allowed( false ); // Mandatory initial value trans->set_response_status( tlm::TLM_INCOMPLETE_RESPONSE ); // Mandatory initial value // Initiator must honor BEGIN_REQ/END_REQ exclusion rule if (request_in_progress) wait(end_request_event); request_in_progress = trans; phase = tlm::BEGIN_REQ; // Timing annotation models processing time of initiator prior to call delay = sc_time(rand_ps(), SC_PS); fout << hex << adr << " " << name() << " new, cmd=" << (cmd ? 'W' : 'R') << ", data=" << hex << data[i % 16] << " at time " << sc_time_stamp() << endl; // Non-blocking transport call on the forward path tlm::tlm_sync_enum status; status = socket->nb_transport_fw( *trans, phase, delay ); // Check value returned from nb_transport_fw if (status == tlm::TLM_UPDATED) { // The timing annotation must be honored m_peq.notify( *trans, phase, delay ); } else if (status == tlm::TLM_COMPLETED) { // The completion of the transaction necessarily ends the BEGIN_REQ phase request_in_progress = 0; // The target has terminated the transaction check_transaction( *trans ); } wait( sc_time(rand_ps(), SC_PS) ); } wait(100, SC_NS); // Allocate a transaction for one final, nominal call to b_transport trans = m_mm.allocate(); trans->acquire(); trans->set_command( tlm::TLM_WRITE_COMMAND ); trans->set_address( 0 ); trans->set_data_ptr( reinterpret_cast<unsigned char*>(&data[0]) ); trans->set_data_length( 4 ); trans->set_streaming_width( 4 ); // = data_length to indicate no streaming trans->set_byte_enable_ptr( 0 ); // 0 indicates unused trans->set_dmi_allowed( false ); // Mandatory initial value trans->set_response_status( tlm::TLM_INCOMPLETE_RESPONSE ); // Mandatory initial value delay = sc_time(rand_ps(), SC_PS); fout << "Calling b_transport at " << sc_time_stamp() << " with delay = " << delay << endl; // Call b_transport to demonstrate the b/nb conversion by the simple_target_socket socket->b_transport( *trans, delay ); check_transaction( *trans ); }
void thread_process() { // TLM-2 generic payload transaction, reused across calls to b_transport, DMI and debug tlm::tlm_generic_payload* trans = new tlm::tlm_generic_payload; sc_time delay = sc_time(10, SC_NS); // Generate a random sequence of reads and writes for (int i = 0; i < 128; i += 4) { int data; tlm::tlm_command cmd = static_cast<tlm::tlm_command>(rand() % 2); if (cmd == tlm::TLM_WRITE_COMMAND) data = 0xFF000000 | i; // ********************************************* // Use DMI if it is available, reusing same transaction object // ********************************************* if (dmi_ptr_valid) { // Bypass transport interface and use direct memory interface // Implement target latency if ( cmd == tlm::TLM_READ_COMMAND ) { assert( dmi_data.is_read_allowed() ); memcpy(&data, dmi_data.get_dmi_ptr() + i, 4); wait( dmi_data.get_read_latency() ); } else if ( cmd == tlm::TLM_WRITE_COMMAND ) { assert( dmi_data.is_write_allowed() ); memcpy(dmi_data.get_dmi_ptr() + i, &data, 4); wait( dmi_data.get_write_latency() ); } cout << "DMI = { " << (cmd ? 'W' : 'R') << ", " << hex << i << " } , data = " << hex << data << " at time " << sc_time_stamp() << endl; } else { trans->set_command( cmd ); trans->set_address( i ); trans->set_data_ptr( reinterpret_cast<unsigned char*>(&data) ); trans->set_data_length( 4 ); trans->set_streaming_width( 4 ); // = data_length to indicate no streaming trans->set_byte_enable_ptr( 0 ); // 0 indicates unused trans->set_dmi_allowed( false ); // Mandatory initial value trans->set_response_status( tlm::TLM_INCOMPLETE_RESPONSE ); // Mandatory initial value #ifdef INJECT_ERROR if (i > 90) trans->set_streaming_width(2); #endif // Other fields default: byte enable = 0, streaming width = 0, DMI_hint = false, no extensions socket->b_transport( *trans, delay ); // Blocking transport call // Initiator obliged to check response status if ( trans->is_response_error() ) { // ********************************************* // Print response string // ********************************************* char txt[100]; sprintf(txt, "Error from b_transport, response status = %s", trans->get_response_string().c_str()); SC_REPORT_ERROR("TLM-2", txt); } // ********************************************* // Check DMI hint // ********************************************* if ( trans->is_dmi_allowed() ) { // Re-user transaction object for DMI dmi_data.init(); dmi_ptr_valid = socket->get_direct_mem_ptr( *trans, dmi_data ); } cout << "trans = { " << (cmd ? 'W' : 'R') << ", " << hex << i << " } , data = " << hex << data << " at time " << sc_time_stamp() << " delay = " << delay << endl; } } // ********************************************* // Use debug transaction interface to dump memory contents, reusing same transaction object // ********************************************* trans->set_address(0); trans->set_read(); trans->set_data_length(128); unsigned char* data = new unsigned char[128]; trans->set_data_ptr(data); unsigned int n_bytes = socket->transport_dbg( *trans ); for (unsigned int i = 0; i < n_bytes; i += 4) { cout << "mem[" << i << "] = " << *(reinterpret_cast<unsigned int*>( &data[i] )) << endl; } }
void thread_process() { // Use debug transaction interface to dump entire memory contents dump(); tlm::tlm_generic_payload* trans = new tlm::tlm_generic_payload; sc_time delay; for (int i = 0; i < RUN_LENGTH; i += 4) { data = i; delay = m_qk.get_local_time(); if (dmi_ptr_valid && sc_dt::uint64(i) >= dmi_data.get_start_address() && sc_dt::uint64(i) <= dmi_data.get_end_address()) { // Bypass transport interface and use direct memory interface assert( dmi_data.is_write_allowed() ); memcpy(dmi_data.get_dmi_ptr() + i - dmi_data.get_start_address(), &data, 4); // Accumulate memory latency into local time delay += dmi_data.get_write_latency(); cout << "WRITE/DMI addr = " << hex << i << ", data = " << data << " at " << sc_time_stamp() << " delay = " << delay << "\n"; } else { // No DMI, so use blocking transport interface trans->set_command( tlm::TLM_WRITE_COMMAND ); trans->set_address( i ); trans->set_data_ptr( reinterpret_cast<unsigned char*>(&data) ); trans->set_data_length( 4 ); trans->set_streaming_width( 4 ); // = data_length to indicate no streaming trans->set_byte_enable_ptr( 0 ); // 0 indicates unused trans->set_dmi_allowed( false ); // Mandatory initial value trans->set_response_status( tlm::TLM_INCOMPLETE_RESPONSE ); // Mandatory initial value socket->b_transport( *trans, delay ); cout << "WRITE addr = " << hex << i << ", data = " << data << " at " << sc_time_stamp() << " delay = " << delay << "\n"; // Initiator obliged to check response status if (trans->is_response_error()) SC_REPORT_ERROR("TLM-2", trans->get_response_string().c_str()); if ( trans->is_dmi_allowed() ) { dmi_data.init(); dmi_ptr_valid = socket->get_direct_mem_ptr( *trans, dmi_data ); } } // Accumulate local time and synchronize when quantum is reached m_qk.set( delay ); m_qk.inc( sc_time(100, SC_NS) ); // Model time used for additional processing if (m_qk.need_sync()) m_qk.sync(); } // Use debug transaction interface to dump entire memory contents dump(); }
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<tlm::tlm_command>(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]) assert( data[i] == ext->ptr[i] ); else assert( data[i] == 0x99 ); else assert( data[i] == ext->ptr[i] ); } trans->release(); } }