+++ /dev/null
-// See LICENSE for license details.
-
-#include "htif.h"
-#include "sim.h"
-#include "mmu.h"
-#include "encoding.h"
-#include <unistd.h>
-#include <stdexcept>
-#include <stdlib.h>
-#include <errno.h>
-#include <assert.h>
-#include <stddef.h>
-#include <poll.h>
-
-htif_isasim_t::htif_isasim_t(sim_t* _sim, const std::vector<std::string>& args)
- : htif_pthread_t(args), sim(_sim), reset(true), seqno(1)
-{
-}
-
-bool htif_isasim_t::tick()
-{
- if (done())
- return false;
-
- do tick_once(); while (reset);
-
- return true;
-}
-
-void htif_isasim_t::tick_once()
-{
- packet_header_t hdr;
- recv(&hdr, sizeof(hdr));
-
- char buf[hdr.get_packet_size()];
- memcpy(buf, &hdr, sizeof(hdr));
- recv(buf + sizeof(hdr), hdr.get_payload_size());
- packet_t p(buf);
-
- assert(hdr.seqno == seqno);
-
- switch (hdr.cmd)
- {
- case HTIF_CMD_READ_MEM:
- {
- packet_header_t ack(HTIF_CMD_ACK, seqno, hdr.data_size, 0);
- send(&ack, sizeof(ack));
-
- uint64_t buf[hdr.data_size];
- for (size_t i = 0; i < hdr.data_size; i++) {
- reg_t addr = (hdr.addr + i) * HTIF_DATA_ALIGN;
- try {
- buf[i] = sim->debug_mmu->load_uint64(addr);
- } catch (trap_load_access_fault& e) {
- fprintf(stderr, "HTIF: attempt to read from illegal address 0x%" PRIx64 "\n", addr);
- exit(-1);
- }
- }
- send(buf, hdr.data_size * sizeof(buf[0]));
- break;
- }
- case HTIF_CMD_WRITE_MEM:
- {
- const uint64_t* buf = (const uint64_t*)p.get_payload();
- for (size_t i = 0; i < hdr.data_size; i++) {
- reg_t addr = (hdr.addr + i) * HTIF_DATA_ALIGN;
- try {
- sim->debug_mmu->store_uint64(addr, buf[i]);
- } catch (trap_store_access_fault& e) {
- fprintf(stderr, "HTIF: attempt to write to illegal address 0x%" PRIx64 "\n", addr);
- exit(-1);
- }
- }
- packet_header_t ack(HTIF_CMD_ACK, seqno, 0, 0);
- send(&ack, sizeof(ack));
- break;
- }
- case HTIF_CMD_READ_CONTROL_REG:
- case HTIF_CMD_WRITE_CONTROL_REG:
- {
- assert(hdr.data_size == 1);
- reg_t coreid = hdr.addr >> 20;
- reg_t regno = hdr.addr & ((1<<20)-1);
- uint64_t old_val, new_val = 0 /* shut up gcc */;
-
- packet_header_t ack(HTIF_CMD_ACK, seqno, 1, 0);
- send(&ack, sizeof(ack));
-
- processor_t* proc = sim->get_core(coreid);
- bool write = hdr.cmd == HTIF_CMD_WRITE_CONTROL_REG;
- if (write)
- memcpy(&new_val, p.get_payload(), sizeof(new_val));
-
- switch (regno)
- {
- case CSR_MRESET:
- old_val = !proc->running();
- if (write)
- {
- reset = reset & (new_val & 1);
- proc->reset(new_val & 1);
- }
- break;
- default:
- abort();
- }
-
- send(&old_val, sizeof(old_val));
- break;
- }
- default:
- abort();
- }
- seqno++;
-}
-
-bool htif_isasim_t::done()
-{
- if (reset)
- return false;
- return !sim->running();
-}
+++ /dev/null
-// See LICENSE for license details.
-
-#ifndef _HTIF_H
-#define _HTIF_H
-
-#include <fesvr/htif_pthread.h>
-
-class sim_t;
-struct packet;
-
-// this class implements the host-target interface for program loading, etc.
-// a simpler implementation would implement the high-level interface
-// (read/write cr, read/write chunk) directly, but we implement the lower-
-// level serialized interface to be more similar to real target machines.
-
-class htif_isasim_t : public htif_pthread_t
-{
-public:
- htif_isasim_t(sim_t* _sim, const std::vector<std::string>& args);
- bool tick();
- bool done();
-
-private:
- sim_t* sim;
- bool reset;
- uint8_t seqno;
-
- void tick_once();
-};
-
-#endif
#include "disasm.h"
#include "sim.h"
#include "mmu.h"
-#include "htif.h"
#include <sys/mman.h>
#include <termios.h>
#include <map>
funcs["help"] = &sim_t::interactive_help;
funcs["h"] = funcs["help"];
- while (!htif->done())
+ while (!done())
{
std::cerr << ": " << std::flush;
std::string s = readline(2);
size_t steps = args.size() ? atoll(args[0].c_str()) : -1;
ctrlc_pressed = false;
set_procs_debug(noisy);
- for (size_t i = 0; i < steps && !ctrlc_pressed && !htif->done(); i++)
+ for (size_t i = 0; i < steps && !ctrlc_pressed && !done(); i++)
step(1);
}
#include "config.h"
#include "sim.h"
#include "mmu.h"
-#include "htif.h"
#include "disasm.h"
#include "gdbserver.h"
#include <cinttypes>
processor_t::processor_t(const char* isa, sim_t* sim, uint32_t id,
bool halt_on_reset)
: debug(false), sim(sim), ext(NULL), disassembler(new disassembler_t),
- id(id), run(false), halt_on_reset(halt_on_reset)
+ id(id), halt_on_reset(halt_on_reset)
{
parse_isa_string(isa);
mmu = new mmu_t(sim, this);
- reset(true);
+ reset();
register_base_instructions();
}
#endif
}
-void processor_t::reset(bool value)
+void processor_t::reset()
{
- if (run == !value)
- return;
- run = !value;
-
state.reset();
state.dcsr.halt = halt_on_reset;
halt_on_reset = false;
void set_debug(bool value);
void set_histogram(bool value);
- void reset(bool value);
+ void reset();
void step(size_t n); // run for n cycles
- bool running() { return run; }
void set_csr(int which, reg_t val);
void raise_interrupt(reg_t which);
reg_t get_csr(int which);
unsigned xlen;
reg_t isa;
std::string isa_string;
- bool run; // !reset
bool histogram_enabled;
bool halt_on_reset;
riscv_install_prog_srcs = \
riscv_hdrs = \
- htif.h \
common.h \
decode.h \
devices.h \
insn_template.h \
riscv_srcs = \
- htif.cc \
processor.cc \
execute.cc \
sim.cc \
#include "sim.h"
#include "mmu.h"
-#include "htif.h"
#include "gdbserver.h"
#include <map>
#include <iostream>
sim_t::sim_t(const char* isa, size_t nprocs, size_t mem_mb, bool halted,
const std::vector<std::string>& args)
- : htif(new htif_isasim_t(this, args)), procs(std::max(nprocs, size_t(1))),
+ : htif_t(args), procs(std::max(nprocs, size_t(1))),
current_step(0), current_proc(0), debug(false), gdbserver(NULL)
{
signal(SIGINT, &handle_signal);
free(mem);
}
-int sim_t::run()
+void sim_thread_main(void* arg)
+{
+ ((sim_t*)arg)->main();
+}
+
+void sim_t::main()
{
if (!debug && log)
set_procs_debug(true);
- while (htif->tick())
+
+ while (!done())
{
if (debug || ctrlc_pressed)
interactive();
gdbserver->handle();
}
}
- return htif->exit_code();
+}
+
+int sim_t::run()
+{
+ host = context_t::current();
+ target.init(sim_thread_main, this);
+ return htif_t::run();
}
void sim_t::step(size_t n)
rtc->increment(INTERLEAVE / INSNS_PER_RTC_TICK);
}
- htif->tick();
+ host->switch_to();
}
}
}
-bool sim_t::running()
-{
- for (size_t i = 0; i < procs.size(); i++)
- if (procs[i]->running())
- return true;
- return false;
-}
-
void sim_t::set_debug(bool value)
{
debug = value;
boot_rom.reset(new rom_device_t(rom));
bus.add_device(DEFAULT_RSTVEC, boot_rom.get());
}
+
+// htif
+
+void sim_t::idle()
+{
+ target.switch_to();
+}
+
+void sim_t::read_chunk(addr_t taddr, size_t len, void* dst)
+{
+ assert(len == 8);
+ auto data = debug_mmu->load_uint64(taddr);
+ memcpy(dst, &data, sizeof data);
+}
+
+void sim_t::write_chunk(addr_t taddr, size_t len, const void* src)
+{
+ assert(len == 8);
+ uint64_t data;
+ memcpy(&data, src, sizeof data);
+ debug_mmu->store_uint64(taddr, data);
+}
#ifndef _RISCV_SIM_H
#define _RISCV_SIM_H
-#include <vector>
-#include <string>
-#include <memory>
#include "processor.h"
#include "devices.h"
#include "debug_module.h"
+#include <fesvr/htif.h>
+#include <fesvr/context.h>
+#include <vector>
+#include <string>
+#include <memory>
-class htif_isasim_t;
class mmu_t;
class gdbserver_t;
// this class encapsulates the processors and memory in a RISC-V machine.
-class sim_t
+class sim_t : public htif_t
{
public:
sim_t(const char* isa, size_t _nprocs, size_t mem_mb, bool halted,
- const std::vector<std::string>& htif_args);
+ const std::vector<std::string>& args);
~sim_t();
// run the simulation to completion
int run();
- bool running();
void set_debug(bool value);
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; }
- htif_isasim_t* get_htif() { return htif.get(); }
const char* get_config_string() { return config_string.c_str(); }
-
- // returns the number of processors in this simulator
- size_t num_cores() { return procs.size(); }
processor_t* get_core(size_t i) { return procs.at(i); }
private:
- std::unique_ptr<htif_isasim_t> htif;
char* mem; // main memory
size_t memsz; // memory size in bytes
mmu_t* debug_mmu; // debug port into main memory
reg_t get_mem(const std::vector<std::string>& args);
reg_t get_pc(const std::vector<std::string>& args);
- friend class htif_isasim_t;
friend class processor_t;
friend class mmu_t;
friend class gdbserver_t;
+
+ // htif
+ friend void sim_thread_main(void*);
+ void main();
+
+ context_t* host;
+ context_t target;
+ void reset() { }
+ void idle();
+ void read_chunk(addr_t taddr, size_t len, void* dst);
+ void write_chunk(addr_t taddr, size_t len, const void* src);
+ size_t chunk_align() { return 8; }
+ size_t chunk_max_size() { return 8; }
};
extern volatile bool ctrlc_pressed;
#include "sim.h"
#include "mmu.h"
#include "gdbserver.h"
-#include "htif.h"
#include "cachesim.h"
#include "extension.h"
#include <dlfcn.h>