scc  2022.4.0
SystemC components library
target.cpp
1 /*******************************************************************************
2  * Copyright 2019-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 #ifndef SC_INCLUDE_DYNAMIC_PROCESSES
18 #define SC_INCLUDE_DYNAMIC_PROCESSES
19 #endif
20 #include "target.h"
21 #include <ahb/ahb_tlm.h>
22 #include <scc/report.h>
23 #include <scc/utilities.h>
24 #include <tlm/scc/tlm_mm.h>
25 
26 using namespace ahb::pin;
27 using namespace sc_core;
28 
29 template <unsigned DWIDTH, unsigned AWIDTH>
30 target<DWIDTH, AWIDTH>::target(const sc_module_name& nm)
31 : sc_module(nm) {
32  SC_HAS_PROCESS(target);
33  SC_THREAD(bus_addr_task);
34  SC_THREAD(bus_data_task);
35  isckt.register_nb_transport_bw([this](tlm::tlm_generic_payload& gp, tlm::tlm_phase& phase, sc_core::sc_time& delay) {
36  if(phase == tlm::END_REQ) {
37  end_req_evt.notify(delay);
38  waiting4end_req = false;
39  } else if(phase == tlm::BEGIN_RESP) {
40  if(waiting4end_req) {
41  end_req_evt.notify(delay);
42  waiting4end_req = false;
43  }
44  resp_que.notify(gp, delay);
45  }
46  return tlm::TLM_ACCEPTED;
47  });
48 }
49 
50 template <unsigned DWIDTH, unsigned AWIDTH> target<DWIDTH, AWIDTH>::~target() = default;
51 
52 template <unsigned DWIDTH, unsigned AWIDTH> void target<DWIDTH, AWIDTH>::bus_addr_task() {
53  auto const width_exp = scc::ilog2(DWIDTH / 8);
54  wait(SC_ZERO_TIME);
55  auto& htrans = HTRANS_i.read();
56  auto& hsel = HSEL_i.read();
57  auto& hready = HREADY_o.read();
58  auto& size = HSIZE_i.read();
59  while(true) {
60  if(!HRESETn_i.read()) {
61  wait(HRESETn_i.posedge_event());
62  } else {
63  wait(HCLK_i.posedge_event());
64  if(hsel && hready && htrans > 1) { // HTRANS/BUSY or IDLE check
65  unsigned sz = size;
66  if(sz > width_exp)
67  SCCERR(SCMOD) << "Access size (" << sz << ") is larger than bus wDWIDTH(" << width_exp << ")!";
68  unsigned length = (1 << sz);
70  gp->acquire();
71  gp->set_streaming_width(length);
72  gp->set_address(HADDR_i.read());
73  auto* ext = gp->get_extension<ahb_extension>();
74  ext->set_locked(HMASTLOCK_i.read());
75  ext->set_protection(HPROT_i.read());
76  ext->set_seq(htrans == 3);
77  ext->set_burst(static_cast<ahb::burst_e>(HBURST_i.read().to_uint()));
78  if(HWRITE_i.read()) {
79  gp->set_write();
80  } else {
81  gp->set_read();
82  }
83  tx_in_flight.notify(*gp);
84  }
85  }
86  }
87 }
88 
89 template <unsigned DWIDTH, unsigned AWIDTH> void target<DWIDTH, AWIDTH>::bus_data_task() {
90  auto const width = DWIDTH / 8;
91  auto& wdata = HWDATA_i.read();
92  wait(SC_ZERO_TIME);
93  while(true) {
94  if(!HRESETn_i.read()) {
95  HREADY_o.write(false);
96  wait(HRESETn_i.posedge_event());
97  } else {
98  HREADY_o.write(true);
99  auto gp = wait4tx(tx_in_flight);
100  auto ext = gp->template get_extension<ahb::ahb_extension>();
101  auto start_offs = gp->get_address() & (width - 1);
102  sc_assert((start_offs + gp->get_data_length()) <= width);
103  auto len = gp->get_data_length();
104  HREADY_o.write(false);
105  if(gp->is_write()) {
106  wait(HCLK_i.negedge_event());
107  for(size_t i = start_offs * 8, j = 0; i < DWIDTH; i += 8, ++j)
108  *(uint8_t*)(gp->get_data_ptr() + j) = wdata.range(i + 7, i).to_uint();
109  }
110  SCCDEBUG(SCMOD) << "Send beg req for " << (gp->is_write() ? "write to" : "read from") << " addr 0x" << std::hex
111  << gp->get_address();
112  sc_time delay;
113  tlm::tlm_phase phase{tlm::BEGIN_REQ};
114  auto res = isckt->nb_transport_fw(*gp, phase, delay);
115  if(res == tlm::TLM_ACCEPTED) {
116  waiting4end_req = true;
117  wait(end_req_evt);
118  phase = tlm::END_REQ;
119  }
120  SCCDEBUG(SCMOD) << "Recv end req for " << (gp->is_write() ? "write to" : "read from") << " addr 0x" << std::hex
121  << gp->get_address();
122  if(phase != tlm::BEGIN_RESP) {
123  auto resp = wait4tx(resp_que);
124  sc_assert(gp == resp);
125  }
126  SCCDEBUG(SCMOD) << "Recv beg resp for " << (gp->is_write() ? "write to" : "read from") << " addr 0x" << std::hex
127  << gp->get_address();
128  if(gp->is_read()) {
129  data_t data{0};
130  for(size_t i = start_offs * 8, j = 0; j < len; i += 8, ++j)
131  data.range(i + 7, i) = *(uint8_t*)(gp->get_data_ptr() + j);
132  HRDATA_o.write(data);
133  }
134  delay = sc_core::SC_ZERO_TIME;
135  phase = tlm::END_RESP;
136  SCCDEBUG(SCMOD) << "Send end resp for " << (gp->is_write() ? "write to" : "read from") << " addr 0x" << std::hex
137  << gp->get_address();
138  res = isckt->nb_transport_fw(*gp, phase, delay);
139  gp->release();
140  HREADY_o.write(true);
141  wait(HCLK_i.posedge_event());
142  }
143  }
144 }
145 template class ahb::pin::target<32, 32>;
146 template class ahb::pin::target<64, 32>;
147 template class ahb::pin::target<128, 32>;
148 template class ahb::pin::target<256, 32>;
149 template class ahb::pin::target<512, 32>;
150 template class ahb::pin::target<1024, 32>;
151 template class ahb::pin::target<32, 64>;
152 template class ahb::pin::target<64, 64>;
153 template class ahb::pin::target<128, 64>;
154 template class ahb::pin::target<256, 64>;
155 template class ahb::pin::target<512, 64>;
156 template class ahb::pin::target<1024, 64>;
payload_type * allocate()
get a plain tlm_payload_type without extensions
Definition: tlm_mm.h:228
static tlm_mm & get()
accessor function of the singleton
Definition: tlm_mm.h:222
pin level adapters
Definition: initiator.h:26