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
// not generally support dynamic xlen, but this code was (partly)
// there since at least 2015 (ea58df8 and c4350ef).
if (proc->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));
if (proc->get_isa().get_max_xlen() > proc->get_xlen()) // Move interrupt bit to top of xlen
return val | ((val >> (proc->get_isa().get_max_xlen()-1)) << (proc->get_xlen()-1));
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"
" status = \"okay\";\n"
" compatible = \"riscv\";\n"
" riscv,isa = \"" << procs[i]->get_isa_string() << "\";\n"
" mmu-type = \"riscv," << (procs[i]->get_max_xlen() <= 32 ? "sv32" : "sv48") << "\";\n"
" riscv,isa = \"" << procs[i]->get_isa().get_isa_string() << "\";\n"
" mmu-type = \"riscv," << (procs[i]->get_isa().get_max_xlen() <= 32 ? "sv32" : "sv48") << "\";\n"
" riscv,pmpregions = <16>;\n"
" riscv,pmpgranularity = <4>;\n"
" clock-frequency = <" << cpu_hz << ">;\n"

4
riscv/insns/vmv_x_s.h

@ -1,7 +1,7 @@
// vmv_x_s: rd = vs2[rs1]
require_vector(true);
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 sew = P.VU.vsew;
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));
break;
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);
else
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();
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());
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();
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());
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)
{
int max_xlen = procs[0]->get_max_xlen();
int max_xlen = procs[0]->get_isa().get_max_xlen();
std::ostream out(sout_.rdbuf());
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();
// 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;
std::vector<std::string> args2;

27
riscv/processor.cc

@ -23,10 +23,10 @@
#undef 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,
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),
log_file(log_file), sout_(sout_.rdbuf()), halt_on_reset(halt_on_reset),
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();
mmu = new mmu_t(sim, this);
disassembler = new disassembler_t(this);
for (auto e : isa_extensions)
disassembler = new disassembler_t(&isa);
for (auto e : isa.get_extensions())
register_extension(e.second);
set_pmp_granularity(1 << PMP_SHIFT);
set_pmp_num(state.max_pmp);
if (max_xlen == 32)
if (isa.get_max_xlen() == 32)
set_mmu_capability(IMPL_MMU_SV32);
else if (max_xlen == 64)
else if (isa.get_max_xlen() == 64)
set_mmu_capability(IMPL_MMU_SV48);
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");
} else if (ext_str != "xdummy") {
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());
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
// mstatus_csr_t::unlogged_write()):
auto xlen = proc->get_max_xlen();
auto xlen = proc->get_isa().get_max_xlen();
prv = PRV_M;
v = false;
@ -716,8 +716,8 @@ void processor_t::enable_log_commits()
void processor_t::reset()
{
xlen = max_xlen;
state.reset(this, max_isa);
xlen = isa.get_max_xlen();
state.reset(this, isa.get_max_isa());
state.dcsr->halt = halt_on_reset;
halt_on_reset = false;
VU.reset();
@ -852,7 +852,7 @@ void processor_t::take_interrupt(reg_t pending_interrupts)
else
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)
{
unsigned max_xlen = isa.get_max_xlen();
if (debug) {
std::stringstream s; // first put everything in a string, later send it to output
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;
}
unsigned max_xlen = isa.get_max_xlen();
s << "core " << std::dec << std::setfill(' ') << std::setw(3) << id
<< std::hex << ": 0x" << std::setfill('0') << std::setw(max_xlen/4)
<< 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()
{
unsigned max_xlen = isa.get_max_xlen();
assert(xlen == max_xlen);
return max_xlen == 64 ? 50 : 34;
}

17
riscv/processor.h

@ -322,23 +322,28 @@ public:
else
return extension_table[ext];
}
const std::unordered_map<std::string, extension_t*> &
get_extensions() const { return extensions; }
protected:
unsigned max_xlen;
reg_t max_isa;
std::vector<bool> extension_table;
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.
class processor_t : public abstract_device_t, public isa_parser_t
class processor_t : public abstract_device_t
{
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,
FILE *log_file, std::ostream& sout_); // because of command line option --log and -s we need both
~processor_t();
const isa_parser_t &get_isa() { return isa; }
void set_debug(bool value);
void set_histogram(bool value);
#ifdef RISCV_ENABLE_COMMITLOG
@ -374,7 +379,7 @@ public:
if (ext >= 'A' && ext <= 'Z')
return state.misa->extension_enabled(ext);
else
return extension_table[ext];
return isa.extension_enabled(ext);
}
// Is this extension enabled? and abort if this extension can
// possibly be disabled dynamically. Useful for documenting
@ -383,7 +388,7 @@ public:
if (ext >= 'A' && ext <= 'Z')
return state.misa->extension_enabled_const(ext);
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; }
bool supports_impl(uint8_t impl) const {
@ -512,6 +517,8 @@ public:
const char* get_symbol(uint64_t addr);
private:
isa_parser_t isa;
simif_t* sim;
mmu_t* mmu; // main memory is always accessed via the mmu
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);
}
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,
reg_t initrd_start, reg_t initrd_end, const char* bootargs,
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
FILE *cmd_file) // needed for command line option --cmd
: htif_t(args),
isa(isa_string, priv),
mems(mems),
plugin_devices(plugin_devices),
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++) {
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_);
}

1
riscv/sim.h

@ -70,6 +70,7 @@ public:
void proc_reset(unsigned id);
private:
isa_parser_t isa;
std::vector<std::pair<reg_t, mem_t*>> mems;
std::vector<std::pair<reg_t, abstract_device_t*>> plugin_devices;
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)
{
string s;
const char* isa = DEFAULT_ISA;
const char* isa_string = DEFAULT_ISA;
std::function<extension_t*()> extension;
option_parser_t parser;
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);
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) {
p.register_extension(extension());
}

Loading…
Cancel
Save