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