17 #ifndef _BUS_AHB_PIN_INITIATOR_H_
18 #define _BUS_AHB_PIN_INITIATOR_H_
20 #ifndef SC_INCLUDE_DYNAMIC_PROCESSES
21 #define SC_INCLUDE_DYNAMIC_PROCESSES
24 #include <interfaces/ahb/ahb_tlm.h>
25 #include <scc/report.h>
26 #include <scc/utilities.h>
27 #include <tlm/scc/target_mixin.h>
29 #include <tlm_utils/peq_with_get.h>
30 #include <type_traits>
35 template <
unsigned DATA_WIDTH,
unsigned ADDR_WIDTH = 32>
class initiator : sc_core::sc_module {
36 static constexpr
bool is_larger(
unsigned x) {
return x > 64U; }
37 using addr_t = sc_dt::sc_uint<ADDR_WIDTH>;
38 using data_t =
typename std::conditional<is_larger(DATA_WIDTH), sc_dt::sc_biguint<DATA_WIDTH>, sc_dt::sc_uint<DATA_WIDTH>>::type;
41 sc_core::sc_in<bool> HCLK_i{
"HCLK_i"};
42 sc_core::sc_in<bool> HRESETn_i{
"HRESETn_i"};
43 sc_core::sc_out<addr_t> HADDR_o{
"HADDR_o"};
44 sc_core::sc_out<sc_dt::sc_uint<3>> HBURST_o{
"HBURST_o"};
45 sc_core::sc_out<bool> HMASTLOCK_o{
"HMASTLOCK_o"};
46 sc_core::sc_out<sc_dt::sc_uint<4>> HPROT_o{
"HPROT_o"};
47 sc_core::sc_out<sc_dt::sc_uint<3>> HSIZE_o{
"HSIZE_o"};
48 sc_core::sc_out<sc_dt::sc_uint<2>> HTRANS_o{
"HTRANS_o"};
49 sc_core::sc_out<data_t> HWDATA_o{
"HWDATA_o"};
50 sc_core::sc_out<bool> HWRITE_o{
"HWRITE_o"};
51 sc_core::sc_in<data_t> HRDATA_i{
"HRDATA_i"};
52 sc_core::sc_in<bool> HREADY_i{
"HREADY_i"};
53 sc_core::sc_in<bool> HRESP_i{
"HRESP_i"};
57 initiator(
const sc_core::sc_module_name& nm);
61 struct data_phase_desc {
62 tlm::tlm_generic_payload* gp;
69 tlm_utils::peq_with_get<tlm::tlm_generic_payload> inqueue{
"inqueue"};
70 tlm_utils::peq_with_get<tlm::tlm_generic_payload> tx_in_flight{
"tx_in_flight"};
76 template <
unsigned DATA_WIDTH,
unsigned ADDR_WIDTH>
80 SC_THREAD(bus_addr_task);
81 SC_THREAD(bus_data_task);
84 [
this](tlm::tlm_generic_payload& payload, tlm::tlm_phase& phase, sc_core::sc_time& delay) -> tlm::tlm_sync_enum {
85 if(phase == tlm::BEGIN_REQ) {
90 ext = new ahb_extension();
91 payload.set_extension(ext);
93 this->inqueue.notify(payload);
95 return tlm::TLM_ACCEPTED;
100 auto& hready = HREADY_i.read();
102 wait(inqueue.get_event());
103 while(
auto trans = inqueue.get_next_transaction()) {
104 sc_assert(trans->get_data_length() * 8 <= DATA_WIDTH &&
"Transaction length larger than bus width, this is not supported");
105 SCCDEBUG(SCMOD) <<
"Recv beg req for read to addr 0x" << std::hex << trans->get_address();
106 auto bytes_exp = scc::ilog2(trans->get_data_length());
107 auto width_exp = scc::ilog2(DATA_WIDTH / 8);
109 for(; size < bytes_exp; ++size)
110 if(trans->get_address() & (1 << size))
112 auto* ext = trans->template get_extension<ahb_extension>();
113 HADDR_o.write(trans->get_address());
114 HWRITE_o.write(trans->is_write());
115 HMASTLOCK_o.write(ext->is_locked());
116 HPROT_o.write(ext->get_protection());
117 HBURST_o.write(
static_cast<unsigned>(ext->get_burst()));
119 HTRANS_o.write(
static_cast<unsigned>(ext->is_seq() ? trans_e::SEQ : trans_e::NONSEQ));
121 wait(HCLK_i.posedge_event());
123 SCCDEBUG(SCMOD) <<
"Send end req for read to addr 0x" << std::hex << trans->get_address();
124 tlm::tlm_phase phase{tlm::END_REQ};
125 sc_core::sc_time delay;
126 auto res = tsckt->nb_transport_bw(*trans, phase, delay);
127 tx_in_flight.notify(*trans);
128 HTRANS_o.write(
static_cast<unsigned>(trans_e::IDLE));
134 auto const width = DATA_WIDTH / 8;
135 auto& hready = HREADY_i.read();
136 auto& rdata = HRDATA_i.read();
138 wait(tx_in_flight.get_event());
139 while(
auto trans = tx_in_flight.get_next_transaction()) {
140 auto bytes_exp = scc::ilog2(trans->get_data_length());
141 auto width_exp = scc::ilog2(DATA_WIDTH / 8);
143 for(; size < width_exp; ++size)
144 if(trans->get_address() & (1 << size))
146 auto beats = bytes_exp < size ? 1 : 1 << (bytes_exp - size);
147 auto start_offs = trans->get_address() & (width - 1);
148 auto len = trans->get_data_length();
149 if(trans->is_write()) {
151 for(
size_t i = start_offs * 8, j = 0; i < DATA_WIDTH; i += 8, ++j)
152 data.range(i + 7, i) = *(uint8_t*)(trans->get_data_ptr() + j);
153 HWDATA_o.write(data);
154 trans->set_response_status(tlm::TLM_OK_RESPONSE);
155 tlm::tlm_phase phase{tlm::BEGIN_RESP};
156 sc_core::sc_time delay;
157 tsckt->nb_transport_bw(*trans, phase, delay);
160 wait(HCLK_i.posedge_event());
162 if(trans->is_read()) {
163 for(
size_t i = start_offs * 8, j = 0; i < DATA_WIDTH; i += 8, ++j)
164 *(uint8_t*)(trans->get_data_ptr() + j) = rdata.range(i + 7, i).to_uint();
165 trans->set_response_status(tlm::TLM_OK_RESPONSE);
166 tlm::tlm_phase phase{tlm::BEGIN_RESP};
167 sc_core::sc_time delay;
168 tsckt->nb_transport_bw(*trans, phase, delay);
initiator ID recording TLM extension
void register_nb_transport_fw(std::function< sync_enum_type(transaction_type &, phase_type &, sc_core::sc_time &)> cb)
TLM2.0 components modeling AHB.