17#include <axi/checker/axi_protocol.h>
18#include <scc/report.h>
22void axi_protocol::fw_pre(
const axi_protocol::payload_type& trans,
const axi_protocol::phase_type& phase) {
23 auto cmd = trans.get_command();
24 if(cmd == tlm::TLM_IGNORE_COMMAND)
25 SCCERR(name) <<
"Illegal command: tlm::TLM_IGNORE_COMMAND on forward path";
26 if(check_phase_change(trans, phase))
28 SCCERR(name) <<
"Illegal phase transition: " << phase.get_name() <<
" on forward path";
30 SCCERR(name) <<
"Illegal phase transition: " << phase <<
" on forward path";
34void axi_protocol::fw_post(
const axi_protocol::payload_type& trans,
const axi_protocol::phase_type& phase, tlm::tlm_sync_enum rstat) {
35 if(rstat == tlm::TLM_ACCEPTED)
37 auto cmd = trans.get_command();
38 if(req_beat[cmd] == tlm::BEGIN_REQ && (phase == tlm::BEGIN_RESP || phase == axi::BEGIN_PARTIAL_RESP))
39 req_beat[cmd] = tlm::UNINITIALIZED_PHASE;
40 if(check_phase_change(trans, phase))
42 SCCERR(name) <<
"Illegal phase transition: " << phase.get_name() <<
" on return in forward path";
44 SCCERR(name) <<
"Illegal phase transition: " << phase <<
" on return in forward path";
48void axi_protocol::bw_pre(
const axi_protocol::payload_type& trans,
const axi_protocol::phase_type& phase) {
49 auto cmd = trans.get_command();
50 if(cmd == tlm::TLM_IGNORE_COMMAND)
51 SCCERR(name) <<
"Illegal command: tlm::TLM_IGNORE_COMMAND on forward path";
52 if(check_phase_change(trans, phase))
54 SCCERR(name) <<
"Illegal phase transition: " << phase.get_name() <<
" on backward path";
56 SCCERR(name) <<
"Illegal phase transition: " << phase <<
" on backward path";
60void axi_protocol::bw_post(
const axi_protocol::payload_type& trans,
const axi_protocol::phase_type& phase, tlm::tlm_sync_enum rstat) {
61 if(rstat == tlm::TLM_ACCEPTED)
63 if(check_phase_change(trans, phase))
65 SCCERR(name) <<
"Illegal phase transition: " << phase.get_name() <<
" on return in backward path";
67 SCCERR(name) <<
"Illegal phase transition: " << phase <<
" on return in backward path";
71bool axi_protocol::check_phase_change(payload_type
const& trans,
const axi_protocol::phase_type& phase) {
73 auto cur_req = req_beat[trans.get_command()];
74 auto cur_resp = resp_beat[trans.get_command()];
76 if(phase == tlm::BEGIN_REQ || phase == axi::BEGIN_PARTIAL_REQ) {
77 error |= cur_req != tlm::UNINITIALIZED_PHASE;
79 }
else if(phase == axi::END_PARTIAL_REQ) {
80 error |= cur_req != axi::BEGIN_PARTIAL_REQ;
81 cur_req = tlm::UNINITIALIZED_PHASE;
82 }
else if(phase == tlm::END_REQ) {
83 error |= cur_req != tlm::BEGIN_REQ;
84 cur_req = tlm::UNINITIALIZED_PHASE;
85 }
else if(phase == tlm::BEGIN_RESP || phase == axi::BEGIN_PARTIAL_RESP) {
86 error |= cur_resp != tlm::UNINITIALIZED_PHASE;
88 }
else if(phase == tlm::END_RESP) {
89 error |= cur_resp != tlm::BEGIN_RESP;
90 cur_resp = tlm::UNINITIALIZED_PHASE;
91 }
else if(phase == axi::END_PARTIAL_RESP) {
92 error |= cur_resp != axi::BEGIN_PARTIAL_RESP;
93 cur_resp = tlm::UNINITIALIZED_PHASE;
97 if(req_beat[trans.get_command()] != cur_req) {
98 req_beat[trans.get_command()] = cur_req;
99 request_update(trans);
101 if(resp_beat[trans.get_command()] != cur_resp) {
102 resp_beat[trans.get_command()] = cur_resp;
103 response_update(trans);
108void axi_protocol::request_update(
const payload_type& trans) {
109 auto axi_id = axi::get_axi_id(trans);
111 if(trans.is_write()) {
112 if(req_beat[tlm::TLM_WRITE_COMMAND] == tlm::UNINITIALIZED_PHASE) {
113 req_id[tlm::TLM_WRITE_COMMAND] = umax;
115 if(req_id[tlm::TLM_WRITE_COMMAND] == umax) {
116 req_id[tlm::TLM_WRITE_COMMAND] = axi_id;
118 }
else if(req_id[tlm::TLM_WRITE_COMMAND] != axi_id) {
119 SCCERR(name) <<
"Illegal ordering: a transaction with AWID:0x" << std::hex << axi_id
120 <<
" starts while a transaction with AWID:0x" << req_id[tlm::TLM_WRITE_COMMAND] <<
" is active";
122 if(req_beat[tlm::TLM_WRITE_COMMAND] == tlm::BEGIN_REQ) {
123 if(wr_req_beat_count != axi_burst_len) {
124 SCCERR(name) <<
"Illegal AXI settings: number of transferred beats (" << wr_req_beat_count
127 wr_req_beat_count = 0;
128 open_tx_by_id[tlm::TLM_WRITE_COMMAND][axi_id].push_back(
reinterpret_cast<uintptr_t
>(&trans));
129 check_properties(trans);
132 }
else if(trans.is_read()) {
133 if(req_beat[tlm::TLM_READ_COMMAND] == tlm::UNINITIALIZED_PHASE) {
134 req_id[tlm::TLM_READ_COMMAND] = umax;
135 }
else if(req_beat[tlm::TLM_READ_COMMAND] == tlm::BEGIN_REQ) {
136 if(req_id[tlm::TLM_READ_COMMAND] == umax) {
137 req_id[tlm::TLM_READ_COMMAND] = axi_id;
138 open_tx_by_id[tlm::TLM_READ_COMMAND][axi_id].push_back(
reinterpret_cast<uintptr_t
>(&trans));
139 }
else if(req_id[tlm::TLM_READ_COMMAND] != axi_id) {
140 SCCERR(name) <<
"Illegal phase: a read transaction uses a phase with id " << req_beat[tlm::TLM_READ_COMMAND];
142 check_properties(trans);
144 SCCERR(name) <<
"Illegal phase: a read transaction uses a phase with id " << req_beat[tlm::TLM_READ_COMMAND];
149void axi_protocol::response_update(
const payload_type& trans) {
150 auto axi_id = axi::get_axi_id(trans);
152 if(trans.is_write()) {
153 if(resp_beat[tlm::TLM_WRITE_COMMAND] == tlm::UNINITIALIZED_PHASE) {
154 resp_id[tlm::TLM_WRITE_COMMAND] = umax;
155 }
else if(resp_beat[tlm::TLM_WRITE_COMMAND] == tlm::BEGIN_RESP) {
156 if(resp_id[tlm::TLM_WRITE_COMMAND] == umax) {
157 resp_id[tlm::TLM_WRITE_COMMAND] = axi_id;
158 if(open_tx_by_id[tlm::TLM_WRITE_COMMAND][axi_id].front() !=
reinterpret_cast<uintptr_t
>(&trans)) {
159 SCCERR(name) <<
"Write response ordering violation: a response with AWID:0x" << std::hex << axi_id
160 <<
" starts before the previous response with the same id finished";
162 }
else if(resp_id[tlm::TLM_WRITE_COMMAND] != axi_id) {
163 SCCERR(name) <<
"Illegal phase: a read transaction uses a phase with id " << resp_beat[tlm::TLM_WRITE_COMMAND];
165 open_tx_by_id[tlm::TLM_WRITE_COMMAND][axi_id].pop_front();
167 SCCERR(name) <<
"Illegal phase: a read transaction uses a phase with id " << resp_beat[tlm::TLM_WRITE_COMMAND];
169 }
else if(trans.is_read()) {
170 if(resp_beat[tlm::TLM_READ_COMMAND] == tlm::UNINITIALIZED_PHASE) {
171 resp_id[tlm::TLM_READ_COMMAND] = umax;
173 if(resp_id[tlm::TLM_READ_COMMAND] == umax) {
174 resp_id[tlm::TLM_READ_COMMAND] = axi_id;
175 if(open_tx_by_id[tlm::TLM_READ_COMMAND][axi_id].front() !=
reinterpret_cast<uintptr_t
>(&trans)) {
176 SCCERR(name) <<
"Read response ordering violation: a response with ARID:0x" << std::hex << axi_id
177 <<
" starts before the previous response with the same id finished";
179 rd_resp_beat_count[axi_id]++;
180 }
else if(resp_id[tlm::TLM_READ_COMMAND] != axi_id) {
181 SCCERR(name) <<
"Illegal phase: a read transaction uses a phase with id " << resp_beat[tlm::TLM_READ_COMMAND];
183 if(resp_beat[tlm::TLM_READ_COMMAND] == tlm::BEGIN_RESP) {
184 if(rd_resp_beat_count[axi_id] != axi_burst_len) {
185 SCCERR(name) <<
"Illegal AXI settings: number of transferred beats (" << wr_req_beat_count
188 open_tx_by_id[tlm::TLM_READ_COMMAND][axi_id].pop_front();
189 rd_resp_beat_count[axi_id] = 0;
195void axi_protocol::check_datawith_settings(payload_type
const& trans) {
198 auto mask = bw - 1ULL;
199 auto offset = trans.get_address() & mask;
201 if(trans.get_data_length() != (axi_burst_size * axi_burst_len)) {
202 SCCERR(name) <<
"Illegal AXI settings: transaction data length (" << trans.get_data_length()
203 <<
") does not correspond to AxSIZE/AxLEN setting (" << axi_burst_size <<
"/" << axi_burst_len - 1
204 <<
") and buswidth " << bw <<
" for " << trans;
207 if((trans.get_data_length() + offset) > (axi_burst_size * axi_burst_len)) {
208 SCCERR(name) <<
"Illegal AXI settings: transaction data length (" << trans.get_data_length()
209 <<
") does not correspond to AxSIZE/AxLEN setting (" << axi_burst_size <<
"/" << axi_burst_len - 1
210 <<
") and buswidth " << bw <<
" for " << trans;
218void axi_protocol::check_properties(
const payload_type& trans) {
219 if(
auto* axi4_ext = trans.get_extension<axi::axi4_extension>()) {
220 check_datawith_settings(trans);
221 if(axi4_ext->get_cache() & 0xc0) {
222 if(!axi4_ext->get_cache())
223 SCCERR(name) <<
"Illegal AXI settings: active allocate bit(s) requires modifiable bit set";
225 if(axi4_ext->get_qos() > 15)
226 SCCERR(name) <<
"Illegal AXI4 settings: maximum value of QoS is 15, illegal value is " << axi4_ext->get_qos();
227 }
else if(
auto* ace_ext = trans.get_extension<axi::ace_extension>()) {
228 if(ace_ext->get_cache() & 0xc0) {
229 if(!ace_ext->get_cache())
230 SCCERR(name) <<
"Illegal ACEL settings: active allocate bit(s) requires modifiable bit set";
231 auto snoop = ace_ext->get_snoop();
232 auto domain = ace_ext->get_domain();
233 auto bar = ace_ext->get_barrier();
234 switch(comb(bar, domain, snoop)) {
235 case comb(bar_e::RESPECT_BARRIER, domain_e::NON_SHAREABLE, snoop_e::READ_NO_SNOOP):
243 check_datawith_settings(trans);
245 case comb(bar_e::RESPECT_BARRIER, domain_e::NON_SHAREABLE, snoop_e::CLEAN_SHARED):
255 case comb(bar_e::RESPECT_BARRIER, domain_e::NON_SHAREABLE, snoop_e::WRITE_NO_SNOOP):
265 check_datawith_settings(trans);
268 SCCERR(name) <<
"Illegal ACEL settings: According to D11.2 ACE-Lite signal requirements of ARM IHI 0022H the following "
269 "setting is illegal:\n"
273 }
else if(
auto* axi3_ext = trans.get_extension<axi::axi4_extension>()) {
274 if(axi3_ext->get_cache() & 0xc0) {
275 if(!axi3_ext->get_cache())
276 SCCERR(name) <<
"Illegal AXI settings: active allocate bit(s) requires modifiable bit set";
TLM2.0 components modeling AHB.
const char * to_char(E t)
unsigned get_burst_length(const request &r)
@ MEMORY_BARRIER
Normal access, respecting barriers.
constexpr ULT to_int(E t)
unsigned get_burst_size(const request &r)