scc  2024.06
SystemC components library
apb_target.cpp
1 /*******************************************************************************
2  * Copyright 2019-2022 MINRES Technologies GmbH
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *******************************************************************************/
16 
17 #include "../../../interfaces/apb/pe/apb_target.h"
18 
19 #include <scc/report.h>
20 #include <systemc>
21 #include <tuple>
22 
23 using namespace sc_core;
24 using namespace tlm;
25 using namespace apb::pe;
26 
27 /******************************************************************************
28  * target
29  ******************************************************************************/
30 
31 apb_target_b::apb_target_b(const sc_core::sc_module_name& nm, sc_core::sc_port_b<tlm::tlm_bw_transport_if<tlm_base_protocol_types>>& port,
32  size_t transfer_width)
33 : sc_module(nm)
34 , socket_bw(port) {
35  SC_METHOD(response);
36  dont_initialize();
37  sensitive << clk_i.pos();
38 }
39 
40 void apb_target_b::end_of_elaboration() { clk_if = dynamic_cast<sc_core::sc_clock*>(clk_i.get_interface()); }
41 
42 void apb_target_b::b_transport(payload_type& trans, sc_time& t) {
43  if(operation_cb)
44  operation_cb(trans);
45  trans.set_dmi_allowed(false);
46  trans.set_response_status(tlm::TLM_OK_RESPONSE);
47  clk_if = dynamic_cast<sc_core::sc_clock*>(clk_i.get_interface());
48  if(clk_if) {
49  t += 1 * clk_if->period();
50  }
51 }
52 
53 tlm_sync_enum apb_target_b::nb_transport_fw(payload_type& trans, phase_type& phase, sc_time& t) {
54  if(phase == tlm::BEGIN_REQ) {
55  sc_assert(active_tx == nullptr);
56  if(operation_cb)
57  operation_cb(trans);
58  active_tx = &trans;
59  if(trans.has_mm())
60  trans.acquire();
61  if(mhndl.valid())
62  mhndl.enable();
63  phase = tlm::END_REQ;
64  t += sc_time(clk_if ? clk_if->period() - 1_ps : SC_ZERO_TIME);
65  return tlm::TLM_UPDATED;
66  } else if(phase == tlm::END_REQ) {
67  sc_assert(active_tx == &trans);
68  if(active_tx->has_mm())
69  active_tx->release();
70  active_tx = nullptr;
71  return tlm::TLM_COMPLETED;
72  }
73  return tlm::TLM_ACCEPTED;
74 }
75 
76 bool apb_target_b::get_direct_mem_ptr(payload_type& trans, tlm_dmi& dmi_data) {
77  trans.set_dmi_allowed(false);
78  return false;
79 }
80 
81 unsigned int apb_target_b::transport_dbg(payload_type& trans) { return 0; }
82 
83 void apb_target_b::response() {
84  if(!mhndl.valid())
85  mhndl = sc_get_current_process_handle();
86  if(active_tx) {
87  tlm_phase phase{tlm::BEGIN_RESP};
88  sc_time delay;
89  auto ret = socket_bw->nb_transport_bw(*active_tx, phase, delay);
90  if((ret == tlm::TLM_UPDATED && phase == tlm::END_RESP) || ret == tlm::TLM_COMPLETED) {
91  if(active_tx->has_mm())
92  active_tx->release();
93  active_tx = nullptr;
94  }
95  if(mhndl.valid())
96  mhndl.disable();
97  }
98 }
protocol engine implementations
Definition: apb_initiator.h:27
SystemC TLM.
Definition: cxs_tlm.h:69