Browse Source

Construct an isa_parser_t and pass it to processor_t constructor

This is a minor change, turning processor_t from a child class of
isa_parser_t into a class that contains an isa_parser_t as a field.
The point is that it is a step toward separating out
"configuration" (and ISA string parsing) from processor state. This
should be helpful for rejigging things so that we construct more from
a supplied device tree.
pull/945/head
Rupert Swarbrick 5 years ago
parent
commit
cb632586bd
  1. 4
      riscv/csrs.cc
  2. 4
      riscv/dts.cc
  3. 4
      riscv/insns/vmv_x_s.h
  4. 8
      riscv/interactive.cc
  5. 27
      riscv/processor.cc
  6. 17
      riscv/processor.h
  7. 5
      riscv/sim.cc
  8. 1
      riscv/sim.h
  9. 7
      spike_main/spike-log-parser.cc

4
riscv/csrs.cc

@ -304,8 +304,8 @@ reg_t cause_csr_t::read() const noexcept {
// When reading, the interrupt bit needs to adjust to xlen. Spike does // When reading, the interrupt bit needs to adjust to xlen. Spike does
// not generally support dynamic xlen, but this code was (partly) // not generally support dynamic xlen, but this code was (partly)
// there since at least 2015 (ea58df8 and c4350ef). // there since at least 2015 (ea58df8 and c4350ef).
if (proc->get_max_xlen() > proc->get_xlen()) // Move interrupt bit to top of xlen if (proc->get_isa().get_max_xlen() > proc->get_xlen()) // Move interrupt bit to top of xlen
return val | ((val >> (proc->get_max_xlen()-1)) << (proc->get_xlen()-1)); return val | ((val >> (proc->get_isa().get_max_xlen()-1)) << (proc->get_xlen()-1));
return val; return val;
} }

4
riscv/dts.cc

