scc  2022.4.0
SystemC components library
reordering_target.cpp
1 /*
2  * Copyright 2020-2022 Arteris IP
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "reordering_target.h"
18 
19 axi::pe::tx_reorderer::tx_reorderer(const sc_core::sc_module_name &nm): sc_core::sc_module(nm) {
20  add_attribute(min_latency);
21  add_attribute(max_latency);
22  add_attribute(prioritize_by_latency);
23  add_attribute(prioritize_by_qos);
24  SC_HAS_PROCESS(tx_reorderer);
25  fw_i(*this);
26  SC_METHOD(clock_cb);
27  sensitive<<clk_i.pos();
28  dont_initialize();
29 }
30 
31 void axi::pe::tx_reorderer::transport(tlm::tlm_generic_payload &payload, bool lt_transport) {
32  if(auto ext = payload.get_extension<axi::axi4_extension>()) {
33  auto id = ext->get_id();
34  reorder_buffer[payload.get_command()][id].emplace_back(payload);
35  } else
36  SCCFATAL(SCMOD)<<"Transaction is not a AXI4 transaction";
37 }
38 
39 void axi::pe::tx_reorderer::clock_cb() {
40  for(unsigned cmd=tlm::TLM_READ_COMMAND; cmd<tlm::TLM_IGNORE_COMMAND; ++cmd) {
41  if(!reorder_buffer[cmd].empty()) {
42  std::vector<unsigned> r1{}, r2{};
43  r1.reserve(reorder_buffer[cmd].size());
44  r2.reserve(reorder_buffer[cmd].size());
45  auto lat_sum = 0U;
46  auto max_qos=0U;
47  for(auto& e:reorder_buffer[cmd]) {
48  if(e.second.size()){
49  e.second.front().age++;
50  if(e.second.front().age>max_latency.value) {
51  r1.push_back(e.first);
52  } else if(e.second.front().age>min_latency.value) {
53  r2.push_back(e.first);
54  lat_sum+=e.second.front().age;
55  max_qos=std::max<unsigned>(max_qos, e.second.front().trans->get_extension<axi::axi4_extension>()->get_qos());
56  }
57  }
58  }
59  if(r1.size()) {
60  //std::random_shuffle(r1.begin(), r1.end(), [](unsigned l) -> unsigned { return scc::MT19937::uniform(0, l);});
61  for (auto i = r1.begin() + 1; i != r1.end(); ++i) {
62  auto j = r1.begin() + scc::MT19937::uniform(0, i - r1.begin());
63  if (i != j) std::iter_swap(i, j);
64  }
65 
66  for(auto& e:r1) {
67  auto& deq = reorder_buffer[cmd][e];
68  auto notok = bw_o->transport(*deq.front().trans);
69  if(notok==0) deq.pop_front();
70  }
71  } else if(r2.size()>window_size.value) {
72  if(prioritize_by_qos.value) {
73  std::vector<unsigned> res;
74  auto& buf = reorder_buffer[cmd];
75  std::copy_if(std::begin(r2), std::end(r2), std::back_inserter(res), [max_qos, &buf](unsigned e){
76  return buf[e].front().trans->get_extension<axi::axi4_extension>()->get_qos() >= max_qos;
77  });
78  if(res.size()==1){
79  auto& deq = reorder_buffer[cmd][res.front()];
80  auto notok = bw_o->transport(*deq.front().trans);
81  if(notok==0) deq.pop_front();
82  return;
83  } else {
84  r2=res;
85  }
86  }
87  if(prioritize_by_latency.value){
88  auto rnd = scc::MT19937::uniform(0, lat_sum);
89  auto part_sum = 0U;
90  for(auto& e:r2){
91  auto& deq = reorder_buffer[cmd][e];
92  part_sum+=deq.front().age;
93  if(part_sum>=rnd) {
94  auto notok = bw_o->transport(*deq.front().trans);
95  if(notok==0) deq.pop_front();
96  return;
97  }
98  }
99  } else {
100  auto rnd = scc::MT19937::uniform(0, r2.size()-1);
101  auto& deq = reorder_buffer[cmd][r2[rnd]];
102  auto notok = bw_o->transport(*deq.front().trans);
103  if(notok==0) deq.pop_front();
104  }
105  }
106  }
107  }
108 }
109 
void transport(tlm::tlm_generic_payload &payload, bool lt_transport=false) override
static uint64_t uniform()
Definition: mt19937_rng.h:60
uint8_t get_qos() const
get the AxQOS (quality of service) value
Definition: axi_tlm.h:1428