22 #ifndef TESTBENCH_OUT_H
23 #define TESTBENCH_OUT_H
26 #define SC_INCLUDE_DYNAMIC_PROCESSES
30 #include "tlm_utils/simple_initiator_socket.h"
31 #include "tlm_utils/simple_target_socket.h"
32 #include "tlm_utils/multi_passthrough_initiator_socket.h"
33 #include "tlm_utils/peq_with_cb_and_phase.h"
40 #include "testbench_algorithms.h"
45 using namespace sc_core;
46 using namespace sc_dt;
49 using namespace tlm_utils;
51 #define FOUT if(generate_logfile()) (*fout)
59 multi_passthrough_initiator_socket<TestbenchOut> output_initiator_socket;
62 simple_initiator_socket<TestbenchOut> manager_initiator_socket;
63 simple_target_socket<TestbenchOut> manager_target_socket;
68 peq_with_cb_and_phase<TestbenchOut> m_peq;
71 map<tlm_generic_payload*, unsigned int> m_id_init_map;
74 sc_event transaction_transmitted_event[No];
75 sc_event configuration_done_event;
76 sc_event all_responses_received_event;
77 sc_event start_initiator_channel_event[No];
78 sc_event end_of_response_channel_event[No];
81 tlm_generic_payload* request_in_progress[No];
82 tlm_generic_payload* configuration_in_progress;
89 uint64 address_out[No];
92 int output_packet_size[No];
95 sc_time begin_req_time[No];
96 sc_time end_resp_time[No];
99 sc_event set_initiator_phase_begin_req_event[No];
100 sc_event set_initiator_phase_end_resp_event[No];
110 vector<int> channel_connection_vector;
111 vector<int> following_modules_list;
113 vector<string> following_modules_connection_name;
114 vector<string> preceding_modules_connection_name;
117 int nb_responses_received;
118 int current_transaction_id;
121 set<int> priority_channels_out;
122 int nb_non_priority_channels_requests_out;
123 sc_event shared_channel_out_ready_event;
125 string applicationName;
131 map<int, vector<int> > channels_required;
134 sc_event_queue algorithm_mode_command_event_queue;
142 output_initiator_socket(
"output_initiator_socket"),
143 manager_initiator_socket(
"manager_initiator_socket"),
144 manager_target_socket(
"manager_target_socket"),
145 m_peq(
this, &TestbenchOut::peq_callback),
147 configuration_in_progress(0),
148 testbench_thread_ptr(tb_thread),
151 for(
int i = 0; i < No; i++) request_in_progress[i]= 0;
153 nb_responses_received = 0;
154 current_transaction_id = 0;
155 nb_non_priority_channels_requests_out = 0;
157 period = SC_ZERO_TIME;
160 for(
int i = 0; i < No; i++) {
161 output_packet_size[i] = 16;
162 data_out[i] =
new int[output_packet_size[i]];
163 for(
int j = 0; j < output_packet_size[i]; j++) data_out[i][j] = 0;
167 for(
int i = 0; i < No; i++) begin_req_time[i] = sc_time(1, SC_US);
168 for(
int i = 0; i < No; i++) end_resp_time[i] = sc_time(1, SC_US);
171 output_initiator_socket.register_nb_transport_bw(
this, &TestbenchOut::nb_transport_bw);
172 manager_target_socket.register_b_transport(
this, &TestbenchOut::b_transport_manager);
175 sc_spawn(sc_bind(testbench_thread_ptr, sc_ref(*
this)),
"testbench_out_thread");
177 SC_METHOD(launch_algorithm_command);
178 sensitive << algorithm_mode_command_event_queue;
182 for(
int i = 0; i < No; i++) {
183 sc_spawn_options method_options;
184 method_options.spawn_method();
185 method_options.dont_initialize();
186 method_options.set_sensitivity(&start_initiator_channel_event[i]);
187 string process_name(
"Dynamic_process_");
190 process_name.append(out.str());
196 for(
int i = 0; i < No; i++) {
197 sc_spawn_options method_options;
198 method_options.spawn_method();
199 method_options.dont_initialize();
200 method_options.set_sensitivity(&set_initiator_phase_begin_req_event[i]);
201 string process_name(
"set_initiator_phase_begin_req_process_");
204 process_name.append(out.str());
210 for(
int i = 0; i < No; i++) {
211 sc_spawn_options method_options;
212 method_options.spawn_method();
213 method_options.dont_initialize();
214 method_options.set_sensitivity(&set_initiator_phase_end_resp_event[i]);
215 string process_name(
"set_initiator_phase_end_resp_process_");
218 process_name.append(out.str());
225 sc_trace(tf, trace_packet, (
string) name());
229 for(
int i = 0; i < No; i++) {
230 delete[] data_out[i];
235 void dynamic_transfer_process_method(
int channel_id);
236 void initiator_process(
int id);
239 void peq_callback(tlm_generic_payload& trans,
const tlm_phase& phase);
242 virtual tlm_sync_enum nb_transport_bw(
int id, tlm_generic_payload& trans, tlm_phase& phase, sc_time& delay);
243 void b_transport_manager(tlm_generic_payload& trans, sc_time& delay);
246 void notify_simulation_controller(
bool);
249 void verify_bindings(
void);
250 void set_packet_size(
string connection_name,
int val);
251 void set_following_modules_list(vector<int> &v);
252 void set_application_offset(
int offset);
254 void add_following_module_connection_name(
string name);
255 void add_timing_info(tlm_phase_enum phase,
string connection_name, sc_time time);
256 void set_begin_req_time(
string connection_name, sc_time t);
257 void set_end_resp_time(
string connection_name, sc_time t);
262 void add_priority_channel(
string connection_name);
263 bool is_priority_channel_out(
int id);
266 void init_packet(
void);
267 void update_initiator_packet(
int id, tlm_generic_payload* trans, tlm_phase phase);
268 void update_initiator_packet(
int id, tlm_generic_payload* trans);
269 void set_initiator_phase_begin_req(
int id);
270 void set_initiator_phase_end_resp(
int id);
272 void set_application_name(
string s);
273 void set_period(sc_time p);
275 int get_output_socket_id(
string connection_name)
const;
278 const char * TB_IF_name(
void)
const;
279 string TB_IF_get_instance_name(
void)
const;
280 int* TB_IF_get_data_out_ptr(
int)
const;
281 int* TB_IF_get_data_out_ptr(
string)
const;
282 void TB_IF_nb_send_data(
int socketID);
283 void TB_IF_nb_send_data(
string connectionName);
284 void TB_IF_nb_send_all_data(
void);
285 const sc_event& TB_IF_all_responses_received_event(
void)
const;
286 void TB_IF_increment_current_transaction_id(
void);
287 string TB_IF_getApplicationName(
void);
288 sc_time TB_IF_get_period(
void)
const;
289 void TB_IF_add_execution_mode_command_to_queue(
string module_name,
string command, sc_time delay);
290 int TB_IF_get_packet_size(
int ID)
const;
291 int TB_IF_get_packet_size(
string connectionName)
const;
292 int TB_IF_get_output_socket_id(
string name)
const;
294 void launch_algorithm_command(
void);
297 void manager_b_transport(
int module_id);
312 tlm_generic_payload* trans;
313 sc_time delay(SC_ZERO_TIME);
314 int local_data = module_id;
317 trans = m_mm.allocate();
321 trans->set_command(TLM_READ_COMMAND);
322 trans->set_address(TB_TO_MANAGER_CHECK_SOCKET);
323 trans->set_data_ptr(reinterpret_cast<unsigned char*>(&local_data));
324 trans->set_data_length(4);
325 trans->set_streaming_width(4);
326 trans->set_byte_enable_ptr(0);
327 trans->set_dmi_allowed(
false);
328 trans->set_response_status(TLM_INCOMPLETE_RESPONSE);
330 manager_initiator_socket->b_transport(*trans, delay);
332 if(trans->is_response_error()) SC_REPORT_ERROR(
"TLM-2",
"Response error from TB b_transport");
334 Utils::check_transaction(*trans);
340 tlm_generic_payload* trans;
341 sc_time delay(SC_ZERO_TIME);
344 trans = m_mm.allocate();
348 trans->set_command(TLM_WRITE_COMMAND);
349 trans->set_address(TB_TO_MANAGER_ALGORITHM_COMMAND);
350 trans->set_data_ptr(reinterpret_cast<unsigned char*>(cmd));
351 trans->set_data_length(4);
352 trans->set_streaming_width(4);
353 trans->set_byte_enable_ptr(0);
354 trans->set_dmi_allowed(
false);
355 trans->set_response_status(TLM_INCOMPLETE_RESPONSE);
357 manager_initiator_socket->b_transport(*trans, delay);
359 if(trans->is_response_error()) SC_REPORT_ERROR(
"TLM-2",
"Response error from TB b_transport");
361 Utils::check_transaction(*trans);
367 if(trans.get_address() == MANAGER_COMMAND_SCHEDULING) {
369 int data = *(
reinterpret_cast<int *
>(trans.get_data_ptr()));
371 int module_ready = data >> 16;
374 if(action == NEXT_MODULE_READY) {
376 FOUT << sc_time_stamp() <<
": " << name() <<
": Module " << module_ready <<
" ready" << endl;
379 for(
int i = 0; i < No; i++) {
381 for(
int i = 0; i < (int) channels_required[module_ready].size(); i++) {
382 FOUT << sc_time_stamp() <<
": " << name() <<
": Channel " << channels_required[module_ready].at(i) <<
" ready" << endl;
383 start_initiator_channel_event[channels_required[module_ready].at(i)].notify();
386 channels_required[module_ready].clear();
393 trans.set_response_status(TLM_OK_RESPONSE);
396 cerr << sc_time_stamp() <<
": " << name() <<
": ERROR: Address contained a wrong command" << endl;
398 Simulation_controller::endSimulation();
411 m_id_init_map[&trans] = id;
412 m_peq.notify(trans, phase, delay);
420 int socketID = m_id_init_map[&trans];
423 if (phase == END_REQ)
424 FOUT << sc_time_stamp() <<
": " << name() <<
" (I" << socketID <<
") received END_REQ at address " << hex << trans.get_address() << endl;
425 else if (phase == BEGIN_RESP)
426 FOUT << sc_time_stamp() <<
": " << name() <<
" (I" << socketID <<
") received BEGIN_RESP at address " << hex << trans.get_address() << endl;
429 if (phase == END_REQ || (&trans == request_in_progress[socketID] && phase == BEGIN_RESP)) {
430 update_initiator_packet(socketID, &trans, phase);
433 request_in_progress[socketID] = 0;
435 if(!is_priority_channel_out(socketID)) nb_non_priority_channels_requests_out--;
436 if(nb_non_priority_channels_requests_out == 0) shared_channel_out_ready_event.notify();
438 }
else if (phase == BEGIN_REQ || phase == END_RESP)
439 SC_REPORT_FATAL(
"TLM-2",
"Illegal transaction phase received by initiator (testbench)");
441 if (phase == BEGIN_RESP) {
444 Utils::check_transaction(trans);
447 tlm_phase fw_phase = END_RESP;
448 sc_time delay = end_resp_time[socketID];
449 output_initiator_socket[socketID]->nb_transport_fw(trans, fw_phase, delay);
452 set_initiator_phase_end_resp_event[socketID].notify(delay);
455 request_in_progress[socketID] = 0;
459 if(++nb_responses_received == No) {
460 nb_responses_received = 0;
461 all_responses_received_event.notify(delay);
464 update_initiator_packet(socketID, &trans, phase);
472 FOUT << sc_time_stamp() <<
": Module " << name() <<
": Channel " << channel_id <<
" ready! Launching initiator" << endl;
473 if(is_priority_channel_out(channel_id)) FOUT << sc_time_stamp() <<
": Module " << name() <<
": Priority channel!" << endl;
474 else FOUT << sc_time_stamp() <<
": Module " << name() <<
": Non priority channel!" << endl;
476 if(request_in_progress[channel_id]) {
477 FOUT << sc_time_stamp() <<
": " << name() <<
": request already in progress in channel " << channel_id <<
", waiting for end_of_response_channel_event" << endl;
478 next_trigger(end_of_response_channel_event[channel_id]);
482 if(!is_priority_channel_out(channel_id) && nb_non_priority_channels_requests_out != 0) {
483 FOUT << sc_time_stamp() <<
": " << name() <<
": request already in progress in shared channel, waiting for shared_channel_ready" << endl;
484 next_trigger(shared_channel_out_ready_event);
488 initiator_process(channel_id);
496 tlm_generic_payload* trans;
497 tlm_phase phase = BEGIN_REQ;
500 if(!is_priority_channel_out(
id)) nb_non_priority_channels_requests_out++;
502 trans = m_mm.allocate();
505 FOUT << endl << sc_time_stamp() <<
": " << name() <<
" creates transaction " << current_transaction_id <<
" for socket " <<
id << endl;
507 int adr = current_transaction_id;
508 FOUT <<
"Address: " << adr << endl;
511 trans->set_command(TLM_WRITE_COMMAND);
512 trans->set_address(adr);
513 trans->set_data_ptr(reinterpret_cast<unsigned char*>(data_out[
id]));
514 trans->set_data_length(4 * output_packet_size[
id]);
515 trans->set_streaming_width(4 * output_packet_size[
id]);
516 trans->set_byte_enable_ptr(0);
517 trans->set_dmi_allowed(
false);
518 trans->set_response_status(TLM_INCOMPLETE_RESPONSE);
520 request_in_progress[id] = trans;
523 delay = begin_req_time[id];
525 tlm_sync_enum status = output_initiator_socket[id]->nb_transport_fw(*trans, phase, delay);
527 set_initiator_phase_begin_req_event[id].notify(delay);
530 if (status == TLM_UPDATED) {
532 m_id_init_map[trans] = id;
533 m_peq.notify(*trans, phase, delay);
534 }
else if (status == TLM_COMPLETED) {
537 Utils::check_transaction(*trans);
539 request_in_progress[id] = 0;
547 Reconfiguration_manager::endApplication(applicationName, success);
557 for(
int i = 0; i < (int) following_modules_connection_name.size(); i++) {
558 if(following_modules_connection_name.at(i).compare(connection_name) == 0) {
565 cout <<
"Following module" << endl;
566 cout <<
"Socket ID: " << socketID << endl;
570 assert(socketID < No);
571 output_packet_size[socketID] = val;
572 delete[] data_out[socketID];
573 data_out[socketID] =
new int[output_packet_size[socketID]];
574 for(
int i = 0; i < output_packet_size[socketID]; i++) data_out[socketID][i] = 0;
575 }
catch (bad_alloc& ba) {
576 cerr <<
"ERROR: " << name() <<
" bad_alloc caught: " << ba.what() << endl;
578 Simulation_controller::endSimulation();
585 channel_connection_vector = v;
586 following_modules_list.clear();
589 for(
int i = 0; i < (int) channel_connection_vector.size(); i++) {
590 bool item_found =
false;
591 for(
int j = 0; j < (int) following_modules_list.size(); j++) {
592 if(following_modules_list.at(j) == channel_connection_vector.at(i)) item_found =
true;
594 if(!item_found) following_modules_list.push_back(channel_connection_vector.at(i));
600 for(
int j = 0; j < (int) following_modules_list.size(); j++) {
601 if(following_modules_list.at(j) != -1) following_modules_list[j] += offset;
603 for(
int j = 0; j < (int) channel_connection_vector.size(); j++) {
604 if(channel_connection_vector.at(j) != -1) channel_connection_vector[j] += offset;
610 if(output_initiator_socket.size() != No) {
611 cerr <<
"ERROR: Incorrect bindings for module " << name() <<
"! Exiting..." << endl;
619 add_timing_info(BEGIN_REQ, connection_name, t);
624 add_timing_info(END_RESP, connection_name, t);
629 following_modules_connection_name.push_back(name);
636 for(
int i = 0; i < (int) following_modules_connection_name.size(); i++) {
637 if(following_modules_connection_name.at(i).compare(connection_name) == 0) {
644 case BEGIN_REQ: begin_req_time[socketID] = time;
break;
645 case END_RESP: end_resp_time[socketID] = time;
break;
646 default: cerr <<
"ERROR: Phase not recognized!" << endl;
653 FOUT << endl <<
"Testbench " << name() <<
":" << endl;
654 FOUT <<
"Period: " << period << endl;
656 for(
int i = 0; i < No; i++) {
657 FOUT <<
"Output socket " << i <<
" (Connection " << following_modules_connection_name.at(i) <<
"):" << endl;
658 if(priority_channels_out.find(i) != priority_channels_out.end()) FOUT <<
" Priority channel" << endl;
659 FOUT <<
" Packet size: " << output_packet_size[i] << endl;
660 FOUT <<
" BEGIN_REQ time: " << begin_req_time[i] << endl;
661 FOUT <<
" END_RESP time: " << end_resp_time[i] << endl;
664 FOUT <<
"Following list: ";
665 for(
int i = 0; i < (int) following_modules_list.size(); i++) FOUT << dec << following_modules_list.at(i) <<
" ";
674 for(
int i = 0; i < (int) following_modules_connection_name.size(); i++) {
675 if(following_modules_connection_name.at(i).compare(connection_name) == 0) {
681 if(
id == -1) cerr <<
"ERROR: Module " << name() <<
" cannot find connection name through preceding or following modules vector!" << endl;
684 priority_channels_out.insert(
id);
689 return (priority_channels_out.find(
id) != priority_channels_out.end());
706 for(
int i = 0; i < (int) following_modules_connection_name.size(); i++) {
707 if(following_modules_connection_name.at(i).compare(connection_name) == 0) {
714 cerr <<
"Error: Testbench unable to retrieve output socket ID via connection name" << endl;
715 exit(RECOSIM_INTERNAL_ERROR_ERRCODE);
732 string fullname(name());
733 if(fullname.find(
"/") != string::npos) {
734 return (fullname.substr(fullname.find(
"/") + 1)).c_str();
735 }
else return name();
740 return data_out[socketID];
745 return data_out[get_output_socket_id(connectionName)];
751 int module_id = channel_connection_vector.at(socketID);
752 FOUT <<
"Module ID: " << module_id << endl;
755 bool first_module_request = (channels_required[module_id].empty());
756 channels_required[module_id].push_back(socketID);
758 if(first_module_request) manager_b_transport(module_id);
763 TB_IF_nb_send_data(get_output_socket_id(connectionName));
768 for(
int i = 0; i < No; i++) TB_IF_nb_send_data(i);
773 return all_responses_received_event;
778 current_transaction_id++;
783 return applicationName;
794 algorithm_mode_command_event_queue.notify(delay);
801 cout << name() <<
": Popping command " << top_command.get_command() <<
" for module " << top_command.get_target_module() <<
" at t=" << sc_time_stamp() << endl;
802 send_algorithm_command_to_manager(&top_command);
803 algorithm_mode_command_priority_queue.pop();
809 return output_packet_size[ID];
814 return TB_IF_get_packet_size(get_output_socket_id(connectionName));
819 return get_output_socket_id(connectionName);
835 trace_packet.initiator_packet[id].phase = tlm_phase_to_ascii(phase);
836 update_initiator_packet(
id, trans);
842 trace_packet.initiator_packet[id].transaction.update_transaction(trans);
848 trace_packet.initiator_packet[id].phase = BEGIN_REQ_ASCII;
854 trace_packet.initiator_packet[id].phase = END_RESP_ASCII;
void TB_IF_nb_send_data(int socketID)
Non-blocking data send through a given socket.
Definition: testbench_out.h:749
int * TB_IF_get_data_out_ptr(int) const
Get pointer to ougoing data structure.
Definition: testbench_out.h:739
string TB_IF_get_instance_name(void) const
Get testbench instance name.
Definition: testbench_out.h:731
int TB_IF_get_packet_size(int ID) const
Get socket packet size.
Definition: testbench_out.h:808
Definition: algorithm_mode_command.h:30
Definition: memory_manager.h:29
string TB_IF_getApplicationName(void)
Get application name (application in which this testbench has been instantiated). ...
Definition: testbench_out.h:782
Definition: testbench_out_interface.h:31
void TB_IF_nb_send_all_data(void)
Non-blocking data send through every socket.
Definition: testbench_out.h:767
sc_time TB_IF_get_period(void) const
Get testbench period.
Definition: testbench_out.h:787
Definition: testbench_out.h:54
const char * TB_IF_name(void) const
Get testbench full name.
Definition: testbench_out.h:726
void TB_IF_increment_current_transaction_id(void)
Increments working transaction counter.
Definition: testbench_out.h:777
const sc_event & TB_IF_all_responses_received_event(void) const
Watch the event issued once all TLM responses have been sent from following modules to testbench...
Definition: testbench_out.h:772
User_algorithm_action
Definition: user_algorithm_interface.h:32
void TB_IF_add_execution_mode_command_to_queue(string module_name, string command, sc_time delay)
Add an algorithm control command to the waiting queue. After the delay passed as parameter, testbench will notify module 'module_name' that its algorithm should go to mode 'command'.
Definition: testbench_out.h:792
Definition: algorithm_mode_command.h:48
int TB_IF_get_output_socket_id(string name) const
Get input socket id by the name of the connection.
Definition: testbench_out.h:818