scc 2025.09
SystemC components library
ahb_initiator.cpp
1/*******************************************************************************
2 * Copyright 2020-2023 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 "ahb_initiator.h"
18
19#include <atp/timing_params.h>
20#include <scc/report.h>
21
22using namespace sc_core;
23using namespace ahb;
24using namespace ahb::pe;
25
26namespace {
27uint8_t log2n(uint8_t siz) { return ((siz > 1) ? 1 + log2n(siz >> 1) : 0); }
28
29} // anonymous namespace
30
31ahb_initiator_b::ahb_initiator_b(sc_core::sc_module_name nm,
32 sc_core::sc_port_b<tlm::tlm_fw_transport_if<tlm::tlm_base_protocol_types>>& port, size_t transfer_width,
33 bool coherent)
34: sc_module(nm)
35, socket_fw(port)
36, transfer_width_in_bytes(transfer_width / 8)
37, coherent(coherent) {
38 add_attribute(artv);
39 add_attribute(awtv);
40 add_attribute(wbv);
41 add_attribute(rbr);
42 add_attribute(br);
43}
44
45ahb_initiator_b::~ahb_initiator_b() {
46 for(auto& e : tx_state_by_id)
47 delete e.second;
48}
49
50tlm::tlm_sync_enum ahb_initiator_b::nb_transport_bw(payload_type& trans, phase_type& phase, sc_core::sc_time& t) {
51
52 auto it = tx_state_by_id.find(&trans);
53 sc_assert(it != tx_state_by_id.end());
54 it->second->peq.notify(std::make_tuple(&trans, phase), t);
55 return tlm::TLM_ACCEPTED;
56}
57
58void ahb_initiator_b::invalidate_direct_mem_ptr(sc_dt::uint64 start_range, sc_dt::uint64 end_range) {}
59
60tlm::tlm_phase ahb_initiator_b::send(payload_type& trans, ahb_initiator_b::tx_state* txs, tlm::tlm_phase phase) {
61 sc_core::sc_time delay;
62 SCCTRACE(SCMOD) << "Send REQ";
63 tlm::tlm_sync_enum ret = socket_fw->nb_transport_fw(trans, phase, delay);
64 if(ret == tlm::TLM_UPDATED) {
65 wait(delay);
66 return phase;
67 } else {
68 auto entry = txs->peq.get();
69 sc_assert(std::get<0>(entry) == &trans);
70 return std::get<1>(entry);
71 }
72}
73
74void ahb_initiator_b::transport(payload_type& trans, bool blocking) {
75 SCCTRACE(SCMOD) << "got transport req for id=" << &trans;
76 if(blocking) {
77 sc_time t;
78 socket_fw->b_transport(trans, t);
79 } else {
80 auto it = tx_state_by_id.find(&trans);
81 if(it == tx_state_by_id.end()) {
82 bool success;
83 std::tie(it, success) = tx_state_by_id.insert(std::make_pair(&trans, new tx_state()));
84 }
85 auto& txs = it->second;
86 auto timing_e = trans.set_extension<atp::timing_params>(nullptr);
87
88 txs->active_tx = &trans;
89 SCCTRACE(SCMOD) << "start transport req for id=" << &trans;
90
91 auto* ext = trans.get_extension<ahb::ahb_extension>();
93 auto delay_in_cycles = trans.is_read() ? (timing_e ? timing_e->artv : artv.value) : (timing_e ? timing_e->awtv : awtv.value);
94 if(delay_in_cycles)
95 delay_in_cycles--; // one cycle implicitly executed
96 for(unsigned i = 0; i < delay_in_cycles; ++i)
97 wait(clk_i.posedge_event());
98 auto burst_length = 0U;
99 switch(ext->get_burst()) {
100 case ahb::burst_e::SINGLE:
101 burst_length = 1;
102 break;
103 case ahb::burst_e::INCR:
104 burst_length = 1;
105 break;
106 case ahb::burst_e::WRAP4:
107 case ahb::burst_e::INCR4:
108 burst_length = 4;
109 break;
110 case ahb::burst_e::WRAP8:
111 case ahb::burst_e::INCR8:
112 burst_length = 8;
113 break;
114 case ahb::burst_e::WRAP16:
115 case ahb::burst_e::INCR16:
116 burst_length = 16;
117 break;
118 }
119 tlm::tlm_phase next_phase{tlm::UNINITIALIZED_PHASE};
120 addr_chnl.wait();
121 SCCTRACE(SCMOD) << "starting read address phase of tx with id=" << &trans;
122 auto res = send(trans, txs, tlm::BEGIN_REQ);
123 if(res == tlm::BEGIN_RESP)
124 next_phase = res;
125 else if(res != tlm::END_REQ)
126 SCCERR(SCMOD) << "target did not repsond with END_REQ to a BEGIN_REQ";
127 wait(clk_i.posedge_event());
128 auto finished = false;
129 const auto exp_burst_length = burst_length;
130 data_chnl.wait();
131 addr_chnl.post();
132 do {
133 // waiting for response
134 auto entry = next_phase == tlm::UNINITIALIZED_PHASE ? txs->peq.get() : std::make_tuple(&trans, next_phase);
135 next_phase = tlm::UNINITIALIZED_PHASE;
136 // Handle optional CRESP response
137 if(std::get<0>(entry) == &trans && std::get<1>(entry) == tlm::BEGIN_RESP) {
138 SCCTRACE(SCMOD) << "received last beat of tx with id=" << &trans;
139 auto delay_in_cycles = timing_e ? (trans.is_read() ? timing_e->rbr : timing_e->br) : br.value;
140 for(unsigned i = 0; i < delay_in_cycles; ++i)
141 wait(clk_i.posedge_event());
142 trans.set_response_status(tlm::TLM_OK_RESPONSE);
143 burst_length--;
144 tlm::tlm_phase phase = tlm::END_RESP;
145 sc_time delay = clk_if ? clk_if->period() - 1_ps : SC_ZERO_TIME;
146 socket_fw->nb_transport_fw(trans, phase, delay);
147 if(burst_length)
148 SCCWARN(SCMOD) << "got wrong number of burst beats, expected " << exp_burst_length << ", got "
149 << exp_burst_length - burst_length;
150 wait(clk_i.posedge_event());
151 finished = true;
152 }
153 } while(!finished);
154 data_chnl.post();
155 SCCTRACE(SCMOD) << "finished non-blocking protocol";
156 txs->active_tx = nullptr;
157 any_tx_finished.notify(SC_ZERO_TIME);
158 }
159 SCCTRACE(SCMOD) << "finished transport req for id=" << &trans;
160}
sc_core::sc_attribute< unsigned > artv
Read address valid to next read address valid.
sc_core::sc_attribute< unsigned > br
Write response valid to ready.
sc_core::sc_attribute< unsigned > awtv
Write address valid to next write address valid.
void transport(payload_type &trans, bool blocking)
The forward transport function. It behaves blocking and is re-entrant.
protocol engine implementations
TLM2.0 components modeling AHB.
Definition ahb_tlm.cpp:19
TYPE get()
blocking get
Definition peq.h:141