17 #include <axi/checker/ace_protocol.h>
18 #include <scc/report.h>
22 ace_protocol::~ace_protocol() =
default;
24 void ace_protocol::fw_pre(
const ace_protocol::payload_type &trans,
const ace_protocol::phase_type &phase) {
25 auto cmd = trans.get_command();
26 if (cmd == tlm::TLM_IGNORE_COMMAND)
27 SCCERR(name) <<
"Illegal command: tlm::TLM_IGNORE_COMMAND on forward path";
28 if (check_phase_change(trans, phase))
30 SCCERR(name) <<
"Illegal phase transition: " << phase.get_name() <<
" on forward path";
32 SCCERR(name) <<
"Illegal phase transition: " << phase <<
" on return in forward path";
36 void ace_protocol::fw_post(
const ace_protocol::payload_type &trans,
const ace_protocol::phase_type &phase, tlm::tlm_sync_enum rstat) {
37 if(rstat == tlm::TLM_ACCEPTED)
return;
38 auto cmd = trans.get_command();
39 if(req_beat[cmd]==tlm::BEGIN_REQ && (phase == tlm::BEGIN_RESP || phase == axi::BEGIN_PARTIAL_RESP))
40 req_beat[cmd]= tlm::UNINITIALIZED_PHASE;
41 if (check_phase_change(trans, phase))
43 SCCERR(name) <<
"Illegal phase transition: " << phase.get_name() <<
" on return in forward path";
45 SCCERR(name) <<
"Illegal phase transition: " << phase <<
" on return in forward path";
49 void ace_protocol::bw_pre(
const ace_protocol::payload_type &trans,
const ace_protocol::phase_type &phase) {
50 auto cmd = trans.get_command();
51 if (cmd == tlm::TLM_IGNORE_COMMAND)
52 SCCERR(name) <<
"Illegal command: tlm::TLM_IGNORE_COMMAND on forward path";
53 if (check_phase_change(trans, phase))
55 SCCERR(name) <<
"Illegal phase transition: " << phase.get_name() <<
" on backward path";
57 SCCERR(name) <<
"Illegal phase transition: " << phase <<
" on backward path";
61 void ace_protocol::bw_post(
const ace_protocol::payload_type &trans,
const ace_protocol::phase_type &phase, tlm::tlm_sync_enum rstat) {
62 if(rstat == tlm::TLM_ACCEPTED)
return;
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 forward path";
71 bool ace_protocol::check_phase_change(payload_type
const& trans,
const ace_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);
108 void ace_protocol::request_update(
const payload_type &trans) {
109 auto axi_id = axi::get_axi_id(trans);
112 if(trans.is_write()){
113 if(req_beat[tlm::TLM_WRITE_COMMAND]==tlm::UNINITIALIZED_PHASE) {
114 req_id[tlm::TLM_WRITE_COMMAND] = umax;
116 if(req_id[tlm::TLM_WRITE_COMMAND] == umax) {
117 req_id[tlm::TLM_WRITE_COMMAND] = axi_id;
119 }
else if(req_id[tlm::TLM_WRITE_COMMAND] != axi_id){
120 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";
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<<
") does not comply with AWLEN:0x"<<std::hex<<
axi::get_burst_length(trans)-1;
127 auto offset = trans.get_address() & mask;
129 if(trans.get_data_length() > (1 << axi_burst_size) * axi_burst_len) {
130 SCCERR(name) <<
"Illegal AXI settings: transaction data length (" << trans.get_data_length() <<
") does not correspond to AxSIZE/AxLEN setting ("
131 << axi_burst_size <<
"/" << axi_burst_len-1 <<
") for " << trans;
134 if((trans.get_data_length() + offset) >= (1 << axi_burst_size) * axi_burst_len) {
135 SCCERR(name) <<
"Illegal AXI settings: transaction data length (" << trans.get_data_length() <<
") does not correspond to AxSIZE/AxLEN setting ("
136 << axi_burst_size <<
"/" << axi_burst_len-1 <<
") for " << trans;
140 open_tx_by_id[tlm::TLM_WRITE_COMMAND][axi_id].push_back(
reinterpret_cast<uintptr_t
>(&trans));
142 check_properties(trans);
144 }
else if(trans.is_read()) {
145 if(req_beat[tlm::TLM_READ_COMMAND]==tlm::UNINITIALIZED_PHASE) {
146 req_id[tlm::TLM_READ_COMMAND] = umax;
147 }
else if(req_beat[tlm::TLM_READ_COMMAND]==tlm::BEGIN_REQ) {
148 if(req_id[tlm::TLM_READ_COMMAND] == umax) {
149 req_id[tlm::TLM_READ_COMMAND] = axi_id;
150 open_tx_by_id[tlm::TLM_READ_COMMAND][axi_id].push_back(
reinterpret_cast<uintptr_t
>(&trans));
151 }
else if(req_id[tlm::TLM_READ_COMMAND] != axi_id){
152 SCCERR(name) <<
"Illegal phase: a read transaction uses a phase with id "<<req_beat[tlm::TLM_READ_COMMAND];
154 check_properties(trans);
156 SCCERR(name) <<
"Illegal phase: a read transaction uses a phase with id "<<req_beat[tlm::TLM_READ_COMMAND];
161 void ace_protocol::response_update(
const payload_type &trans) {
162 auto axi_id = axi::get_axi_id(trans);
165 if(trans.is_write()){
166 if(resp_beat[tlm::TLM_WRITE_COMMAND]==tlm::UNINITIALIZED_PHASE) {
167 resp_id[tlm::TLM_WRITE_COMMAND] = umax;
168 }
else if(resp_beat[tlm::TLM_WRITE_COMMAND]==tlm::BEGIN_RESP) {
169 if(resp_id[tlm::TLM_WRITE_COMMAND] == umax) {
170 resp_id[tlm::TLM_WRITE_COMMAND] = axi_id;
171 if(open_tx_by_id[tlm::TLM_WRITE_COMMAND][axi_id].front()!=
reinterpret_cast<uintptr_t
>(&trans)) {
172 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";
174 }
else if(resp_id[tlm::TLM_WRITE_COMMAND] != axi_id){
175 SCCERR(name) <<
"Illegal phase: a read transaction uses a phase with id "<<resp_beat[tlm::TLM_WRITE_COMMAND];
177 open_tx_by_id[tlm::TLM_WRITE_COMMAND][axi_id].pop_front();
179 SCCERR(name) <<
"Illegal phase: a read transaction uses a phase with id "<<resp_beat[tlm::TLM_WRITE_COMMAND];
181 }
else if(trans.is_read()) {
182 if(resp_beat[tlm::TLM_READ_COMMAND]==tlm::UNINITIALIZED_PHASE) {
183 resp_id[tlm::TLM_READ_COMMAND] = umax;
185 if(resp_id[tlm::TLM_READ_COMMAND] == umax) {
186 resp_id[tlm::TLM_READ_COMMAND] = axi_id;
187 if(open_tx_by_id[tlm::TLM_READ_COMMAND][axi_id].front()!=
reinterpret_cast<uintptr_t
>(&trans)) {
188 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";
190 rd_resp_beat_count[axi_id]++;
191 }
else if(resp_id[tlm::TLM_READ_COMMAND] != axi_id){
192 SCCERR(name) <<
"Illegal phase: a read transaction uses a phase with id "<<resp_beat[tlm::TLM_READ_COMMAND];
194 if(resp_beat[tlm::TLM_READ_COMMAND]==tlm::BEGIN_RESP) {
195 if(rd_resp_beat_count[axi_id] != axi_burst_len){
196 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;
199 auto offset = trans.get_address() & mask;
201 if(trans.get_data_length() > (1 << axi_burst_size) * axi_burst_len) {
202 SCCERR(name) <<
"Illegal AXI settings: transaction data length (" << trans.get_data_length() <<
") does not correspond to AxSIZE/AxLEN setting ("
203 << axi_burst_size <<
"/" << axi_burst_len-1 <<
") for " << trans;
206 if((trans.get_data_length() + offset) >= (1 << axi_burst_size) * axi_burst_len) {
207 SCCERR(name) <<
"Illegal AXI settings: transaction data length (" << trans.get_data_length() <<
") does not correspond to AxSIZE/AxLEN setting ("
208 << axi_burst_size <<
"/" << axi_burst_len-1 <<
") for " << trans;
211 open_tx_by_id[tlm::TLM_READ_COMMAND][axi_id].pop_front();
212 rd_resp_beat_count[axi_id]=0;
222 void ace_protocol::check_properties(
const payload_type &trans) {
224 if(ace_ext->get_cache()&0xc0) {
225 if(!ace_ext->get_cache())
226 SCCERR(name)<<
"Illegal ACEL settings: active allocate bit(s) requires modifiable bit set";
228 auto snoop = ace_ext->get_snoop();
229 auto domain = ace_ext->get_domain();
230 auto bar = ace_ext->get_barrier();
231 switch(comb(bar, domain, snoop)){
233 case comb(bar_e::RESPECT_BARRIER, domain_e::NON_SHAREABLE, snoop_e::READ_NO_SNOOP):
292 SCCERR(name)<<
"Illegal ACE settings: According to D3.1.1 Read and write Shareable transaction types of ARM IHI 0022H the following setting is illegal:\n"
297 case snoop_e::READ_CLEAN:
298 case snoop_e::READ_NOT_SHARED_DIRTY:
299 case snoop_e::READ_SHARED:
300 case snoop_e::READ_UNIQUE:
301 case snoop_e::CLEAN_UNIQUE:
302 case snoop_e::MAKE_UNIQUE:
303 case snoop_e::WRITE_LINE_UNIQUE:
305 if(ace_ext->get_domain()==domain_e::NON_SHAREABLE) {
306 SCCERR(name)<<
"Illegal ACE settings: According to D3.1.6 Transaction constraints of ARM IHI 0022H the following setting is illegal:\n"
307 <<
"AxDOMAIN:"<<
to_char(ace_ext->get_domain());
310 case snoop_e::CLEAN_SHARED:
311 case snoop_e::CLEAN_INVALID:
312 case snoop_e::MAKE_INVALID:
313 case snoop_e::WRITE_EVICT:
314 if(ace_ext->get_domain()==domain_e::SYSTEM) {
315 SCCERR(name)<<
"Illegal ACE settings: According to D3.1.6 Transaction constraints of ARM IHI 0022H the following setting is illegal:\n"
316 <<
"AxDOMAIN:"<<
to_char(ace_ext->get_domain());
318 if(ace_ext->get_length() && (1u<<ace_ext->get_size()) != bw) {
319 SCCERR(name)<<
"Illegal ACE settings: According to D3.1.6 Transaction constraints of ARM IHI 0022H the following setting is illegal:\n"
320 <<
"AxLEN:"<<
static_cast<unsigned>(ace_ext->get_length())<<
", AxSIZE:"<<
static_cast<unsigned>(ace_ext->get_size())<<
" with bus with:"<<bw;
323 switch(ace_ext->get_burst()) {
325 width=(1+ace_ext->get_length())*(1u<<ace_ext->get_size());
328 if(trans.get_address()&(width-1)){
329 SCCERR(name)<<
"Illegal ACE settings: According to D3.1.6 Transaction constraints of ARM IHI 0022H the following setting is illegal:\n"
330 <<
"AxBURST:"<<
to_char(ace_ext->get_burst())<<
", ADDR:0x"<<std::hex<<trans.get_address();
334 SCCERR(name)<<
"Illegal ACE settings: According to D3.1.6 Transaction constraints of ARM IHI 0022H the following setting is illegal:\n"
335 <<
"AxBURST:"<<
to_char(ace_ext->get_burst());
338 SCCERR(name)<<
"Illegal ACE settings: According to D3.1.6 Transaction constraints of ARM IHI 0022H the following setting is illegal:\n"
339 <<
"AxBAR:"<<
to_char(ace_ext->get_barrier());
341 if(!ace_ext->is_modifiable()) {
342 SCCERR(name)<<
"Illegal ACE settings: According to D3.1.6 Transaction constraints of ARM IHI 0022H the following setting is illegal:\n"
343 <<
"AxCACHE:"<<
static_cast<unsigned>(ace_ext->get_cache());
TLM2.0 components modeling AHB.
unsigned get_burst_length(const request &r)
@ MEMORY_BARRIER
Normal access, respecting barriers.
@ IGNORE_BARRIER
Memory barrier.
const char * to_char(E t)
constexpr ULT to_int(E t)
unsigned get_burst_size(const request &r)