scc 2025.09
SystemC components library
ace_target_pe.cpp
1/*
2 * Copyright 2020 Arteris IP
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.axi_util.cpp
15 */
16
17#ifndef SC_INCLUDE_DYNAMIC_PROCESSES
18#define SC_INCLUDE_DYNAMIC_PROCESSES
19#endif
20
21#include <axi/fsm/protocol_fsm.h>
22#include <axi/fsm/types.h>
23#include <axi/pe/ace_target_pe.h>
24#include <scc/mt19937_rng.h>
25#include <scc/report.h>
26#include <scc/utilities.h>
27#include <systemc>
28#include <tuple>
29
30using namespace sc_core;
31using namespace tlm;
32using namespace axi;
33using namespace axi::fsm;
34using namespace axi::pe;
35
36/******************************************************************************
37 * target
38 ******************************************************************************/
40 ace_target_pe* const that;
41 bw_intor_impl(ace_target_pe* that)
42 : that(that) {}
43 unsigned transport(tlm::tlm_generic_payload& payload) override {
44 if((payload.is_read() && that->rd_resp_fifo.num_free())) {
45 that->rd_resp_fifo.write(&payload);
46 return 0;
47 } else if((payload.is_write() && that->wr_resp_fifo.num_free())) {
48 that->wr_resp_fifo.write(&payload);
49 return 0;
50 }
51 return std::numeric_limits<unsigned>::max();
52 }
53 virtual ~bw_intor_impl() = default;
54};
55
56#if SYSTEMC_VERSION < 20250221
57SC_HAS_PROCESS(ace_target_pe);
58#endif
59ace_target_pe::ace_target_pe(const sc_core::sc_module_name& nm, size_t transfer_width)
60: sc_module(nm)
61, base(transfer_width, true) // coherent true
62, bw_intor(new bw_intor_impl(this)) {
63 isckt_axi.bind(*this);
64 instance_name = name();
65
66 bw_i.bind(*bw_intor);
67
68 SC_METHOD(fsm_clk_method);
69 dont_initialize();
70 sensitive << clk_i.pos();
71}
72
73ace_target_pe::~ace_target_pe() = default;
74
75void ace_target_pe::end_of_elaboration() { clk_if = dynamic_cast<sc_core::sc_clock*>(clk_i.get_interface()); }
76
77void ace_target_pe::start_of_simulation() {
78 if(!socket_bw)
79 SCCFATAL(SCMOD) << "No backward interface registered!";
80}
81
82inline unsigned get_cci_randomized_value(cci::cci_param<int> const& p) {
83 if(p.get_value() < 0)
84 return ::scc::MT19937::uniform(0, -p.get_value());
85 return p.get_value();
86}
87
88void ace_target_pe::b_transport(payload_type& trans, sc_time& t) {
89 auto latency = operation_cb ? operation_cb(trans)
90 : trans.is_read() ? get_cci_randomized_value(rd_resp_delay)
91 : get_cci_randomized_value(wr_resp_delay);
92 trans.set_dmi_allowed(false);
93 trans.set_response_status(tlm::TLM_OK_RESPONSE);
94 if(clk_if)
95 t += clk_if->period() * latency;
96}
97
98tlm_sync_enum ace_target_pe::nb_transport_fw(payload_type& trans, phase_type& phase, sc_time& t) {
99 SCCTRACE(SCMOD) << "in nb_transport_fw receives pahse " << phase;
100 auto ret = TLM_ACCEPTED;
101 if(phase == END_REQ) { // snoop
102 schedule(phase == END_REQ ? EndReqE : EndPartReqE, &trans, t, false);
103 } else if(phase == BEGIN_PARTIAL_RESP || phase == BEGIN_RESP) { // snoop response
104 schedule(phase == BEGIN_RESP ? BegRespE : BegPartRespE, &trans, t, false);
105 } else { // forward read/Write
106 if(phase == axi::ACK)
107 return tlm::TLM_COMPLETED;
108 SCCTRACE(SCMOD) << " forward via axi_i_sckt, in nb_transport_fw () with phase " << phase;
109 return isckt_axi->nb_transport_fw(trans, phase, t);
110 }
111 return ret;
112}
113
114bool ace_target_pe::get_direct_mem_ptr(payload_type& trans, tlm_dmi& dmi_data) {
115 trans.set_dmi_allowed(false);
116 return false;
117}
118
119unsigned int ace_target_pe::transport_dbg(payload_type& trans) { return 0; }
120
122
124 fsm_hndl->fsm->cb[RequestPhaseBeg] = [this, fsm_hndl]() -> void {
125 fsm_hndl->beat_count = 0;
126 outstanding_cnt[fsm_hndl->trans->get_command()]++;
127 };
128 fsm_hndl->fsm->cb[BegPartReqE] = [this, fsm_hndl]() -> void {
129 // for snoop, state will not receive this event
130 };
131 fsm_hndl->fsm->cb[EndPartReqE] = [this, fsm_hndl]() -> void {
132 // for snoop, state will not receive this event
133 };
134 fsm_hndl->fsm->cb[BegReqE] = [this, fsm_hndl]() -> void {
135 SCCTRACE(SCMOD) << "in BegReq of setup_cb";
136 if(fsm_hndl->is_snoop) {
137 sc_time t;
138 tlm::tlm_phase phase = tlm::BEGIN_REQ;
139 auto ret = socket_bw->nb_transport_bw(*fsm_hndl->trans, phase, t);
140 }
141 };
142 fsm_hndl->fsm->cb[EndReqE] = [this, fsm_hndl]() -> void { SCCTRACE(SCMOD) << " EndReqE in setup_cb"; };
143 fsm_hndl->fsm->cb[BegPartRespE] = [this, fsm_hndl]() -> void {
144 SCCTRACE(SCMOD) << "in BegPartRespE of setup_cb, ";
145 sc_time t(clk_if ? ::scc::time_to_next_posedge(clk_if) - 1_ps : SC_ZERO_TIME);
146 schedule(EndPartRespE, fsm_hndl->trans, t);
147 };
148 fsm_hndl->fsm->cb[EndPartRespE] = [this, fsm_hndl]() -> void {
149 SCCTRACE(SCMOD) << "in EndPartRespE of setup_cb";
150 // sc_time t(clk_if ? ::scc::time_to_next_posedge(clk_if) - 1_ps : SC_ZERO_TIME);
151 sc_time t(SC_ZERO_TIME);
152 tlm::tlm_phase phase = axi::END_PARTIAL_RESP;
153 auto ret = socket_bw->nb_transport_bw(*fsm_hndl->trans, phase, t);
154 fsm_hndl->beat_count++;
155 };
156 fsm_hndl->fsm->cb[BegRespE] = [this, fsm_hndl]() -> void {
157 SCCTRACE(SCMOD) << "in BegRespE of setup_cb";
158 sc_time t(clk_if ? ::scc::time_to_next_posedge(clk_if) - 1_ps : SC_ZERO_TIME);
159 tlm::tlm_phase phase = tlm::END_RESP;
160 auto ret = socket_bw->nb_transport_bw(*fsm_hndl->trans, phase, t);
161 t = ::scc::time_to_next_posedge(clk_if);
162 /* here *3 because after send() of intiator ,there is one cycle wait
163 * target here need to wait long cycles so that gp_shared_ptr can be released
164 */
165 schedule(EndRespE, fsm_hndl->trans, 3 * t);
166 };
167 fsm_hndl->fsm->cb[EndRespE] = [this, fsm_hndl]() -> void {
168 /*
169 sc_time t(clk_if ? ::scc::time_to_next_posedge(clk_if) - 1_ps : SC_ZERO_TIME);
170 tlm::tlm_phase phase = tlm::END_RESP;
171 auto ret = socket_bw->nb_transport_bw(*fsm_hndl->trans, phase, t);
172 */
173 SCCTRACE(SCMOD) << "notifying finish ";
174 fsm_hndl->finish.notify();
175 };
176 /*TBD threre is ack for snoop_trans
177 * */
178}
179
180void ace_target_pe::snoop(payload_type& trans) {
181 SCCTRACE(SCMOD) << "got transport snoop trans ";
182 bool ace = true;
183 fsm_handle* fsm = find_or_create(&trans, true);
184 fsm->is_snoop = true;
185 react(RequestPhaseBeg, fsm->trans); //
186 SCCTRACE(SCMOD) << "started non-blocking protocol";
187 sc_core::wait(fsm->finish);
188 SCCTRACE(SCMOD) << "finished non-blocking protocol";
189}
fsm::fsm_handle * create_fsm_handle() override
cci::cci_param< int > wr_resp_delay
the latency between write request and response phase. Will be overwritten by the return of the callba...
cci::cci_param< int > rd_resp_delay
the latency between read request and response phase. Will be overwritten by the return of the callbac...
ace_target_pe(const sc_core::sc_module_name &nm, size_t transfer_width)
void setup_callbacks(fsm::fsm_handle *) override
protocol engine implementations
TLM2.0 components modeling AHB.
SystemC TLM.
Definition dmi_mgr.h:19
unsigned transport(tlm::tlm_generic_payload &payload) override
void react(axi::fsm::protocol_time_point_e event, tlm::scc::tlm_gp_shared_ptr &trans)
triggers the FSM with event and given transaction
Definition base.h:134
base(size_t transfer_width, bool coherent=false, axi::fsm::protocol_time_point_e wr_start=axi::fsm::RequestPhaseBeg)
the constructor
Definition base.cpp:43
void schedule(axi::fsm::protocol_time_point_e e, tlm::scc::tlm_gp_shared_ptr &gp, unsigned cycles)
processes the fsm_sched_queue and propagates events to fsm_clk_queue. Should be registered as falling...
Definition base.h:107
axi::fsm::fsm_handle * find_or_create(payload_type *gp=nullptr, bool ace=false)
retrieve the FSM handle based on the transaction passed. If non exist one will be created
Definition base.cpp:65
tlm::scc::tlm_gp_shared_ptr trans
pointer to the associated AXITLM payload
Definition types.h:62
sc_core::sc_event finish
event indicating the end of the transaction
Definition types.h:68
size_t beat_count
beat count of this transaction
Definition types.h:64
AxiProtocolFsm *const fsm
pointer to the FSM
Definition types.h:60
bool is_snoop
indicator if this is a snoop access
Definition types.h:66