From: Andrew Waterman Date: Sat, 20 Dec 2014 21:37:14 +0000 (-0800) Subject: Support building from within root directory X-Git-Url: https://git.libre-soc.org/?p=riscv-isa-sim.git;a=commitdiff_plain;h=416c8be88c712a99451f3770534a7fe712cb17af Support building from within root directory --- diff --git a/configure b/configure index e98db52..fbbd294 100755 --- a/configure +++ b/configure @@ -4393,7 +4393,7 @@ $as_echo "#define SOFTFLOAT_ENABLED /**/" >>confdefs.h # Add subproject to our running list - subprojects="$subprojects spike" + subprojects="$subprojects spike_main" # Process the subproject appropriately. If enabled add it to the # $enabled_subprojects running shell variable, set a @@ -4401,14 +4401,14 @@ $as_echo "#define SOFTFLOAT_ENABLED /**/" >>confdefs.h # 'subproject.ac'. - { $as_echo "$as_me:${as_lineno-$LINENO}: configuring default subproject : spike" >&5 -$as_echo "$as_me: configuring default subproject : spike" >&6;} - ac_config_files="$ac_config_files spike.mk:spike/spike.mk.in" + { $as_echo "$as_me:${as_lineno-$LINENO}: configuring default subproject : spike_main" >&5 +$as_echo "$as_me: configuring default subproject : spike_main" >&6;} + ac_config_files="$ac_config_files spike_main.mk:spike_main/spike_main.mk.in" - enable_spike_sproj="yes" - subprojects_enabled="$subprojects_enabled spike" + enable_spike_main_sproj="yes" + subprojects_enabled="$subprojects_enabled spike_main" -$as_echo "#define SPIKE_ENABLED /**/" >>confdefs.h +$as_echo "#define SPIKE_MAIN_ENABLED /**/" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } @@ -5194,7 +5194,7 @@ do "hwacha.mk") CONFIG_FILES="$CONFIG_FILES hwacha.mk:hwacha/hwacha.mk.in" ;; "dummy_rocc.mk") CONFIG_FILES="$CONFIG_FILES dummy_rocc.mk:dummy_rocc/dummy_rocc.mk.in" ;; "softfloat.mk") CONFIG_FILES="$CONFIG_FILES softfloat.mk:softfloat/softfloat.mk.in" ;; - "spike.mk") CONFIG_FILES="$CONFIG_FILES spike.mk:spike/spike.mk.in" ;; + "spike_main.mk") CONFIG_FILES="$CONFIG_FILES spike_main.mk:spike_main/spike_main.mk.in" ;; "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; diff --git a/configure.ac b/configure.ac index 89d4dcf..084028f 100644 --- a/configure.ac +++ b/configure.ac @@ -82,7 +82,7 @@ AC_SUBST([CXXFLAGS],["-Wall -Wno-unused -O2 -std=c++11"]) # The '*' suffix indicates an optional subproject. The '**' suffix # indicates an optional subproject which is also the name of a group. -MCPPBS_SUBPROJECTS([ riscv, hwacha, dummy_rocc, softfloat, spike ]) +MCPPBS_SUBPROJECTS([ riscv, hwacha, dummy_rocc, softfloat, spike_main ]) #------------------------------------------------------------------------- # MCPPBS subproject groups diff --git a/dummy_rocc/dummy_rocc.mk.in b/dummy_rocc/dummy_rocc.mk.in index 298b9f9..0143ffd 100644 --- a/dummy_rocc/dummy_rocc.mk.in +++ b/dummy_rocc/dummy_rocc.mk.in @@ -1,5 +1,5 @@ dummy_rocc_subproject_deps = \ - spike \ + spike_main \ riscv \ softfloat \ diff --git a/hwacha/hwacha.mk.in b/hwacha/hwacha.mk.in index d1d9a01..6b258a0 100644 --- a/hwacha/hwacha.mk.in +++ b/hwacha/hwacha.mk.in @@ -1,5 +1,5 @@ hwacha_subproject_deps = \ - spike \ + spike_main \ riscv \ softfloat \ diff --git a/spike/disasm.cc b/spike/disasm.cc deleted file mode 100644 index 8fb1db8..0000000 --- a/spike/disasm.cc +++ /dev/null @@ -1,395 +0,0 @@ -// See LICENSE for license details. - -#include "disasm.h" -#include -#include -#include -#include -#include - - -struct : public arg_t { - std::string to_string(insn_t insn) const { - return std::to_string((int)insn.i_imm()) + '(' + xpr_name[insn.rs1()] + ')'; - } -} load_address; - -struct : public arg_t { - std::string to_string(insn_t insn) const { - return std::to_string((int)insn.s_imm()) + '(' + xpr_name[insn.rs1()] + ')'; - } -} store_address; - -struct : public arg_t { - std::string to_string(insn_t insn) const { - return std::string("0(") + xpr_name[insn.rs1()] + ')'; - } -} amo_address; - -struct : public arg_t { - std::string to_string(insn_t insn) const { - return xpr_name[insn.rd()]; - } -} xrd; - -struct : public arg_t { - std::string to_string(insn_t insn) const { - return xpr_name[insn.rs1()]; - } -} xrs1; - -struct : public arg_t { - std::string to_string(insn_t insn) const { - return xpr_name[insn.rs2()]; - } -} xrs2; - -struct : public arg_t { - std::string to_string(insn_t insn) const { - return fpr_name[insn.rd()]; - } -} frd; - -struct : public arg_t { - std::string to_string(insn_t insn) const { - return fpr_name[insn.rs1()]; - } -} frs1; - -struct : public arg_t { - std::string to_string(insn_t insn) const { - return fpr_name[insn.rs2()]; - } -} frs2; - -struct : public arg_t { - std::string to_string(insn_t insn) const { - return fpr_name[insn.rs3()]; - } -} frs3; - -struct : public arg_t { - std::string to_string(insn_t insn) const { - switch (insn.csr()) - { - #define DECLARE_CSR(name, num) case num: return #name; - #include "encoding.h" - #undef DECLARE_CSR - default: return "unknown"; - } - } -} csr; - -struct : public arg_t { - std::string to_string(insn_t insn) const { - return std::to_string((int)insn.i_imm()); - } -} imm; - -struct : public arg_t { - std::string to_string(insn_t insn) const { - std::stringstream s; - s << std::hex << "0x" << ((uint32_t)insn.u_imm() >> 12); - return s.str(); - } -} bigimm; - -struct : public arg_t { - std::string to_string(insn_t insn) const { - return std::to_string(insn.rs1()); - } -} zimm5; - -struct : public arg_t { - std::string to_string(insn_t insn) const { - std::stringstream s; - int32_t target = insn.sb_imm(); - char sign = target >= 0 ? '+' : '-'; - s << "pc " << sign << ' ' << abs(target); - return s.str(); - } -} branch_target; - -struct : public arg_t { - std::string to_string(insn_t insn) const { - std::stringstream s; - int32_t target = insn.uj_imm(); - char sign = target >= 0 ? '+' : '-'; - s << "pc " << sign << std::hex << " 0x" << abs(target); - return s.str(); - } -} jump_target; - -std::string disassembler_t::disassemble(insn_t insn) -{ - const disasm_insn_t* disasm_insn = lookup(insn); - return disasm_insn ? disasm_insn->to_string(insn) : "unknown"; -} - -disassembler_t::disassembler_t() -{ - const uint32_t mask_rd = 0x1fUL << 7; - const uint32_t match_rd_ra = 1UL << 7; - const uint32_t mask_rs1 = 0x1fUL << 15; - const uint32_t match_rs1_ra = 1UL << 15; - const uint32_t mask_rs2 = 0x1fUL << 20; - const uint32_t mask_imm = 0xfffUL << 20; - - #define DECLARE_INSN(code, match, mask) \ - const uint32_t match_##code = match; \ - const uint32_t mask_##code = mask; - #include "encoding.h" - #undef DECLARE_INSN - - // explicit per-instruction disassembly - #define DISASM_INSN(name, code, extra, ...) \ - add_insn(new disasm_insn_t(name, match_##code, mask_##code | (extra), __VA_ARGS__)); - #define DEFINE_NOARG(code) \ - add_insn(new disasm_insn_t(#code, match_##code, mask_##code, {})); - #define DEFINE_RTYPE(code) DISASM_INSN(#code, code, 0, {&xrd, &xrs1, &xrs2}) - #define DEFINE_ITYPE(code) DISASM_INSN(#code, code, 0, {&xrd, &xrs1, &imm}) - #define DEFINE_I0TYPE(name, code) DISASM_INSN(name, code, mask_rs1, {&xrd, &imm}) - #define DEFINE_I1TYPE(name, code) DISASM_INSN(name, code, mask_imm, {&xrd, &xrs1}) - #define DEFINE_I2TYPE(name, code) DISASM_INSN(name, code, mask_rd | mask_imm, {&xrs1}) - #define DEFINE_LTYPE(code) DISASM_INSN(#code, code, 0, {&xrd, &bigimm}) - #define DEFINE_BTYPE(code) DISASM_INSN(#code, code, 0, {&xrs1, &xrs2, &branch_target}) - #define DEFINE_B0TYPE(name, code) DISASM_INSN(name, code, mask_rs1 | mask_rs2, {&branch_target}) - #define DEFINE_B1TYPE(name, code) DISASM_INSN(name, code, mask_rs2, {&xrs1, &branch_target}) - #define DEFINE_XLOAD(code) DISASM_INSN(#code, code, 0, {&xrd, &load_address}) - #define DEFINE_XSTORE(code) DISASM_INSN(#code, code, 0, {&xrs2, &store_address}) - #define DEFINE_XAMO(code) DISASM_INSN(#code, code, 0, {&xrd, &xrs2, &amo_address}) - #define DEFINE_FLOAD(code) DISASM_INSN(#code, code, 0, {&frd, &load_address}) - #define DEFINE_FSTORE(code) DISASM_INSN(#code, code, 0, {&frs2, &store_address}) - #define DEFINE_FRTYPE(code) DISASM_INSN(#code, code, 0, {&frd, &frs1, &frs2}) - #define DEFINE_FR1TYPE(code) DISASM_INSN(#code, code, 0, {&frd, &frs1}) - #define DEFINE_FR3TYPE(code) DISASM_INSN(#code, code, 0, {&frd, &frs1, &frs2, &frs3}) - #define DEFINE_FXTYPE(code) DISASM_INSN(#code, code, 0, {&xrd, &frs1}) - #define DEFINE_XFTYPE(code) DISASM_INSN(#code, code, 0, {&frd, &xrs1}) - - DEFINE_XLOAD(lb) - DEFINE_XLOAD(lbu) - DEFINE_XLOAD(lh) - DEFINE_XLOAD(lhu) - DEFINE_XLOAD(lw) - DEFINE_XLOAD(lwu) - DEFINE_XLOAD(ld) - - DEFINE_XSTORE(sb) - DEFINE_XSTORE(sh) - DEFINE_XSTORE(sw) - DEFINE_XSTORE(sd) - - DEFINE_XAMO(amoadd_w) - DEFINE_XAMO(amoswap_w) - DEFINE_XAMO(amoand_w) - DEFINE_XAMO(amoor_w) - DEFINE_XAMO(amoxor_w) - DEFINE_XAMO(amomin_w) - DEFINE_XAMO(amomax_w) - DEFINE_XAMO(amominu_w) - DEFINE_XAMO(amomaxu_w) - DEFINE_XAMO(amoadd_d) - DEFINE_XAMO(amoswap_d) - DEFINE_XAMO(amoand_d) - DEFINE_XAMO(amoor_d) - DEFINE_XAMO(amoxor_d) - DEFINE_XAMO(amomin_d) - DEFINE_XAMO(amomax_d) - DEFINE_XAMO(amominu_d) - DEFINE_XAMO(amomaxu_d) - - DEFINE_XAMO(lr_w) - DEFINE_XAMO(sc_w) - DEFINE_XAMO(lr_d) - DEFINE_XAMO(sc_d) - - DEFINE_FLOAD(flw) - DEFINE_FLOAD(fld) - - DEFINE_FSTORE(fsw) - DEFINE_FSTORE(fsd) - - add_insn(new disasm_insn_t("j", match_jal, mask_jal | mask_rd, {&jump_target})); - add_insn(new disasm_insn_t("jal", match_jal | match_rd_ra, mask_jal | mask_rd, {&jump_target})); - add_insn(new disasm_insn_t("jal", match_jal, mask_jal, {&xrd, &jump_target})); - - DEFINE_B0TYPE("b", beq); - DEFINE_B1TYPE("beqz", beq); - DEFINE_B1TYPE("bnez", bne); - DEFINE_B1TYPE("bltz", blt); - DEFINE_B1TYPE("bgez", bge); - DEFINE_BTYPE(beq) - DEFINE_BTYPE(bne) - DEFINE_BTYPE(blt) - DEFINE_BTYPE(bge) - DEFINE_BTYPE(bltu) - DEFINE_BTYPE(bgeu) - - DEFINE_LTYPE(lui); - DEFINE_LTYPE(auipc); - - DEFINE_I2TYPE("jr", jalr); - add_insn(new disasm_insn_t("jalr", match_jalr | match_rd_ra, mask_jalr | mask_rd | mask_imm, {&xrs1})); - add_insn(new disasm_insn_t("ret", match_jalr | match_rs1_ra, mask_jalr | mask_rd | mask_rs1 | mask_imm, {})); - DEFINE_ITYPE(jalr); - - add_insn(new disasm_insn_t("nop", match_addi, mask_addi | mask_rd | mask_rs1 | mask_imm, {})); - add_insn(new disasm_insn_t(" - ", match_xor, mask_xor | mask_rd | mask_rs1 | mask_rs2, {})); // for machine-generated bubbles - DEFINE_I0TYPE("li", addi); - DEFINE_I1TYPE("move", addi); - DEFINE_ITYPE(addi); - DEFINE_ITYPE(slli); - DEFINE_ITYPE(slti); - DEFINE_ITYPE(sltiu); - DEFINE_ITYPE(xori); - DEFINE_ITYPE(srli); - DEFINE_ITYPE(srai); - DEFINE_ITYPE(ori); - DEFINE_ITYPE(andi); - DEFINE_ITYPE(addiw); - DEFINE_ITYPE(slliw); - DEFINE_ITYPE(srliw); - DEFINE_ITYPE(sraiw); - - DEFINE_RTYPE(add); - DEFINE_RTYPE(sub); - DEFINE_RTYPE(sll); - DEFINE_RTYPE(slt); - DEFINE_RTYPE(sltu); - DEFINE_RTYPE(xor); - DEFINE_RTYPE(srl); - DEFINE_RTYPE(sra); - DEFINE_RTYPE(or); - DEFINE_RTYPE(and); - DEFINE_RTYPE(mul); - DEFINE_RTYPE(mulh); - DEFINE_RTYPE(mulhu); - DEFINE_RTYPE(mulhsu); - DEFINE_RTYPE(div); - DEFINE_RTYPE(divu); - DEFINE_RTYPE(rem); - DEFINE_RTYPE(remu); - DEFINE_RTYPE(addw); - DEFINE_RTYPE(subw); - DEFINE_RTYPE(sllw); - DEFINE_RTYPE(srlw); - DEFINE_RTYPE(sraw); - DEFINE_RTYPE(mulw); - DEFINE_RTYPE(divw); - DEFINE_RTYPE(divuw); - DEFINE_RTYPE(remw); - DEFINE_RTYPE(remuw); - - DEFINE_NOARG(scall); - DEFINE_NOARG(sbreak); - DEFINE_NOARG(fence); - DEFINE_NOARG(fence_i); - - add_insn(new disasm_insn_t("csrr", match_csrrs, mask_csrrs | mask_rs1, {&xrd, &csr})); - add_insn(new disasm_insn_t("csrw", match_csrrw, mask_csrrw | mask_rd, {&csr, &xrs1})); - add_insn(new disasm_insn_t("csrrw", match_csrrw, mask_csrrw, {&xrd, &csr, &xrs1})); - add_insn(new disasm_insn_t("csrrs", match_csrrs, mask_csrrs, {&xrd, &csr, &xrs1})); - add_insn(new disasm_insn_t("csrrc", match_csrrc, mask_csrrc, {&xrd, &csr, &xrs1})); - add_insn(new disasm_insn_t("csrrwi", match_csrrwi, mask_csrrwi, {&xrd, &csr, &zimm5})); - add_insn(new disasm_insn_t("csrrsi", match_csrrsi, mask_csrrsi, {&xrd, &csr, &zimm5})); - add_insn(new disasm_insn_t("csrrci", match_csrrci, mask_csrrci, {&xrd, &csr, &zimm5})); - DEFINE_NOARG(sret) - - DEFINE_FRTYPE(fadd_s); - DEFINE_FRTYPE(fsub_s); - DEFINE_FRTYPE(fmul_s); - DEFINE_FRTYPE(fdiv_s); - DEFINE_FR1TYPE(fsqrt_s); - DEFINE_FRTYPE(fmin_s); - DEFINE_FRTYPE(fmax_s); - DEFINE_FR3TYPE(fmadd_s); - DEFINE_FR3TYPE(fmsub_s); - DEFINE_FR3TYPE(fnmadd_s); - DEFINE_FR3TYPE(fnmsub_s); - DEFINE_FRTYPE(fsgnj_s); - DEFINE_FRTYPE(fsgnjn_s); - DEFINE_FRTYPE(fsgnjx_s); - DEFINE_FR1TYPE(fcvt_s_d); - DEFINE_XFTYPE(fcvt_s_l); - DEFINE_XFTYPE(fcvt_s_lu); - DEFINE_XFTYPE(fcvt_s_w); - DEFINE_XFTYPE(fcvt_s_wu); - DEFINE_XFTYPE(fcvt_s_wu); - DEFINE_XFTYPE(fmv_s_x); - DEFINE_FXTYPE(fcvt_l_s); - DEFINE_FXTYPE(fcvt_lu_s); - DEFINE_FXTYPE(fcvt_w_s); - DEFINE_FXTYPE(fcvt_wu_s); - DEFINE_FXTYPE(fclass_s); - DEFINE_FXTYPE(fmv_x_s); - DEFINE_FXTYPE(feq_s); - DEFINE_FXTYPE(flt_s); - DEFINE_FXTYPE(fle_s); - - DEFINE_FRTYPE(fadd_d); - DEFINE_FRTYPE(fsub_d); - DEFINE_FRTYPE(fmul_d); - DEFINE_FRTYPE(fdiv_d); - DEFINE_FR1TYPE(fsqrt_d); - DEFINE_FRTYPE(fmin_d); - DEFINE_FRTYPE(fmax_d); - DEFINE_FR3TYPE(fmadd_d); - DEFINE_FR3TYPE(fmsub_d); - DEFINE_FR3TYPE(fnmadd_d); - DEFINE_FR3TYPE(fnmsub_d); - DEFINE_FRTYPE(fsgnj_d); - DEFINE_FRTYPE(fsgnjn_d); - DEFINE_FRTYPE(fsgnjx_d); - DEFINE_FR1TYPE(fcvt_d_s); - DEFINE_XFTYPE(fcvt_d_l); - DEFINE_XFTYPE(fcvt_d_lu); - DEFINE_XFTYPE(fcvt_d_w); - DEFINE_XFTYPE(fcvt_d_wu); - DEFINE_XFTYPE(fcvt_d_wu); - DEFINE_XFTYPE(fmv_d_x); - DEFINE_FXTYPE(fcvt_l_d); - DEFINE_FXTYPE(fcvt_lu_d); - DEFINE_FXTYPE(fcvt_w_d); - DEFINE_FXTYPE(fcvt_wu_d); - DEFINE_FXTYPE(fclass_d); - DEFINE_FXTYPE(fmv_x_d); - DEFINE_FXTYPE(feq_d); - DEFINE_FXTYPE(flt_d); - DEFINE_FXTYPE(fle_d); - - // provide a default disassembly for all instructions as a fallback - #define DECLARE_INSN(code, match, mask) \ - add_insn(new disasm_insn_t(#code " (args unknown)", match, mask, {})); - #include "encoding.h" - #undef DECLARE_INSN -} - -const disasm_insn_t* disassembler_t::lookup(insn_t insn) -{ - size_t idx = insn.bits() % HASH_SIZE; - for (size_t j = 0; j < chain[idx].size(); j++) - if(*chain[idx][j] == insn) - return chain[idx][j]; - - idx = HASH_SIZE; - for (size_t j = 0; j < chain[idx].size(); j++) - if(*chain[idx][j] == insn) - return chain[idx][j]; - - return NULL; -} - -void disassembler_t::add_insn(disasm_insn_t* insn) -{ - size_t idx = HASH_SIZE; - if (insn->get_mask() % HASH_SIZE == HASH_SIZE - 1) - idx = insn->get_match() % HASH_SIZE; - chain[idx].push_back(insn); -} - -disassembler_t::~disassembler_t() -{ - for (size_t i = 0; i < HASH_SIZE+1; i++) - for (size_t j = 0; j < chain[i].size(); j++) - delete chain[i][j]; -} diff --git a/spike/extensions.cc b/spike/extensions.cc deleted file mode 100644 index 315621f..0000000 --- a/spike/extensions.cc +++ /dev/null @@ -1,35 +0,0 @@ -#include "extension.h" -#include -#include -#include - -static std::map>& extensions() -{ - static std::map> v; - return v; -} - -void register_extension(const char* name, std::function f) -{ - extensions()[name] = f; -} - -std::function find_extension(const char* name) -{ - if (!extensions().count(name)) { - // try to find extension xyz by loading libxyz.so - std::string libname = std::string("lib") + name + ".so"; - if (!dlopen(libname.c_str(), RTLD_LAZY)) { - fprintf(stderr, "couldn't find extension '%s' (or library '%s')\n", - name, libname.c_str()); - exit(-1); - } - if (!extensions().count(name)) { - fprintf(stderr, "couldn't find extension '%s' in shared library '%s'\n", - name, libname.c_str()); - exit(-1); - } - } - - return extensions()[name]; -} diff --git a/spike/riscv-dis.cc b/spike/riscv-dis.cc deleted file mode 100644 index d0af451..0000000 --- a/spike/riscv-dis.cc +++ /dev/null @@ -1,45 +0,0 @@ -// See LICENSE for license details. - -// This little program finds occurrences of strings like -// DASM(ffabc013) -// in its input, then replaces them with the disassembly -// enclosed hexadecimal number, interpreted as a RISC-V -// instruction. - -#include "disasm.h" -#include "extension.h" -#include -#include -#include -#include -using namespace std; - -int main(int argc, char** argv) -{ - string s; - disassembler_t d; - - std::function extension; - option_parser_t parser; - parser.option(0, "extension", 1, [&](const char* s){extension = find_extension(s);}); - - while (getline(cin, s)) - { - for (size_t start = 0; (start = s.find("DASM(", start)) != string::npos; ) - { - size_t end = s.find(')', start); - if (end == string::npos) - break; - - size_t numstart = start + strlen("DASM("); - insn_bits_t bits = strtoull(&s[numstart], NULL, 16); - string dis = d.disassemble(bits); - s = s.substr(0, start) + dis + s.substr(end+1); - start += dis.length(); - } - - cout << s << '\n'; - } - - return 0; -} diff --git a/spike/spike.ac b/spike/spike.ac deleted file mode 100644 index f8d63ce..0000000 --- a/spike/spike.ac +++ /dev/null @@ -1 +0,0 @@ -AC_CHECK_LIB(dl, dlopen, [], [AC_MSG_ERROR([libdl is required])]) diff --git a/spike/spike.cc b/spike/spike.cc deleted file mode 100644 index ab5cea5..0000000 --- a/spike/spike.cc +++ /dev/null @@ -1,81 +0,0 @@ -// See LICENSE for license details. - -#include "sim.h" -#include "htif.h" -#include "cachesim.h" -#include "extension.h" -#include -#include -#include -#include -#include -#include -#include -#include - -static void help() -{ - fprintf(stderr, "usage: spike [host options] [target options]\n"); - fprintf(stderr, "Host Options:\n"); - fprintf(stderr, " -p Simulate processors\n"); - fprintf(stderr, " -m Provide MB of target memory\n"); - fprintf(stderr, " -d Interactive debug mode\n"); - fprintf(stderr, " -g Track histogram of PCs\n"); - fprintf(stderr, " -h Print this help message\n"); - fprintf(stderr, " --ic=:: Instantiate a cache model with S sets,\n"); - fprintf(stderr, " --dc=:: W ways, and B-byte blocks (with S and\n"); - fprintf(stderr, " --l2=:: B both powers of 2).\n"); - fprintf(stderr, " --extension= Specify RoCC Extension\n"); - fprintf(stderr, " --extlib= Shared library to load\n"); - exit(1); -} - -int main(int argc, char** argv) -{ - bool debug = false; - bool histogram = false; - size_t nprocs = 1; - size_t mem_mb = 0; - std::unique_ptr ic; - std::unique_ptr dc; - std::unique_ptr l2; - std::function extension; - - 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('g', 0, 0, [&](const char* s){histogram = true;}); - parser.option('p', 0, 1, [&](const char* s){nprocs = atoi(s);}); - parser.option('m', 0, 1, [&](const char* s){mem_mb = atoi(s);}); - parser.option(0, "ic", 1, [&](const char* s){ic.reset(new icache_sim_t(s));}); - parser.option(0, "dc", 1, [&](const char* s){dc.reset(new dcache_sim_t(s));}); - parser.option(0, "l2", 1, [&](const char* s){l2.reset(cache_sim_t::construct(s, "L2$"));}); - parser.option(0, "extension", 1, [&](const char* s){extension = find_extension(s);}); - parser.option(0, "extlib", 1, [&](const char *s){ - void *lib = dlopen(s, RTLD_NOW | RTLD_GLOBAL); - if (lib == NULL) { - fprintf(stderr, "Unable to load extlib '%s': %s\n", s, dlerror()); - exit(-1); - } - }); - - auto argv1 = parser.parse(argv); - if (!*argv1) - help(); - std::vector htif_args(argv1, (const char*const*)argv + argc); - sim_t s(nprocs, mem_mb, htif_args); - - if (ic && l2) ic->set_miss_handler(&*l2); - if (dc && l2) dc->set_miss_handler(&*l2); - for (size_t i = 0; i < nprocs; i++) - { - if (ic) s.get_core(i)->get_mmu()->register_memtracer(&*ic); - if (dc) s.get_core(i)->get_mmu()->register_memtracer(&*dc); - if (extension) s.get_core(i)->register_extension(extension()); - } - - s.set_debug(debug); - s.set_histogram(histogram); - return s.run(); -} diff --git a/spike/spike.mk.in b/spike/spike.mk.in deleted file mode 100644 index 96f0126..0000000 --- a/spike/spike.mk.in +++ /dev/null @@ -1,14 +0,0 @@ -spike_subproject_deps = \ - softfloat \ - riscv \ - -spike_install_prog_srcs = \ - spike.cc \ - riscv-dis.cc \ - xspike.cc \ - termios-xspike.cc \ - -spike_hdrs = \ - -spike_srcs = \ - extensions.cc \ diff --git a/spike/termios-xspike.cc b/spike/termios-xspike.cc deleted file mode 100644 index e533933..0000000 --- a/spike/termios-xspike.cc +++ /dev/null @@ -1,29 +0,0 @@ -// 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 -#include -#include -#include -#include -#include - -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); -} diff --git a/spike/xspike.cc b/spike/xspike.cc deleted file mode 100644 index 4331dbe..0000000 --- a/spike/xspike.cc +++ /dev/null @@ -1,102 +0,0 @@ -// See LICENSE for license details. - -// xspike forks an xterm for spike's target machine console, -// preserving the current terminal for debugging. - -#include -#include -#include -#include -#include -#include -#include -#include - -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; }; - - if ((xterm = fork_xterm(&tty_fd)) < 0) - { - fprintf(stderr, "could not open xterm\n"); - goto out; - } - - signal(SIGINT, handle_signal); - - if ((spike = fork_spike(tty_fd, argc, argv)) < 0) - { - fprintf(stderr, "could not open spike\n"); - goto close_xterm; - } - - while ((ret = waitpid(spike, &wait_status, 0)) < 0) - if (signal_exit) - break; - - if (ret < 0) // signal_exit - kill(spike, SIGTERM); - else - ret = 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; -} diff --git a/spike_main/disasm.cc b/spike_main/disasm.cc new file mode 100644 index 0000000..8fb1db8 --- /dev/null +++ b/spike_main/disasm.cc @@ -0,0 +1,395 @@ +// See LICENSE for license details. + +#include "disasm.h" +#include +#include +#include +#include +#include + + +struct : public arg_t { + std::string to_string(insn_t insn) const { + return std::to_string((int)insn.i_imm()) + '(' + xpr_name[insn.rs1()] + ')'; + } +} load_address; + +struct : public arg_t { + std::string to_string(insn_t insn) const { + return std::to_string((int)insn.s_imm()) + '(' + xpr_name[insn.rs1()] + ')'; + } +} store_address; + +struct : public arg_t { + std::string to_string(insn_t insn) const { + return std::string("0(") + xpr_name[insn.rs1()] + ')'; + } +} amo_address; + +struct : public arg_t { + std::string to_string(insn_t insn) const { + return xpr_name[insn.rd()]; + } +} xrd; + +struct : public arg_t { + std::string to_string(insn_t insn) const { + return xpr_name[insn.rs1()]; + } +} xrs1; + +struct : public arg_t { + std::string to_string(insn_t insn) const { + return xpr_name[insn.rs2()]; + } +} xrs2; + +struct : public arg_t { + std::string to_string(insn_t insn) const { + return fpr_name[insn.rd()]; + } +} frd; + +struct : public arg_t { + std::string to_string(insn_t insn) const { + return fpr_name[insn.rs1()]; + } +} frs1; + +struct : public arg_t { + std::string to_string(insn_t insn) const { + return fpr_name[insn.rs2()]; + } +} frs2; + +struct : public arg_t { + std::string to_string(insn_t insn) const { + return fpr_name[insn.rs3()]; + } +} frs3; + +struct : public arg_t { + std::string to_string(insn_t insn) const { + switch (insn.csr()) + { + #define DECLARE_CSR(name, num) case num: return #name; + #include "encoding.h" + #undef DECLARE_CSR + default: return "unknown"; + } + } +} csr; + +struct : public arg_t { + std::string to_string(insn_t insn) const { + return std::to_string((int)insn.i_imm()); + } +} imm; + +struct : public arg_t { + std::string to_string(insn_t insn) const { + std::stringstream s; + s << std::hex << "0x" << ((uint32_t)insn.u_imm() >> 12); + return s.str(); + } +} bigimm; + +struct : public arg_t { + std::string to_string(insn_t insn) const { + return std::to_string(insn.rs1()); + } +} zimm5; + +struct : public arg_t { + std::string to_string(insn_t insn) const { + std::stringstream s; + int32_t target = insn.sb_imm(); + char sign = target >= 0 ? '+' : '-'; + s << "pc " << sign << ' ' << abs(target); + return s.str(); + } +} branch_target; + +struct : public arg_t { + std::string to_string(insn_t insn) const { + std::stringstream s; + int32_t target = insn.uj_imm(); + char sign = target >= 0 ? '+' : '-'; + s << "pc " << sign << std::hex << " 0x" << abs(target); + return s.str(); + } +} jump_target; + +std::string disassembler_t::disassemble(insn_t insn) +{ + const disasm_insn_t* disasm_insn = lookup(insn); + return disasm_insn ? disasm_insn->to_string(insn) : "unknown"; +} + +disassembler_t::disassembler_t() +{ + const uint32_t mask_rd = 0x1fUL << 7; + const uint32_t match_rd_ra = 1UL << 7; + const uint32_t mask_rs1 = 0x1fUL << 15; + const uint32_t match_rs1_ra = 1UL << 15; + const uint32_t mask_rs2 = 0x1fUL << 20; + const uint32_t mask_imm = 0xfffUL << 20; + + #define DECLARE_INSN(code, match, mask) \ + const uint32_t match_##code = match; \ + const uint32_t mask_##code = mask; + #include "encoding.h" + #undef DECLARE_INSN + + // explicit per-instruction disassembly + #define DISASM_INSN(name, code, extra, ...) \ + add_insn(new disasm_insn_t(name, match_##code, mask_##code | (extra), __VA_ARGS__)); + #define DEFINE_NOARG(code) \ + add_insn(new disasm_insn_t(#code, match_##code, mask_##code, {})); + #define DEFINE_RTYPE(code) DISASM_INSN(#code, code, 0, {&xrd, &xrs1, &xrs2}) + #define DEFINE_ITYPE(code) DISASM_INSN(#code, code, 0, {&xrd, &xrs1, &imm}) + #define DEFINE_I0TYPE(name, code) DISASM_INSN(name, code, mask_rs1, {&xrd, &imm}) + #define DEFINE_I1TYPE(name, code) DISASM_INSN(name, code, mask_imm, {&xrd, &xrs1}) + #define DEFINE_I2TYPE(name, code) DISASM_INSN(name, code, mask_rd | mask_imm, {&xrs1}) + #define DEFINE_LTYPE(code) DISASM_INSN(#code, code, 0, {&xrd, &bigimm}) + #define DEFINE_BTYPE(code) DISASM_INSN(#code, code, 0, {&xrs1, &xrs2, &branch_target}) + #define DEFINE_B0TYPE(name, code) DISASM_INSN(name, code, mask_rs1 | mask_rs2, {&branch_target}) + #define DEFINE_B1TYPE(name, code) DISASM_INSN(name, code, mask_rs2, {&xrs1, &branch_target}) + #define DEFINE_XLOAD(code) DISASM_INSN(#code, code, 0, {&xrd, &load_address}) + #define DEFINE_XSTORE(code) DISASM_INSN(#code, code, 0, {&xrs2, &store_address}) + #define DEFINE_XAMO(code) DISASM_INSN(#code, code, 0, {&xrd, &xrs2, &amo_address}) + #define DEFINE_FLOAD(code) DISASM_INSN(#code, code, 0, {&frd, &load_address}) + #define DEFINE_FSTORE(code) DISASM_INSN(#code, code, 0, {&frs2, &store_address}) + #define DEFINE_FRTYPE(code) DISASM_INSN(#code, code, 0, {&frd, &frs1, &frs2}) + #define DEFINE_FR1TYPE(code) DISASM_INSN(#code, code, 0, {&frd, &frs1}) + #define DEFINE_FR3TYPE(code) DISASM_INSN(#code, code, 0, {&frd, &frs1, &frs2, &frs3}) + #define DEFINE_FXTYPE(code) DISASM_INSN(#code, code, 0, {&xrd, &frs1}) + #define DEFINE_XFTYPE(code) DISASM_INSN(#code, code, 0, {&frd, &xrs1}) + + DEFINE_XLOAD(lb) + DEFINE_XLOAD(lbu) + DEFINE_XLOAD(lh) + DEFINE_XLOAD(lhu) + DEFINE_XLOAD(lw) + DEFINE_XLOAD(lwu) + DEFINE_XLOAD(ld) + + DEFINE_XSTORE(sb) + DEFINE_XSTORE(sh) + DEFINE_XSTORE(sw) + DEFINE_XSTORE(sd) + + DEFINE_XAMO(amoadd_w) + DEFINE_XAMO(amoswap_w) + DEFINE_XAMO(amoand_w) + DEFINE_XAMO(amoor_w) + DEFINE_XAMO(amoxor_w) + DEFINE_XAMO(amomin_w) + DEFINE_XAMO(amomax_w) + DEFINE_XAMO(amominu_w) + DEFINE_XAMO(amomaxu_w) + DEFINE_XAMO(amoadd_d) + DEFINE_XAMO(amoswap_d) + DEFINE_XAMO(amoand_d) + DEFINE_XAMO(amoor_d) + DEFINE_XAMO(amoxor_d) + DEFINE_XAMO(amomin_d) + DEFINE_XAMO(amomax_d) + DEFINE_XAMO(amominu_d) + DEFINE_XAMO(amomaxu_d) + + DEFINE_XAMO(lr_w) + DEFINE_XAMO(sc_w) + DEFINE_XAMO(lr_d) + DEFINE_XAMO(sc_d) + + DEFINE_FLOAD(flw) + DEFINE_FLOAD(fld) + + DEFINE_FSTORE(fsw) + DEFINE_FSTORE(fsd) + + add_insn(new disasm_insn_t("j", match_jal, mask_jal | mask_rd, {&jump_target})); + add_insn(new disasm_insn_t("jal", match_jal | match_rd_ra, mask_jal | mask_rd, {&jump_target})); + add_insn(new disasm_insn_t("jal", match_jal, mask_jal, {&xrd, &jump_target})); + + DEFINE_B0TYPE("b", beq); + DEFINE_B1TYPE("beqz", beq); + DEFINE_B1TYPE("bnez", bne); + DEFINE_B1TYPE("bltz", blt); + DEFINE_B1TYPE("bgez", bge); + DEFINE_BTYPE(beq) + DEFINE_BTYPE(bne) + DEFINE_BTYPE(blt) + DEFINE_BTYPE(bge) + DEFINE_BTYPE(bltu) + DEFINE_BTYPE(bgeu) + + DEFINE_LTYPE(lui); + DEFINE_LTYPE(auipc); + + DEFINE_I2TYPE("jr", jalr); + add_insn(new disasm_insn_t("jalr", match_jalr | match_rd_ra, mask_jalr | mask_rd | mask_imm, {&xrs1})); + add_insn(new disasm_insn_t("ret", match_jalr | match_rs1_ra, mask_jalr | mask_rd | mask_rs1 | mask_imm, {})); + DEFINE_ITYPE(jalr); + + add_insn(new disasm_insn_t("nop", match_addi, mask_addi | mask_rd | mask_rs1 | mask_imm, {})); + add_insn(new disasm_insn_t(" - ", match_xor, mask_xor | mask_rd | mask_rs1 | mask_rs2, {})); // for machine-generated bubbles + DEFINE_I0TYPE("li", addi); + DEFINE_I1TYPE("move", addi); + DEFINE_ITYPE(addi); + DEFINE_ITYPE(slli); + DEFINE_ITYPE(slti); + DEFINE_ITYPE(sltiu); + DEFINE_ITYPE(xori); + DEFINE_ITYPE(srli); + DEFINE_ITYPE(srai); + DEFINE_ITYPE(ori); + DEFINE_ITYPE(andi); + DEFINE_ITYPE(addiw); + DEFINE_ITYPE(slliw); + DEFINE_ITYPE(srliw); + DEFINE_ITYPE(sraiw); + + DEFINE_RTYPE(add); + DEFINE_RTYPE(sub); + DEFINE_RTYPE(sll); + DEFINE_RTYPE(slt); + DEFINE_RTYPE(sltu); + DEFINE_RTYPE(xor); + DEFINE_RTYPE(srl); + DEFINE_RTYPE(sra); + DEFINE_RTYPE(or); + DEFINE_RTYPE(and); + DEFINE_RTYPE(mul); + DEFINE_RTYPE(mulh); + DEFINE_RTYPE(mulhu); + DEFINE_RTYPE(mulhsu); + DEFINE_RTYPE(div); + DEFINE_RTYPE(divu); + DEFINE_RTYPE(rem); + DEFINE_RTYPE(remu); + DEFINE_RTYPE(addw); + DEFINE_RTYPE(subw); + DEFINE_RTYPE(sllw); + DEFINE_RTYPE(srlw); + DEFINE_RTYPE(sraw); + DEFINE_RTYPE(mulw); + DEFINE_RTYPE(divw); + DEFINE_RTYPE(divuw); + DEFINE_RTYPE(remw); + DEFINE_RTYPE(remuw); + + DEFINE_NOARG(scall); + DEFINE_NOARG(sbreak); + DEFINE_NOARG(fence); + DEFINE_NOARG(fence_i); + + add_insn(new disasm_insn_t("csrr", match_csrrs, mask_csrrs | mask_rs1, {&xrd, &csr})); + add_insn(new disasm_insn_t("csrw", match_csrrw, mask_csrrw | mask_rd, {&csr, &xrs1})); + add_insn(new disasm_insn_t("csrrw", match_csrrw, mask_csrrw, {&xrd, &csr, &xrs1})); + add_insn(new disasm_insn_t("csrrs", match_csrrs, mask_csrrs, {&xrd, &csr, &xrs1})); + add_insn(new disasm_insn_t("csrrc", match_csrrc, mask_csrrc, {&xrd, &csr, &xrs1})); + add_insn(new disasm_insn_t("csrrwi", match_csrrwi, mask_csrrwi, {&xrd, &csr, &zimm5})); + add_insn(new disasm_insn_t("csrrsi", match_csrrsi, mask_csrrsi, {&xrd, &csr, &zimm5})); + add_insn(new disasm_insn_t("csrrci", match_csrrci, mask_csrrci, {&xrd, &csr, &zimm5})); + DEFINE_NOARG(sret) + + DEFINE_FRTYPE(fadd_s); + DEFINE_FRTYPE(fsub_s); + DEFINE_FRTYPE(fmul_s); + DEFINE_FRTYPE(fdiv_s); + DEFINE_FR1TYPE(fsqrt_s); + DEFINE_FRTYPE(fmin_s); + DEFINE_FRTYPE(fmax_s); + DEFINE_FR3TYPE(fmadd_s); + DEFINE_FR3TYPE(fmsub_s); + DEFINE_FR3TYPE(fnmadd_s); + DEFINE_FR3TYPE(fnmsub_s); + DEFINE_FRTYPE(fsgnj_s); + DEFINE_FRTYPE(fsgnjn_s); + DEFINE_FRTYPE(fsgnjx_s); + DEFINE_FR1TYPE(fcvt_s_d); + DEFINE_XFTYPE(fcvt_s_l); + DEFINE_XFTYPE(fcvt_s_lu); + DEFINE_XFTYPE(fcvt_s_w); + DEFINE_XFTYPE(fcvt_s_wu); + DEFINE_XFTYPE(fcvt_s_wu); + DEFINE_XFTYPE(fmv_s_x); + DEFINE_FXTYPE(fcvt_l_s); + DEFINE_FXTYPE(fcvt_lu_s); + DEFINE_FXTYPE(fcvt_w_s); + DEFINE_FXTYPE(fcvt_wu_s); + DEFINE_FXTYPE(fclass_s); + DEFINE_FXTYPE(fmv_x_s); + DEFINE_FXTYPE(feq_s); + DEFINE_FXTYPE(flt_s); + DEFINE_FXTYPE(fle_s); + + DEFINE_FRTYPE(fadd_d); + DEFINE_FRTYPE(fsub_d); + DEFINE_FRTYPE(fmul_d); + DEFINE_FRTYPE(fdiv_d); + DEFINE_FR1TYPE(fsqrt_d); + DEFINE_FRTYPE(fmin_d); + DEFINE_FRTYPE(fmax_d); + DEFINE_FR3TYPE(fmadd_d); + DEFINE_FR3TYPE(fmsub_d); + DEFINE_FR3TYPE(fnmadd_d); + DEFINE_FR3TYPE(fnmsub_d); + DEFINE_FRTYPE(fsgnj_d); + DEFINE_FRTYPE(fsgnjn_d); + DEFINE_FRTYPE(fsgnjx_d); + DEFINE_FR1TYPE(fcvt_d_s); + DEFINE_XFTYPE(fcvt_d_l); + DEFINE_XFTYPE(fcvt_d_lu); + DEFINE_XFTYPE(fcvt_d_w); + DEFINE_XFTYPE(fcvt_d_wu); + DEFINE_XFTYPE(fcvt_d_wu); + DEFINE_XFTYPE(fmv_d_x); + DEFINE_FXTYPE(fcvt_l_d); + DEFINE_FXTYPE(fcvt_lu_d); + DEFINE_FXTYPE(fcvt_w_d); + DEFINE_FXTYPE(fcvt_wu_d); + DEFINE_FXTYPE(fclass_d); + DEFINE_FXTYPE(fmv_x_d); + DEFINE_FXTYPE(feq_d); + DEFINE_FXTYPE(flt_d); + DEFINE_FXTYPE(fle_d); + + // provide a default disassembly for all instructions as a fallback + #define DECLARE_INSN(code, match, mask) \ + add_insn(new disasm_insn_t(#code " (args unknown)", match, mask, {})); + #include "encoding.h" + #undef DECLARE_INSN +} + +const disasm_insn_t* disassembler_t::lookup(insn_t insn) +{ + size_t idx = insn.bits() % HASH_SIZE; + for (size_t j = 0; j < chain[idx].size(); j++) + if(*chain[idx][j] == insn) + return chain[idx][j]; + + idx = HASH_SIZE; + for (size_t j = 0; j < chain[idx].size(); j++) + if(*chain[idx][j] == insn) + return chain[idx][j]; + + return NULL; +} + +void disassembler_t::add_insn(disasm_insn_t* insn) +{ + size_t idx = HASH_SIZE; + if (insn->get_mask() % HASH_SIZE == HASH_SIZE - 1) + idx = insn->get_match() % HASH_SIZE; + chain[idx].push_back(insn); +} + +disassembler_t::~disassembler_t() +{ + for (size_t i = 0; i < HASH_SIZE+1; i++) + for (size_t j = 0; j < chain[i].size(); j++) + delete chain[i][j]; +} diff --git a/spike_main/extensions.cc b/spike_main/extensions.cc new file mode 100644 index 0000000..315621f --- /dev/null +++ b/spike_main/extensions.cc @@ -0,0 +1,35 @@ +#include "extension.h" +#include +#include +#include + +static std::map>& extensions() +{ + static std::map> v; + return v; +} + +void register_extension(const char* name, std::function f) +{ + extensions()[name] = f; +} + +std::function find_extension(const char* name) +{ + if (!extensions().count(name)) { + // try to find extension xyz by loading libxyz.so + std::string libname = std::string("lib") + name + ".so"; + if (!dlopen(libname.c_str(), RTLD_LAZY)) { + fprintf(stderr, "couldn't find extension '%s' (or library '%s')\n", + name, libname.c_str()); + exit(-1); + } + if (!extensions().count(name)) { + fprintf(stderr, "couldn't find extension '%s' in shared library '%s'\n", + name, libname.c_str()); + exit(-1); + } + } + + return extensions()[name]; +} diff --git a/spike_main/riscv-dis.cc b/spike_main/riscv-dis.cc new file mode 100644 index 0000000..d0af451 --- /dev/null +++ b/spike_main/riscv-dis.cc @@ -0,0 +1,45 @@ +// See LICENSE for license details. + +// This little program finds occurrences of strings like +// DASM(ffabc013) +// in its input, then replaces them with the disassembly +// enclosed hexadecimal number, interpreted as a RISC-V +// instruction. + +#include "disasm.h" +#include "extension.h" +#include +#include +#include +#include +using namespace std; + +int main(int argc, char** argv) +{ + string s; + disassembler_t d; + + std::function extension; + option_parser_t parser; + parser.option(0, "extension", 1, [&](const char* s){extension = find_extension(s);}); + + while (getline(cin, s)) + { + for (size_t start = 0; (start = s.find("DASM(", start)) != string::npos; ) + { + size_t end = s.find(')', start); + if (end == string::npos) + break; + + size_t numstart = start + strlen("DASM("); + insn_bits_t bits = strtoull(&s[numstart], NULL, 16); + string dis = d.disassemble(bits); + s = s.substr(0, start) + dis + s.substr(end+1); + start += dis.length(); + } + + cout << s << '\n'; + } + + return 0; +} diff --git a/spike_main/spike.cc b/spike_main/spike.cc new file mode 100644 index 0000000..ab5cea5 --- /dev/null +++ b/spike_main/spike.cc @@ -0,0 +1,81 @@ +// See LICENSE for license details. + +#include "sim.h" +#include "htif.h" +#include "cachesim.h" +#include "extension.h" +#include +#include +#include +#include +#include +#include +#include +#include + +static void help() +{ + fprintf(stderr, "usage: spike [host options] [target options]\n"); + fprintf(stderr, "Host Options:\n"); + fprintf(stderr, " -p Simulate processors\n"); + fprintf(stderr, " -m Provide MB of target memory\n"); + fprintf(stderr, " -d Interactive debug mode\n"); + fprintf(stderr, " -g Track histogram of PCs\n"); + fprintf(stderr, " -h Print this help message\n"); + fprintf(stderr, " --ic=:: Instantiate a cache model with S sets,\n"); + fprintf(stderr, " --dc=:: W ways, and B-byte blocks (with S and\n"); + fprintf(stderr, " --l2=:: B both powers of 2).\n"); + fprintf(stderr, " --extension= Specify RoCC Extension\n"); + fprintf(stderr, " --extlib= Shared library to load\n"); + exit(1); +} + +int main(int argc, char** argv) +{ + bool debug = false; + bool histogram = false; + size_t nprocs = 1; + size_t mem_mb = 0; + std::unique_ptr ic; + std::unique_ptr dc; + std::unique_ptr l2; + std::function extension; + + 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('g', 0, 0, [&](const char* s){histogram = true;}); + parser.option('p', 0, 1, [&](const char* s){nprocs = atoi(s);}); + parser.option('m', 0, 1, [&](const char* s){mem_mb = atoi(s);}); + parser.option(0, "ic", 1, [&](const char* s){ic.reset(new icache_sim_t(s));}); + parser.option(0, "dc", 1, [&](const char* s){dc.reset(new dcache_sim_t(s));}); + parser.option(0, "l2", 1, [&](const char* s){l2.reset(cache_sim_t::construct(s, "L2$"));}); + parser.option(0, "extension", 1, [&](const char* s){extension = find_extension(s);}); + parser.option(0, "extlib", 1, [&](const char *s){ + void *lib = dlopen(s, RTLD_NOW | RTLD_GLOBAL); + if (lib == NULL) { + fprintf(stderr, "Unable to load extlib '%s': %s\n", s, dlerror()); + exit(-1); + } + }); + + auto argv1 = parser.parse(argv); + if (!*argv1) + help(); + std::vector htif_args(argv1, (const char*const*)argv + argc); + sim_t s(nprocs, mem_mb, htif_args); + + if (ic && l2) ic->set_miss_handler(&*l2); + if (dc && l2) dc->set_miss_handler(&*l2); + for (size_t i = 0; i < nprocs; i++) + { + if (ic) s.get_core(i)->get_mmu()->register_memtracer(&*ic); + if (dc) s.get_core(i)->get_mmu()->register_memtracer(&*dc); + if (extension) s.get_core(i)->register_extension(extension()); + } + + s.set_debug(debug); + s.set_histogram(histogram); + return s.run(); +} diff --git a/spike_main/spike_main.ac b/spike_main/spike_main.ac new file mode 100644 index 0000000..f8d63ce --- /dev/null +++ b/spike_main/spike_main.ac @@ -0,0 +1 @@ +AC_CHECK_LIB(dl, dlopen, [], [AC_MSG_ERROR([libdl is required])]) diff --git a/spike_main/spike_main.mk.in b/spike_main/spike_main.mk.in new file mode 100644 index 0000000..0ac70ef --- /dev/null +++ b/spike_main/spike_main.mk.in @@ -0,0 +1,14 @@ +spike_main_subproject_deps = \ + softfloat \ + riscv \ + +spike_main_install_prog_srcs = \ + spike.cc \ + riscv-dis.cc \ + xspike.cc \ + termios-xspike.cc \ + +spike_main_hdrs = \ + +spike_main_srcs = \ + extensions.cc \ diff --git a/spike_main/termios-xspike.cc b/spike_main/termios-xspike.cc new file mode 100644 index 0000000..e533933 --- /dev/null +++ b/spike_main/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 +#include +#include +#include +#include +#include + +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); +} diff --git a/spike_main/xspike.cc b/spike_main/xspike.cc new file mode 100644 index 0000000..4331dbe --- /dev/null +++ b/spike_main/xspike.cc @@ -0,0 +1,102 @@ +// See LICENSE for license details. + +// xspike forks an xterm for spike's target machine console, +// preserving the current terminal for debugging. + +#include +#include +#include +#include +#include +#include +#include +#include + +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; }; + + if ((xterm = fork_xterm(&tty_fd)) < 0) + { + fprintf(stderr, "could not open xterm\n"); + goto out; + } + + signal(SIGINT, handle_signal); + + if ((spike = fork_spike(tty_fd, argc, argv)) < 0) + { + fprintf(stderr, "could not open spike\n"); + goto close_xterm; + } + + while ((ret = waitpid(spike, &wait_status, 0)) < 0) + if (signal_exit) + break; + + if (ret < 0) // signal_exit + kill(spike, SIGTERM); + else + ret = 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; +}