]>
Commit | Line | Data |
---|---|---|
b20cd0c7 KC |
1 | #!/usr/bin/env python |
2 | ||
3 | # Tool for canonical RISC-V architecture string. | |
83ffe9cd | 4 | # Copyright (C) 2011-2023 Free Software Foundation, Inc. |
b20cd0c7 KC |
5 | # Contributed by Andrew Waterman (andrew@sifive.com). |
6 | # | |
7 | # This file is part of GCC. | |
8 | # | |
9 | # GCC is free software; you can redistribute it and/or modify | |
10 | # it under the terms of the GNU General Public License as published by | |
11 | # the Free Software Foundation; either version 3, or (at your option) | |
12 | # any later version. | |
13 | # | |
14 | # GCC is distributed in the hope that it will be useful, | |
15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | # GNU General Public License for more details. | |
18 | # | |
19 | # You should have received a copy of the GNU General Public License | |
20 | # along with GCC; see the file COPYING3. If not see | |
21 | # <http://www.gnu.org/licenses/>. | |
22 | ||
7d25f9b6 KC |
23 | # TODO: Extract riscv_subset_t from riscv-common.cc and make it can be compiled |
24 | # standalone to replace this script, that also prevents us implementing | |
25 | # that twice and keep sync again and again. | |
b20cd0c7 KC |
26 | |
27 | from __future__ import print_function | |
28 | import sys | |
4132f6ba | 29 | import argparse |
b20cd0c7 KC |
30 | import collections |
31 | import itertools | |
32 | from functools import reduce | |
33 | ||
4132f6ba | 34 | SUPPORTED_ISA_SPEC = ["2.2", "20190608", "20191213"] |
075fb873 | 35 | CANONICAL_ORDER = "imafdgqlcbkjtpvn" |
b20cd0c7 KC |
36 | LONG_EXT_PREFIXES = ['z', 's', 'h', 'x'] |
37 | ||
38 | # | |
39 | # IMPLIED_EXT(ext) -> implied extension list. | |
40 | # | |
41 | IMPLIED_EXT = { | |
7d25f9b6 KC |
42 | "d" : ["f", "zicsr"], |
43 | "f" : ["zicsr"], | |
e0933572 J |
44 | "zdinx" : ["zfinx", "zicsr"], |
45 | "zfinx" : ["zicsr"], | |
46 | "zhinx" : ["zhinxmin", "zfinx", "zicsr"], | |
47 | "zhinxmin" : ["zfinx", "zicsr"], | |
48 | ||
7d25f9b6 KC |
49 | "zk" : ["zkn", "zkr", "zkt"], |
50 | "zkn" : ["zbkb", "zbkc", "zbkx", "zkne", "zknd", "zknh"], | |
51 | "zks" : ["zbkb", "zbkc", "zbkx", "zksed", "zksh"], | |
52 | ||
53 | "v" : ["zvl128b", "zve64d"], | |
54 | "zve32x" : ["zvl32b"], | |
55 | "zve64x" : ["zve32x", "zvl64b"], | |
56 | "zve32f" : ["f", "zve32x"], | |
57 | "zve64f" : ["f", "zve32f", "zve64x"], | |
58 | "zve64d" : ["d", "zve64f"], | |
59 | ||
60 | "zvl64b" : ["zvl32b"], | |
61 | "zvl128b" : ["zvl64b"], | |
62 | "zvl256b" : ["zvl128b"], | |
63 | "zvl512b" : ["zvl256b"], | |
64 | "zvl1024b" : ["zvl512b"], | |
65 | "zvl2048b" : ["zvl1024b"], | |
66 | "zvl4096b" : ["zvl2048b"], | |
67 | "zvl8192b" : ["zvl4096b"], | |
68 | "zvl16384b" : ["zvl8192b"], | |
69 | "zvl32768b" : ["zvl16384b"], | |
70 | "zvl65536b" : ["zvl32768b"], | |
b20cd0c7 KC |
71 | } |
72 | ||
4132f6ba | 73 | def arch_canonicalize(arch, isa_spec): |
b20cd0c7 | 74 | # TODO: Support extension version. |
4132f6ba | 75 | is_isa_spec_2p2 = isa_spec == '2.2' |
b20cd0c7 | 76 | new_arch = "" |
4132f6ba | 77 | extra_long_ext = [] |
27239e13 | 78 | std_exts = [] |
b20cd0c7 | 79 | if arch[:5] in ['rv32e', 'rv32i', 'rv32g', 'rv64i', 'rv64g']: |
27239e13 | 80 | new_arch = arch[:5].replace("g", "i") |
4132f6ba | 81 | if arch[:5] in ['rv32g', 'rv64g']: |
63f19855 | 82 | std_exts = ['m', 'a', 'f', 'd'] |
4132f6ba KC |
83 | if not is_isa_spec_2p2: |
84 | extra_long_ext = ['zicsr', 'zifencei'] | |
b20cd0c7 KC |
85 | else: |
86 | raise Exception("Unexpected arch: `%s`" % arch[:5]) | |
87 | ||
88 | # Find any Z, S, H or X | |
89 | long_ext_prefixes_idx = map(lambda x: arch.find(x), LONG_EXT_PREFIXES) | |
90 | ||
91 | # Filter out any non-existent index. | |
92 | long_ext_prefixes_idx = list(filter(lambda x: x != -1, long_ext_prefixes_idx)) | |
93 | if long_ext_prefixes_idx: | |
94 | first_long_ext_idx = min(long_ext_prefixes_idx) | |
95 | long_exts = arch[first_long_ext_idx:].split("_") | |
27239e13 | 96 | std_exts += list(arch[5:first_long_ext_idx]) |
b20cd0c7 KC |
97 | else: |
98 | long_exts = [] | |
27239e13 | 99 | std_exts += list(arch[5:]) |
b20cd0c7 | 100 | |
4132f6ba KC |
101 | long_exts += extra_long_ext |
102 | ||
b20cd0c7 KC |
103 | # |
104 | # Handle implied extensions. | |
105 | # | |
7d25f9b6 KC |
106 | any_change = True |
107 | while any_change: | |
108 | any_change = False | |
109 | for ext in std_exts + long_exts: | |
110 | if ext in IMPLIED_EXT: | |
111 | implied_exts = IMPLIED_EXT[ext] | |
112 | for implied_ext in implied_exts: | |
4132f6ba KC |
113 | if implied_ext == 'zicsr' and is_isa_spec_2p2: |
114 | continue | |
115 | ||
7d25f9b6 KC |
116 | if implied_ext not in std_exts + long_exts: |
117 | long_exts.append(implied_ext) | |
118 | any_change = True | |
b20cd0c7 KC |
119 | |
120 | # Single letter extension might appear in the long_exts list, | |
121 | # becasue we just append extensions list to the arch string. | |
122 | std_exts += list(filter(lambda x:len(x) == 1, long_exts)) | |
123 | ||
9ee33d7c GQ |
124 | def longext_sort (exts): |
125 | if not exts.startswith("zxm") and exts.startswith("z"): | |
126 | # If "Z" extensions are named, they should be ordered first by CANONICAL. | |
127 | if exts[1] not in CANONICAL_ORDER: | |
128 | raise Exception("Unsupported extension `%s`" % exts) | |
129 | canonical_sort = CANONICAL_ORDER.index(exts[1]) | |
130 | else: | |
131 | canonical_sort = -1 | |
132 | return (exts.startswith("x"), exts.startswith("zxm"), | |
133 | LONG_EXT_PREFIXES.index(exts[0]), canonical_sort, exts[1:]) | |
134 | ||
4132f6ba KC |
135 | # Removing duplicates. |
136 | long_exts = list(set(long_exts)) | |
137 | ||
b20cd0c7 | 138 | # Multi-letter extension must be in lexicographic order. |
9ee33d7c GQ |
139 | long_exts = list(sorted(filter(lambda x:len(x) != 1, long_exts), |
140 | key=longext_sort)) | |
b20cd0c7 KC |
141 | |
142 | # Put extensions in canonical order. | |
143 | for ext in CANONICAL_ORDER: | |
144 | if ext in std_exts: | |
145 | new_arch += ext | |
146 | ||
147 | # Check every extension is processed. | |
148 | for ext in std_exts: | |
149 | if ext == '_': | |
150 | continue | |
151 | if ext not in CANONICAL_ORDER: | |
152 | raise Exception("Unsupported extension `%s`" % ext) | |
153 | ||
154 | # Concat rest of the multi-char extensions. | |
155 | if long_exts: | |
156 | new_arch += "_" + "_".join(long_exts) | |
4132f6ba | 157 | |
b20cd0c7 KC |
158 | return new_arch |
159 | ||
160 | if len(sys.argv) < 2: | |
161 | print ("Usage: %s <arch_str> [<arch_str>*]" % sys.argv) | |
162 | sys.exit(1) | |
163 | ||
4132f6ba KC |
164 | parser = argparse.ArgumentParser() |
165 | parser.add_argument('-misa-spec', type=str, | |
166 | default='20191213', | |
167 | choices=SUPPORTED_ISA_SPEC) | |
168 | parser.add_argument('arch_strs', nargs=argparse.REMAINDER) | |
169 | ||
170 | args = parser.parse_args() | |
171 | ||
172 | for arch in args.arch_strs: | |
173 | print (arch_canonicalize(arch, args.misa_spec)) |