|
|
|
@ -7,7 +7,7 @@ import elftools.elf.elffile |
|
|
|
import elftools.elf.enums |
|
|
|
import elftools.elf.sections |
|
|
|
|
|
|
|
EXT_OPTS = { |
|
|
|
QEMU_EXT_OPTS = { |
|
|
|
"zba": "zba=true", |
|
|
|
"zbb": "zbb=true", |
|
|
|
"zbc": "zbc=true", |
|
|
|
@ -16,12 +16,34 @@ EXT_OPTS = { |
|
|
|
"zve32f": "Zve32f=true", |
|
|
|
"zve64f": "Zve64f=true", |
|
|
|
"zfh": "Zfh=true", |
|
|
|
"zfhmin": "Zfhmin=true", |
|
|
|
"zfhmin": "Zfhmin=true", |
|
|
|
"zhinx": "zhinx=true", |
|
|
|
"zfinx": "zfinx=true", |
|
|
|
"zdinx": "zdinx=true", |
|
|
|
} |
|
|
|
|
|
|
|
SPIKE_EXT_NOT_ALLOWED = [ |
|
|
|
"zve32x", |
|
|
|
"zve32f", |
|
|
|
"zve64x", |
|
|
|
"zve64f", |
|
|
|
"zve64d", |
|
|
|
"zvl32b", |
|
|
|
"zvl64b", |
|
|
|
"zvl128b", |
|
|
|
"zvl256b", |
|
|
|
"zvl512b", |
|
|
|
"zvl1024b", |
|
|
|
"zvl2048b", |
|
|
|
"zvl4096b", |
|
|
|
] |
|
|
|
|
|
|
|
CPU_OPTIONS = { |
|
|
|
"xlen": "", |
|
|
|
"vlen": "", |
|
|
|
"extensions": [], |
|
|
|
} |
|
|
|
|
|
|
|
SUPPORTTED_EXTS = "iemafdcbvph" |
|
|
|
MC_EXT_PREFIX = "zsx" |
|
|
|
|
|
|
|
@ -29,8 +51,13 @@ def parse_opt(argv): |
|
|
|
parser = argparse.ArgumentParser() |
|
|
|
parser.add_argument('-march', '--with-arch', type=str, dest='march') |
|
|
|
parser.add_argument('-selftest', action='store_true') |
|
|
|
parser.add_argument('--get-riscv-tag', type=str) |
|
|
|
parser.add_argument('--get-elf-class', type=str) |
|
|
|
parser.add_argument('--elf-file-path', type=str) |
|
|
|
parser.add_argument('--print-xlen', action='store_true', default=False) |
|
|
|
parser.add_argument('--print-vlen', action='store_true', default=False) |
|
|
|
parser.add_argument('--print-qemu-cpu', action='store_true', default=False) |
|
|
|
parser.add_argument('--print-spike-isa', action='store_true', default=False) |
|
|
|
parser.add_argument('--print-spike-varch', action='store_true', |
|
|
|
default=False) |
|
|
|
opt = parser.parse_args() |
|
|
|
return opt |
|
|
|
|
|
|
|
@ -119,31 +146,47 @@ def get_vlen(ext_dict): |
|
|
|
vlen = max(vlen, zvelen) |
|
|
|
return vlen |
|
|
|
|
|
|
|
def conver_arch_to_qemu_cpu_opt(march): |
|
|
|
if len(march) < 5: |
|
|
|
return None |
|
|
|
|
|
|
|
ext_dict = parse_march(march) |
|
|
|
|
|
|
|
cpu_opt = [] |
|
|
|
cpu_opt.append(march[0:4]) # rv32 or rv64 |
|
|
|
|
|
|
|
vlen = get_vlen(ext_dict) |
|
|
|
def print_qemu_cpu(): |
|
|
|
cpu_options = [] |
|
|
|
cpu_options.append("rv{0}".format(CPU_OPTIONS['xlen'])) |
|
|
|
|
|
|
|
if vlen != 0: |
|
|
|
cpu_opt.append("vlen=%d" % vlen) |
|
|
|
if CPU_OPTIONS['vlen']: |
|
|
|
cpu_options.append("vlen={0}".format(CPU_OPTIONS['vlen'])) |
|
|
|
|
|
|
|
disable_all_fd = False |
|
|
|
for ext in ext_dict.keys(): |
|
|
|
if ext in EXT_OPTS: |
|
|
|
cpu_opt.append(EXT_OPTS[ext]) |
|
|
|
for ext in CPU_OPTIONS['extensions']: |
|
|
|
if ext in QEMU_EXT_OPTS: |
|
|
|
cpu_options.append(QEMU_EXT_OPTS[ext]) |
|
|
|
|
|
|
|
if ext in ['zhinx', 'zfinx', 'zdinx']: |
|
|
|
disable_all_fd = True |
|
|
|
|
|
|
|
if disable_all_fd: |
|
|
|
cpu_opt.append("f=false") |
|
|
|
cpu_opt.append("d=false") |
|
|
|
return ",".join(cpu_opt) |
|
|
|
cpu_options.append("f=false") |
|
|
|
cpu_options.append("d=false") |
|
|
|
|
|
|
|
return ",".join(cpu_options) |
|
|
|
|
|
|
|
def print_spike_isa(): |
|
|
|
cpu_options = [] |
|
|
|
cpu_options.append("rv{0}".format(CPU_OPTIONS['xlen'])) |
|
|
|
|
|
|
|
for ext in CPU_OPTIONS['extensions']: |
|
|
|
if ext not in SPIKE_EXT_NOT_ALLOWED: |
|
|
|
normalized_ext_name = ext |
|
|
|
|
|
|
|
if len(ext) > 1: |
|
|
|
normalized_ext_name = "_{0}".format(normalized_ext_name) |
|
|
|
|
|
|
|
cpu_options.append(normalized_ext_name) |
|
|
|
|
|
|
|
return "".join(cpu_options) |
|
|
|
|
|
|
|
def print_spike_varch(): |
|
|
|
if not CPU_OPTIONS['vlen']: |
|
|
|
return "" |
|
|
|
|
|
|
|
return "vlen:{0},elen:{1}".format(CPU_OPTIONS['vlen'], CPU_OPTIONS['xlen']) |
|
|
|
|
|
|
|
class TestArchStringParse(unittest.TestCase): |
|
|
|
def _test(self, arch, expected_arch_list, expected_vlen=0): |
|
|
|
@ -168,7 +211,7 @@ def open_elf(path): |
|
|
|
raise Exception("%s is not ELF file!" % path) |
|
|
|
return elffile |
|
|
|
|
|
|
|
def read_elf_class(path): |
|
|
|
def get_xlen(path): |
|
|
|
elffile = open_elf(path) |
|
|
|
return elffile.elfclass |
|
|
|
|
|
|
|
@ -204,21 +247,41 @@ def read_arch_attr (path): |
|
|
|
return val |
|
|
|
raise Exception("Not found ELF attribute in %s?" % path) |
|
|
|
|
|
|
|
def parse_elf_file(elf_file_path): |
|
|
|
extensions = [] |
|
|
|
extension_dict = parse_march(read_arch_attr(elf_file_path)) |
|
|
|
|
|
|
|
for extension in extension_dict.keys(): |
|
|
|
extensions.append(extension) |
|
|
|
|
|
|
|
CPU_OPTIONS["extensions"] = extensions |
|
|
|
CPU_OPTIONS["vlen"] = get_vlen(extension_dict) |
|
|
|
CPU_OPTIONS["xlen"] = get_xlen(elf_file_path) |
|
|
|
|
|
|
|
def main(argv): |
|
|
|
opt = parse_opt(argv) |
|
|
|
if opt.selftest: |
|
|
|
selftest() |
|
|
|
return 0 |
|
|
|
if (opt.get_elf_class): |
|
|
|
elf_class = read_elf_class (opt.get_elf_class) |
|
|
|
print (elf_class) |
|
|
|
|
|
|
|
parse_elf_file(opt.elf_file_path) |
|
|
|
|
|
|
|
if opt.print_xlen: |
|
|
|
print(CPU_OPTIONS['xlen']) |
|
|
|
return |
|
|
|
if (opt.get_riscv_tag): |
|
|
|
march = read_arch_attr (opt.get_riscv_tag) |
|
|
|
else: |
|
|
|
march = opt.march |
|
|
|
cpu_opt = conver_arch_to_qemu_cpu_opt(march) |
|
|
|
print (cpu_opt) |
|
|
|
|
|
|
|
if opt.print_vlen: |
|
|
|
print(CPU_OPTIONS['vlen']) |
|
|
|
return |
|
|
|
|
|
|
|
if opt.print_qemu_cpu: |
|
|
|
print(print_qemu_cpu()) |
|
|
|
|
|
|
|
if opt.print_spike_isa: |
|
|
|
print(print_spike_isa()) |
|
|
|
|
|
|
|
if opt.print_spike_varch: |
|
|
|
print(print_spike_varch()) |
|
|
|
|
|
|
|
if __name__ == '__main__': |
|
|
|
sys.exit(main(sys.argv)) |
|
|
|
|