X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=riscv%2Finteractive.cc;h=dbcd22455d5fe6fdb75388946df176d7227ca6df;hb=a91d9f7d89abd6cda6fafb7b5e7cacf4b3590c29;hp=4f7891f1bd924035881eee38ce2d1aec3c5c981c;hpb=77452a26e7d95d29dbaa797595ae683f03a3345b;p=riscv-isa-sim.git diff --git a/riscv/interactive.cc b/riscv/interactive.cc index 4f7891f..dbcd224 100644 --- a/riscv/interactive.cc +++ b/riscv/interactive.cc @@ -1,52 +1,141 @@ +// See LICENSE for license details. + +#include "decode.h" +#include "disasm.h" #include "sim.h" -#include "htif.h" +#include "mmu.h" #include +#include #include #include #include +#include #include +#include +#include +#include +#include +#include +#include +#include -void sim_t::interactive() +DECLARE_TRAP(-1, interactive) + +processor_t *sim_t::get_core(const std::string& i) +{ + char *ptr; + unsigned long p = strtoul(i.c_str(), &ptr, 10); + if (*ptr || p >= procs.size()) + throw trap_interactive(); + return get_core(p); +} + +static std::string readline(int fd) { - putchar(':'); - char s[128]; - std::cin.getline(s,sizeof(s)-1); + struct termios tios; + bool noncanonical = tcgetattr(fd, &tios) == 0 && (tios.c_lflag & ICANON) == 0; - char* p = strtok(s," "); - if(!p) + std::string s; + for (char ch; read(fd, &ch, 1) == 1; ) { - interactive_run_noisy(std::string("r"), std::vector(1,"1")); - return; + 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 + + if (ch == '\n') + break; + if (ch != '\x7f') + s += ch; } - std::string cmd = p; - - std::vector args; - while((p = strtok(NULL," "))) - args.push_back(p); - + return s; +} +void sim_t::interactive() +{ typedef void (sim_t::*interactive_func)(const std::string&, const std::vector&); std::map funcs; - funcs["r"] = &sim_t::interactive_run_noisy; + funcs["run"] = &sim_t::interactive_run_noisy; + funcs["r"] = funcs["run"]; funcs["rs"] = &sim_t::interactive_run_silent; - funcs["rp"] = &sim_t::interactive_run_proc_noisy; - funcs["rps"] = &sim_t::interactive_run_proc_silent; funcs["reg"] = &sim_t::interactive_reg; + funcs["freg"] = &sim_t::interactive_freg; funcs["fregs"] = &sim_t::interactive_fregs; funcs["fregd"] = &sim_t::interactive_fregd; + funcs["pc"] = &sim_t::interactive_pc; 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; + funcs["quit"] = &sim_t::interactive_quit; + funcs["q"] = funcs["quit"]; + funcs["help"] = &sim_t::interactive_help; + funcs["h"] = funcs["help"]; - try + while (!done()) { - 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 args; + + if (!(ss >> cmd)) + { + set_procs_debug(true); + step(1); + continue; + } + + while (ss >> tmp) + args.push_back(tmp); + + try + { + if(funcs.count(cmd)) + (this->*funcs[cmd])(cmd, args); + else + fprintf(stderr, "Unknown command %s\n", cmd.c_str()); + } + catch(trap_t t) {} } - catch(trap_t t) {} + ctrlc_pressed = false; +} + +void sim_t::interactive_help(const std::string& cmd, const std::vector& args) +{ + std::cerr << + "Interactive commands:\n" + "reg [reg] # Display [reg] (all if omitted) in \n" + "fregs # Display single precision in \n" + "fregd # Display double precision in \n" + "pc # Show current PC in \n" + "mem # Show contents of physical memory\n" + "str # Show NUL-terminated C string\n" + "until reg # Stop when in hits \n" + "until pc # Stop when PC in hits \n" + "until mem # Stop when memory becomes \n" + "while reg # Run while in is \n" + "while pc # Run while PC in is \n" + "while mem # Run while memory is \n" + "run [count] # Resume noisy execution (until CTRL+C, or [count] insns)\n" + "r [count] Alias for run\n" + "rs [count] # Resume silent execution (until CTRL+C, or [count] insns)\n" + "quit # End the simulation\n" + "q Alias for quit\n" + "help # This screen!\n" + "h Alias for help\n" + "Note: Hitting enter is the same as: run 1\n" + << std::flush; } void sim_t::interactive_run_noisy(const std::string& cmd, const std::vector& args) @@ -61,119 +150,125 @@ void sim_t::interactive_run_silent(const std::string& cmd, const std::vector& args, bool noisy) { - if(args.size()) - step_all(atoll(args[0].c_str()),1,noisy); - else - while(1) step_all(1,1,noisy); -} - -void sim_t::interactive_run_proc_noisy(const std::string& cmd, const std::vector& args) -{ - interactive_run_proc(cmd,args,true); -} - -void sim_t::interactive_run_proc_silent(const std::string& cmd, const std::vector& args) -{ - interactive_run_proc(cmd,args,false); -} - -void sim_t::interactive_run_proc(const std::string& cmd, const std::vector& a, bool noisy) -{ - if(a.size() == 0) - return; - - int p = atoi(a[0].c_str()); - if(p >= (int)num_cores()) - return; - - if(a.size() == 2) - procs[p]->step(atoi(a[1].c_str()),noisy); - else - while(1) procs[p]->step(1,noisy); + 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 && !done(); i++) + step(1); } void sim_t::interactive_quit(const std::string& cmd, const std::vector& args) { - stop(); + exit(0); } reg_t sim_t::get_pc(const std::vector& args) { if(args.size() != 1) - throw trap_illegal_instruction; + throw trap_interactive(); - int p = atoi(args[0].c_str()); - if(p >= (int)num_cores()) - throw trap_illegal_instruction; + processor_t *p = get_core(args[0]); + return p->state.pc; +} - return procs[p]->pc; +void sim_t::interactive_pc(const std::string& cmd, const std::vector& args) +{ + fprintf(stderr, "0x%016" PRIx64 "\n", get_pc(args)); } reg_t sim_t::get_reg(const std::vector& args) { if(args.size() != 2) - throw trap_illegal_instruction; + throw trap_interactive(); + + processor_t *p = get_core(args[0]); + + unsigned long r = std::find(xpr_name, xpr_name + NXPR, args[1]) - xpr_name; + if (r == NXPR) { + char *ptr; + r = strtoul(args[1].c_str(), &ptr, 10); + if (*ptr) { + #define DECLARE_CSR(name, number) if (args[1] == #name) return p->get_csr(number); + #include "encoding.h" // generates if's for all csrs + r = NXPR; // else case (csr name not found) + #undef DECLARE_CSR + } + } - int p = atoi(args[0].c_str()); - int r = atoi(args[1].c_str()); - if(p >= (int)num_cores() || r >= NXPR) - throw trap_illegal_instruction; + if (r >= NXPR) + throw trap_interactive(); - return procs[p]->XPR[r]; + return p->state.XPR[r]; } -reg_t sim_t::get_freg(const std::vector& args) +freg_t sim_t::get_freg(const std::vector& args) { if(args.size() != 2) - throw trap_illegal_instruction; + throw trap_interactive(); - int p = atoi(args[0].c_str()); - int r = atoi(args[1].c_str()); - if(p >= (int)num_cores() || r >= NFPR) - throw trap_illegal_instruction; + processor_t *p = get_core(args[0]); + int r = std::find(fpr_name, fpr_name + NFPR, args[1]) - fpr_name; + if (r == NFPR) + r = atoi(args[1].c_str()); + if (r >= NFPR) + throw trap_interactive(); - return procs[p]->FPR[r]; + return p->state.FPR[r]; } void sim_t::interactive_reg(const std::string& cmd, const std::vector& args) { - printf("0x%016llx\n",(unsigned long long)get_reg(args)); + if (args.size() == 1) { + // Show all the regs! + processor_t *p = get_core(args[0]); + + for (int r = 0; r < NXPR; ++r) { + fprintf(stderr, "%-4s: 0x%016" PRIx64 " ", xpr_name[r], p->state.XPR[r]); + if ((r + 1) % 4 == 0) + fprintf(stderr, "\n"); + } + } else + fprintf(stderr, "0x%016" PRIx64 "\n", get_reg(args)); } union fpr { - reg_t r; + freg_t r; float s; double d; }; +void sim_t::interactive_freg(const std::string& cmd, const std::vector& args) +{ + freg_t r = get_freg(args); + fprintf(stderr, "0x%016" PRIx64 "%016" PRIx64 "\n", r.v[1], r.v[0]); +} + void sim_t::interactive_fregs(const std::string& cmd, const std::vector& args) { fpr f; f.r = get_freg(args); - printf("%g\n",f.s); + fprintf(stderr, "%g\n", isBoxedF32(f.r) ? (double)f.s : NAN); } void sim_t::interactive_fregd(const std::string& cmd, const std::vector& args) { fpr f; f.r = get_freg(args); - printf("%g\n",f.d); + fprintf(stderr, "%g\n", isBoxedF64(f.r) ? f.d : NAN); } reg_t sim_t::get_mem(const std::vector& args) { if(args.size() != 1 && args.size() != 2) - throw trap_illegal_instruction; + throw trap_interactive(); std::string addr_str = args[0]; + mmu_t* mmu = debug_mmu; if(args.size() == 2) { - int p = atoi(args[0].c_str()); - if(p >= (int)num_cores()) - throw trap_illegal_instruction; - mmu->set_vm_enabled(!!(procs[p]->sr & SR_VM)); - mmu->set_ptbr(procs[p]->mmu.get_ptbr()); + processor_t *p = get_core(args[0]); + mmu = p->get_mmu(); addr_str = args[1]; } @@ -202,18 +297,18 @@ reg_t sim_t::get_mem(const std::vector& args) void sim_t::interactive_mem(const std::string& cmd, const std::vector& args) { - printf("0x%016llx\n",(unsigned long long)get_mem(args)); + fprintf(stderr, "0x%016" PRIx64 "\n", get_mem(args)); } void sim_t::interactive_str(const std::string& cmd, const std::vector& args) { if(args.size() != 1) - throw trap_illegal_instruction; + throw trap_interactive(); reg_t addr = strtol(args[0].c_str(),NULL,16); char ch; - while((ch = mmu->load_uint8(addr++))) + while((ch = debug_mmu->load_uint8(addr++))) putchar(ch); putchar('\n'); @@ -221,10 +316,11 @@ void sim_t::interactive_str(const std::string& cmd, const std::vector& 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); @@ -232,25 +328,30 @@ void sim_t::interactive_until(const std::string& cmd, const std::vector args2; args2 = std::vector(args.begin()+1,args.end()-1); - 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 if(scmd == "tohost") - current = tohost; - else - return; - - if(cmd == "until" && current == val) - break; - if(cmd == "while" && current != val) - break; + 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; - step_all(1,1,false); + ctrlc_pressed = false; + + while (1) + { + try + { + reg_t current = (this->*func)(args2); + + if (cmd_until == (current == val)) + break; + if (ctrlc_pressed) + break; + } + catch (trap_t t) {} + + set_procs_debug(false); + step(1); } }