1 // 2 // Copyright (c) 2010-2025 Antmicro 3 // 4 // This file is licensed under the MIT License. 5 // Full license text is available in 'licenses/MIT.txt'. 6 // 7 8 #ifndef WishboneInitiator_H 9 #define WishboneInitiator_H 10 11 #include "src/renode.h" 12 #include "wishbone.h" 13 14 template <typename data_t, typename addr_t> 15 class WishboneInitiator : public WishboneBase, public BaseInitiatorBus 16 { 17 public: WishboneInitiator()18 WishboneInitiator() 19 : readState(0), writeState(0) 20 { 21 } 22 areSignalsConnected()23 bool areSignalsConnected() 24 { 25 return isSignalConnected(wb_clk, "wb_clk") 26 && isSignalConnected(wb_rst, "wb_rst") 27 && isSignalConnected(wb_addr, "wb_addr") 28 && isSignalConnected(wb_rd_dat, "wb_rd_dat") 29 && isSignalConnected(wb_wr_dat, "wb_wr_dat") 30 && isSignalConnected(wb_we, "wb_we") 31 && isSignalConnected(wb_sel, "wb_sel") 32 && isSignalConnected(wb_stb, "wb_stb") 33 && isSignalConnected(wb_ack, "wb_ack") 34 && isSignalConnected(wb_cyc, "wb_cyc") 35 && isSignalConnected(wb_stall, "wb_stall"); 36 } 37 tick(bool countEnable,uint64_t steps)38 void tick(bool countEnable, uint64_t steps) override 39 { 40 for (size_t i = 0; i < steps; i++) 41 { 42 readHandler(); 43 writeHandler(); 44 *wb_clk = high; 45 evaluateModel(); 46 *wb_clk = low; 47 evaluateModel(); 48 } 49 50 clearSignals(); 51 52 if (countEnable) 53 tickCounter += steps; 54 } 55 timeoutTick(uint8_t * signal,uint8_t expectedValue,int timeout)56 void timeoutTick(uint8_t* signal, uint8_t expectedValue, int timeout) 57 { 58 throw "Unsupported operation"; 59 } 60 readWord(uint64_t addr,uint8_t sel)61 void readWord(uint64_t addr, uint8_t sel) 62 { 63 #ifdef DEBUG 64 agent->log(LOG_LEVEL_NOISY, "Wishbone read from: 0x%" PRIX64 ", sel: %i", addr, int(sel)); 65 #endif 66 data = agent->requestDoubleWordFromAgent(addr); 67 68 constexpr size_t bits = 8; 69 for (size_t i = 0; i < bits; i++) 70 { 71 if ((sel & (1 << i)) == 0) 72 ((uint8_t *)&data)[i] = 0; 73 } 74 } 75 writeWord(uint64_t addr,uint64_t data,uint8_t sel)76 void writeWord(uint64_t addr, uint64_t data, uint8_t sel) 77 { 78 #ifdef DEBUG 79 agent->log(LOG_LEVEL_NOISY, "Wishbone write to: 0x%" PRIX64 ", data: 0x%" PRIX64 ", sel: %i", addr, data, int(sel)); 80 #endif 81 82 switch (sel) 83 { 84 case 1 << 0: 85 agent->pushByteToAgent(addr, ((uint8_t *)&data)[0]); 86 break; 87 case 1 << 1: 88 agent->pushByteToAgent(addr + 1, ((uint8_t *)&data)[1]); 89 break; 90 case 1 << 2: 91 agent->pushByteToAgent(addr + 2, ((uint8_t *)&data)[2]); 92 break; 93 case 1 << 3: 94 agent->pushByteToAgent(addr + 3, ((uint8_t *)&data)[3]); 95 break; 96 97 case (1 << 0) | (1 << 1): 98 agent->pushWordToAgent(addr, data & 0xFFFF); 99 break; 100 case (1 << 2) | (1 << 3): 101 agent->pushWordToAgent(addr + 2, (data >> 16) & 0xFFFF); 102 break; 103 104 case 15: 105 agent->pushDoubleWordToAgent(addr, data); 106 break; 107 108 default: 109 { 110 uint64_t oldData = agent->requestDoubleWordFromAgent(addr); 111 112 constexpr size_t bits = 8; 113 for (size_t i = 0; i < bits; i++) 114 { 115 if (sel & (1 << i)) 116 ((uint8_t *)&oldData)[i] = ((uint8_t *)&data)[i]; 117 } 118 119 agent->pushDoubleWordToAgent(addr, oldData); 120 break; 121 } 122 } 123 } 124 readHandler()125 void readHandler() 126 { 127 switch (readState) 128 { 129 case 0: 130 if (*wb_cyc && *wb_stb && !*wb_we) 131 { 132 *wb_stall = low; 133 *wb_ack = low; 134 readWord(*wb_addr * sizeof(data_t), *wb_sel); 135 readState = 1; 136 } 137 break; 138 case 1: 139 *wb_stall = high; 140 *wb_ack = high; 141 *wb_rd_dat = data; 142 readState = 0; 143 break; 144 } 145 } 146 writeHandler()147 void writeHandler() 148 { 149 switch (writeState) 150 { 151 case 0: 152 if (*wb_cyc && *wb_stb && *wb_we) 153 { 154 *wb_stall = low; 155 *wb_ack = low; 156 writeWord(*wb_addr * sizeof(data_t), *wb_wr_dat, *wb_sel); 157 writeState = 1; 158 } 159 break; 160 case 1: 161 *wb_stall = high; 162 *wb_ack = high; 163 writeState = 0; 164 break; 165 } 166 } 167 clearSignals()168 void clearSignals() 169 { 170 *wb_stall = high; 171 *wb_ack = low; 172 } 173 reset()174 void reset() 175 { 176 *wb_rst = 1; 177 tick(true, 1); 178 *wb_rst = 0; 179 tick(true, 1); 180 } 181 hasSpecifiedAdress()182 bool hasSpecifiedAdress() override 183 { 184 return *wb_cyc && *wb_stb; 185 } 186 getSpecifiedAdress()187 uint64_t getSpecifiedAdress() override { return *wb_addr * sizeof(data_t); } 188 189 addr_t *wb_addr; 190 data_t *wb_rd_dat; 191 data_t *wb_wr_dat; 192 193 uint8_t readState, writeState; 194 uint64_t data; 195 196 static constexpr uint32_t high = 1, low = 0; 197 }; 198 199 #endif 200