@ -55,8 +55,8 @@ std::string make_dts(size_t insns_per_rtc_tick, size_t cpu_hz,
" reg = <" << i << ">;\n" " reg = <" << i << ">;\n"
" status = \"okay\";\n" " status = \"okay\";\n"
" compatible = \"riscv\";\n" " compatible = \"riscv\";\n"
" riscv,isa = \"" << procs[i]->get_isa_string() << "\";\n" " riscv,isa = \"" << procs[i]->get_isa().get_isa_string() << "\";\n"
" mmu-type = \"riscv," << (procs[i]->get_max_xlen() <= 32 ? "sv32" : "sv48") << "\";\n" " mmu-type = \"riscv," << (procs[i]->get_isa().get_max_xlen() <= 32 ? "sv32" : "sv48") << "\";\n"
" riscv,pmpregions = <16>;\n" " riscv,pmpregions = <16>;\n"
" riscv,pmpgranularity = <4>;\n" " riscv,pmpgranularity = <4>;\n"
" clock-frequency = <" << cpu_hz << ">;\n" " clock-frequency = <" << cpu_hz << ">;\n"

4
riscv/insns/vmv_x_s.h

@ -1,7 +1,7 @@
// vmv_x_s: rd = vs2[rs1] // vmv_x_s: rd = vs2[rs1]
require_vector(true); require_vector(true);
require(insn.v_vm() == 1); require(insn.v_vm() == 1);
uint64_t xmask = UINT64_MAX >> (64 - P.get_max_xlen()); uint64_t xmask = UINT64_MAX >> (64 - P.get_isa().get_max_xlen());
reg_t rs1 = RS1; reg_t rs1 = RS1;
reg_t sew = P.VU.vsew; reg_t sew = P.VU.vsew;
reg_t rs2_num = insn.rs2(); reg_t rs2_num = insn.rs2();
@ -20,7 +20,7 @@ if (!(rs1 >= 0 && rs1 < (P.VU.get_vlen() / sew))) {
WRITE_RD(P.VU.elt<int32_t>(rs2_num, rs1)); WRITE_RD(P.VU.elt<int32_t>(rs2_num, rs1));
break; break;
case e64: case e64:
if (P.get_max_xlen() <= sew) if (P.get_isa().get_max_xlen() <= sew)
WRITE_RD(P.VU.elt<uint64_t>(rs2_num, rs1) & xmask); WRITE_RD(P.VU.elt<uint64_t>(rs2_num, rs1) & xmask);
else else
WRITE_RD(P.VU.elt<uint64_t>(rs2_num, rs1)); WRITE_RD(P.VU.elt<uint64_t>(rs2_num, rs1));

8
riscv/interactive.cc

@ -273,7 +273,7 @@ void sim_t::interactive_pc(const std::string& cmd, const std::vector<std::string
throw trap_interactive(); throw trap_interactive();
processor_t *p = get_core(args[0]); processor_t *p = get_core(args[0]);
int max_xlen = p->get_max_xlen(); int max_xlen = p->get_isa().get_max_xlen();
std::ostream out(sout_.rdbuf()); std::ostream out(sout_.rdbuf());
out << std::hex << std::setfill('0') << "0x" << std::setw(max_xlen/4) out << std::hex << std::setfill('0') << "0x" << std::setw(max_xlen/4)
@ -379,7 +379,7 @@ void sim_t::interactive_reg(const std::string& cmd, const std::vector<std::strin
throw trap_interactive(); throw trap_interactive();
processor_t *p = get_core(args[0]); processor_t *p = get_core(args[0]);
int max_xlen = p->get_max_xlen(); int max_xlen = p->get_isa().get_max_xlen();
std::ostream out(sout_.rdbuf()); std::ostream out(sout_.rdbuf());
out << std::hex; out << std::hex;
@ -481,7 +481,7 @@ reg_t sim_t::get_mem(const std::vector<std::string>& args)
void sim_t::interactive_mem(const std::string& cmd, const std::vector<std::string>& args) void sim_t::interactive_mem(const std::string& cmd, const std::vector<std::string>& args)
{ {
int max_xlen = procs[0]->get_max_xlen(); int max_xlen = procs[0]->get_isa().get_max_xlen();
std::ostream out(sout_.rdbuf()); std::ostream out(sout_.rdbuf());
out << std::hex << "0x" << std::setfill('0') << std::setw(max_xlen/4) out << std::hex << "0x" << std::setfill('0') << std::setw(max_xlen/4)
@ -541,7 +541,7 @@ void sim_t::interactive_until(const std::string& cmd, const std::vector<std::str
throw trap_interactive(); throw trap_interactive();
// mask bits above max_xlen // mask bits above max_xlen
int max_xlen = procs[strtol(args[1].c_str(),NULL,10)]->get_max_xlen(); int max_xlen = procs[strtol(args[1].c_str(),NULL,10)]->get_isa().get_max_xlen();
if (max_xlen == 32) val &= 0xFFFFFFFF; if (max_xlen == 32) val &= 0xFFFFFFFF;
std::vector<std::string> args2; std::vector<std::string> args2;

27
riscv/processor.cc

@ -23,10 +23,10 @@
#undef STATE #undef STATE
#define STATE state #define STATE state
processor_t::processor_t(const char* isa, const char* priv, const char* varch, processor_t::processor_t(isa_parser_t isa, const char* varch,
simif_t* sim, uint32_t id, bool halt_on_reset, simif_t* sim, uint32_t id, bool halt_on_reset,
FILE* log_file, std::ostream& sout_) FILE* log_file, std::ostream& sout_)
: isa_parser_t(isa, priv), debug(false), halt_request(HR_NONE), sim(sim), id(id), xlen(0), : debug(false), halt_request(HR_NONE), isa(isa), sim(sim), id(id), xlen(0),
histogram_enabled(false), log_commits_enabled(false), histogram_enabled(false), log_commits_enabled(false),
log_file(log_file), sout_(sout_.rdbuf()), halt_on_reset(halt_on_reset), log_file(log_file), sout_(sout_.rdbuf()), halt_on_reset(halt_on_reset),
impl_table(256, false), last_pc(1), executions(1) impl_table(256, false), last_pc(1), executions(1)
@ -45,16 +45,16 @@ processor_t::processor_t(const char* isa, const char* priv, const char* varch,
register_base_instructions(); register_base_instructions();
mmu = new mmu_t(sim, this); mmu = new mmu_t(sim, this);
disassembler = new disassembler_t(this); disassembler = new disassembler_t(&isa);
for (auto e : isa_extensions) for (auto e : isa.get_extensions())
register_extension(e.second); register_extension(e.second);
set_pmp_granularity(1 << PMP_SHIFT); set_pmp_granularity(1 << PMP_SHIFT);
set_pmp_num(state.max_pmp); set_pmp_num(state.max_pmp);
if (max_xlen == 32) if (isa.get_max_xlen() == 32)
set_mmu_capability(IMPL_MMU_SV32); set_mmu_capability(IMPL_MMU_SV32);
else if (max_xlen == 64) else if (isa.get_max_xlen() == 64)
set_mmu_capability(IMPL_MMU_SV48); set_mmu_capability(IMPL_MMU_SV48);
reset(); reset();
@ -355,7 +355,7 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv)
bad_isa_string(str, "single 'X' is not a proper name"); bad_isa_string(str, "single 'X' is not a proper name");
} else if (ext_str != "xdummy") { } else if (ext_str != "xdummy") {
extension_t* x = find_extension(ext_str.substr(1).c_str())(); extension_t* x = find_extension(ext_str.substr(1).c_str())();
if (!isa_extensions.insert(std::make_pair(x->name(), x)).second) { if (!extensions.insert(std::make_pair(x->name(), x)).second) {
fprintf(stderr, "extensions must have unique names (got two named \"%s\"!)\n", x->name()); fprintf(stderr, "extensions must have unique names (got two named \"%s\"!)\n", x->name());
abort(); abort();
} }
@ -411,7 +411,7 @@ void state_t::reset(processor_t* const proc, reg_t max_isa)
// This assumes xlen is always max_xlen, which is true today (see // This assumes xlen is always max_xlen, which is true today (see
// mstatus_csr_t::unlogged_write()): // mstatus_csr_t::unlogged_write()):
auto xlen = proc->get_max_xlen(); auto xlen = proc->get_isa().get_max_xlen();
prv = PRV_M; prv = PRV_M;
v = false; v = false;
@ -716,8 +716,8 @@ void processor_t::enable_log_commits()
void processor_t::reset() void processor_t::reset()
{ {
xlen = max_xlen; xlen = isa.get_max_xlen();
state.reset(this, max_isa); state.reset(this, isa.get_max_isa());
state.dcsr->halt = halt_on_reset; state.dcsr->halt = halt_on_reset;
halt_on_reset = false; halt_on_reset = false;
VU.reset(); VU.reset();
@ -852,7 +852,7 @@ void processor_t::take_interrupt(reg_t pending_interrupts)
else else
abort(); abort();
throw trap_t(((reg_t)1 << (max_xlen-1)) | ctz(enabled_interrupts)); throw trap_t(((reg_t)1 << (isa.get_max_xlen()-1)) | ctz(enabled_interrupts));
} }
} }
@ -916,6 +916,8 @@ void processor_t::debug_output_log(std::stringstream *s)
void processor_t::take_trap(trap_t& t, reg_t epc) void processor_t::take_trap(trap_t& t, reg_t epc)
{ {
unsigned max_xlen = isa.get_max_xlen();
if (debug) { if (debug) {
std::stringstream s; // first put everything in a string, later send it to output std::stringstream s; // first put everything in a string, later send it to output
s << "core " << std::dec << std::setfill(' ') << std::setw(3) << id s << "core " << std::dec << std::setfill(' ') << std::setw(3) << id
@ -1039,6 +1041,8 @@ void processor_t::disasm(insn_t insn)
<< ": Executed " << executions << " times" << std::endl; << ": Executed " << executions << " times" << std::endl;
} }
unsigned max_xlen = isa.get_max_xlen();
s << "core " << std::dec << std::setfill(' ') << std::setw(3) << id s << "core " << std::dec << std::setfill(' ') << std::setw(3) << id
<< std::hex << ": 0x" << std::setfill('0') << std::setw(max_xlen/4) << std::hex << ": 0x" << std::setfill('0') << std::setw(max_xlen/4)
<< zext(state.pc, max_xlen) << " (0x" << std::setw(8) << bits << ") " << zext(state.pc, max_xlen) << " (0x" << std::setw(8) << bits << ") "
@ -1056,6 +1060,7 @@ void processor_t::disasm(insn_t insn)
int processor_t::paddr_bits() int processor_t::paddr_bits()
{ {
unsigned max_xlen = isa.get_max_xlen();
assert(xlen == max_xlen); assert(xlen == max_xlen);
return max_xlen == 64 ? 50 : 34; return max_xlen == 64 ? 50 : 34;
} }

17
riscv/processor.h

@ -322,23 +322,28 @@ public:
else else
return extension_table[ext]; return extension_table[ext];
} }
const std::unordered_map<std::string, extension_t*> &
get_extensions() const { return extensions; }
protected: protected:
unsigned max_xlen; unsigned max_xlen;
reg_t max_isa; reg_t max_isa;
std::vector<bool> extension_table; std::vector<bool> extension_table;
std::string isa_string; std::string isa_string;
std::unordered_map<std::string, extension_t*> isa_extensions; std::unordered_map<std::string, extension_t*> extensions;
}; };
// this class represents one processor in a RISC-V machine. // this class represents one processor in a RISC-V machine.
class processor_t : public abstract_device_t, public isa_parser_t class processor_t : public abstract_device_t
{ {
public: public:
processor_t(const char* isa, const char* priv, const char* varch, processor_t(isa_parser_t isa, const char* varch,
simif_t* sim, uint32_t id, bool halt_on_reset, simif_t* sim, uint32_t id, bool halt_on_reset,
FILE *log_file, std::ostream& sout_); // because of command line option --log and -s we need both FILE *log_file, std::ostream& sout_); // because of command line option --log and -s we need both
~processor_t(); ~processor_t();
const isa_parser_t &get_isa() { return isa; }
void set_debug(bool value); void set_debug(bool value);
void set_histogram(bool value); void set_histogram(bool value);
#ifdef RISCV_ENABLE_COMMITLOG #ifdef RISCV_ENABLE_COMMITLOG
@ -374,7 +379,7 @@ public:
if (ext >= 'A' && ext <= 'Z') if (ext >= 'A' && ext <= 'Z')
return state.misa->extension_enabled(ext); return state.misa->extension_enabled(ext);
else else
return extension_table[ext]; return isa.extension_enabled(ext);
} }
// Is this extension enabled? and abort if this extension can // Is this extension enabled? and abort if this extension can
// possibly be disabled dynamically. Useful for documenting // possibly be disabled dynamically. Useful for documenting
@ -383,7 +388,7 @@ public:
if (ext >= 'A' && ext <= 'Z') if (ext >= 'A' && ext <= 'Z')
return state.misa->extension_enabled_const(ext); return state.misa->extension_enabled_const(ext);
else else
return extension_table[ext]; // assume this can't change return isa.extension_enabled(ext); // assume this can't change
} }
void set_impl(uint8_t impl, bool val) { impl_table[impl] = val; } void set_impl(uint8_t impl, bool val) { impl_table[impl] = val; }
bool supports_impl(uint8_t impl) const { bool supports_impl(uint8_t impl) const {
@ -512,6 +517,8 @@ public:
const char* get_symbol(uint64_t addr); const char* get_symbol(uint64_t addr);
private: private:
isa_parser_t isa;
simif_t* sim; simif_t* sim;
mmu_t* mmu; // main memory is always accessed via the mmu mmu_t* mmu; // main memory is always accessed via the mmu
std::unordered_map<std::string, extension_t*> custom_extensions; std::unordered_map<std::string, extension_t*> custom_extensions;

5
riscv/sim.cc

@ -28,7 +28,7 @@ static void handle_signal(int sig)
signal(sig, &handle_signal); signal(sig, &handle_signal);
} }
sim_t::sim_t(const char* isa, const char* priv, const char* varch, sim_t::sim_t(const char* isa_string, const char* priv, const char* varch,
size_t nprocs, bool halted, bool real_time_clint, size_t nprocs, bool halted, bool real_time_clint,
reg_t initrd_start, reg_t initrd_end, const char* bootargs, reg_t initrd_start, reg_t initrd_end, const char* bootargs,
reg_t start_pc, std::vector<std::pair<reg_t, mem_t*>> mems, reg_t start_pc, std::vector<std::pair<reg_t, mem_t*>> mems,
@ -43,6 +43,7 @@ sim_t::sim_t(const char* isa, const char* priv, const char* varch,
#endif #endif
FILE *cmd_file) // needed for command line option --cmd FILE *cmd_file) // needed for command line option --cmd
: htif_t(args), : htif_t(args),
isa(isa_string, priv),
mems(mems), mems(mems),
plugin_devices(plugin_devices), plugin_devices(plugin_devices),
procs(std::max(nprocs, size_t(1))), procs(std::max(nprocs, size_t(1))),
@ -91,7 +92,7 @@ sim_t::sim_t(const char* isa, const char* priv, const char* varch,
for (size_t i = 0; i < nprocs; i++) { for (size_t i = 0; i < nprocs; i++) {
int hart_id = hartids.empty() ? i : hartids[i]; int hart_id = hartids.empty() ? i : hartids[i];
procs[i] = new processor_t(isa, priv, varch, this, hart_id, halted, procs[i] = new processor_t(isa, varch, this, hart_id, halted,
log_file.get(), sout_); log_file.get(), sout_);
} }

1
riscv/sim.h

@ -70,6 +70,7 @@ public:
void proc_reset(unsigned id); void proc_reset(unsigned id);
private: private:
isa_parser_t isa;
std::vector<std::pair<reg_t, mem_t*>> mems; std::vector<std::pair<reg_t, mem_t*>> mems;
std::vector<std::pair<reg_t, abstract_device_t*>> plugin_devices; std::vector<std::pair<reg_t, abstract_device_t*>> plugin_devices;
mmu_t* debug_mmu; // debug port into main memory mmu_t* debug_mmu; // debug port into main memory

7
spike_main/spike-log-parser.cc

@ -19,15 +19,16 @@ using namespace std;
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
string s; string s;
const char* isa = DEFAULT_ISA; const char* isa_string = DEFAULT_ISA;
std::function<extension_t*()> extension; std::function<extension_t*()> extension;
option_parser_t parser; option_parser_t parser;
parser.option(0, "extension", 1, [&](const char* s){extension = find_extension(s);}); parser.option(0, "extension", 1, [&](const char* s){extension = find_extension(s);});
parser.option(0, "isa", 1, [&](const char* s){isa = s;}); parser.option(0, "isa", 1, [&](const char* s){isa_string = s;});
parser.parse(argv); parser.parse(argv);
processor_t p(isa, DEFAULT_PRIV, DEFAULT_VARCH, 0, 0, false, nullptr, cerr); isa_parser_t isa(isa_string, DEFAULT_PRIV);
processor_t p(isa, DEFAULT_VARCH, 0, 0, false, nullptr, cerr);
if (extension) { if (extension) {
p.register_extension(extension()); p.register_extension(extension());
} }

Loading…
Cancel
Save