1+
2+
3+ #ifndef IMG_INITIATOR_CPP
4+ #define IMG_INITIATOR_CPP
5+
6+ #include " tlm_transaction.cpp"
7+ #include " transaction_memory_manager.cpp"
8+
9+ #include " systemc.h"
10+ using namespace sc_core ;
11+ using namespace sc_dt ;
12+ using namespace std ;
13+
14+ #include " tlm.h"
15+ #include " tlm_utils/simple_initiator_socket.h"
16+ #include " tlm_utils/simple_target_socket.h"
17+ #include " tlm_utils/peq_with_cb_and_phase.h"
18+
19+ // const char* tlm_enum_names[] = {"TLM_ACCEPTED", "TLM_UPDATED", "TLM_COMPLETED"};
20+
21+ // Initiator module generating generic payload transactions
22+ struct img_initiator : sc_module
23+ {
24+ // TLM2.0 Socket
25+ tlm_utils::simple_initiator_socket<img_initiator> socket;
26+
27+ // Memory Manager for transaction memory allocation
28+ mm memory_manager;
29+
30+ // Internal fields
31+ unsigned char * data_ptr;
32+ unsigned int data_length;
33+ unsigned int address;
34+
35+ // Pointer to transaction in progress
36+ tlm::tlm_generic_payload* pending_transaction;
37+
38+ // Payload event queue with callback and phase
39+ tlm_utils::peq_with_cb_and_phase<img_initiator> m_peq;
40+
41+ // Events
42+ sc_event transaction_received_e;
43+
44+ // Delay
45+ sc_time write_delay = sc_time(10 , SC_NS);
46+ sc_time read_delay = sc_time(10 ,SC_NS);
47+
48+ // Constructor
49+ SC_CTOR (img_initiator)
50+ : socket(" socket" ), pending_transaction(0 ), m_peq(this , &img_initiator::peq_cb) // Construct and name socket
51+ {
52+ // Register callbacks for incoming interface method calls
53+ socket.register_nb_transport_bw (this , &img_initiator::nb_transport_bw);
54+ }
55+
56+ // Method to send_reading transaction and wait for response
57+ void read (int *& data, unsigned int address, unsigned int data_length){
58+
59+ // Create transaction and allocate it
60+ tlm::tlm_generic_payload* transaction = memory_manager.allocate ();
61+ transaction->acquire ();
62+
63+ // Set transaction fields
64+ transaction->set_command (tlm::TLM_READ_COMMAND);
65+ transaction->set_address (address);
66+ transaction->set_data_ptr (reinterpret_cast <unsigned char *>(data));
67+ transaction->set_data_length (data_length); // In Bytes
68+ transaction->set_streaming_width (data_length);
69+ transaction->set_dmi_allowed (false ); // Mandatory Initial Value
70+ transaction->set_response_status (tlm::TLM_INCOMPLETE_RESPONSE); // Mandatory Initial Value
71+
72+ // Send transaction
73+ this ->send_transaction (transaction);
74+
75+ data = reinterpret_cast <int *>(pending_transaction->get_data_ptr ());
76+ // -----------DEBUG-----------
77+ printf (" [DEBUG] Reading at Initiator: " );
78+ for (int i = 0 ; i < this ->data_length ; ++i){
79+ printf (" %02x" , *(reinterpret_cast <int *>(data)+i));
80+ }
81+ printf (" \n " );
82+ // -----------DEBUG-----------
83+ }
84+
85+ void write (int *& data, unsigned int address, unsigned int data_length){
86+
87+ // Create transaction and allocate it
88+ tlm::tlm_generic_payload* transaction = memory_manager.allocate ();
89+ transaction->acquire ();
90+
91+ // Set transaction fields
92+ transaction->set_command (tlm::TLM_WRITE_COMMAND);
93+ transaction->set_address (address);
94+ transaction->set_data_ptr (reinterpret_cast <unsigned char *>(data));
95+ transaction->set_data_length (data_length); // In Bytes
96+ transaction->set_streaming_width (data_length);
97+ transaction->set_dmi_allowed (false ); // Mandatory Initial Value
98+ transaction->set_response_status (tlm::TLM_INCOMPLETE_RESPONSE); // Mandatory Initial Value
99+
100+ // -----------DEBUG-----------
101+ printf (" [DEBUG] Writing: " );
102+ for (int i = 0 ; i < data_length; ++i){
103+ printf (" %02x" , *(reinterpret_cast <int *>(data)+i));
104+ }
105+ printf (" \n " );
106+ // -----------DEBUG-----------
107+
108+ // Set transaction
109+ this ->send_transaction (transaction);
110+ }
111+
112+ void send_transaction (tlm::tlm_generic_payload*& transaction) {
113+
114+ // Transaction Management Variables
115+ tlm::tlm_phase phase;
116+ tlm::tlm_sync_enum status;
117+
118+ // Begin Request
119+ phase = tlm::BEGIN_REQ;
120+ cout << name () << " BEGIN_REQ SENT" << " TRANS ID " << 0 << " at time " << sc_time_stamp () << endl;
121+ pending_transaction = transaction;
122+ status = socket->nb_transport_fw (*transaction, phase, this ->write_delay ); // Non-blocking transport call
123+
124+ // Check request status returned by target
125+ switch (status) {
126+ // Case 1: Transaction was accepted
127+ case tlm::TLM_ACCEPTED: {
128+ // printf("%s:\t %s received -> Transaction ID %d at time %s", name(), "TLM_ACCEPTED", this->id_extension->transaction_id, sc_time_stamp());
129+ // cout << name() << " TLM_ACCEPTED RECEIVED " << " TRANS ID " << transaction->transaction_id << " at time " << sc_time_stamp() << endl;
130+ check_transaction (*transaction);
131+ pending_transaction = 0 ;
132+ // Initiator only cares about sending the transaction, doesnt need to wait for response (non-blocking)
133+ break ;
134+ }
135+
136+ // Not implementing Updated and Completed Status
137+ default : {
138+ // printf("%s:\t [ERROR] %s status is not supported by initiator", name(), status);
139+ break ;
140+ }
141+ }
142+
143+ // Wait for response transaction
144+ wait (transaction_received_e);
145+ // Increment transaction ID
146+ }
147+
148+
149+ // TLM2 backward path non-blocking transport method
150+ virtual tlm::tlm_sync_enum nb_transport_bw (tlm::tlm_generic_payload& trans,
151+ tlm::tlm_phase& phase, sc_time& delay )
152+ {
153+ // Call event queue
154+ m_peq.notify (trans, phase, delay);
155+ return tlm::TLM_ACCEPTED;
156+ }
157+
158+ // Payload event and queue callback to handle transactions received from target
159+ void peq_cb (tlm::tlm_generic_payload& trans, const tlm::tlm_phase& phase)
160+ {
161+
162+ // printf("%s:\t %s received -> Transaction ID %d from address %x at time %s\n", name(), phase, this->id_extension->transaction_id, trans.get_address(), sc_time_stamp());
163+ // cout << name() << " " <<hex << trans.get_address() << " BEGIN_RESP RECEIVED at " << sc_time_stamp() << endl;
164+ switch (phase) {
165+ case tlm::BEGIN_RESP: {
166+
167+ printf (" WAITING" );
168+ pending_transaction = &trans; // Set response transaction to return
169+ check_transaction (trans);
170+
171+ // Initiator dont care about confirming resp transaction. So nothing else to do.
172+
173+ // -----------DEBUG-----------
174+ printf (" [DEBUG] Reading at Initiator: " );
175+ for (int i = 0 ; i < trans.get_data_length ()/4 ; ++i){
176+ printf (" %02x" , *(reinterpret_cast <int *>(trans.get_data_ptr ())+i));
177+ }
178+ printf (" \n " );
179+ // -----------DEBUG-----------
180+
181+ transaction_received_e.notify ();
182+ break ;
183+ }
184+ default : {
185+ SC_REPORT_FATAL (" TLM-2" , " Illegal transaction phase received by initiator" );
186+ break ;
187+ }
188+ }
189+ }
190+
191+ // Function to check transaction integrity
192+ void check_transaction (tlm::tlm_generic_payload& trans)
193+ {
194+ // Check transaction if here
195+
196+ // tlm::tlm_command command = trans.get_command();
197+ // sc_dt::uint64 address = trans.get_address();
198+ // unsigned char* data_ptr = reinterpret_cast<unsigned char*>(trans.get_data_ptr());
199+
200+ // Allow the memory manager to free the transaction object
201+ // trans.release();
202+ }
203+ } ;
204+
205+ #endif
0 commit comments