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