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)