7f22cd3223be06176c1229201f90eecfab226b5e
[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 /////////// Circular buffer
15
16 template <typename T>
17 unsigned int circular_buffer_t<T>::size() const
18 {
19 if (end >= start)
20 return end - start;
21 else
22 return end + capacity - start;
23 }
24
25 template <typename T>
26 void circular_buffer_t<T>::consume(unsigned int bytes)
27 {
28 start = (start + bytes) % capacity;
29 }
30
31 template <typename T>
32 unsigned int circular_buffer_t<T>::contiguous_empty_size() const
33 {
34 if (end >= start)
35 if (start == 0)
36 return capacity - end - 1;
37 else
38 return capacity - end;
39 else
40 return start - end - 1;
41 }
42
43 template <typename T>
44 unsigned int circular_buffer_t<T>::contiguous_data_size() const
45 {
46 if (end >= start)
47 return end - start;
48 else
49 return capacity - start;
50 }
51
52 template <typename T>
53 void circular_buffer_t<T>::data_added(unsigned int bytes)
54 {
55 end += bytes;
56 assert(end <= capacity);
57 if (end == capacity)
58 end = 0;
59 }
60
61 template <typename T>
62 void circular_buffer_t<T>::reset()
63 {
64 start = 0;
65 end = 0;
66 }
67
68 template <typename T>
69 void circular_buffer_t<T>::append(const T *src, unsigned int count)
70 {
71 unsigned int copy = std::min(count, contiguous_empty_size());
72 memcpy(contiguous_empty(), src, copy * sizeof(T));
73 data_added(copy);
74 count -= copy;
75 if (count > 0) {
76 assert(count < contiguous_empty_size());
77 memcpy(contiguous_empty(), src+copy, count * sizeof(T));
78 data_added(count);
79 }
80 }
81
82 template <typename T>
83 void circular_buffer_t<T>::append(T value)
84 {
85 append(&value, 1);
86 }
87
88 /////////// remote_bitbang_t
89
90 remote_bitbang_t::remote_bitbang_t(uint16_t port, sim_t *sim) :
91 socket_fd(0),
92 client_fd(0),
93 recv_buf(64 * 1024),
94 send_buf(64 * 1024)
95 {
96 socket_fd = socket(AF_INET, SOCK_STREAM, 0);
97 if (socket_fd == -1) {
98 fprintf(stderr, "remote_bitbang failed to make socket: %s (%d)\n",
99 strerror(errno), errno);
100 abort();
101 }
102
103 fcntl(socket_fd, F_SETFL, O_NONBLOCK);
104 int reuseaddr = 1;
105 if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr,
106 sizeof(int)) == -1) {
107 fprintf(stderr, "remote_bitbang failed setsockopt: %s (%d)\n",
108 strerror(errno), errno);
109 abort();
110 }
111
112 struct sockaddr_in addr;
113 memset(&addr, 0, sizeof(addr));
114 addr.sin_family = AF_INET;
115 addr.sin_addr.s_addr = INADDR_ANY;
116 addr.sin_port = htons(port);
117
118 if (bind(socket_fd, (struct sockaddr *) &addr, sizeof(addr)) == -1) {
119 fprintf(stderr, "remote_bitbang failed to bind socket: %s (%d)\n",
120 strerror(errno), errno);
121 abort();
122 }
123
124 if (listen(socket_fd, 1) == -1) {
125 fprintf(stderr, "remote_bitbang failed to listen on socket: %s (%d)\n",
126 strerror(errno), errno);
127 abort();
128 }
129 }
130
131 void remote_bitbang_t::accept()
132 {
133 client_fd = ::accept(socket_fd, NULL, NULL);
134 if (client_fd == -1) {
135 if (errno == EAGAIN) {
136 // No client waiting to connect right now.
137 } else {
138 fprintf(stderr, "failed to accept on socket: %s (%d)\n", strerror(errno),
139 errno);
140 abort();
141 }
142 } else {
143 fcntl(client_fd, F_SETFL, O_NONBLOCK);
144 }
145 }
146
147 void remote_bitbang_t::read()
148 {
149 // Reading from a non-blocking socket still blocks if there is no data
150 // available.
151
152 size_t count = recv_buf.contiguous_empty_size();
153 ssize_t bytes = ::read(client_fd, recv_buf.contiguous_empty(), count);
154 if (bytes == -1) {
155 if (errno == EAGAIN) {
156 // We'll try again the next call.
157 } else {
158 fprintf(stderr, "failed to read on socket: %s (%d)\n", strerror(errno), errno);
159 abort();
160 }
161 } else if (bytes == 0) {
162 // The remote disconnected.
163 client_fd = 0;
164 recv_buf.reset();
165 send_buf.reset();
166 } else {
167 recv_buf.data_added(bytes);
168 D(fprintf(stderr, "receive buffer: "));
169 for (unsigned i = 0; i < recv_buf.size(); i++) {
170 D(fprintf(stderr, "%c", recv_buf[i]));
171 }
172 D(fprintf(stderr, "\n"));
173 }
174 }
175
176 void remote_bitbang_t::write()
177 {
178 if (send_buf.empty())
179 return;
180
181 while (!send_buf.empty()) {
182 unsigned int count = send_buf.contiguous_data_size();
183 assert(count > 0);
184 ssize_t bytes = ::write(client_fd, send_buf.contiguous_data(), count);
185 if (bytes == -1) {
186 fprintf(stderr, "failed to write to socket: %s (%d)\n", strerror(errno), errno);
187 abort();
188 } else if (bytes == 0) {
189 // Client can't take any more data right now.
190 break;
191 } else {
192 D(fprintf(stderr, "wrote %zd bytes: ", bytes));
193 for (int i = 0; i < bytes; i++) {
194 D(fprintf(stderr, "%c", send_buf[i]));
195 }
196 D(fprintf(stderr, "\n"));
197 send_buf.consume(bytes);
198 }
199 }
200 }
201
202 void remote_bitbang_t::tick()
203 {
204 if (client_fd > 0) {
205 this->read();
206 process_input();
207 this->write();
208 } else {
209 this->accept();
210 }
211 }
212
213 void remote_bitbang_t::process_input()
214 {
215 for (unsigned i = 0; i < recv_buf.size(); i++) {
216 uint8_t command = recv_buf[i];
217
218 switch (command) {
219 case 'B': fprintf(stderr, "*BLINK*\n"); break;
220 case 'b': fprintf(stderr, "_______\n"); break;
221 case 'r': tap.reset(); break;
222 case '0': tap.set_pins(0, 0, 0); break;
223 case '1': tap.set_pins(0, 0, 1); break;
224 case '2': tap.set_pins(0, 1, 0); break;
225 case '3': tap.set_pins(0, 1, 1); break;
226 case '4': tap.set_pins(1, 0, 0); break;
227 case '5': tap.set_pins(1, 0, 1); break;
228 case '6': tap.set_pins(1, 1, 0); break;
229 case '7': tap.set_pins(1, 1, 1); break;
230 case 'R': send_buf.append(tap.tdo() ? '1' : '0'); break;
231 default:
232 fprintf(stderr, "remote_bitbang got unsupported command '%c'\n", command);
233 }
234 }
235 recv_buf.reset();
236 }