summaryrefslogtreecommitdiff
path: root/platform/wavelet3d/remote_bitbang.cpp
diff options
context:
space:
mode:
authorAlejandro Soto <alejandro@34project.org>2024-05-12 13:28:53 -0600
committerAlejandro Soto <alejandro@34project.org>2024-05-12 18:13:02 -0600
commitde49ebb80d1e2ef8283818332a0ac6bf5d70440d (patch)
treefc437474dfe336a43dd4fca9cd31ed150a435868 /platform/wavelet3d/remote_bitbang.cpp
parente581090bb9e7965c463be35544395406f5a5441d (diff)
platform/wavelet3d: implement JTAG TAP bridge in simulation
Diffstat (limited to '')
-rw-r--r--platform/wavelet3d/remote_bitbang.cpp300
1 files changed, 300 insertions, 0 deletions
diff --git a/platform/wavelet3d/remote_bitbang.cpp b/platform/wavelet3d/remote_bitbang.cpp
new file mode 100644
index 0000000..5e87233
--- /dev/null
+++ b/platform/wavelet3d/remote_bitbang.cpp
@@ -0,0 +1,300 @@
+// https://github.com/pulp-platform/riscv-dbg/blob/master/tb/remote_bitbang/remote_bitbang.c
+// See LICENSE.Berkeley for license details.
+
+#include <arpa/inet.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "remote_bitbang.h"
+
+//Public globals, declared in remote_bitbang.h
+
+int rbs_err;
+
+unsigned char tck;
+unsigned char tms;
+unsigned char tdi;
+unsigned char trstn;
+unsigned char tdo;
+unsigned char quit;
+
+int socket_fd;
+int client_fd;
+
+//static const ssize_t buf_size = 64 * 1024;
+char recv_buf[64 * 1024];
+ssize_t recv_start, recv_end;
+
+int rbs_init(uint16_t port)
+{
+ socket_fd = 0;
+ client_fd = 0;
+ recv_start = 0;
+ recv_end = 0;
+ rbs_err = 0;
+
+ socket_fd = socket(AF_INET, SOCK_STREAM, 0);
+ if (socket_fd == -1) {
+ fprintf(stderr, "remote_bitbang failed to make socket: %s (%d)\n",
+ strerror(errno), errno);
+ abort();
+ }
+
+ fcntl(socket_fd, F_SETFL, O_NONBLOCK);
+ int reuseaddr = 1;
+ if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr,
+ sizeof(int)) == -1) {
+ fprintf(stderr, "remote_bitbang failed setsockopt: %s (%d)\n",
+ strerror(errno), errno);
+ abort();
+ }
+
+ struct sockaddr_in addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = INADDR_ANY;
+ addr.sin_port = htons(port);
+
+ if (bind(socket_fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
+ fprintf(stderr, "remote_bitbang failed to bind socket: %s (%d)\n",
+ strerror(errno), errno);
+ abort();
+ }
+
+ if (listen(socket_fd, 1) == -1) {
+ fprintf(stderr, "remote_bitbang failed to listen on socket: %s (%d)\n",
+ strerror(errno), errno);
+ abort();
+ }
+
+ socklen_t addrlen = sizeof(addr);
+ if (getsockname(socket_fd, (struct sockaddr *)&addr, &addrlen) == -1) {
+ fprintf(stderr, "remote_bitbang getsockname failed: %s (%d)\n",
+ strerror(errno), errno);
+ abort();
+ }
+
+ tck = 1;
+ tms = 1;
+ tdi = 1;
+ trstn = 1;
+ quit = 0;
+
+ fprintf(stderr, "JTAG remote bitbang server is ready\n");
+ fprintf(stderr, "Listening on port %d\n", ntohs(addr.sin_port));
+ return 1;
+}
+
+void rbs_accept()
+{
+ fprintf(stderr, "Attempting to accept client socket\n");
+ int again = 1;
+ while (again != 0) {
+ client_fd = accept(socket_fd, NULL, NULL);
+ if (client_fd == -1) {
+ if (errno == EAGAIN) {
+ // No client waiting to connect right now.
+ } else {
+ fprintf(stderr, "failed to accept on socket: %s (%d)\n",
+ strerror(errno), errno);
+ again = 0;
+ abort();
+ }
+ } else {
+ fcntl(client_fd, F_SETFL, O_NONBLOCK);
+ fprintf(stderr, "Accepted successfully.\n");
+ again = 0;
+ }
+ }
+}
+
+void rbs_tick(unsigned char *jtag_tck, unsigned char *jtag_tms,
+ unsigned char *jtag_tdi, unsigned char *jtag_trstn,
+ unsigned char jtag_tdo)
+{
+ if (client_fd > 0) {
+ tdo = jtag_tdo;
+ rbs_execute_command();
+ } else {
+ rbs_accept();
+ }
+
+ *jtag_tck = tck;
+ *jtag_tms = tms;
+ *jtag_tdi = tdi;
+ *jtag_trstn = trstn;
+}
+
+void rbs_reset()
+{
+ trstn = 0;
+}
+
+void rbs_set()
+{
+ trstn = 1;
+}
+
+void rbs_set_pins(char _tck, char _tms, char _tdi)
+{
+ tck = _tck;
+ tms = _tms;
+ tdi = _tdi;
+}
+
+void rbs_execute_command()
+{
+ char command;
+ int again = 1;
+ while (again) {
+ ssize_t num_read = read(client_fd, &command, sizeof(command));
+ if (num_read == -1) {
+ if (errno == EAGAIN) {
+ // We'll try again the next call.
+ if (VERBOSE)
+ fprintf(
+ stderr,
+ "Received no command. Will try again on the next call\n");
+ } else {
+ fprintf(stderr,
+ "remote_bitbang failed to read on socket: %s (%d)\n",
+ strerror(errno), errno);
+ again = 0;
+ abort();
+ }
+ } else if (num_read == 0) {
+ fprintf(stderr, "No command received. Stopping further reads.\n");
+ close(client_fd);
+ client_fd = -1;
+ // again = 1;
+ return;
+ } else {
+ again = 0;
+ }
+ }
+
+ int dosend = 0;
+
+ char tosend = '?';
+
+ switch (command) {
+ case 'B':
+ if (VERBOSE)
+ fprintf(stderr, "*BLINK*\n");
+ break;
+ case 'b':
+ if (VERBOSE)
+ fprintf(stderr, "blink off\n");
+ break;
+ case 'r':
+ if (VERBOSE)
+ fprintf(stderr, "r-reset\n");
+ rbs_set(); //r-reset command deasserts TRST. See: openocd/blob/master/doc/manual/jtag/drivers/remote_bitbang.txt
+ break;
+ case 's':
+ if (VERBOSE)
+ fprintf(stderr, "s-reset\n");
+ rbs_set(); //s-reset command deasserts TRST. See: openocd/blob/master/doc/manual/jtag/drivers/remote_bitbang.txt
+ break;
+ case 't':
+ if (VERBOSE)
+ fprintf(stderr, "t-reset\n");
+ rbs_reset(); //t-reset command asserts TRST. See: openocd/blob/master/doc/manual/jtag/drivers/remote_bitbang.txt
+ break;
+ case 'u':
+ if (VERBOSE)
+ fprintf(stderr, "u-reset\n");
+ rbs_reset(); //u-reset command asserts TRST. See: openocd/blob/master/doc/manual/jtag/drivers/remote_bitbang.txt
+ break;
+ case '0':
+ if (VERBOSE)
+ fprintf(stderr, "Write 0 0 0\n");
+ rbs_set_pins(0, 0, 0);
+ break;
+ case '1':
+ if (VERBOSE)
+ fprintf(stderr, "Write 0 0 1\n");
+ rbs_set_pins(0, 0, 1);
+ break;
+ case '2':
+ if (VERBOSE)
+ fprintf(stderr, "Write 0 1 0\n");
+ rbs_set_pins(0, 1, 0);
+ break;
+ case '3':
+ if (VERBOSE)
+ fprintf(stderr, "Write 0 1 1\n");
+ rbs_set_pins(0, 1, 1);
+ break;
+ case '4':
+ if (VERBOSE)
+ fprintf(stderr, "Write 1 0 0\n");
+ rbs_set_pins(1, 0, 0);
+ break;
+ case '5':
+ if (VERBOSE)
+ fprintf(stderr, "Write 1 0 1\n");
+ rbs_set_pins(1, 0, 1);
+ break;
+ case '6':
+ if (VERBOSE)
+ fprintf(stderr, "Write 1 1 0\n");
+ rbs_set_pins(1, 1, 0);
+ break;
+ case '7':
+ if (VERBOSE)
+ fprintf(stderr, "Write 1 1 1\n");
+ rbs_set_pins(1, 1, 1);
+ break;
+ case 'R':
+ if (VERBOSE)
+ fprintf(stderr, "Read req\n");
+ dosend = 1;
+ tosend = tdo ? '1' : '0';
+ break;
+ case 'Q':
+ if (VERBOSE)
+ fprintf(stderr, "Quit req\n");
+ quit = 1;
+ break;
+ default:
+ fprintf(stderr, "remote_bitbang got unsupported command '%c'\n",
+ command);
+ }
+ if (dosend) {
+ while (1) {
+ ssize_t bytes = write(client_fd, &tosend, sizeof(tosend));
+ if (bytes == -1) {
+ fprintf(stderr, "failed to write to socket: %s (%d)\n",
+ strerror(errno), errno);
+ abort();
+ }
+ if (bytes > 0) {
+ break;
+ }
+ }
+ }
+
+ if (quit) {
+ fprintf(stderr, "Remote end disconnected\n");
+ close(client_fd);
+ client_fd = 0;
+ }
+}
+
+unsigned char rbs_done()
+{
+ return quit;
+}
+
+int rbs_exit_code()
+{
+ return rbs_err;
+}