From 3caf790c80a9ee5f1fe14bc61c99b4a872617895 Mon Sep 17 00:00:00 2001 From: Alexander Romanov Date: Sun, 12 Apr 2026 23:10:48 +0000 Subject: [PATCH] feat: make chunk_max_size non-virtual This allows to completely eliminate virtual call overhead for functions that usually return a constant number --- fesvr/dtm.cc | 17 +++++------------ fesvr/dtm.h | 2 -- fesvr/htif.cc | 14 +++++++------- fesvr/htif.h | 9 +++------ fesvr/htif_hexwriter.cc | 9 ++------- fesvr/htif_hexwriter.h | 6 ++---- fesvr/htif_pthread.cc | 2 +- fesvr/htif_pthread.h | 3 --- fesvr/memif.cc | 10 +++++----- fesvr/memif.h | 8 ++++++-- fesvr/tsi.cc | 6 +----- fesvr/tsi.h | 4 ---- riscv/sim.cc | 2 +- riscv/sim.h | 2 -- 14 files changed, 33 insertions(+), 61 deletions(-) diff --git a/fesvr/dtm.cc b/fesvr/dtm.cc index a0c3254d..98b72a3b 100644 --- a/fesvr/dtm.cc +++ b/fesvr/dtm.cc @@ -213,11 +213,6 @@ uint32_t dtm_t::run_abstract_command(uint32_t command, } -size_t dtm_t::chunk_align() -{ - return xlen / 8; -} - void dtm_t::read_chunk(uint64_t taddr, size_t len, void* dst) { uint32_t prog[MAX_PROG_WORDS]; @@ -468,12 +463,6 @@ uint64_t dtm_t::modify_csr(unsigned which, uint64_t data, uint32_t type) return res; } -size_t dtm_t::chunk_max_size() -{ - // Arbitrary choice. 4k Page size seems reasonable. - return 4096; -} - uint32_t dtm_t::get_xlen() { // Attempt to read S0 to find out what size it is. @@ -601,9 +590,13 @@ void dtm_t::start_host_thread() } dtm_t::dtm_t(int argc, char** argv) - : htif_t(argc, argv), running(false) + // Arbitrary choice. 4k Page size seems reasonable. + : htif_t(argc, argv, /*chunk_max_size=*/4096, /*chunk_align=*/8), running(false) { start_host_thread(); + // Here we reset chunk_align because we can't call get_xlen in the + // base class constructor + chunk_align = get_xlen() / 8; } dtm_t::~dtm_t() diff --git a/fesvr/dtm.h b/fesvr/dtm.h index 03c2f793..d6d4e0eb 100644 --- a/fesvr/dtm.h +++ b/fesvr/dtm.h @@ -65,8 +65,6 @@ class dtm_t : public htif_t virtual void read_chunk(addr_t taddr, size_t len, void* dst) override; virtual void write_chunk(addr_t taddr, size_t len, const void* src) override; virtual void clear_chunk(addr_t taddr, size_t len) override; - virtual size_t chunk_align() override; - virtual size_t chunk_max_size() override; virtual void reset() override; virtual void idle() override; diff --git a/fesvr/htif.cc b/fesvr/htif.cc index 267bb498..a711e6a5 100644 --- a/fesvr/htif.cc +++ b/fesvr/htif.cc @@ -53,8 +53,8 @@ static void handle_signal(int sig) signal(sig, &handle_signal); } -htif_t::htif_t() - : mem(this), entry(DRAM_BASE), sig_addr(0), sig_len(0), +htif_t::htif_t(size_t chunk_max_sz, size_t chunk_al) + : chunked_memif_t(chunk_max_sz, chunk_al), mem(this), entry(DRAM_BASE), sig_addr(0), sig_len(0), tohost_addr(0), fromhost_addr(0), stopped(false), syscall_proxy(this) { @@ -63,7 +63,7 @@ htif_t::htif_t() signal(SIGABRT, &handle_signal); // we still want to call static destructors } -htif_t::htif_t(int argc, char** argv) : htif_t() +htif_t::htif_t(int argc, char** argv, size_t chunk_max_sz, size_t chunk_al) : htif_t(chunk_max_sz, chunk_al) { //Set line size as 16 by default. line_size = 16; @@ -71,7 +71,7 @@ htif_t::htif_t(int argc, char** argv) : htif_t() register_devices(); } -htif_t::htif_t(const std::vector& args) : htif_t() +htif_t::htif_t(const std::vector& args, size_t chunk_max_sz, size_t chunk_al) : htif_t(chunk_max_sz, chunk_al) { int argc = args.size() + 1; std::vectorargv(argc); @@ -275,10 +275,10 @@ void htif_t::stop() void htif_t::clear_chunk(addr_t taddr, size_t len) { - std::vector zeros(chunk_max_size(), 0); + std::vector zeros(get_chunk_max_size(), 0); - for (size_t pos = 0; pos < len; pos += chunk_max_size()) - write_chunk(taddr + pos, std::min(len - pos, chunk_max_size()), &zeros[0]); + for (size_t pos = 0; pos < len; pos += get_chunk_max_size()) + write_chunk(taddr + pos, std::min(len - pos, get_chunk_max_size()), &zeros[0]); } int htif_t::run() diff --git a/fesvr/htif.h b/fesvr/htif.h index 380e24af..621c63d0 100644 --- a/fesvr/htif.h +++ b/fesvr/htif.h @@ -16,9 +16,9 @@ class htif_t : public chunked_memif_t { public: - htif_t(); - htif_t(int argc, char** argv); - htif_t(const std::vector& args); + htif_t(size_t chunk_max_sz, size_t chunk_al); + htif_t(int argc, char** argv, size_t chunk_max_sz, size_t chunk_al); + htif_t(const std::vector& argsm, size_t chunk_max_sz, size_t chunk_al); virtual ~htif_t(); virtual void start(); @@ -59,9 +59,6 @@ class htif_t : public chunked_memif_t virtual void write_chunk(addr_t taddr, size_t len, const void* src) = 0; virtual void clear_chunk(addr_t taddr, size_t len); - virtual size_t chunk_align() = 0; - virtual size_t chunk_max_size() = 0; - virtual std::map load_payload(const std::string& payload, reg_t* entry, reg_t load_addr); virtual void load_program(); diff --git a/fesvr/htif_hexwriter.cc b/fesvr/htif_hexwriter.cc index e4811b3b..d1a6bb4d 100644 --- a/fesvr/htif_hexwriter.cc +++ b/fesvr/htif_hexwriter.cc @@ -4,16 +4,11 @@ #include #include "htif_hexwriter.h" -htif_hexwriter_t::htif_hexwriter_t(size_t b, size_t w, size_t d) - : base(b), width(w), depth(d) -{ -} - void htif_hexwriter_t::read_chunk(addr_t taddr, size_t len, void* vdst) { taddr -= base; - assert(len % chunk_align() == 0); + assert(len % get_chunk_align() == 0); assert(taddr < width*depth); assert(taddr+len <= width*depth); @@ -36,7 +31,7 @@ void htif_hexwriter_t::write_chunk(addr_t taddr, size_t len, const void* vsrc) { taddr -= base; - assert(len % chunk_align() == 0); + assert(len % get_chunk_align() == 0); assert(taddr < width*depth); assert(taddr+len <= width*depth); diff --git a/fesvr/htif_hexwriter.h b/fesvr/htif_hexwriter.h index 0cd859b1..81519be8 100644 --- a/fesvr/htif_hexwriter.h +++ b/fesvr/htif_hexwriter.h @@ -11,7 +11,8 @@ class htif_hexwriter_t : public chunked_memif_t { public: - htif_hexwriter_t(size_t b, size_t w, size_t d); + htif_hexwriter_t(size_t b, size_t w, size_t d) + : chunked_memif_t(w, w), base(b), width(w), depth(d) {} protected: size_t base; @@ -23,9 +24,6 @@ protected: void write_chunk(addr_t taddr, size_t len, const void* src); void clear_chunk(addr_t, size_t) {} - size_t chunk_max_size() { return width; } - size_t chunk_align() { return width; } - friend std::ostream& operator<< (std::ostream&, const htif_hexwriter_t&); }; diff --git a/fesvr/htif_pthread.cc b/fesvr/htif_pthread.cc index b9e3832b..98da35a6 100644 --- a/fesvr/htif_pthread.cc +++ b/fesvr/htif_pthread.cc @@ -13,7 +13,7 @@ void htif_pthread_t::thread_main(void* arg) } htif_pthread_t::htif_pthread_t(int argc, char** argv) - : htif_t(argc, argv) + : htif_t(argc, argv, /*max_sz=*/1024, /*chunk_align=*/64) { target = context_t::current(); host.init(thread_main, this); diff --git a/fesvr/htif_pthread.h b/fesvr/htif_pthread.h index ab560072..77996971 100644 --- a/fesvr/htif_pthread.h +++ b/fesvr/htif_pthread.h @@ -23,9 +23,6 @@ class htif_pthread_t : public htif_t virtual ssize_t read(void* buf, size_t max_size); virtual ssize_t write(const void* buf, size_t size); - virtual size_t chunk_align() { return 64; } - virtual size_t chunk_max_size() { return 1024; } - private: context_t host; context_t* target; diff --git a/fesvr/memif.cc b/fesvr/memif.cc index 59938b91..0fc252a3 100644 --- a/fesvr/memif.cc +++ b/fesvr/memif.cc @@ -8,7 +8,7 @@ void memif_t::read(addr_t addr, size_t len, void* bytes) { - size_t align = cmemif->chunk_align(); + size_t align = cmemif->get_chunk_align(); if (len && (addr & (align-1))) { size_t this_len = std::min(len, align - size_t(addr & (align-1))); @@ -35,13 +35,13 @@ void memif_t::read(addr_t addr, size_t len, void* bytes) } // now we're aligned - for (size_t pos = 0; pos < len; pos += cmemif->chunk_max_size()) - cmemif->read_chunk(addr + pos, std::min(cmemif->chunk_max_size(), len - pos), (char*)bytes + pos); + for (size_t pos = 0; pos < len; pos += cmemif->get_chunk_max_size()) + cmemif->read_chunk(addr + pos, std::min(cmemif->get_chunk_max_size(), len - pos), (char*)bytes + pos); } void memif_t::write(addr_t addr, size_t len, const void* bytes) { - size_t align = cmemif->chunk_align(); + size_t align = cmemif->get_chunk_align(); if (len && (addr & (align-1))) { size_t this_len = std::min(len, align - size_t(addr & (align-1))); @@ -77,7 +77,7 @@ void memif_t::write(addr_t addr, size_t len, const void* bytes) if (all_zero) { cmemif->clear_chunk(addr, len); } else { - size_t max_chunk = cmemif->chunk_max_size(); + size_t max_chunk = cmemif->get_chunk_max_size(); for (size_t pos = 0; pos < len; pos += max_chunk) cmemif->write_chunk(addr + pos, std::min(max_chunk, len - pos), (char*)bytes + pos); } diff --git a/fesvr/memif.h b/fesvr/memif.h index ebed3d72..8334a896 100644 --- a/fesvr/memif.h +++ b/fesvr/memif.h @@ -15,13 +15,17 @@ typedef reg_t addr_t; class chunked_memif_t { + size_t chunk_max_size = 0; +protected: + size_t chunk_align = 0; + chunked_memif_t(size_t chunk_max_sz, size_t chunk_al) : chunk_max_size(chunk_max_sz), chunk_align(chunk_al) {} public: virtual void read_chunk(addr_t taddr, size_t len, void* dst) = 0; virtual void write_chunk(addr_t taddr, size_t len, const void* src) = 0; virtual void clear_chunk(addr_t taddr, size_t len) = 0; - virtual size_t chunk_align() = 0; - virtual size_t chunk_max_size() = 0; + size_t get_chunk_max_size() const {return chunk_max_size;} + size_t get_chunk_align() const {return chunk_align;} virtual endianness_t get_target_endianness() const { return endianness_little; diff --git a/fesvr/tsi.cc b/fesvr/tsi.cc index 5ccafc4b..3fd36e57 100644 --- a/fesvr/tsi.cc +++ b/fesvr/tsi.cc @@ -13,16 +13,12 @@ void tsi_t::host_thread(void *arg) tsi->target->switch_to(); } -tsi_t::tsi_t(int argc, char** argv) : htif_t(argc, argv) +tsi_t::tsi_t(int argc, char** argv) : htif_t(argc, argv, /*chunk_max_size=*/1024, /*chunk_align=*/4) { target = context_t::current(); host.init(host_thread, this); } -tsi_t::~tsi_t(void) -{ -} - #define MSIP_BASE 0x2000000 // Interrupt core 0 to make it start executing the program in DRAM diff --git a/fesvr/tsi.h b/fesvr/tsi.h index fe60fcc3..4d0b614c 100644 --- a/fesvr/tsi.h +++ b/fesvr/tsi.h @@ -19,7 +19,6 @@ class tsi_t : public htif_t { public: tsi_t(int argc, char** argv); - virtual ~tsi_t(); bool data_available(); void send_word(uint32_t word); @@ -37,9 +36,6 @@ class tsi_t : public htif_t void write_chunk(addr_t taddr, size_t nbytes, const void* src) override; void switch_to_target(); - size_t chunk_align() override { return 4; } - size_t chunk_max_size() override { return 1024; } - int get_ipi_addrs(addr_t *addrs); private: diff --git a/riscv/sim.cc b/riscv/sim.cc index ca20cbf8..ba57009c 100644 --- a/riscv/sim.cc +++ b/riscv/sim.cc @@ -48,7 +48,7 @@ sim_t::sim_t(const cfg_t *cfg, bool halted, bool socket_enabled, FILE *cmd_file, // needed for command line option --cmd std::optional instruction_limit) - : htif_t(args), + : htif_t(args, /*chunk_max_size=*/8, /*chunk_align=*/8), cfg(cfg), mems(mems), dtb_discovery(dtb_discovery), diff --git a/riscv/sim.h b/riscv/sim.h index fd2f993f..a496a494 100644 --- a/riscv/sim.h +++ b/riscv/sim.h @@ -158,8 +158,6 @@ private: virtual void idle() override; virtual void read_chunk(addr_t taddr, size_t len, void* dst) override; virtual void write_chunk(addr_t taddr, size_t len, const void* src) override; - virtual size_t chunk_align() override { return 8; } - virtual size_t chunk_max_size() override { return 8; } virtual endianness_t get_target_endianness() const override; public: