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 #include "renode_bus.h"
8 #include "communication/socket_channel.h"
9 #include "src/renode.h"
10 static RenodeAgent* renodeAgent;
11
12 #define IO_THREADS 1
13
14 //=================================================
15 // RenodeAgent
16 //=================================================
17
RenodeAgent()18 RenodeAgent::RenodeAgent() { }
19
addBus(BaseBus * bus)20 void RenodeAgent::addBus(BaseBus* bus)
21 {
22 bus->setAgent(this);
23 if(targetInterfaces.empty())
24 {
25 firstInterface = bus;
26 }
27 }
addBus(BaseTargetBus * bus)28 void RenodeAgent::addBus(BaseTargetBus* bus)
29 {
30 addBus((BaseBus*)bus);
31 targetInterfaces.push_back(std::unique_ptr<BaseTargetBus>(bus));
32 }
33
addBus(BaseInitiatorBus * bus)34 void RenodeAgent::addBus(BaseInitiatorBus* bus)
35 {
36 addBus((BaseBus*)bus);
37 initatorInterfaces.push_back(std::unique_ptr<BaseInitiatorBus>(bus));
38 }
39
writeToBus(int width,uint64_t addr,uint64_t value)40 void RenodeAgent::writeToBus(int width, uint64_t addr, uint64_t value)
41 {
42 try {
43 targetInterfaces[0]->write(width, addr, value);
44 communicationChannel->sendMain(Protocol(ok, 0, 0));
45 }
46 catch(const char* msg) {
47 log(LOG_LEVEL_ERROR, msg);
48 communicationChannel->sendMain(Protocol(error, 0, 0));
49 }
50 }
51
readFromBus(int width,uint64_t addr)52 void RenodeAgent::readFromBus(int width, uint64_t addr)
53 {
54 try {
55 uint64_t readValue = targetInterfaces[0]->read(width, addr);
56 communicationChannel->sendMain(Protocol(readRequest, addr, readValue));
57 }
58 catch(const char* msg) {
59 log(LOG_LEVEL_ERROR, msg);
60 communicationChannel->sendMain(Protocol(error, 0, 0));
61 }
62 }
63
pushByteToAgent(uint64_t addr,uint8_t value)64 void RenodeAgent::pushByteToAgent(uint64_t addr, uint8_t value)
65 {
66 pushToAgent(pushByte, addr, value);
67 }
68
pushWordToAgent(uint64_t addr,uint16_t value)69 void RenodeAgent::pushWordToAgent(uint64_t addr, uint16_t value)
70 {
71 pushToAgent(pushWord, addr, value);
72 }
73
pushDoubleWordToAgent(uint64_t addr,uint32_t value)74 void RenodeAgent::pushDoubleWordToAgent(uint64_t addr, uint32_t value)
75 {
76 pushToAgent(pushDoubleWord, addr, value);
77 }
78
requestDoubleWordFromAgent(uint64_t addr)79 uint64_t RenodeAgent::requestDoubleWordFromAgent(uint64_t addr)
80 {
81 return requestFromAgent(getDoubleWord, addr);
82 }
83
pushToAgent(Action action,uint64_t addr,uint64_t value)84 void RenodeAgent::pushToAgent(Action action, uint64_t addr, uint64_t value)
85 {
86 communicationChannel->sendSender(Protocol(action, addr, value));
87 Protocol* received = communicationChannel->receive();
88 while (received->actionId != pushConfirmation)
89 {
90 handleRequest(received);
91 delete received;
92 received = communicationChannel->receive();
93 }
94 delete received;
95 }
96
requestFromAgent(Action action,uint64_t addr)97 uint64_t RenodeAgent::requestFromAgent(Action action, uint64_t addr)
98 {
99 communicationChannel->sendSender(Protocol(action, addr, 0));
100 Protocol* received = communicationChannel->receive();
101 while (received->actionId != writeRequest)
102 {
103 handleRequest(received);
104 delete received;
105 received = communicationChannel->receive();
106 }
107 auto result = received->value;
108 delete received;
109 return result;
110 }
111
tick(bool countEnable,uint64_t steps)112 void RenodeAgent::tick(bool countEnable, uint64_t steps)
113 {
114 for(auto& b : targetInterfaces)
115 b->tick(countEnable, steps);
116 for(auto& b : initatorInterfaces)
117 b->tick(countEnable, steps);
118 }
119
timeoutTick(uint8_t * signal,uint8_t expectedValue,int timeout)120 void RenodeAgent::timeoutTick(uint8_t* signal, uint8_t expectedValue, int timeout)
121 {
122 for(auto& b : targetInterfaces)
123 b->timeoutTick(signal, expectedValue, timeout);
124 for(auto& b : initatorInterfaces)
125 b->timeoutTick(signal, expectedValue, timeout);
126 }
127
reset()128 void RenodeAgent::reset()
129 {
130 for(auto& b : targetInterfaces)
131 b->reset();
132 for(auto& b : initatorInterfaces)
133 b->reset();
134 }
135
fatalError()136 void RenodeAgent::fatalError()
137 {
138 communicationChannel->sendSender(Protocol(error, 0, 0));
139 handleDisconnect();
140 }
141
handleCustomRequestType(Protocol * message)142 void RenodeAgent::handleCustomRequestType(Protocol* message)
143 {
144 log(LOG_LEVEL_WARNING, "Unhandled request type: %d", message->actionId);
145 }
146
log(int level,const char * fmt,...)147 void RenodeAgent::log(int level, const char* fmt, ...)
148 {
149 char s[1024];
150 va_list ap;
151 va_start(ap, fmt);
152 vsnprintf(s, 1024, fmt, ap);
153 communicationChannel->log(level, s);
154 va_end(ap);
155 }
156
receive()157 Protocol* RenodeAgent::receive()
158 {
159 return communicationChannel->receive();
160 }
161
registerInterrupt(uint8_t * irq,uint8_t irq_addr)162 void RenodeAgent::registerInterrupt(uint8_t *irq, uint8_t irq_addr)
163 {
164 if (irq == nullptr) {
165 log(LOG_LEVEL_ERROR, "The irq address cannot be null");
166 communicationChannel->sendMain(Protocol(error, 0, 0));
167 return;
168 }
169
170 interrupts.push_back({irq, 0, irq_addr});
171 }
172
handleInterrupts(void)173 void RenodeAgent::handleInterrupts(void)
174 {
175 for (unsigned long i = 0; i < interrupts.size(); i++) {
176 if (*interrupts[i].irq != interrupts[i].prev_irq) {
177 communicationChannel->sendSender(Protocol(interrupt, interrupts[i].irq_addr, *interrupts[i].irq));
178 interrupts[i].prev_irq = *interrupts[i].irq;
179 }
180 }
181 }
182
connect(int receiverPort,int senderPort,const char * address)183 void RenodeAgent::connect(int receiverPort, int senderPort, const char* address)
184 {
185 renodeAgent = this;
186 SocketCommunicationChannel* channel = new SocketCommunicationChannel();
187 communicationChannel = channel;
188 channel->connect(receiverPort, senderPort, address);
189 }
190
connectNative()191 void RenodeAgent::connectNative()
192 {
193 renodeAgent = this;
194 communicationChannel = new NativeCommunicationChannel;
195 }
196
simulate()197 void RenodeAgent::simulate()
198 {
199 Protocol* result;
200 reset();
201
202 while(communicationChannel->isConnected()) {
203 result = receive();
204 handleRequest(result);
205 delete result;
206 }
207 }
208
handleRequest(Protocol * request)209 void RenodeAgent::handleRequest(Protocol* request)
210 {
211 switch(request->actionId) {
212 case invalidAction:
213 break;
214 case tickClock:
215 {
216 long ticks = request->value - firstInterface->tickCounter;
217 if(ticks < 0) {
218 firstInterface->tickCounter -= request->value;
219 }
220 else {
221 tick(false, ticks);
222 }
223 firstInterface->tickCounter = 0;
224 communicationChannel->sendSender(Protocol(tickClock, 0, 0));
225 }
226 break;
227 case writeRequestByte:
228 writeToBus(1, request->addr, request->value);
229 break;
230 case writeRequestWord:
231 writeToBus(2, request->addr, request->value);
232 break;
233 case writeRequest: // due to historical reasons, writeRequest defaults to 32bits
234 case writeRequestDoubleWord:
235 writeToBus(4, request->addr, request->value);
236 break;
237 case writeRequestQuadWord:
238 writeToBus(8, request->addr, request->value);
239 break;
240 case readRequestByte:
241 readFromBus(1, request->addr);
242 break;
243 case readRequestWord:
244 readFromBus(2, request->addr);
245 break;
246 case readRequest: // due to historical reasons, writeRequest defaults to 32bits
247 case readRequestDoubleWord:
248 readFromBus(4, request->addr);
249 break;
250 case readRequestQuadWord:
251 readFromBus(8, request->addr);
252 break;
253 case resetPeripheral:
254 reset();
255 break;
256 case disconnect:
257 handleDisconnect();
258 break;
259 default:
260 handleCustomRequestType(request);
261 break;
262 }
263 }
264
handleDisconnect()265 void RenodeAgent::handleDisconnect()
266 {
267 SocketCommunicationChannel* channel;
268 if((channel = dynamic_cast<SocketCommunicationChannel*>(communicationChannel)) != nullptr) {
269 communicationChannel->sendSender(Protocol(ok, 0, 0));
270 channel->disconnect();
271 }
272 }
273
274 //=================================================
275 // NativeCommunicationChannel
276 //=================================================
277
278 extern void handleMainMessage(void* ptr);
279 extern void handleSenderMessage(void* ptr);
280 extern void receive(void* ptr);
281
282 EXTERNAL_AS(void, HandleMainMessage, handleMainMessage, voidptr);
283 EXTERNAL_AS(void, HandleSenderMessage, handleSenderMessage, voidptr);
284 EXTERNAL_AS(void, Receive, receive, voidptr);
285
sendMain(const Protocol message)286 void NativeCommunicationChannel::sendMain(const Protocol message)
287 {
288 handleMainMessage(new Protocol(message));
289 }
290
sendSender(const Protocol message)291 void NativeCommunicationChannel::sendSender(const Protocol message)
292 {
293 handleSenderMessage(new Protocol(message));
294 }
295
log(int logLevel,const char * data)296 void NativeCommunicationChannel::log(int logLevel, const char* data)
297 {
298 handleSenderMessage(new Protocol(logMessage, strlen(data) + 1, (uint64_t)data));
299 handleSenderMessage(new Protocol(logMessage, 0, logLevel));
300 }
301
isConnected()302 bool NativeCommunicationChannel::isConnected()
303 {
304 return true;
305 }
306
receive()307 Protocol* NativeCommunicationChannel::receive()
308 {
309 Protocol* message = new Protocol;
310 ::receive(message);
311 return message;
312 }
313
314 //=================================================
315 // Functions exported to Renode
316 //=================================================
317
initialize_native()318 void initialize_native()
319 {
320 renodeAgent = Init();
321 }
322
handle_request(Protocol * request)323 void handle_request(Protocol* request)
324 {
325 renodeAgent->handleRequest(request);
326 }
327
reset_peripheral()328 void reset_peripheral()
329 {
330 renodeAgent->reset();
331 }
332