Line data Source code
1 : #include <map> 2 : 3 : extern "C" { 4 : #include "log.h" 5 : #include "completion_table.h" 6 : } 7 : 8 : /** 9 : * The completion table is the data structure that 10 : * allows to advance the DMA buffer read pointer as 11 : * completion objects from send operations are returned 12 : * The table is implemented using a pair of std::map used 13 : * in tandem to deal with address wrap-around. 14 : */ 15 : 16 : 17 : typedef uint32_t address_t; 18 : typedef uint32_t counter_t; 19 : 20 : 21 23 : struct completion_table 22 : { 23 : address_t rd; 24 : address_t last_pushed_addr; 25 : address_t last_provided_addr; 26 : std::map<address_t, counter_t> table_a; 27 : std::map<address_t, counter_t> table_b; 28 : std::map<address_t, counter_t>* current_table; 29 : std::map<address_t, counter_t>* wrap_table; 30 : }; 31 : 32 : 33 23 : void completion_table_init(completion_table** t) 34 : { 35 23 : (*t) = new completion_table; 36 23 : (*t)->rd = UINT32_MAX; 37 23 : (*t)->current_table = &(*t)->table_a; 38 23 : (*t)->wrap_table = &(*t)->table_b; 39 23 : (*t)->last_pushed_addr = 0x0; 40 23 : (*t)->last_provided_addr = 0x0; 41 23 : } 42 : 43 : 44 6 : void completion_table_close(completion_table** t) 45 : { 46 6 : delete (*t); 47 6 : (*t) = NULL; 48 6 : } 49 : 50 : 51 : // When a chunk has been decoded 52 86744382 : void completion_table_push(completion_table* t, uint32_t addr) 53 : { 54 86744382 : if (addr >= t->rd || t->rd == UINT32_MAX){ 55 84804699 : (*t->current_table)[addr]++; 56 : } else { 57 1939683 : (*t->wrap_table)[addr]++; 58 : } 59 86744382 : t->last_pushed_addr = addr; 60 : //swap tables if current is empty 61 86744382 : if (t->current_table->empty() && !t->wrap_table->empty()) { 62 1137 : t->rd = t->wrap_table->begin()->first; 63 1137 : std::swap(t->current_table, t->wrap_table); 64 : } 65 86744382 : } 66 : 67 : // When a completion object is read 68 86744382 : int completion_table_update(completion_table* t, uint32_t addr) 69 : { 70 86744382 : if (t->current_table->empty() && t->wrap_table->empty()){ 71 : return CT_EMPTY; 72 : } 73 86744382 : t->last_provided_addr = t->rd; 74 : 75 86744382 : if (t->rd <= addr || t->rd == UINT32_MAX){ 76 : 77 84897772 : auto it = t->current_table->find(addr); 78 84897772 : if (it == t->current_table->end()){ 79 1 : LOG_WARN("Completion object provided block addr 0x%x not in current table", addr); 80 1 : return CT_ERR; 81 : } 82 : 83 84897771 : --(it->second); 84 84897771 : if (it->second == 0){ 85 83825089 : if(it == t->current_table->begin()){ 86 105914251 : t->rd = t->current_table->size() > 1 ? std::next(it, 1)->first : it->first; 87 : } 88 83825089 : t->current_table->erase(it); 89 : } 90 : 91 : } else { 92 : 93 1846610 : auto it = t->wrap_table->find(addr); 94 1846610 : if (it == t->wrap_table->end()){ 95 1 : return CT_ERR; 96 : } 97 1846610 : --(it->second); 98 1846610 : if (it->second == 0){ 99 1838908 : t->wrap_table->erase(it); 100 : } 101 : 102 : } 103 : 104 : return CT_OK; 105 : } 106 : 107 : 108 8 : uint32_t completion_table_get_count(completion_table* t, uint32_t addr) 109 : { 110 8 : uint32_t count = 0; 111 8 : if (t->rd <= addr || t->rd == UINT32_MAX) { 112 8 : if(t->current_table->count(addr) == 1){ 113 8 : count = t->current_table->at(addr); 114 : } 115 : } else { 116 0 : if(t->wrap_table->count(addr) == 1){ 117 0 : count = t->wrap_table->at(addr); 118 : } 119 : } 120 8 : return count; 121 : } 122 : 123 : 124 2667852 : uint32_t completion_table_get_rd(completion_table* t) 125 : { 126 2667852 : return t->rd; 127 : } 128 : 129 : 130 6 : size_t completion_table_get_entries(completion_table* t) 131 : { 132 6 : return (t->current_table->size() + t->wrap_table->size()); 133 : } 134 : 135 : 136 10 : void completion_table_inspect(completion_table* t) 137 : { 138 10 : LOG_INFO("Completion table contains %lu entries", (t->current_table->size()+t->wrap_table->size()) ); 139 10 : int printed{0}, max_printout{100}; 140 12 : for (auto & c : *t->current_table){ 141 2 : LOG_INFO("CT Block 0x%08x count %u", c.first, c.second); 142 2 : ++printed; 143 2 : if(printed == max_printout){break;} 144 : } 145 10 : for (auto & w : *t->wrap_table){ 146 0 : LOG_INFO("WT Block 0x%08x count %u", w.first, w.second); 147 0 : ++printed; 148 0 : if(printed == max_printout){break;} 149 : } 150 10 : } 151 : 152 : 153 0 : uint32_t get_previous_rd(completion_table* t) 154 : { 155 0 : return t->last_provided_addr; 156 : }