54bc6d7e5aa1912fd9c3d99424d5ffb244177948
[riscv-isa-sim.git] / riscv / remote_bitbang.cc
1 #include <arpa/inet.h>
2 #include <errno.h>
3 #include <fcntl.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <unistd.h>
7
8 #include <algorithm>
9 #include <cassert>
10 #include <cstdio>
11
12 #include "remote_bitbang.h"
13
14 #if 1
15 # define D(x) x
16 #else
17 # define D(x)
18 #endif
19
20 /////////// remote_bitbang_t
21
22 remote_bitbang_t::remote_bitbang_t(uint16_t port, jtag_dtm_t *tap) :
23 tap(tap),
24 socket_fd(0),
25 client_fd(0)
26 {
27 socket_fd = socket(AF_INET, SOCK_STREAM, 0);
28 if (socket_fd == -1) {
29 fprintf(stderr, "remote_bitbang failed to make socket: %s (%d)\n",
30 strerror(errno), errno);
31 abort();
32 }
33
34 fcntl(socket_fd, F_SETFL, O_NONBLOCK);
35 int reuseaddr = 1;
36 if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr,
37 sizeof(int)) == -1) {
38 fprintf(stderr, "remote_bitbang failed setsockopt: %s (%d)\n",
39 strerror(errno), errno);
40 abort();
41 }
42
43 struct sockaddr_in addr;
44 memset(&addr, 0, sizeof(addr));
45 addr.sin_family = AF_INET;
46 addr.sin_addr.s_addr = INADDR_ANY;
47 addr.sin_port = htons(port);
48
49 if (bind(socket_fd, (struct sockaddr *) &addr, sizeof(addr)) == -1) {
50 fprintf(stderr, "remote_bitbang failed to bind socket: %s (%d)\n",
51 strerror(errno), errno);
52 abort();
53 }
54
55 if (listen(socket_fd, 1) == -1) {
56 fprintf(stderr, "remote_bitbang failed to listen on socket: %s (%d)\n",
57 strerror(errno), errno);
58 abort();
59 }
60 }
61
62 void remote_bitbang_t::accept()
63 {
64 client_fd = ::accept(socket_fd, NULL, NULL);
65 if (client_fd == -1) {
66 if (errno == EAGAIN) {
67 // No client waiting to connect right now.
68 } else {
69 fprintf(stderr, "failed to accept on socket: %s (%d)\n", strerror(errno),
70 errno);
71 abort();
72 }
73 } else {
74 fcntl(client_fd, F_SETFL, O_NONBLOCK);
75 }
76 }
77
78 void remote_bitbang_t::tick()
79 {
80 if (client_fd > 0) {
81 execute_commands();
82 } else {
83 this->accept();
84 }
85 }
86
87 void remote_bitbang_t::execute_commands()
88 {
89 const unsigned buf_size = 64 * 1024;
90 char recv_buf[buf_size];
91 char send_buf[buf_size];
92 unsigned total_received = 0;
93 ssize_t bytes = read(client_fd, recv_buf, buf_size);
94 while (bytes > 0) {
95 total_received += bytes;
96 unsigned send_offset = 0;
97 for (unsigned i = 0; i < bytes; i++) {
98 uint8_t command = recv_buf[i];
99
100 switch (command) {
101 case 'B': fprintf(stderr, "*BLINK*\n"); break;
102 case 'b': fprintf(stderr, "_______\n"); break;
103 case 'r': tap->reset(); break;
104 case '0': tap->set_pins(0, 0, 0); break;
105 case '1': tap->set_pins(0, 0, 1); break;
106 case '2': tap->set_pins(0, 1, 0); break;
107 case '3': tap->set_pins(0, 1, 1); break;
108 case '4': tap->set_pins(1, 0, 0); break;
109 case '5': tap->set_pins(1, 0, 1); break;
110 case '6': tap->set_pins(1, 1, 0); break;
111 case '7': tap->set_pins(1, 1, 1); break;
112 case 'R': send_buf[send_offset++] = tap->tdo() ? '1' : '0'; break;
113 default:
114 fprintf(stderr, "remote_bitbang got unsupported command '%c'\n",
115 command);
116 }
117 }
118 unsigned sent = 0;
119 while (sent < send_offset) {
120 bytes = write(client_fd, send_buf + sent, send_offset);
121 if (bytes == -1) {
122 fprintf(stderr, "failed to write to socket: %s (%d)\n", strerror(errno), errno);
123 abort();
124 }
125 sent += bytes;
126 }
127
128 if (total_received > buf_size) {
129 // Don't go forever, because that could starve the main simulation.
130 break;
131 }
132 bytes = read(client_fd, recv_buf, buf_size);
133 }
134
135 if (bytes == -1) {
136 if (errno == EAGAIN) {
137 // We'll try again the next call.
138 } else {
139 fprintf(stderr, "remote_bitbang failed to read on socket: %s (%d)\n",
140 strerror(errno), errno);
141 abort();
142 }
143 } else if (bytes == 0) {
144 // The remote disconnected.
145 close(client_fd);
146 client_fd = 0;
147 }
148 }