scc  2024.06
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/pe/ace_target_pe.h>
22 #include <axi/fsm/protocol_fsm.h>
23 #include <axi/fsm/types.h>
24 #include <scc/mt19937_rng.h>
25 #include <scc/report.h>
26 #include <scc/utilities.h>
27 #include <systemc>
28 #include <tuple>
29 
30 using namespace sc_core;
31 using namespace tlm;
32 using namespace axi;
33 using namespace axi::fsm;
34 using namespace axi::pe;
35 
36 /******************************************************************************
37  * target
38  ******************************************************************************/
40  ace_target_pe* const 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 SC_HAS_PROCESS(ace_target_pe);
57 
58 ace_target_pe::ace_target_pe(const sc_core::sc_module_name& nm, size_t transfer_width)
59 : sc_module(nm)
60 , base(transfer_width, true) // coherent true
61 , bw_intor(new bw_intor_impl(this)) {
62  isckt_axi.bind(*this);
63  instance_name = name();
64 
65  bw_i.bind(*bw_intor);
66 
67  SC_METHOD(fsm_clk_method);
68  dont_initialize();
69  sensitive << clk_i.pos();
70 }
71 
72 ace_target_pe::~ace_target_pe() = default;
73 
74 void ace_target_pe::end_of_elaboration() {
75  clk_if = dynamic_cast<sc_core::sc_clock*>(clk_i.get_interface());
76 }
77 
78 void ace_target_pe::start_of_simulation() {
79  if (!socket_bw)
80  SCCFATAL(SCMOD) << "No backward interface registered!";
81 }
82 
83 inline unsigned get_cci_randomized_value(cci::cci_param<int> const& p) {
84  if(p.get_value()<0) return ::scc::MT19937::uniform(0, -p.get_value());
85  return p.get_value();
86 }
87 
88 void ace_target_pe::b_transport(payload_type& trans, sc_time& t) {
89  auto latency = operation_cb ? operation_cb(trans) : trans.is_read()?get_cci_randomized_value(rd_resp_delay):get_cci_randomized_value(wr_resp_delay);
90  trans.set_dmi_allowed(false);
91  trans.set_response_status(tlm::TLM_OK_RESPONSE);
92  if(clk_if)
93  t += clk_if->period() * latency;
94 }
95 
96 tlm_sync_enum ace_target_pe::nb_transport_fw(payload_type& trans, phase_type& phase, sc_time& t) {
97  SCCTRACE(SCMOD)<<"in nb_transport_fw receives pahse " << phase;
98  auto ret = TLM_ACCEPTED;
99  if( phase == END_REQ) { // snoop
100  schedule(phase == END_REQ ? EndReqE : EndPartReqE, &trans, t, false);
101  } else if(phase == BEGIN_PARTIAL_RESP || phase == BEGIN_RESP) { // snoop response
102  schedule(phase == BEGIN_RESP ? BegRespE : BegPartRespE, &trans, t, false);
103  } else { // forward read/Write
104  if(phase==axi::ACK)
105  return tlm::TLM_COMPLETED;
106  SCCTRACE(SCMOD) << " forward via axi_i_sckt, in nb_transport_fw () with phase "<<phase ;
107  return isckt_axi->nb_transport_fw(trans, phase, t);
108  }
109  return ret;
110 }
111 
112 bool ace_target_pe::get_direct_mem_ptr(payload_type& trans, tlm_dmi& dmi_data) {
113  trans.set_dmi_allowed(false);
114  return false;
115 }
116 
117 unsigned int ace_target_pe::transport_dbg(payload_type& trans) { return 0; }
118 
120 
122  fsm_hndl->fsm->cb[RequestPhaseBeg] = [this, fsm_hndl]() -> void {
123  fsm_hndl->beat_count = 0;
124  outstanding_cnt[fsm_hndl->trans->get_command()]++;
125  };
126  fsm_hndl->fsm->cb[BegPartReqE] = [this, fsm_hndl]() -> void {
127  // for snoop, state will not receive this event
128  };
129  fsm_hndl->fsm->cb[EndPartReqE] = [this, fsm_hndl]() -> void {
130  // for snoop, state will not receive this event
131  };
132  fsm_hndl->fsm->cb[BegReqE] = [this, fsm_hndl]() -> void {
133  SCCTRACE(SCMOD)<< "in BegReq of setup_cb";
134  if(fsm_hndl->is_snoop) {
135  sc_time t;
136  tlm::tlm_phase phase = tlm::BEGIN_REQ;
137  auto ret = socket_bw->nb_transport_bw(*fsm_hndl->trans, phase, t);
138  }
139  };
140  fsm_hndl->fsm->cb[EndReqE] = [this, fsm_hndl]() -> void {
141  SCCTRACE(SCMOD)<<" EndReqE in setup_cb";
142  };
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 
180 void 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 }
190 
191 
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...
Definition: ace_target_pe.h:68
cci::cci_param< int > rd_resp_delay
the latency between read request and response phase. Will be overwritten by the return of the callbac...
Definition: ace_target_pe.h:63
void setup_callbacks(fsm::fsm_handle *) override
protocol engine implementations
Definition: ace_target_pe.h:37
TLM2.0 components modeling AHB.
Definition: axi_initiator.h:30
SystemC TLM.
Definition: cxs_tlm.h:69
unsigned transport(tlm::tlm_generic_payload &payload) override
base class of all AXITLM based adapters and interfaces.
Definition: base.h:43
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
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