diff options
-rw-r--r-- | riscv/sim.cc | 88 |
1 files changed, 87 insertions, 1 deletions
diff --git a/riscv/sim.cc b/riscv/sim.cc index 49b0336..004ccaa 100644 --- a/riscv/sim.cc +++ b/riscv/sim.cc @@ -10,6 +10,9 @@ #include <cstdlib> #include <cassert> #include <signal.h> +#include <unistd.h> +#include <sys/wait.h> +#include <sys/types.h> volatile bool ctrlc_pressed = false; static void handle_signal(int sig) @@ -150,6 +153,87 @@ bool sim_t::mmio_store(reg_t addr, size_t len, const uint8_t* bytes) return bus.store(addr, len, bytes); } +static std::string dts_compile(const std::string& dts) +{ + // Convert the DTS to DTB + int dts_pipe[2]; + pid_t dts_pid; + + if (pipe(dts_pipe) != 0 || (dts_pid = fork()) < 0) { + std::cerr << "Failed to fork dts child: " << strerror(errno) << std::endl; + exit(1); + } + + // Child process to output dts + if (dts_pid == 0) { + close(dts_pipe[0]); + int step, len = dts.length(); + const char *buf = dts.c_str(); + for (int done = 0; done < len; done += step) { + step = write(dts_pipe[1], buf+done, len-done); + if (step == -1) { + std::cerr << "Failed to write dts: " << strerror(errno) << std::endl; + exit(1); + } + } + close(dts_pipe[1]); + exit(0); + } + + pid_t dtb_pid; + int dtb_pipe[2]; + if (pipe(dtb_pipe) != 0 || (dtb_pid = fork()) < 0) { + std::cerr << "Failed to fork dtb child: " << strerror(errno) << std::endl; + exit(1); + } + + // Child process to output dtb + if (dtb_pid == 0) { + dup2(dts_pipe[0], 0); + dup2(dtb_pipe[1], 1); + close(dts_pipe[0]); + close(dts_pipe[1]); + close(dtb_pipe[0]); + close(dtb_pipe[1]); + execl(DTC, DTC, "-O", "dtb", 0); + std::cerr << "Failed to run " DTC ": " << strerror(errno) << std::endl; + exit(1); + } + + close(dts_pipe[1]); + close(dts_pipe[0]); + close(dtb_pipe[1]); + + // Read-out dtb + std::stringstream dtb; + + int got; + char buf[4096]; + while ((got = read(dtb_pipe[0], buf, sizeof(buf))) > 0) { + dtb.write(buf, got); + } + if (got == -1) { + std::cerr << "Failed to read dtb: " << strerror(errno) << std::endl; + exit(1); + } + close(dtb_pipe[0]); + + // Reap children + int status; + waitpid(dts_pid, &status, 0); + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { + std::cerr << "Child dts process failed" << std::endl; + exit(1); + } + waitpid(dtb_pid, &status, 0); + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { + std::cerr << "Child dtb process failed" << std::endl; + exit(1); + } + + return dtb.str(); +} + void sim_t::make_config_string() { reg_t rtc_addr = EXT_IO_BASE; @@ -220,7 +304,9 @@ void sim_t::make_config_string() "};\n"; config_string = s.str(); - rom.insert(rom.end(), config_string.begin(), config_string.end()); + std::string dtb = dts_compile(config_string); + + rom.insert(rom.end(), dtb.begin(), dtb.end()); rom.resize((rom.size() / align + 1) * align); boot_rom.reset(new rom_device_t(rom)); |