diff options
Diffstat (limited to 'src/systemc/tests/tlm/update_original')
3 files changed, 357 insertions, 0 deletions
diff --git a/src/systemc/tests/tlm/update_original/golden/update_original.log b/src/systemc/tests/tlm/update_original/golden/update_original.log new file mode 100644 index 000000000..17680a7f7 --- /dev/null +++ b/src/systemc/tests/tlm/update_original/golden/update_original.log @@ -0,0 +1,2 @@ +SystemC Simulation +Unit test for update_original_from(). Should remain silent diff --git a/src/systemc/tests/tlm/update_original/mm.h b/src/systemc/tests/tlm/update_original/mm.h new file mode 100644 index 000000000..c91dd3ed5 --- /dev/null +++ b/src/systemc/tests/tlm/update_original/mm.h @@ -0,0 +1,85 @@ + +// ******************************************************************* +// User-defined memory manager, which maintains a pool of transactions +// ******************************************************************* + +#include "tlm.h" + +class mm: public tlm::tlm_mm_interface +{ + typedef tlm::tlm_generic_payload gp_t; + +public: + mm() : free_list(0), empties(0) {} + + virtual ~mm() + { + gp_t* ptr; + + while (free_list) + { + ptr = free_list->trans; + + // Delete generic payload and all extensions + sc_assert(ptr); + delete ptr; + + free_list = free_list->next; + } + + while (empties) + { + access* x = empties; + empties = empties->next; + + // Delete free list access struct + delete x; + } + } + + gp_t* allocate(); + void free(gp_t* trans); + +private: + struct access + { + gp_t* trans; + access* next; + access* prev; + }; + + access* free_list; + access* empties; +}; + +mm::gp_t* mm::allocate() +{ + gp_t* ptr; + if (free_list) + { + ptr = free_list->trans; + empties = free_list; + free_list = free_list->next; + } + else + { + ptr = new gp_t(this); + } + return ptr; +} + +void mm::free(gp_t* trans) +{ + trans->reset(); // Delete auto extensions + if (!empties) + { + empties = new access; + empties->next = free_list; + empties->prev = 0; + if (free_list) + free_list->prev = empties; + } + free_list = empties; + free_list->trans = trans; + empties = free_list->prev; +} diff --git a/src/systemc/tests/tlm/update_original/update_original.cpp b/src/systemc/tests/tlm/update_original/update_original.cpp new file mode 100644 index 000000000..e99d70c03 --- /dev/null +++ b/src/systemc/tests/tlm/update_original/update_original.cpp @@ -0,0 +1,270 @@ + +// Unit test for tlm_generic_payload update_original_from() method + +#include <iomanip> + +#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> +{ + 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<my_extension const &>(ext).len; + bel = static_cast<my_extension const &>(ext).bel; + ptr = static_cast<my_extension const &>(ext).ptr; + byt = static_cast<my_extension const &>(ext).byt; + } + + unsigned int len; + unsigned int bel; + unsigned char* ptr; + unsigned char* byt; +}; + + +struct Initiator: sc_module +{ + tlm_utils::simple_initiator_socket<Initiator> 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<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]) + 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 <Interconnect> targ_socket; + tlm_utils::simple_initiator_socket<Interconnect> 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<Target> 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; +} + |