scc  2022.4.0
SystemC components library
axi_initiator.h
1 /*
2  * Copyright 2021 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.
15  */
16 
17 #pragma once
18 
19 #include <axi/axi_tlm.h>
20 #include <axi/fsm/protocol_fsm.h>
21 #include <tlm/scc/pe/intor_if.h>
22 #include <scc/ordered_semaphore.h>
23 #include <scc/peq.h>
24 #include <systemc>
25 #include <tlm_utils/peq_with_get.h>
26 #include <tuple>
27 #include <unordered_map>
28 
29 namespace axi {
30 namespace pe {
31 
33  public sc_core::sc_module,
34  public axi::ace_bw_transport_if<axi::axi_protocol_types>,
36 {
37 public:
38 
39  using payload_type = axi::axi_protocol_types::tlm_payload_type;
40  using phase_type = axi::axi_protocol_types::tlm_phase_type;
41 
42  sc_core::sc_in<bool> clk_i{"clk_i"};
43 
44  sc_core::sc_export<tlm::scc::pe::intor_fw_b> fw_i{"fw_i"};
45 
46  sc_core::sc_port<tlm::scc::pe::intor_bw_b, 1, sc_core::SC_ZERO_OR_MORE_BOUND> bw_o{"bw_o"};
47 
48  void b_snoop(payload_type& trans, sc_core::sc_time& t) override;
49 
50  tlm::tlm_sync_enum nb_transport_bw(payload_type& trans, phase_type& phase, sc_core::sc_time& t) override;
51 
52  void invalidate_direct_mem_ptr(sc_dt::uint64 start_range, sc_dt::uint64 end_range) override;
53 
54  size_t get_transferwith_in_bytes() const { return transfer_width_in_bytes; }
64  void transport(payload_type& trans, bool blocking) override;
71  void snoop_resp(payload_type& trans, bool sync = false) override;
72 
73  axi_initiator_b(sc_core::sc_module_name nm, sc_core::sc_port_b<axi::axi_fw_transport_if<axi_protocol_types>>& port,
74  size_t transfer_width, flavor_e flavor);
75 
76  virtual ~axi_initiator_b();
77 
78  axi_initiator_b() = delete;
79 
80  axi_initiator_b(axi_initiator_b const&) = delete;
81 
82  axi_initiator_b(axi_initiator_b&&) = delete;
83 
84  axi_initiator_b& operator=(axi_initiator_b const&) = delete;
85 
86  axi_initiator_b& operator=(axi_initiator_b&&) = delete;
87 
88  // AXI4 does not allow write data interleaving, and ncore3 only supports AXI4.
89  // However, AXI3 allows data interleaving and there may be support for AXI3 in Symphony, so keep it configurable in
90  // the testbench.
91  sc_core::sc_attribute<bool> data_interleaving{"data_interleaving", false};
93  sc_core::sc_attribute<unsigned> artv{"artv", 1};
95  sc_core::sc_attribute<unsigned> awtv{"awtv", 1};
97  sc_core::sc_attribute<unsigned> wbv{"wbv", 1};
99  sc_core::sc_attribute<unsigned> rbr{"rbr", 0};
101  sc_core::sc_attribute<unsigned> br{"br", 0};
103  sc_core::sc_attribute<unsigned> rla{"rla", 1};
105  sc_core::sc_attribute<unsigned> ba{"ba", 1};
107  sc_core::sc_attribute<bool> enable_id_serializing{"enable_id_serializing", false};
109  sc_core::sc_attribute<unsigned> outstanding_snoops{"outstanding_snoops", 8};
110 
120  void add_protocol_cb(axi::fsm::protocol_time_point_e e, std::function<void(payload_type&, bool)> cb) {
121  assert(e < axi::fsm::CB_CNT);
122  protocol_cb[e] = cb;
123  }
124 
125 
126 protected:
127  unsigned calculate_beats(payload_type& p) {
128  sc_assert(p.get_data_length() > 0);
129  return p.get_data_length() < transfer_width_in_bytes ? 1 : p.get_data_length() / transfer_width_in_bytes;
130  }
131 
132  void snoop_thread();
133 
134  const size_t transfer_width_in_bytes;
135 
136  const flavor_e flavor;
137 
138  sc_core::sc_port_b<axi::axi_fw_transport_if<axi_protocol_types>>& socket_fw;
139 
140  struct tx_state {
141  payload_type* active_tx{nullptr};
143  };
144  std::unordered_map<void*, tx_state*> tx_state_by_tx;
145  std::unordered_map<unsigned, scc::ordered_semaphore*> id_mtx;
146 
147  tlm_utils::peq_with_get<payload_type> snp_peq{"snp_peq"};
148 
149  std::unordered_map<void*, tx_state*> snp_state_by_id;
150 
151  scc::ordered_semaphore rd_chnl{1};
152 
153  scc::ordered_semaphore wr_chnl{1};
154 
155  scc::ordered_semaphore sresp_chnl{1};
156 
157  sc_core::sc_event any_tx_finished;
158 
159  sc_core::sc_time clk_period{10, sc_core::SC_NS};
160 
161 private:
162  sc_core::sc_clock* clk_if{nullptr};
163  void end_of_elaboration() override;
164  void clk_counter() { m_clock_counter++; }
165  unsigned get_clk_cnt() { return m_clock_counter; }
166 
167  tlm::tlm_phase send(payload_type& trans, axi::pe::axi_initiator_b::tx_state* txs, tlm::tlm_phase phase);
168 
169  unsigned m_clock_counter{0};
170  unsigned m_prev_clk_cnt{0};
171  unsigned snoops_in_flight{0};
172 
173  std::array<std::function<void(payload_type&, bool)>, axi::fsm::CB_CNT> protocol_cb;
174 };
175 
179 template <unsigned int BUSWIDTH = 32, typename TYPES = axi::axi_protocol_types, int N = 1,
180  sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND>
182 public:
183  using base = axi_initiator_b;
184 
185  using payload_type = base::payload_type;
186  using phase_type = base::phase_type;
191  axi_initiator(const sc_core::sc_module_name& nm, axi::axi_initiator_socket<BUSWIDTH, TYPES, N, POL>& socket_)
192  : axi_initiator_b(nm, socket_.get_base_port(), BUSWIDTH, flavor_e::AXI)
193  , socket(socket_) {
194  socket(*this);
195  }
196 
197  axi_initiator() = delete;
198 
199  axi_initiator(axi_initiator const&) = delete;
200 
201  axi_initiator(axi_initiator&&) = delete;
202 
203  axi_initiator& operator=(axi_initiator const&) = delete;
204 
205  axi_initiator& operator=(axi_initiator&&) = delete;
206 
207 private:
209 };
210 
214 template <unsigned int BUSWIDTH = 32, typename TYPES = axi::axi_protocol_types, int N = 1,
215  sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND>
217 public:
218  using base = axi_initiator_b;
219 
220  using payload_type = base::payload_type;
221  using phase_type = base::phase_type;
226  ace_lite_initiator(const sc_core::sc_module_name& nm, axi::axi_initiator_socket<BUSWIDTH, TYPES, N, POL>& socket_)
227  : axi_initiator_b(nm, socket_.get_base_port(), BUSWIDTH, flavor_e::ACEL)
228  , socket(socket_) {
229  socket(*this);
230  }
231 
232  ace_lite_initiator() = delete;
233 
234  ace_lite_initiator(ace_lite_initiator const&) = delete;
235 
237 
238  ace_lite_initiator& operator=(ace_lite_initiator const&) = delete;
239 
240  ace_lite_initiator& operator=(ace_lite_initiator&&) = delete;
241 
242 private:
244 };
245 
249 template <unsigned int BUSWIDTH = 32, typename TYPES = axi::axi_protocol_types, int N = 1,
250  sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND>
252 public:
253  using base = axi_initiator_b;
254 
255  using payload_type = base::payload_type;
256  using phase_type = base::phase_type;
261  ace_initiator(const sc_core::sc_module_name& nm, axi::ace_initiator_socket<BUSWIDTH, TYPES, N, POL>& socket_)
262  : axi_initiator_b(nm, socket_.get_base_port(), BUSWIDTH, flavor_e::ACE)
263  , socket(socket_) {
264  socket(*this);
265  }
266 
267  ace_initiator() = delete;
268 
269  ace_initiator(ace_initiator const&) = delete;
270 
271  ace_initiator(ace_initiator&&) = delete;
272 
273  ace_initiator& operator=(ace_initiator const&) = delete;
274 
275  ace_initiator& operator=(ace_initiator&&) = delete;
276 
277 private:
279 };
280 
281 } /* namespace pe */
282 } /* namespace axi */
ace_initiator(const sc_core::sc_module_name &nm, axi::ace_initiator_socket< BUSWIDTH, TYPES, N, POL > &socket_)
the constructor
ace_lite_initiator(const sc_core::sc_module_name &nm, axi::axi_initiator_socket< BUSWIDTH, TYPES, N, POL > &socket_)
the constructor
sc_core::sc_attribute< unsigned > artv
Read address valid to next read address valid.
Definition: axi_initiator.h:93
void snoop_resp(payload_type &trans, bool sync=false) override
triggers a non-blocking snoop response if the snoop callback does not do so.
sc_core::sc_attribute< unsigned > rbr
Read data valid to same beat ready.
Definition: axi_initiator.h:99
void add_protocol_cb(axi::fsm::protocol_time_point_e e, std::function< void(payload_type &, bool)> cb)
register a callback for a certain time point
sc_core::sc_attribute< unsigned > ba
Write response handshake to acknowledge.
sc_core::sc_attribute< unsigned > rla
Read last data handshake to acknowledge.
sc_core::sc_attribute< unsigned > awtv
Write address valid to next write address valid.
Definition: axi_initiator.h:95
sc_core::sc_attribute< bool > enable_id_serializing
Quirks enable.
sc_core::sc_attribute< unsigned > br
Write response valid to ready.
sc_core::sc_attribute< unsigned > wbv
Write data handshake to next beat valid.
Definition: axi_initiator.h:97
void transport(payload_type &trans, bool blocking) override
The forward transport function. It behaves blocking and is re-entrant.
sc_core::sc_attribute< unsigned > outstanding_snoops
number of snoops which can be handled
axi_initiator(const sc_core::sc_module_name &nm, axi::axi_initiator_socket< BUSWIDTH, TYPES, N, POL > &socket_)
the constructor
The ordered_semaphore primitive channel class.
TLM2.0 components modeling AHB.
Definition: axi_initiator.h:30
tlm::tlm_fw_transport_if< TYPES > axi_fw_transport_if
alias declaration for the forward interface
Definition: axi_tlm.h:916
The AXI protocol traits class. Since the protocoll defines additional non-ignorable phases a dedicate...
Definition: axi_tlm.h:890
priority event queue
Definition: peq.h:41