Skip to content

Commit

Permalink
OpenOCD connects, and sends some data that we receive.
Browse files Browse the repository at this point in the history
  • Loading branch information
timsifive committed Feb 3, 2017
1 parent e9e3059 commit d1f2cf3
Show file tree
Hide file tree
Showing 6 changed files with 300 additions and 18 deletions.
211 changes: 211 additions & 0 deletions riscv/remote_bitbang.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <algorithm>
#include <cassert>
#include <cstdio>

#include "remote_bitbang.h"

#define DEBUG
#ifdef DEBUG
# define D(x) x
#else
# define D(x)
#endif // DEBUG

/////////// Circular buffer

template <typename T>
unsigned int circular_buffer_t<T>::size() const
{
if (end >= start)
return end - start;
else
return end + capacity - start;
}

template <typename T>
void circular_buffer_t<T>::consume(unsigned int bytes)
{
start = (start + bytes) % capacity;
}

template <typename T>
unsigned int circular_buffer_t<T>::contiguous_empty_size() const
{
if (end >= start)
if (start == 0)
return capacity - end - 1;
else
return capacity - end;
else
return start - end - 1;
}

template <typename T>
unsigned int circular_buffer_t<T>::contiguous_data_size() const
{
if (end >= start)
return end - start;
else
return capacity - start;
}

template <typename T>
void circular_buffer_t<T>::data_added(unsigned int bytes)
{
end += bytes;
assert(end <= capacity);
if (end == capacity)
end = 0;
}

template <typename T>
void circular_buffer_t<T>::reset()
{
start = 0;
end = 0;
}

template <typename T>
void circular_buffer_t<T>::append(const T *src, unsigned int count)
{
unsigned int copy = std::min(count, contiguous_empty_size());
memcpy(contiguous_empty(), src, copy * sizeof(T));
data_added(copy);
count -= copy;
if (count > 0) {
assert(count < contiguous_empty_size());
memcpy(contiguous_empty(), src+copy, count * sizeof(T));
data_added(count);
}
}

/////////// remote_bitbang_t

remote_bitbang_t::remote_bitbang_t(uint16_t port, sim_t *sim) :
socket_fd(0),
client_fd(0),
recv_buf(64 * 1024),
send_buf(64 * 1024)
{
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();
}
}

void remote_bitbang_t::accept()
{
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);
abort();
}
} else {
fcntl(client_fd, F_SETFL, O_NONBLOCK);
}
}

void remote_bitbang_t::read()
{
// Reading from a non-blocking socket still blocks if there is no data
// available.

size_t count = recv_buf.contiguous_empty_size();
ssize_t bytes = ::read(client_fd, recv_buf.contiguous_empty(), count);
if (bytes == -1) {
if (errno == EAGAIN) {
// We'll try again the next call.
} else {
fprintf(stderr, "failed to read on socket: %s (%d)\n", strerror(errno), errno);
abort();
}
} else if (bytes == 0) {
// The remote disconnected.
client_fd = 0;
recv_buf.reset();
send_buf.reset();
} else {
recv_buf.data_added(bytes);
D(fprintf(stderr, "receive buffer: "));
for (unsigned i = 0; i < recv_buf.size(); i++) {
D(fprintf(stderr, "%c", recv_buf[i]));
}
D(fprintf(stderr, "\n"));
}
}

void remote_bitbang_t::write()
{
if (send_buf.empty())
return;

while (!send_buf.empty()) {
unsigned int count = send_buf.contiguous_data_size();
assert(count > 0);
ssize_t bytes = ::write(client_fd, send_buf.contiguous_data(), count);
if (bytes == -1) {
fprintf(stderr, "failed to write to socket: %s (%d)\n", strerror(errno), errno);
abort();
} else if (bytes == 0) {
// Client can't take any more data right now.
break;
} else {
D(fprintf(stderr, "wrote %zd bytes: ", bytes));
for (int i = 0; i < bytes; i++) {
D(fprintf(stderr, "%c", send_buf[i]));
}
D(fprintf(stderr, "\n"));
send_buf.consume(bytes);
}
}
}

void remote_bitbang_t::tick()
{
if (client_fd > 0) {
this->read();
this->write();
} else {
this->accept();
}
}
70 changes: 70 additions & 0 deletions riscv/remote_bitbang.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#ifndef REMOTE_BITBANG_H
#define REMOTE_BITBANG_H

#include <stdint.h>

class sim_t;

