Browse Source

Generalize DTC compilation to support both DTS/B

pull/1721/head
abejgonzalez 2 years ago
parent
commit
398101b53f
  1. 87
      riscv/dts.cc
  2. 2
      riscv/dts.h
  3. 3
      riscv/sim.cc

87
riscv/dts.cc

@ -99,86 +99,91 @@ std::string make_dts(size_t insns_per_rtc_tick, size_t cpu_hz,
return s.str();
}
std::string dts_compile(const std::string& dts)
std::string dtc_compile(const std::string& dtc_input, const std::string& input_type, const std::string& output_type)
{
// Convert the DTS to DTB
int dts_pipe[2];
pid_t dts_pid;
if (input_type == output_type)
std::cerr << "Must have differing {in,out}put types for running " DTC << std::endl;
if (!((input_type == "dts" && output_type == "dtb") || (input_type == "dtb" && output_type == "dts")))
std::cerr << "Invalid {in,out}put types for running " DTC ": Must convert from 'dts' to 'dtb' (or vice versa)" << std::endl;
int dtc_input_pipe[2];
pid_t dtc_input_pid;
fflush(NULL); // flush stdout/stderr before forking
if (pipe(dts_pipe) != 0 || (dts_pid = fork()) < 0) {
std::cerr << "Failed to fork dts child: " << strerror(errno) << std::endl;
if (pipe(dtc_input_pipe) != 0 || (dtc_input_pid = fork()) < 0) {
std::cerr << "Failed to fork dtc_input 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();
// Child process to output dtc_input
if (dtc_input_pid == 0) {
close(dtc_input_pipe[0]);
int step, len = dtc_input.length();
const char *buf = dtc_input.c_str();
for (int done = 0; done < len; done += step) {
step = write(dts_pipe[1], buf+done, len-done);
step = write(dtc_input_pipe[1], buf+done, len-done);
if (step == -1) {
std::cerr << "Failed to write dts: " << strerror(errno) << std::endl;
std::cerr << "Failed to write dtc_input: " << strerror(errno) << std::endl;
exit(1);
}
}
close(dts_pipe[1]);
close(dtc_input_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;
pid_t dtc_output_pid;
int dtc_output_pipe[2];
if (pipe(dtc_output_pipe) != 0 || (dtc_output_pid = fork()) < 0) {
std::cerr << "Failed to fork dtc_output 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]);
execlp(DTC, DTC, "-O", "dtb", (char *)0);
// Child process to output dtc_output
if (dtc_output_pid == 0) {
dup2(dtc_input_pipe[0], 0);
dup2(dtc_output_pipe[1], 1);
close(dtc_input_pipe[0]);
close(dtc_input_pipe[1]);
close(dtc_output_pipe[0]);
close(dtc_output_pipe[1]);
execlp(DTC, DTC, "-O", output_type.c_str(), "-I", input_type.c_str(), (char *)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]);
close(dtc_input_pipe[1]);
close(dtc_input_pipe[0]);
close(dtc_output_pipe[1]);
// Read-out dtb
std::stringstream dtb;
// Read-out dtc_output
std::stringstream dtc_output;
int got;
char buf[4096];
while ((got = read(dtb_pipe[0], buf, sizeof(buf))) > 0) {
dtb.write(buf, got);
while ((got = read(dtc_output_pipe[0], buf, sizeof(buf))) > 0) {
dtc_output.write(buf, got);
}
if (got == -1) {
std::cerr << "Failed to read dtb: " << strerror(errno) << std::endl;
std::cerr << "Failed to read dtc_output: " << strerror(errno) << std::endl;
exit(1);
}
close(dtb_pipe[0]);
close(dtc_output_pipe[0]);
// Reap children
int status;
waitpid(dts_pid, &status, 0);
waitpid(dtc_input_pid, &status, 0);
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
std::cerr << "Child dts process failed" << std::endl;
std::cerr << "Child dtc_input process failed" << std::endl;
exit(1);
}
waitpid(dtb_pid, &status, 0);
waitpid(dtc_output_pid, &status, 0);
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
std::cerr << "Child dtb process failed" << std::endl;
std::cerr << "Child dtc_output process failed" << std::endl;
exit(1);
}
return dtb.str();
return dtc_output.str();
}
int fdt_get_node_addr_size(const void *fdt, int node, reg_t *addr,

2
riscv/dts.h

@ -11,7 +11,7 @@ std::string make_dts(size_t insns_per_rtc_tick, size_t cpu_hz,
std::vector<std::pair<reg_t, abstract_mem_t*>> mems,
std::string device_nodes);
std::string dts_compile(const std::string& dts);
std::string dtc_compile(const std::string& dtc_input, const std::string& input_type, const std::string& output_type);
int fdt_get_node_addr_size(const void *fdt, int node, reg_t *addr,
unsigned long *size, const char *field);

3
riscv/sim.cc

@ -133,6 +133,7 @@ sim_t::sim_t(const cfg_t *cfg, bool halted,
std::stringstream strstream;
strstream << fin.rdbuf();
dtb = strstream.str();
dts = dtc_compile(dtb, "dtb", "dts");
} else {
std::pair<reg_t, reg_t> initrd_bounds = cfg->initrd_bounds;
std::string device_nodes;
@ -142,7 +143,7 @@ sim_t::sim_t(const cfg_t *cfg, bool halted,
device_nodes.append(factory->generate_dts(this, sargs));
}
dts = make_dts(INSNS_PER_RTC_TICK, CPU_HZ, cfg, mems, device_nodes);
dtb = dts_compile(dts);
dtb = dtc_compile(dts, "dts", "dtb");
}
int fdt_code = fdt_check_header(dtb.c_str());

Loading…
Cancel
Save