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