template <typename T>
class circular_buffer_t
{
public:
// The buffer can store capacity-1 data elements.
circular_buffer_t(unsigned int capacity) : data(new T[capacity]),
start(0), end(0), capacity(capacity) {}
circular_buffer_t() : start(0), end(0), capacity(0) {}
~circular_buffer_t() { delete[] data; }

T *data;
unsigned int start; // Data start, inclusive.
unsigned int end; // Data end, exclusive.
unsigned int capacity; // Size of the buffer.
unsigned int size() const;
bool empty() const { return start == end; }
bool full() const { return ((end+1) % capacity) == start; }
T entry(unsigned index) { return data[(start + index) % capacity]; }

// Return size and address of the block of RAM where more data can be copied
// to be added to the buffer.
unsigned int contiguous_empty_size() const;
T *contiguous_empty() { return data + end; }
void data_added(unsigned int bytes);

unsigned int contiguous_data_size() const;
T *contiguous_data() { return data + start; }
// Tell the buffer that some bytes were consumed from the start of the
// buffer.
void consume(unsigned int bytes);

void reset();

T operator[](unsigned int i) const { return data[(start + i) % capacity]; }

void append(const T *src, unsigned int count);
};

class remote_bitbang_t
{
public:
// Create a new server, listening for connections from localhost on the given
// port.
remote_bitbang_t(uint16_t port, sim_t *sim);

// Do a bit of work.
void tick();

private:
int socket_fd;
int client_fd;
circular_buffer_t<uint8_t> recv_buf;
circular_buffer_t<uint8_t> send_buf;

// Check for a client connecting, and accept if there is one.
void accept();
// Read as much into recv_buf as possible.
void read();
// Write as much of send_buf as possible.
void write();
};

#endif
4 changes: 2 additions & 2 deletions riscv/riscv.mk.in
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ riscv_hdrs = \
rocc.h \
insn_template.h \
mulhi.h \
gdbserver.h \
debug_module.h \
remote_bitbang.h \

riscv_precompiled_hdrs = \
insn_template.h \
Expand All @@ -45,8 +45,8 @@ riscv_srcs = \
devices.cc \
rom.cc \
rtc.cc \
gdbserver.cc \
debug_module.cc \
remote_bitbang.cc \
$(riscv_gen_srcs) \

riscv_test_srcs =
Expand Down
8 changes: 4 additions & 4 deletions riscv/sim.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

#include "sim.h"
#include "mmu.h"
#include "gdbserver.h"
#include "remote_bitbang.h"
#include <map>
#include <iostream>
#include <sstream>
Expand All @@ -23,7 +23,7 @@ static void handle_signal(int sig)
sim_t::sim_t(const char* isa, size_t nprocs, size_t mem_mb, bool halted,
const std::vector<std::string>& args)
: htif_t(args), procs(std::max(nprocs, size_t(1))),
current_step(0), current_proc(0), debug(false), gdbserver(NULL)
current_step(0), current_proc(0), debug(false), remote_bitbang(NULL)
{
signal(SIGINT, &handle_signal);
// allocate target machine's memory, shrinking it as necessary
Expand Down Expand Up @@ -77,8 +77,8 @@ void sim_t::main()
interactive();
else
step(INTERLEAVE);
if (gdbserver) {
gdbserver->handle();
if (remote_bitbang) {
remote_bitbang->tick();
}
}
}
Expand Down
9 changes: 5 additions & 4 deletions riscv/sim.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
#include <memory>

class mmu_t;
class gdbserver_t;
class remote_bitbang_t;

// this class encapsulates the processors and memory in a RISC-V machine.
class sim_t : public htif_t
Expand All @@ -29,7 +29,9 @@ class sim_t : public htif_t
void set_log(bool value);
void set_histogram(bool value);
void set_procs_debug(bool value);
void set_gdbserver(gdbserver_t* gdbserver) { this->gdbserver = gdbserver; }
void set_remote_bitbang(remote_bitbang_t* remote_bitbang) {
this->remote_bitbang = remote_bitbang;
}
const char* get_config_string() { return config_string.c_str(); }
processor_t* get_core(size_t i) { return procs.at(i); }

Expand All @@ -53,7 +55,7 @@ class sim_t : public htif_t
bool debug;
bool log;
bool histogram_enabled; // provide a histogram of PCs
gdbserver_t* gdbserver;
remote_bitbang_t* remote_bitbang;

// memory-mapped I/O routines
bool addr_is_mem(reg_t addr) {
Expand Down Expand Up @@ -88,7 +90,6 @@ class sim_t : public htif_t

friend class processor_t;
friend class mmu_t;
friend class gdbserver_t;

// htif
friend void sim_thread_main(void*);
Expand Down

0 comments on commit d1f2cf3

Please sign in to comment.