aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Newsome <tim@sifive.com>2017-10-03 14:21:27 -0700
committerTim Newsome <tim@sifive.com>2017-10-03 15:38:31 -0700
commit1b11d579eab1eff6248dfc41416c6a5aeca34e39 (patch)
treea97ced3704eb5f7a43058875599079c7570d7e4b
parente94c809ce4fa46dd0d58e0dfb426f0bce08553b2 (diff)
downloadriscv-openocd-1b11d579eab1eff6248dfc41416c6a5aeca34e39.zip
riscv-openocd-1b11d579eab1eff6248dfc41416c6a5aeca34e39.tar.gz
riscv-openocd-1b11d579eab1eff6248dfc41416c6a5aeca34e39.tar.bz2
Add read buffer to bitbang, improving performance.
This reduces the time for one testcase where OpenOCD connects to a simulator from 12.30s to 5.35s! Running all our tests went from 13m13s to 3m55s. Change-Id: I7dc774e1e0f5752905ac4318fd9b85b930374a05
-rw-r--r--src/jtag/drivers/bitbang.c21
-rw-r--r--src/jtag/drivers/bitbang.h14
-rw-r--r--src/jtag/drivers/remote_bitbang.c100
3 files changed, 111 insertions, 24 deletions
diff --git a/src/jtag/drivers/bitbang.c b/src/jtag/drivers/bitbang.c
index c9ec9c9..bde48e0 100644
--- a/src/jtag/drivers/bitbang.c
+++ b/src/jtag/drivers/bitbang.c
@@ -203,7 +203,6 @@ static void bitbang_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int
}
for (bit_cnt = 0; bit_cnt < scan_size; bit_cnt++) {
- int val = 0;
int tms = (bit_cnt == scan_size-1) ? 1 : 0;
int tdi;
int bytec = bit_cnt/8;
@@ -219,12 +218,26 @@ static void bitbang_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int
bitbang_interface->write(0, tms, tdi);
- if (type != SCAN_OUT)
- val = bitbang_interface->read();
+ if (type != SCAN_OUT) {
+ if (bitbang_interface->sample) {
+ bitbang_interface->sample();
+ } else {
+ int val = bitbang_interface->read();
+ if (val)
+ buffer[bytec] |= bcval;
+ else
+ buffer[bytec] &= ~bcval;
+ }
+ }
bitbang_interface->write(1, tms, tdi);
+ }
- if (type != SCAN_OUT) {
+ if (type != SCAN_OUT && bitbang_interface->sample) {
+ for (bit_cnt = 0; bit_cnt < scan_size; bit_cnt++) {
+ int bytec = bit_cnt/8;
+ int bcval = 1 << (bit_cnt % 8);
+ int val = bitbang_interface->read_sample();
if (val)
buffer[bytec] |= bcval;
else
diff --git a/src/jtag/drivers/bitbang.h b/src/jtag/drivers/bitbang.h
index c5b44bf..563ea10 100644
--- a/src/jtag/drivers/bitbang.h
+++ b/src/jtag/drivers/bitbang.h
@@ -27,7 +27,21 @@
struct bitbang_interface {
/* low level callbacks (for bitbang)
*/
+
+ /* Either read() or sample()/read_sample() must be implemented. */
+
+ /* Sample TDO and return 0 or 1. */
int (*read)(void);
+
+ /* The sample functions allow an interface to batch a number of writes and
+ * sample requests together. Not waiting for a value to come back can
+ * greatly increase throughput. */
+ /* Sample TDO and put the result in a buffer. */
+ void (*sample)(void);
+ /* Return the next unread value from the buffer. */
+ int (*read_sample)(void);
+
+ /* Set TCK, TMS, and TDI to the given values. */
void (*write)(int tck, int tms, int tdi);
void (*reset)(int trst, int srst);
void (*blink)(int on);
diff --git a/src/jtag/drivers/remote_bitbang.c b/src/jtag/drivers/remote_bitbang.c
index b898e95..3907a07 100644
--- a/src/jtag/drivers/remote_bitbang.c
+++ b/src/jtag/drivers/remote_bitbang.c
@@ -40,11 +40,44 @@
static char *remote_bitbang_host;
static char *remote_bitbang_port;
-FILE *remote_bitbang_in;
-FILE *remote_bitbang_out;
+static FILE *remote_bitbang_in;
+static FILE *remote_bitbang_out;
+static int remote_bitbang_fd;
+
+static char remote_bitbang_buf[64];
+static unsigned remote_bitbang_start;
+static unsigned remote_bitbang_end;
+
+/* Read any incoming data, placing it into the buffer. */
+static void remote_bitbang_fill_buf(void)
+{
+ fcntl(remote_bitbang_fd, F_SETFL, O_NONBLOCK);
+ while (1) {
+ ssize_t count = read(remote_bitbang_fd,
+ remote_bitbang_buf + remote_bitbang_end,
+ sizeof(remote_bitbang_buf) - remote_bitbang_end);
+ if (count > 0) {
+ remote_bitbang_end += count;
+ // TODO: check for overflow.
+ if (remote_bitbang_end == sizeof(remote_bitbang_buf)) {
+ remote_bitbang_end = 0;
+ }
+ } else if (count == 0) {
+ return;
+ } else if (count < 0) {
+ if (errno == EAGAIN) {
+ return;
+ } else {
+ REMOTE_BITBANG_RAISE_ERROR("remote_bitbang_fill_buf: %s (%d)",
+ strerror(errno), errno);
+ }
+ }
+ }
+}
static void remote_bitbang_putc(int c)
{
+ remote_bitbang_fill_buf();
if (EOF == fputc(c, remote_bitbang_out))
REMOTE_BITBANG_RAISE_ERROR("remote_bitbang_putc: %s", strerror(errno));
}
@@ -75,15 +108,8 @@ static int remote_bitbang_quit(void)
return ERROR_OK;
}
-/* Get the next read response. */
-static int remote_bitbang_rread(void)
+static int char_to_int(int c)
{
- if (EOF == fflush(remote_bitbang_out)) {
- remote_bitbang_quit();
- REMOTE_BITBANG_RAISE_ERROR("fflush: %s", strerror(errno));
- }
-
- int c = fgetc(remote_bitbang_in);
switch (c) {
case '0':
return 0;
@@ -96,9 +122,40 @@ static int remote_bitbang_rread(void)
}
}
-static int remote_bitbang_read(void)
+/* Get the next read response. */
+static int remote_bitbang_rread(void)
+{
+ if (EOF == fflush(remote_bitbang_out)) {
+ remote_bitbang_quit();
+ REMOTE_BITBANG_RAISE_ERROR("fflush: %s", strerror(errno));
+ }
+
+ /* Enable blocking access. */
+ fcntl(remote_bitbang_fd, F_SETFL, 0);
+ char c;
+ ssize_t count = read(remote_bitbang_fd, &c, 1);
+ if (count == 1) {
+ return char_to_int(c);
+ } else {
+ remote_bitbang_quit();
+ REMOTE_BITBANG_RAISE_ERROR("read: count=%d, error=%s", (int) count,
+ strerror(errno));
+ }
+}
+
+static void remote_bitbang_sample(void)
{
remote_bitbang_putc('R');
+}
+
+static int remote_bitbang_read_sample(void)
+{
+ if (remote_bitbang_start != remote_bitbang_end) {
+ int c = remote_bitbang_buf[remote_bitbang_start];
+ remote_bitbang_start =
+ (remote_bitbang_start + 1) % sizeof(remote_bitbang_buf);
+ return char_to_int(c);
+ }
return remote_bitbang_rread();
}
@@ -121,7 +178,8 @@ static void remote_bitbang_blink(int on)
}
static struct bitbang_interface remote_bitbang_bitbang = {
- .read = &remote_bitbang_read,
+ .sample = &remote_bitbang_sample,
+ .read_sample = &remote_bitbang_read_sample,
.write = &remote_bitbang_write,
.reset = &remote_bitbang_reset,
.blink = &remote_bitbang_blink,
@@ -199,26 +257,28 @@ static int remote_bitbang_init_unix(void)
static int remote_bitbang_init(void)
{
- int fd;
bitbang_interface = &remote_bitbang_bitbang;
+ remote_bitbang_start = 0;
+ remote_bitbang_end = 0;
+
LOG_INFO("Initializing remote_bitbang driver");
if (remote_bitbang_port == NULL)
- fd = remote_bitbang_init_unix();
+ remote_bitbang_fd = remote_bitbang_init_unix();
else
- fd = remote_bitbang_init_tcp();
+ remote_bitbang_fd = remote_bitbang_init_tcp();
- if (fd < 0)
- return fd;
+ if (remote_bitbang_fd < 0)
+ return remote_bitbang_fd;
- remote_bitbang_in = fdopen(fd, "r");
+ remote_bitbang_in = fdopen(remote_bitbang_fd, "r");
if (remote_bitbang_in == NULL) {
LOG_ERROR("fdopen: failed to open read stream");
- close(fd);
+ close(remote_bitbang_fd);
return ERROR_FAIL;
}
- remote_bitbang_out = fdopen(fd, "w");
+ remote_bitbang_out = fdopen(remote_bitbang_fd, "w");
if (remote_bitbang_out == NULL) {
LOG_ERROR("fdopen: failed to open write stream");
fclose(remote_bitbang_in);