return '\n'.join(res)
+sv_hdr_template = """\
+ reg_t sv_proc_t::%s(processor_t* p, insn_t s_insn, reg_t pc);
+"""
+
if __name__ == '__main__':
files = list_insns()
for (fname, insn) in files:
txt += find_registers(fname, insn, twin_predication,
immed_offset, is_branch)
f.write(txt)
+
#define str(s) #s
#include "sv.h"
+#include "sv_insn_redirect.h"
#ifdef INSN_TYPE_BRANCH
#define set_pc(x) insn.setpc(xlen, vlen, npc, x, *dest_offs, target_reg);
#endif
reg_t FN(processor_t* p, insn_t s_insn, reg_t pc)
+{
+ return p->s.FN(p, s_insn, pc);
+}
+
+reg_t sv_proc_t::FN(processor_t* p, insn_t s_insn, reg_t pc)
{
int xlen = ISASZ;
reg_t npc = sext_xlen(pc + insn_length(INSNCODE));
#include <limits.h>
#include <stdexcept>
#include <algorithm>
+#ifdef SPIKE_SIMPLEV
+#include "sv_insn_redirect.h"
+#endif
#undef STATE
#define STATE state
bool halt_on_reset)
: debug(false), halt_request(false), sim(sim), ext(NULL), id(id),
halt_on_reset(halt_on_reset), last_pc(1), executions(1)
+#ifdef SPIKE_SIMPLEV
+ , s()
+#endif
{
parse_isa_string(isa);
register_base_instructions();
#include "debug_rom_defines.h"
#ifdef SPIKE_SIMPLEV
#include "sv_decode.h"
+#include "sv_insn_redirect.h"
#endif
class processor_t;
// Track repeated executions for processor_t::disasm()
uint64_t last_pc, last_bits, executions;
+
+#ifdef SPIKE_SIMPLEV
+public:
+ sv_proc_t s;
+#endif
};
reg_t illegal_instruction(processor_t* p, insn_t insn, reg_t pc);
extension.h \
rocc.h \
insn_template.h \
+ sv.h \
+ sv_decode.h \
+ sv_insn_redirect.h \
mulhi.h \
debug_module.h \
debug_rom_defines.h \
debug_module.cc \
remote_bitbang.cc \
sv.cc \
+ sv_insn_redirect.cc \
jtag_dtm.cc \
$(riscv_gen_srcs) \
printf 'DEFINE_INSN(%s)\n' "$${insn}" ; \
done > $@.tmp
mv $@.tmp $@
+ python sv_proc_gen.py
$(riscv_gen_srcs): %.cc: insns/%.h insn_template.cc
sed 's/NAME/$(subst .cc,,$@)/' $(src_dir)/riscv/insn_template.cc | sed 's/OPCODE/$(call get_opcode,$(src_dir)/riscv/encoding.h,$(subst .cc,,$@))/' > $@
--- /dev/null
+#include "sv_insn_redirect.h"
+
+/*
+void (WRITE_RD)(reg_t value)
+{
+ WRITE_RD( value );
+}
+*/
--- /dev/null
+#ifndef SV_INSN_REDIRECT_H
+#define SV_INSN_REDIRECT_H
+
+#include "decode.h"
+
+//extern void (WRITE_RD)(reg_t value);
+
+class processor_t;
+
+class sv_proc_t
+{
+public:
+ sv_proc_t() {}
+#include "sv_insn_decl.h"
+};
+
+#endif
--- /dev/null
+#!/usr/bin/env python
+# Copyright (C) 2018 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
+
+""" identify registers used in riscv/insns/*.h and create code
+ that can be used in spike at runtime
+
+ the design of spike assumes that once an opcode is identified,
+ the role of decoding the instruction is implicitly rolled into
+ and included inside the function that emulates that opcode.
+
+ however there may be circumstances where the behaviour of an
+ instruction has to change depending on "tags" associated with
+ the registers (security extensions, simple-v extension).
+
+ therefore this code walks the instruction implementations
+ in riscv/insns/*.h looking for register usage patterns.
+ the resultant table can be used *prior* to the emulation,
+ without having to manually maintain such a table.
+"""
+
+import os
+import sys
+
+insns_dir = "./riscv/insns"
+def list_insns():
+ if len(sys.argv) == 2:
+ fullfname = sys.argv[1]
+ pth, fname = os.path.split(fullfname)
+ insn = fname[:-2]
+ return [(fullfname, insn)]
+
+ res = []
+ for fname in os.listdir(insns_dir):
+ if not fname.endswith(".h"):
+ continue
+ if fname.startswith("regs_"):
+ continue
+ insn = fname[:-2]
+ res.append((os.path.join(insns_dir, fname), insn))
+ return res
+
+sv_hdr_template = """\
+ reg_t (rv32_{0}) (processor_t* p, insn_t s_insn, reg_t pc);
+ reg_t (rv64_{0}) (processor_t* p, insn_t s_insn, reg_t pc);
+"""
+
+if __name__ == '__main__':
+ files = list_insns()
+ with open("riscv/sv_insn_decl.h", "w") as f:
+ for (fname, insn) in files:
+ f.write(sv_hdr_template.format(insn))
+