aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Waterman <andrew@sifive.com>2023-01-11 15:38:00 -0800
committerAndrew Waterman <andrew@sifive.com>2023-01-11 16:40:28 -0800
commit2cb5cf5d66d5df8f310a335032d836ad5f0dc977 (patch)
tree124dc4a6bdf9d306beaf8b29962c2798cd91b6a5
parenta4d62fd274ae64cb06cff2d97789c29a3c2e0da4 (diff)
downloadspike-tmp.zip
spike-tmp.tar.gz
spike-tmp.tar.bz2
For NS16550 UART, poll stdin less oftentmp
On my Mac Mini, calling `poll()` on stdin takes around 10 us, and we are invoking it every 20 us or so. Reduce the frequency of polling by 16x when not actively receiving data, thereby reducing the fraction of time spent in `poll()` to a trivial amount.
-rw-r--r--riscv/devices.h3
-rw-r--r--riscv/ns16550.cc10
2 files changed, 12 insertions, 1 deletions
diff --git a/riscv/devices.h b/riscv/devices.h
index 0030da8..040fe3e 100644
--- a/riscv/devices.h
+++ b/riscv/devices.h
@@ -148,6 +148,9 @@ class ns16550_t : public abstract_device_t {
void update_interrupt(void);
uint8_t rx_byte(void);
void tx_byte(uint8_t val);
+
+ int backoff_counter;
+ static const int MAX_BACKOFF = 16;
};
class mmio_plugin_device_t : public abstract_device_t {
diff --git a/riscv/ns16550.cc b/riscv/ns16550.cc
index 7bc1d20..8d7e4de 100644
--- a/riscv/ns16550.cc
+++ b/riscv/ns16550.cc
@@ -71,7 +71,7 @@
ns16550_t::ns16550_t(class bus_t *bus, abstract_interrupt_controller_t *intctrl,
uint32_t interrupt_id, uint32_t reg_shift, uint32_t reg_io_width)
- : bus(bus), intctrl(intctrl), interrupt_id(interrupt_id), reg_shift(reg_shift), reg_io_width(reg_io_width)
+ : bus(bus), intctrl(intctrl), interrupt_id(interrupt_id), reg_shift(reg_shift), reg_io_width(reg_io_width), backoff_counter(0)
{
ier = 0;
iir = UART_IIR_NO_INT;
@@ -300,11 +300,19 @@ void ns16550_t::tick(void)
return;
}
+ if (backoff_counter > 0 && backoff_counter < MAX_BACKOFF) {
+ backoff_counter++;
+ return;
+ }
+
int rc = canonical_terminal_t::read();
if (rc < 0) {
+ backoff_counter = 1;
return;
}
+ backoff_counter = 0;
+
rx_queue.push((uint8_t)rc);
lsr |= UART_LSR_DR;
update_interrupt();