#!/usr/bin/python3 import argparse import sys import unittest EXT_OPTS = { "zba": "zba=true", "zbb": "zbb=true", "zbc": "zbc=true", "zbs": "zbs=true", "v": "v=true", "zve32f": "Zve32f=true", "zve64f": "Zve64f=true", "zfh": "Zfh=true", "zfhmin": "Zfhmin=true", "zhinx": "zhinx=true", "zfinx": "zfinx=true", "zdinx": "zdinx=true", } SUPPORTTED_EXTS = "iemafdcbvph" MC_EXT_PREFIX = "zsx" def parse_opt(argv): parser = argparse.ArgumentParser() parser.add_argument('-march', '--with-arch', type=str, dest='march') parser.add_argument('-selftest', action='store_true') opt = parser.parse_args() return opt def parse_mc_ext(ext_str, idx): end_idx = ext_str[idx+1:].find('_') if end_idx == -1: end_idx = len(ext_str) else: end_idx = end_idx + idx + 1 major = 0 minor = 0 version_begin_idx = end_idx if ext_str[end_idx-1].isdigit(): # This ext is come with version. v_idx = end_idx - 1 while (ext_str[v_idx].isdigit()) and v_idx > idx: v_idx -= 1 major = int(ext_str[v_idx+1:end_idx]) version_begin_idx = v_idx+1 if (ext_str[v_idx] == 'p'): minor = major major_v_idx = v_idx - 1 while (ext_str[major_v_idx].isdigit()) and major_v_idx > idx: major_v_idx -= 1 major = int(ext_str[major_v_idx+1:v_idx]) version_begin_idx = major_v_idx+1 return end_idx, ext_str[idx:version_begin_idx], major, minor def parse_version(ext_str, idx): major = 2 minor = 0 strlen = len(ext_str) end_idx = idx + 1 if idx+1 < strlen and ext_str[idx+1].isdigit(): v_idx = idx + 1 while v_idx < strlen and (ext_str[v_idx].isdigit()): v_idx += 1 major = int(ext_str[idx+1:v_idx]) end_idx = v_idx if (ext_str[v_idx] == 'p'): minor_v_idx = v_idx + 1 while minor_v_idx < strlen and (ext_str[minor_v_idx].isdigit()): minor_v_idx += 1 minor = int(ext_str[v_idx+1:minor_v_idx]) end_idx = minor_v_idx return end_idx, ext_str[idx], major, minor def parse_march(march): if len(march) < 5: return None march = march.replace("rv64g", "rv64imafd").replace("rv32g", "rv32imafd") if march[0:5] not in ['rv64i', 'rv32i', 'rv32e']: print (march[0:5]) return None ext_str = march[4:] idx = 0 extstrlens = len(ext_str) exts = dict() while idx < extstrlens: if ext_str[idx] in SUPPORTTED_EXTS: idx, ext_name, major, minor = parse_version(ext_str, idx) elif ext_str[idx] in MC_EXT_PREFIX: idx, ext_name, major, minor = parse_mc_ext(ext_str, idx) elif ext_str[idx] == '_': idx = idx + 1 continue else: raise Exception("Unrecognized ext : `%s`, %s" % (ext_str[idx], ext_str)) exts[ext_name] = (major, minor) return exts def get_vlen(ext_dict): vlen = 0 for ext in ext_dict.keys(): if ext == 'v': vlen = max(vlen, 128) elif (ext.startswith('zvl') and ext[-1] == 'b'): zvlen = int(ext[3:-1]) vlen = max(vlen, zvlen) elif ext.startswith("zve"): zvelen = int(ext[3:-1]) 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) if vlen != 0: cpu_opt.append("vlen=%d" % vlen) disable_all_fd = False for ext in ext_dict.keys(): if ext in EXT_OPTS: cpu_opt.append(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) class TestArchStringParse(unittest.TestCase): def _test(self, arch, expected_arch_list, expected_vlen=0): exts = parse_march(arch) vlen = get_vlen(exts) self.assertEqual(expected_vlen, vlen) self.assertEqual(set(expected_arch_list), set(exts.keys())) def test_rv64gc(self): self._test("rv64gc", ['i', 'm', 'a', 'f', 'd', 'c']) self._test("rv32imc_zve32x", ['i', 'm', 'c', 'zve32x'], expected_vlen=32) self._test("rv32imc_zve32x_zvl128b", ['i', 'm', 'c', 'zve32x', 'zvl128b'], expected_vlen=128) def selftest(): unittest.main(argv=sys.argv[1:]) def main(argv): opt = parse_opt(argv) if opt.selftest: selftest() return 0 cpu_opt = conver_arch_to_qemu_cpu_opt(opt.march) print (cpu_opt) if __name__ == '__main__': sys.exit(main(sys.argv))