17 #include <axi/checker/axi_protocol.h>
18 #include <scc/report.h>
22 void 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";
34 void 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)
return;
36 auto cmd = trans.get_command();
37 if(req_beat[cmd]==tlm::BEGIN_REQ && (phase == tlm::BEGIN_RESP || phase == axi::BEGIN_PARTIAL_RESP))
38 req_beat[cmd]= tlm::UNINITIALIZED_PHASE;
39 if (check_phase_change(trans, phase))
41 SCCERR(name) <<
"Illegal phase transition: " << phase.get_name() <<
" on return in forward path";
43 SCCERR(name) <<
"Illegal phase transition: " << phase <<
" on return in forward path";
47 void axi_protocol::bw_pre(
const axi_protocol::payload_type &trans,
const axi_protocol::phase_type &phase) {
48 auto cmd = trans.get_command();
49 if (cmd == tlm::TLM_IGNORE_COMMAND)
50 SCCERR(name) <<
"Illegal command: tlm::TLM_IGNORE_COMMAND on forward path";
51 if (check_phase_change(trans, phase))
53 SCCERR(name) <<
"Illegal phase transition: " << phase.get_name() <<
" on backward path";
55 SCCERR(name) <<
"Illegal phase transition: " << phase <<
" on backward path";
59 void axi_protocol::bw_post(
const axi_protocol::payload_type &trans,
const axi_protocol::phase_type &phase, tlm::tlm_sync_enum rstat) {
60 if(rstat == tlm::TLM_ACCEPTED)
return;
61 if (check_phase_change(trans, phase))
63 SCCERR(name) <<
"Illegal phase transition: " << phase.get_name() <<
" on return in backward path";
65 SCCERR(name) <<
"Illegal phase transition: " << phase <<
" on return in backward path";
69 bool axi_protocol::check_phase_change(payload_type
const& trans,
const axi_protocol::phase_type &phase) {
71 auto cur_req = req_beat[trans.get_command()];
72 auto cur_resp = resp_beat[trans.get_command()];
74 if (phase == tlm::BEGIN_REQ || phase == axi::BEGIN_PARTIAL_REQ) {
75 error |= cur_req != tlm::UNINITIALIZED_PHASE;
77 }
else if(phase==axi::END_PARTIAL_REQ) {
78 error |= cur_req != axi::BEGIN_PARTIAL_REQ;
79 cur_req = tlm::UNINITIALIZED_PHASE;
80 }
else if(phase==tlm::END_REQ) {
81 error |= cur_req != tlm::BEGIN_REQ;
82 cur_req = tlm::UNINITIALIZED_PHASE;
83 }
else if(phase == tlm::BEGIN_RESP || phase == axi::BEGIN_PARTIAL_RESP) {
84 error |= cur_resp!=tlm::UNINITIALIZED_PHASE;
86 }
else if (phase == tlm::END_RESP) {
87 error |= cur_resp != tlm::BEGIN_RESP;
88 cur_resp = tlm::UNINITIALIZED_PHASE;
89 }
else if (phase == axi::END_PARTIAL_RESP) {
90 error |= cur_resp != axi::BEGIN_PARTIAL_RESP;
91 cur_resp = tlm::UNINITIALIZED_PHASE;
95 if(req_beat[trans.get_command()] != cur_req){
96 req_beat[trans.get_command()] = cur_req;
97 request_update(trans);
99 if(resp_beat[trans.get_command()] != cur_resp){
100 resp_beat[trans.get_command()] = cur_resp;
101 response_update(trans);
106 void axi_protocol::request_update(
const payload_type &trans) {
107 auto axi_id = axi::get_axi_id(trans);
109 if(trans.is_write()){
110 if(req_beat[tlm::TLM_WRITE_COMMAND]==tlm::UNINITIALIZED_PHASE) {
111 req_id[tlm::TLM_WRITE_COMMAND] = umax;
113 if(req_id[tlm::TLM_WRITE_COMMAND] == umax) {
114 req_id[tlm::TLM_WRITE_COMMAND] = axi_id;
116 }
else if(req_id[tlm::TLM_WRITE_COMMAND] != axi_id){
117 SCCERR(name) <<
"Illegal ordering: a transaction with AWID:0x"<<std::hex<<axi_id<<
" starts while a transaction with AWID:0x"<<req_id[tlm::TLM_WRITE_COMMAND]<<
" is active";
119 if(req_beat[tlm::TLM_WRITE_COMMAND]==tlm::BEGIN_REQ) {
120 if(wr_req_beat_count != axi_burst_len){
121 SCCERR(name) <<
"Illegal AXI settings: number of transferred beats ("<<wr_req_beat_count<<
") does not comply with AWLEN:0x"<<std::hex<<
axi::get_burst_length(trans)-1;
124 open_tx_by_id[tlm::TLM_WRITE_COMMAND][axi_id].push_back(
reinterpret_cast<uintptr_t
>(&trans));
125 check_properties(trans);
128 }
else if(trans.is_read()) {
129 if(req_beat[tlm::TLM_READ_COMMAND]==tlm::UNINITIALIZED_PHASE) {
130 req_id[tlm::TLM_READ_COMMAND] = umax;
131 }
else if(req_beat[tlm::TLM_READ_COMMAND]==tlm::BEGIN_REQ) {
132 if(req_id[tlm::TLM_READ_COMMAND] == umax) {
133 req_id[tlm::TLM_READ_COMMAND] = axi_id;
134 open_tx_by_id[tlm::TLM_READ_COMMAND][axi_id].push_back(
reinterpret_cast<uintptr_t
>(&trans));
135 }
else if(req_id[tlm::TLM_READ_COMMAND] != axi_id){
136 SCCERR(name) <<
"Illegal phase: a read transaction uses a phase with id "<<req_beat[tlm::TLM_READ_COMMAND];
138 check_properties(trans);
140 SCCERR(name) <<
"Illegal phase: a read transaction uses a phase with id "<<req_beat[tlm::TLM_READ_COMMAND];
145 void axi_protocol::response_update(
const payload_type &trans) {
146 auto axi_id = axi::get_axi_id(trans);
148 if(trans.is_write()){
149 if(resp_beat[tlm::TLM_WRITE_COMMAND]==tlm::UNINITIALIZED_PHASE) {
150 resp_id[tlm::TLM_WRITE_COMMAND] = umax;
151 }
else if(resp_beat[tlm::TLM_WRITE_COMMAND]==tlm::BEGIN_RESP) {
152 if(resp_id[tlm::TLM_WRITE_COMMAND] == umax) {
153 resp_id[tlm::TLM_WRITE_COMMAND] = axi_id;
154 if(open_tx_by_id[tlm::TLM_WRITE_COMMAND][axi_id].front()!=
reinterpret_cast<uintptr_t
>(&trans)) {
155 SCCERR(name) <<
"Write response ordering violation: a response with AWID:0x"<<std::hex<<axi_id<<
" starts before the previous response with the same id finished";
157 }
else if(resp_id[tlm::TLM_WRITE_COMMAND] != axi_id){
158 SCCERR(name) <<
"Illegal phase: a read transaction uses a phase with id "<<resp_beat[tlm::TLM_WRITE_COMMAND];
160 open_tx_by_id[tlm::TLM_WRITE_COMMAND][axi_id].pop_front();
162 SCCERR(name) <<
"Illegal phase: a read transaction uses a phase with id "<<resp_beat[tlm::TLM_WRITE_COMMAND];
164 }
else if(trans.is_read()) {
165 if(resp_beat[tlm::TLM_READ_COMMAND]==tlm::UNINITIALIZED_PHASE) {
166 resp_id[tlm::TLM_READ_COMMAND] = umax;
168 if(resp_id[tlm::TLM_READ_COMMAND] == umax) {
169 resp_id[tlm::TLM_READ_COMMAND] = axi_id;
170 if(open_tx_by_id[tlm::TLM_READ_COMMAND][axi_id].front()!=
reinterpret_cast<uintptr_t
>(&trans)) {
171 SCCERR(name) <<
"Read response ordering violation: a response with ARID:0x"<<std::hex<<axi_id<<
" starts before the previous response with the same id finished";
173 rd_resp_beat_count[axi_id]++;
174 }
else if(resp_id[tlm::TLM_READ_COMMAND] != axi_id){
175 SCCERR(name) <<
"Illegal phase: a read transaction uses a phase with id "<<resp_beat[tlm::TLM_READ_COMMAND];
177 if(resp_beat[tlm::TLM_READ_COMMAND]==tlm::BEGIN_RESP) {
178 if(rd_resp_beat_count[axi_id] != axi_burst_len){
179 SCCERR(name) <<
"Illegal AXI settings: number of transferred beats ("<<wr_req_beat_count<<
") does not comply with AWLEN:0x"<<std::hex<<
axi::get_burst_length(trans)-1;
181 open_tx_by_id[tlm::TLM_READ_COMMAND][axi_id].pop_front();
182 rd_resp_beat_count[axi_id]=0;
188 void axi_protocol::check_datawith_settings(payload_type
const&trans){
192 auto offset = trans.get_address() & mask;
194 if(trans.get_data_length() != (axi_burst_size * axi_burst_len)) {
195 SCCERR(name) <<
"Illegal AXI settings: transaction data length (" << trans.get_data_length() <<
") does not correspond to AxSIZE/AxLEN setting ("
196 << axi_burst_size <<
"/" << axi_burst_len-1 <<
") and buswidth "<<bw<<
" for " << trans;
199 if((trans.get_data_length() + offset) > (axi_burst_size * axi_burst_len)) {
200 SCCERR(name) <<
"Illegal AXI settings: transaction data length (" << trans.get_data_length() <<
") does not correspond to AxSIZE/AxLEN setting ("
201 << axi_burst_size <<
"/" << axi_burst_len-1 <<
") and buswidth "<<bw<<
" for " << trans;
210 void axi_protocol::check_properties(
const payload_type &trans) {
211 check_datawith_settings(trans);
213 if(axi4_ext->get_cache()&0xc0) {
214 if(!axi4_ext->get_cache())
215 SCCERR(name)<<
"Illegal AXI settings: active allocate bit(s) requires modifiable bit set";
217 if(axi4_ext->get_qos()>15)
218 SCCERR(name)<<
"Illegal AXI4 settings: maximum value of QoS is 15, illegal value is "<<axi4_ext->get_qos();
220 if(ace_ext->get_cache()&0xc0) {
221 if(!ace_ext->get_cache())
222 SCCERR(name)<<
"Illegal ACEL settings: active allocate bit(s) requires modifiable bit set";
223 auto snoop = ace_ext->get_snoop();
224 auto domain = ace_ext->get_domain();
225 auto bar = ace_ext->get_barrier();
226 switch(comb(bar, domain, snoop)){
227 case comb(bar_e::RESPECT_BARRIER, domain_e::NON_SHAREABLE, snoop_e::READ_NO_SNOOP):
257 SCCERR(name)<<
"Illegal ACEL settings: According to D11.2 ACE-Lite signal requirements of ARM IHI 0022H the following setting is illegal:\n"
262 if(axi3_ext->get_cache()&0xc0) {
263 if(!axi3_ext->get_cache())
264 SCCERR(name)<<
"Illegal AXI settings: active allocate bit(s) requires modifiable bit set";
TLM2.0 components modeling AHB.
unsigned get_burst_length(const request &r)
@ MEMORY_BARRIER
Normal access, respecting barriers.
const char * to_char(E t)
constexpr ULT to_int(E t)
unsigned get_burst_size(const request &r)