22 #ifndef TESTBENCH_IN_H
23 #define TESTBENCH_IN_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/multi_passthrough_target_socket.h"
34 #include "tlm_utils/peq_with_cb_and_phase.h"
41 #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)
53 DECLARE_EXTENDED_PHASE(internal_ph_tb);
61 multi_passthrough_target_socket<TestbenchIn> input_target_socket;
66 peq_with_cb_and_phase<TestbenchIn> m_peq_targ;
69 map<tlm_generic_payload*, unsigned int> m_id_targ_map;
72 sc_event response_received_event[Ni];
73 sc_event transaction_received;
76 tlm_generic_payload* incoming_transaction[Ni];
77 tlm_generic_payload* incoming_transaction_pending[Ni];
84 uint64 address_in[Ni];
85 int nb_data_received[Ni];
88 int input_packet_size[Ni];
91 sc_time end_req_time[Ni];
92 sc_time begin_resp_time[Ni];
93 sc_time computation_time;
96 sc_event set_target_phase_end_req_event[Ni];
97 sc_event set_target_phase_begin_resp_event[Ni];
107 int nb_responses_received;
108 int current_transaction_id;
110 vector<string> preceding_modules_connection_name;
114 set<int> priority_channels_in;
115 int nb_non_priority_channels_requests_in;
116 sc_event decrement_nb_non_priority_channels_requests_in_event;
117 sc_event shared_channel_in_ready_event;
118 sc_event send_end_req_event[Ni];
120 string applicationName;
124 vector<int> sockets_with_new_transactions;
131 input_target_socket(
"input_socket"),
132 m_peq_targ(
this, &TestbenchIn::peq_targ_callback),
134 testbench_thread_ptr(tb_thread),
137 for(
int i = 0; i < Ni; i++) {
138 incoming_transaction[i]= 0;
139 incoming_transaction_pending[i]= 0;
140 nb_data_received[i] = 0;
143 nb_responses_received = 0;
144 current_transaction_id = 0;
145 nb_non_priority_channels_requests_in = 0;
148 for(
int i = 0; i < Ni; i++) {
149 input_packet_size[i] = 16;
150 data_in[i] =
new int[input_packet_size[i]];
151 for(
int j = 0; j < input_packet_size[i]; j++) data_in[i][j] = 0;
155 for(
int i = 0; i < Ni; i++) end_req_time[Ni] = sc_time(50, SC_US);
156 for(
int i = 0; i < Ni; i++) begin_resp_time[Ni] = sc_time(50, SC_US);
157 computation_time = sc_time(500, SC_US);
160 input_target_socket.register_nb_transport_fw(
this, &TestbenchIn::nb_transport_fw);
163 sc_spawn(sc_bind(testbench_thread_ptr, sc_ref(*
this)),
"testbench_in_thread");
165 SC_METHOD(decrement_nb_non_priority_channels_requests_in_method);
166 sensitive << decrement_nb_non_priority_channels_requests_in_event;
170 for(
int i = 0; i < Ni; i++) {
171 sc_spawn_options method_options;
172 method_options.spawn_method();
173 method_options.dont_initialize();
174 method_options.set_sensitivity(&set_target_phase_end_req_event[i]);
175 string process_name(
"set_target_phase_end_req_process_");
178 process_name.append(out.str());
184 for(
int i = 0; i < Ni; i++) {
185 sc_spawn_options method_options;
186 method_options.spawn_method();
187 method_options.dont_initialize();
188 method_options.set_sensitivity(&set_target_phase_begin_resp_event[i]);
189 string process_name(
"set_target_phase_begin_resp_process_");
192 process_name.append(out.str());
198 for(
int i = 0; i < Ni; i++) {
199 sc_spawn_options method_options;
200 method_options.spawn_method();
201 method_options.dont_initialize();
202 method_options.set_sensitivity(&send_end_req_event[i]);
203 string process_name(
"set_end_req_process_process_");
206 process_name.append(out.str());
213 sc_trace(tf, trace_packet, (
string) name());
217 for(
int i = 0; i < Ni; i++) {
223 void peq_targ_callback(tlm_generic_payload& trans,
const tlm_phase& phase);
226 virtual tlm_sync_enum nb_transport_fw(
int id, tlm_generic_payload& trans, tlm_phase& phase, sc_time& delay);
229 void send_response(
int id, tlm_generic_payload& trans);
230 tlm_sync_enum send_end_req(
int socketID, tlm_generic_payload& trans);
232 void decrement_nb_non_priority_channels_requests_in_method(
void);
235 void notify_simulation_controller(
bool);
238 string getName(
void)
const;
241 void verify_bindings(
void);
242 void set_packet_size(
string connection_name,
int val);
244 void add_preceding_module_connection_name(
string name);
245 void add_timing_info(tlm_phase_enum phase,
string connection_name, sc_time time);
246 void set_end_req_time(
string connection_name, sc_time t);
247 void set_begin_resp_time(
string connection_name, sc_time t);
252 void init_packet(
void);
253 void update_target_packet(
int id, tlm_phase phase);
254 void update_target_packet(
int id);
255 void set_target_phase_end_req(
int id);
256 void set_target_phase_begin_resp(
int id);
259 void add_priority_channel(
string connection_name);
260 bool is_priority_channel_in(
int id);
261 void send_end_req_method(
int id);
263 void set_application_name(
string n);
265 int get_input_socket_id(
string connection_name)
const;
269 const char * TB_IF_name(
void)
const;
270 string TB_IF_get_instance_name(
void)
const;
271 const sc_event& TB_IF_transaction_received_event(
void)
const;
272 const int TB_IF_get_nb_transactions_received_per_socket(
int socketID)
const;
273 const int TB_IF_get_nb_transactions_received_per_socket(
string channelName)
const;
274 const int TB_IF_get_nb_transactions_received(
void)
const;
275 int* TB_IF_get_data_in_ptr(
int)
const;
276 int* TB_IF_get_data_in_ptr(
string)
const;
277 void TB_IF_notify_simulation_controller(
bool);
278 int TB_IF_get_packet_size(
int ID)
const;
279 int TB_IF_get_packet_size(
string name)
const;
280 int TB_IF_get_input_socket_id(
string name)
const;
281 string TB_IF_get_connection_name(
int id)
const;
282 vector<int> TB_IF_get_sockets_with_new_transactions(
void);
294 sc_dt::uint64 adr = trans.get_address();
295 unsigned int len = trans.get_data_length();
296 unsigned char* byt = trans.get_byte_enable_ptr();
297 unsigned int wid = trans.get_streaming_width();
302 trans.set_response_status(TLM_BYTE_ENABLE_ERROR_RESPONSE);
303 return TLM_COMPLETED;
305 if (len > (4 * (
unsigned int) input_packet_size[
id]) || wid < len) {
306 trans.set_response_status(TLM_BURST_ERROR_RESPONSE);
307 return TLM_COMPLETED;
311 m_id_targ_map[&trans] = id;
312 m_peq_targ.notify(trans, phase, delay);
321 int socketID = m_id_targ_map[&trans];
323 int nb_total_data_received = 0;
326 if(phase == BEGIN_REQ)
327 FOUT << sc_time_stamp() <<
": " << name() <<
" (T" << socketID <<
") received BEGIN_REQ at address " << hex << trans.get_address() << endl;
328 else if(phase == END_RESP)
329 FOUT << sc_time_stamp() <<
": " << name() <<
" (T" << socketID <<
") received END_RESP at address " << hex << trans.get_address() << endl;
330 else if(phase == internal_ph_tb)
331 FOUT << sc_time_stamp() <<
": " << name() <<
" (T" << socketID <<
") received int_phase at address " << hex << trans.get_address() << endl;
340 send_end_req_event[socketID].notify();
342 incoming_transaction[socketID] = &trans;
347 update_target_packet(socketID, phase);
355 incoming_transaction[socketID] = 0;
357 sockets_with_new_transactions.push_back(socketID);
358 transaction_received.notify();
360 update_target_packet(socketID, phase);
368 SC_REPORT_FATAL(
"TLM-2",
"Illegal transaction phase received by target");
373 if (phase == internal_ph_tb) {
376 trans.set_response_status(TLM_OK_RESPONSE);
377 send_response(socketID, trans);
378 update_target_packet(socketID);
389 nb_non_priority_channels_requests_in--;
390 if(nb_non_priority_channels_requests_in == 0) shared_channel_in_ready_event.notify();
396 if(!is_priority_channel_in(
id)) {
397 if(nb_non_priority_channels_requests_in != 0) {
398 FOUT << sc_time_stamp() <<
": " << name() <<
": (I) request already in progress in shared channel, waiting for shared_channel_in_ready_event" << endl;
399 next_trigger(shared_channel_in_ready_event);
403 nb_non_priority_channels_requests_in++;
407 address_in[id] = incoming_transaction[id]->get_address();
408 memcpy(data_in[
id], reinterpret_cast<int *>(incoming_transaction[
id]->get_data_ptr()), incoming_transaction[
id]->get_data_length());
412 FOUT << sc_time_stamp() <<
": " << name() <<
" (T" <<
id <<
") Updating address and data. New address: " << address_in[id] <<
" (Transaction " << dec << nb_data_received[id] <<
")" << endl;
414 FOUT <<
"Data: " << hex;
415 for(
int i = 0; i < 16; i++) FOUT << data_in[
id][i] <<
" ";
417 FOUT << endl << endl;
421 send_end_req(
id, *incoming_transaction[
id]);
429 tlm_sync_enum status;
431 tlm_phase int_phase = internal_ph_tb;
436 delay = end_req_time[socketID];
437 status = input_target_socket[socketID]->nb_transport_bw(trans, bw_phase, delay);
438 if (status == TLM_COMPLETED) {
445 set_target_phase_end_req_event[socketID].notify(delay);
448 delay = delay + computation_time;
449 m_id_targ_map[&trans] = socketID;
450 m_peq_targ.notify(trans, int_phase, delay);
452 if(!is_priority_channel_in(socketID)) decrement_nb_non_priority_channels_requests_in_event.notify(delay);
454 nb_data_received[socketID]++;
462 tlm_sync_enum status;
466 bw_phase = BEGIN_RESP;
467 delay = begin_resp_time[id];
469 status = input_target_socket[id]->nb_transport_bw(trans, bw_phase, delay);
471 set_target_phase_begin_resp_event[id].notify(delay);
473 if (status == TLM_UPDATED) {
475 m_id_targ_map[&trans] = id;
476 m_peq_targ.notify(trans, bw_phase, delay);
477 }
else if (status == TLM_COMPLETED) {
486 Reconfiguration_manager::endApplication(applicationName, success);
504 for(
int i = 0; i < (int) preceding_modules_connection_name.size(); i++) {
505 if(preceding_modules_connection_name.at(i).compare(connection_name) == 0) {
512 cout <<
"Preceding module" << endl;
513 cout <<
"Socket ID: " << socketID << endl;
516 assert(socketID < Ni);
517 input_packet_size[socketID] = val;
520 delete[] data_in[socketID];
521 data_in[socketID] =
new int[input_packet_size[socketID]];
522 for(
int i = 0; i < input_packet_size[socketID]; i++) data_in[socketID][i] = 0;
523 }
catch (bad_alloc& ba) {
524 cerr <<
"ERROR: " << name() <<
" bad_alloc caught: " << ba.what() << endl;
526 Simulation_controller::endSimulation();
532 if(input_target_socket.size() != Ni) {
533 cerr <<
"ERROR: Incorrect bindings for module " << name() <<
"! Exiting..." << endl;
540 add_timing_info(END_REQ, connection_name, t);
545 add_timing_info(BEGIN_RESP, connection_name, t);
550 preceding_modules_connection_name.push_back(name);
557 for(
int i = 0; i < (int) preceding_modules_connection_name.size(); i++) {
558 if(preceding_modules_connection_name.at(i).compare(connection_name) == 0) {
565 case END_REQ: end_req_time[socketID] = time;
break;
566 case BEGIN_RESP: begin_resp_time[socketID] = time;
break;
567 default: cerr <<
"ERROR: Phase not recognized!" << endl;
574 FOUT << endl <<
"Testbench " << name() <<
":" << endl;
576 for(
int i = 0; i < Ni; i++) {
577 FOUT <<
"Input socket " << i <<
" (Connection " << preceding_modules_connection_name.at(i) <<
"):" << endl;
578 if(priority_channels_in.find(i) != priority_channels_in.end()) FOUT <<
" Priority channel" << endl;
579 FOUT <<
" Packet size: " << input_packet_size[i] << endl;
580 FOUT <<
" END_REQ time: " << end_req_time[i] << endl;
581 FOUT <<
" BEGIN_RESP time: " << begin_resp_time[i] << endl;
589 for(
int i = 0; i < (int) preceding_modules_connection_name.size(); i++) {
590 if(preceding_modules_connection_name.at(i).compare(connection_name) == 0) {
596 if(
id == -1) cerr <<
"ERROR: Module " << name() <<
" cannot find connection name through preceding or following modules vector!" << endl;
599 priority_channels_in.insert(
id);
604 return (priority_channels_in.find(
id) != priority_channels_in.end());
617 for(
int i = 0; i < (int) preceding_modules_connection_name.size(); i++) {
618 if(preceding_modules_connection_name.at(i).compare(connection_name) == 0) {
625 cerr <<
"Error: Testbench unable to retrieve input socket ID via connection name" << endl;
626 exit(RECOSIM_INTERNAL_ERROR_ERRCODE);
643 string fullname(name());
644 if(fullname.find(
"/") != string::npos) {
645 return (fullname.substr(fullname.find(
"/") + 1)).c_str();
646 }
else return name();
651 return transaction_received;
656 return nb_data_received[socketID];
661 return TB_IF_get_nb_transactions_received_per_socket(get_input_socket_id(channelName));
666 int nb_total_data_received = 0;
667 for(
int i = 0; i < Ni; i++) nb_total_data_received += nb_data_received[i];
668 return nb_total_data_received;
673 return data_in[socketID];
678 return data_in[get_input_socket_id(connectionName)];
683 notify_simulation_controller(val);
688 return input_packet_size[ID];
693 return TB_IF_get_packet_size(get_input_socket_id(connectionName));
698 return get_input_socket_id(connectionName);
703 return preceding_modules_connection_name.at(
id);
708 vector<int> vectorCopy(sockets_with_new_transactions);
709 sockets_with_new_transactions.clear();
729 update_target_packet(
id);
730 trace_packet.target_packet[id].phase = tlm_phase_to_ascii(phase);
736 trace_packet.target_packet[id].transaction.update_transaction(incoming_transaction[
id]);
737 trace_packet.target_packet[id].transaction_pending.update_transaction(incoming_transaction_pending[
id]);
743 trace_packet.target_packet[id].phase = END_REQ_ASCII;
749 trace_packet.target_packet[id].phase = BEGIN_RESP_ASCII;
string getName(void) const
Definition: testbench_in.h:493
vector< int > TB_IF_get_sockets_with_new_transactions(void)
Get a list of the sockets that received a new transaction since last function call. WARNING: Calling this function will reset the vector stored within the testbench and hence should be stored in a new vector within the algorithm thread.
Definition: testbench_in.h:707
Definition: testbench_in_interface.h:31
Definition: memory_manager.h:29
const int TB_IF_get_nb_transactions_received(void) const
Get the number of transactions processed by every socket.
Definition: testbench_in.h:665
string TB_IF_get_instance_name(void) const
Get testbench instance name.
Definition: testbench_in.h:642
int TB_IF_get_input_socket_id(string name) const
Get input socket id by the name of the connection.
Definition: testbench_in.h:697
const char * TB_IF_name(void) const
Get testbench full name.
Definition: testbench_in.h:637
int * TB_IF_get_data_in_ptr(int) const
Get incoming data pointer.
Definition: testbench_in.h:672
int TB_IF_get_packet_size(int ID) const
Get socket packet size.
Definition: testbench_in.h:687
string TB_IF_get_connection_name(int id) const
Get the name of the connection bound to a particular socket.
Definition: testbench_in.h:702
Definition: testbench_in.h:56
const int TB_IF_get_nb_transactions_received_per_socket(int socketID) const
Get the number of transactions processed per socket.
Definition: testbench_in.h:655
void TB_IF_notify_simulation_controller(bool)
Notifies simulation controller about success/failure of the simulation (e.g. data corruption)...
Definition: testbench_in.h:682
const sc_event & TB_IF_transaction_received_event(void) const
Get the event launched when a transaction has been received.
Definition: testbench_in.h:650