Browse Source

Add xspike program

confprec
Andrew Waterman 13 years ago
parent
commit
a68c33c2a4
  1. 125
      riscv/interactive.cc
  2. 12
      riscv/processor.cc
  3. 2
      riscv/riscv.mk.in
  4. 13
      riscv/sim.cc
  5. 2
      riscv/sim.h
  6. 2
      riscv/spike.cc
  7. 29
      riscv/termios-xspike.cc
  8. 96
      riscv/xspike.cc

125
riscv/interactive.cc

@ -3,6 +3,7 @@
#include "sim.h"
#include "htif.h"
#include <sys/mman.h>
#include <termios.h>
#include <map>
#include <iostream>
#include <climits>
@ -14,65 +15,76 @@
#include <string>
#include <vector>
static std::string readline()
static std::string readline(int fd)
{
struct termios tios;
bool noncanonical = tcgetattr(fd, &tios) == 0 && (tios.c_lflag & ICANON) == 0;
std::string s;
while (1)
for (char ch; read(fd, &ch, 1) == 1; )
{
char ch;
assert(read(1, &ch, 1) == 1);
if (ch == '\x7f')
{
if (s.empty())
continue;
s.erase(s.end()-1);
if (noncanonical && write(fd, "\b \b", 3) != 3)
; // shut up gcc
}
else if (noncanonical && write(fd, &ch, 1) != 1)
; // shut up gcc
assert(write(1, &ch, 1) == 1);
if (ch == '\n')
return s;
break;
if (ch != '\x7f')
s += ch;
}
return s;
}
void sim_t::interactive()
{
std::cout << ": " << std::flush;
std::string s = readline();
std::stringstream ss(s);
std::string cmd, tmp;
std::vector<std::string> args;
if (!(ss >> cmd))
while (true)
{
interactive_run_noisy(std::string("r"), std::vector<std::string>(1,"1"));
return;
}
while (ss >> tmp)
args.push_back(tmp);
typedef void (sim_t::*interactive_func)(const std::string&, const std::vector<std::string>&);
std::map<std::string,interactive_func> funcs;
funcs["r"] = &sim_t::interactive_run_noisy;
funcs["rs"] = &sim_t::interactive_run_silent;
funcs["reg"] = &sim_t::interactive_reg;
funcs["fregs"] = &sim_t::interactive_fregs;
funcs["fregd"] = &sim_t::interactive_fregd;
funcs["mem"] = &sim_t::interactive_mem;
funcs["str"] = &sim_t::interactive_str;
funcs["until"] = &sim_t::interactive_until;
funcs["while"] = &sim_t::interactive_until;
funcs["q"] = &sim_t::interactive_quit;
try
{
if(funcs.count(cmd))
(this->*funcs[cmd])(cmd, args);
std::cerr << ": " << std::flush;
std::string s = readline(2);
std::stringstream ss(s);
std::string cmd, tmp;
std::vector<std::string> args;
if (!(ss >> cmd))
{
step(1, true);
continue;
}
while (ss >> tmp)
args.push_back(tmp);
typedef void (sim_t::*interactive_func)(const std::string&, const std::vector<std::string>&);
std::map<std::string,interactive_func> funcs;
funcs["r"] = &sim_t::interactive_run_noisy;
funcs["rs"] = &sim_t::interactive_run_silent;
funcs["reg"] = &sim_t::interactive_reg;
funcs["fregs"] = &sim_t::interactive_fregs;
funcs["fregd"] = &sim_t::interactive_fregd;
funcs["mem"] = &sim_t::interactive_mem;
funcs["str"] = &sim_t::interactive_str;
funcs["until"] = &sim_t::interactive_until;
funcs["while"] = &sim_t::interactive_until;
funcs["q"] = &sim_t::interactive_quit;
try
{
if(funcs.count(cmd))
(this->*funcs[cmd])(cmd, args);
}
catch(trap_t t) {}
}
catch(trap_t t) {}
ctrlc_pressed = false;
}
void sim_t::interactive_run_noisy(const std::string& cmd, const std::vector<std::string>& args)
@ -88,12 +100,14 @@ void sim_t::interactive_run_silent(const std::string& cmd, const std::vector<std
void sim_t::interactive_run(const std::string& cmd, const std::vector<std::string>& args, bool noisy)
{
size_t steps = args.size() ? atoll(args[0].c_str()) : -1;
step(steps, noisy);
ctrlc_pressed = false;
for (size_t i = 0; i < steps && !ctrlc_pressed; i++)
step(1, noisy);
}
void sim_t::interactive_quit(const std::string& cmd, const std::vector<std::string>& args)
{
stop();
exit(0);
}
reg_t sim_t::get_pc(const std::vector<std::string>& args)
@ -220,10 +234,11 @@ void sim_t::interactive_str(const std::string& cmd, const std::vector<std::strin
void sim_t::interactive_until(const std::string& cmd, const std::vector<std::string>& args)
{
bool cmd_until = cmd == "until";
if(args.size() < 3)
return;
std::string scmd = args[0];
reg_t val = strtol(args[args.size()-1].c_str(),NULL,16);
if(val == LONG_MAX)
val = strtoul(args[args.size()-1].c_str(),NULL,16);
@ -231,21 +246,23 @@ void sim_t::interactive_until(const std::string& cmd, const std::vector<std::str
std::vector<std::string> args2;
args2 = std::vector<std::string>(args.begin()+1,args.end()-1);
auto func = args[0] == "reg" ? &sim_t::get_reg :
args[0] == "pc" ? &sim_t::get_pc :
args[0] == "mem" ? &sim_t::get_mem :
NULL;
if (func == NULL)
return;
ctrlc_pressed = false;
while (1)
{
reg_t current;
if(scmd == "reg")
current = get_reg(args2);
else if(scmd == "pc")
current = get_pc(args2);
else if(scmd == "mem")
current = get_mem(args2);
else
return;
if(cmd == "until" && current == val)
reg_t current = (this->*func)(args2);
if (cmd_until == (current == val))
break;
if(cmd == "while" && current != val)
if (ctrlc_pressed)
break;
step(1, false);

12
riscv/processor.cc

@ -177,11 +177,11 @@ void processor_t::take_trap(reg_t t, bool noisy)
if(noisy)
{
if ((sreg_t)t < 0)
printf("core %3d: interrupt %d, epc 0x%016" PRIx64 "\n",
id, uint8_t(t), pc);
fprintf(stderr, "core %3d: interrupt %d, epc 0x%016" PRIx64 "\n",
id, uint8_t(t), pc);
else
printf("core %3d: trap %s, epc 0x%016" PRIx64 "\n",
id, trap_name(trap_t(t)), pc);
fprintf(stderr, "core %3d: trap %s, epc 0x%016" PRIx64 "\n",
id, trap_name(trap_t(t)), pc);
}
// switch to supervisor, set previous supervisor bit, disable traps
@ -202,8 +202,8 @@ void processor_t::disasm(insn_t insn, reg_t pc)
{
// the disassembler is stateless, so we share it
static disassembler disasm;
printf("core %3d: 0x%016" PRIx64 " (0x%08" PRIx32 ") %s\n",
id, pc, insn.bits, disasm.disassemble(insn).c_str());
fprintf(stderr, "core %3d: 0x%016" PRIx64 " (0x%08" PRIx32 ") %s\n",
id, pc, insn.bits, disasm.disassemble(insn).c_str());
}
void processor_t::set_pcr(int which, reg_t val)

2
riscv/riscv.mk.in

@ -4,6 +4,8 @@ riscv_subproject_deps = \
riscv_install_prog_srcs = \
spike.cc \
xspike.cc \
termios-xspike.cc \
riscv_hdrs = \
htif.h \

13
riscv/sim.cc

@ -7,11 +7,22 @@
#include <climits>
#include <cstdlib>
#include <cassert>
#include <signal.h>
volatile bool ctrlc_pressed = false;
static void handle_signal(int sig)
{
if (ctrlc_pressed)
exit(-1);
ctrlc_pressed = true;
signal(sig, &handle_signal);
}
sim_t::sim_t(size_t _nprocs, size_t mem_mb, const std::vector<std::string>& args)
: htif(new htif_isasim_t(this, args)),
procs(_nprocs), current_step(0), current_proc(0), debug(false)
{
signal(SIGINT, &handle_signal);
// allocate target machine's memory, shrinking it as necessary
// until the allocation succeeds
size_t memsz0 = (size_t)mem_mb << 20;
@ -67,7 +78,7 @@ void sim_t::run()
{
while (!htif->done())
{
if (debug)
if (debug || ctrlc_pressed)
interactive();
else
step(INTERLEAVE, false);

2
riscv/sim.h

@ -70,4 +70,6 @@ private:
friend class htif_isasim_t;
};
extern volatile bool ctrlc_pressed;
#endif

2
riscv/spike.cc

@ -19,7 +19,6 @@ static void help()
fprintf(stderr, " -m <n> Provide <n> MB of target memory\n");
fprintf(stderr, " -d Interactive debug mode\n");
fprintf(stderr, " -h Print this help message\n");
fprintf(stderr, " -h Print this help message\n");
fprintf(stderr, " --ic=<S>:<W>:<B> Instantiate a cache model with S sets,\n");
fprintf(stderr, " --dc=<S>:<W>:<B> W ways, and B-byte blocks (with S and\n");
fprintf(stderr, " --l2=<S>:<W>:<B> B both powers of 2).\n");
@ -37,6 +36,7 @@ int main(int argc, char** argv)
option_parser_t parser;
parser.help(&help);
parser.option('h', 0, 0, [&](const char* s){help();});
parser.option('d', 0, 0, [&](const char* s){debug = true;});
parser.option('p', 0, 1, [&](const char* s){nprocs = atoi(s);});
parser.option('m', 0, 1, [&](const char* s){mem_mb = atoi(s);});

29
riscv/termios-xspike.cc

@ -0,0 +1,29 @@
// See LICENSE for license details.
// termios-xspike sets up a canonical terminal and blocks forever.
// It allows us to send Ctrl-C etc. to the target machine.
#include <unistd.h>
#include <termios.h>
#include <signal.h>
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
int main()
{
struct termios old_tios;
if (tcgetattr(0, &old_tios) < 0)
return -1;
signal(SIGTERM, [](int) { });
struct termios new_tios = old_tios;
new_tios.c_lflag &= ~(ICANON | ECHO | ISIG);
if (tcsetattr(0, TCSANOW, &new_tios) < 0)
return -1;
pause();
return tcsetattr(0, TCSANOW, &old_tios);
}

96
riscv/xspike.cc

@ -0,0 +1,96 @@
// See LICENSE for license details.
// xspike forks an xterm for spike's target machine console,
// preserving the current terminal for debugging.
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/wait.h>
#include <cstdio>
#include <climits>
#include <cstring>
#include <stdexcept>
static pid_t fork_spike(int tty_fd, int argc, char** argv);
static pid_t fork_xterm(int* tty_fd);
int main(int argc, char** argv)
{
int tty_fd, wait_status, ret = -1;
pid_t xterm, spike;
static bool signal_exit = false;
auto handle_signal = [](int) { signal_exit = true; };
signal(SIGINT, handle_signal);
if ((xterm = fork_xterm(&tty_fd)) < 0)
{
fprintf(stderr, "could not open xterm\n");
goto out;
}
if ((spike = fork_spike(tty_fd, argc, argv)) < 0)
{
fprintf(stderr, "could not open spike\n");
goto close_xterm;
}
while (waitpid(spike, &wait_status, 0) < 0 && !signal_exit)
;
ret = !signal_exit && WIFEXITED(wait_status) ? WEXITSTATUS(wait_status) : -1;
close_xterm:
kill(-xterm, SIGTERM);
out:
return ret;
}
static pid_t fork_spike(int tty_fd, int argc, char** argv)
{
pid_t pid = fork();
if (pid < 0)
return -1;
if (pid == 0)
{
if (dup2(tty_fd, STDIN_FILENO) < 0 || dup2(tty_fd, STDOUT_FILENO) < 0)
return -1;
execvp("spike", argv);
return -1;
}
return pid;
}
static pid_t fork_xterm(int* tty_fd)
{
static const char cmd[] = "3>&1 xterm -title xspike -e sh -c 'tty 1>&3; termios-xspike'";
int fds[2];
if (pipe(fds) < 0)
return -1;
pid_t pid = fork();
if (pid < 0)
return -1;
if (pid == 0)
{
setpgid(0, 0);
if (dup2(fds[1], STDOUT_FILENO) < 0)
return -1;
execl("/bin/sh", "sh", "-c", cmd, NULL);
return -1;
}
char tty[NAME_MAX];
ssize_t ttylen = read(fds[0], tty, sizeof(tty));
if (ttylen <= 1 || tty[ttylen-1] != '\n')
return -1;
tty[ttylen-1] = '\0';
if ((*tty_fd = open(tty, O_RDWR)) < 0)
return -1;
return pid;
}
Loading…
Cancel
Save