mirror of
https://github.com/SerenityOS/serenity
synced 2026-04-25 17:15:42 +02:00
This header will be used to generate the RISC-V CPUFeature definition and set the feature bits based on the "riscv,isa-extensions" devicetree property.
131 lines
4.5 KiB
Python
Executable File
131 lines
4.5 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
import argparse
|
|
import os
|
|
from pathlib import Path
|
|
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("extension_file")
|
|
parser.add_argument("-o", "--output")
|
|
args = parser.parse_args()
|
|
|
|
SINGLE_LETTER_EXTENSION_ORDER = "iemafdgqlcbkjtpvh"
|
|
|
|
single_letter_extensions = set()
|
|
unprivileged_extensions = set() # Z*
|
|
supervisor_extensions = set() # Ss*, Sv*
|
|
hypervisor_extensions = set() # Sh*
|
|
machine_extensions = set() # Sm*
|
|
non_standard_extensions = set() # X*
|
|
|
|
with open(args.extension_file) as extension_file:
|
|
for line in extension_file.readlines():
|
|
extension = line.partition("#")[0].strip()
|
|
|
|
if not extension:
|
|
continue
|
|
|
|
extension = extension.lower()
|
|
|
|
if extension.startswith("z"):
|
|
unprivileged_extensions.add(extension)
|
|
elif extension.startswith("ss") or extension.startswith("sv"):
|
|
supervisor_extensions.add(extension)
|
|
elif extension.startswith("sh"):
|
|
hypervisor_extensions.add(extension)
|
|
elif extension.startswith("sm"):
|
|
machine_extensions.add(extension)
|
|
elif extension.startswith("x"):
|
|
non_standard_extensions.add(extension)
|
|
elif len(extension) == 1:
|
|
single_letter_extensions.add(extension)
|
|
else:
|
|
raise Exception(f"Unknown extension category: {extension}")
|
|
|
|
|
|
def unprivileged_extension_sort_key(extension):
|
|
# Z* extensions are sorted first by their related single-letter extension and then alphabetically.
|
|
related_single_letter_extension = extension[1]
|
|
return SINGLE_LETTER_EXTENSION_ORDER.index(related_single_letter_extension), extension[2:]
|
|
|
|
|
|
sorted_single_letter_extensions = sorted(single_letter_extensions, key=SINGLE_LETTER_EXTENSION_ORDER.index)
|
|
sorted_unprivileged_extensions = sorted(unprivileged_extensions, key=unprivileged_extension_sort_key)
|
|
sorted_supervisor_extensions = sorted(supervisor_extensions)
|
|
sorted_hypervisor_extensions = sorted(hypervisor_extensions)
|
|
sorted_machine_extensions = sorted(machine_extensions)
|
|
sorted_non_standard_extensions = sorted(non_standard_extensions)
|
|
|
|
sorted_extension_file = """\
|
|
# This file is used to generate the RISC-V Extensions.h header.
|
|
# It is automatically sorted by Meta/riscv_extensions_generator.py to keep the canonical extension order defined by the RISC-V ISA manual.
|
|
# To add an extension, simply insert it anywhere in this file and run the script to sort it correctly.
|
|
|
|
""" # noqa: E501
|
|
|
|
extension_header = """\
|
|
// This file was automatically generated by Meta/riscv_extensions_generator.py.
|
|
|
|
#pragma once
|
|
|
|
namespace Kernel {
|
|
|
|
// The extensions are sorted in canonical order, see https://github.com/riscv/riscv-isa-manual/blob/main/src/naming.adoc.
|
|
|
|
// 1st argument: extension name (used as our CPUFeature flag name)
|
|
// 2nd argument: lowercase extension name (used in the devicetree, see https://www.kernel.org/doc/Documentation/devicetree/bindings/riscv/extensions.yaml)
|
|
// 3rd argument: CPUFeature bitmask index
|
|
#define ENUMERATE_RISCV_EXTENSIONS(E) \\
|
|
""" # noqa: E501
|
|
|
|
i = 0
|
|
|
|
for extension_category, extension_list in (
|
|
("Single-letter extensions", sorted_single_letter_extensions),
|
|
("Unprivileged extensions", sorted_unprivileged_extensions),
|
|
("Supervisor extensions", sorted_supervisor_extensions),
|
|
("Hypervisor extensions", sorted_hypervisor_extensions),
|
|
("Machine extensions", sorted_machine_extensions),
|
|
("Non-standard extensions", sorted_non_standard_extensions),
|
|
):
|
|
sorted_extension_file += f"# {extension_category}\n"
|
|
|
|
for extension in extension_list:
|
|
capitalized_extension = extension[0].upper() + extension[1:]
|
|
extension_header += f" E({capitalized_extension}, {extension}, {i}) \\\n"
|
|
|
|
sorted_extension_file += capitalized_extension + "\n"
|
|
|
|
i += 1
|
|
|
|
sorted_extension_file += "\n"
|
|
|
|
# Remove the last trailing " \".
|
|
extension_header = extension_header.removesuffix(" \\\n")
|
|
|
|
extension_header += "\n\n}"
|
|
|
|
|
|
# FIXME: Share this function with TIFFGenerator.py.
|
|
def update_file(target: Path, new_content: str):
|
|
should_update = True
|
|
|
|
if target.exists():
|
|
with target.open('r') as file:
|
|
content = file.read()
|
|
if content == new_content:
|
|
should_update = False
|
|
|
|
if should_update:
|
|
with target.open('w') as file:
|
|
file.write(new_content)
|
|
|
|
|
|
extension_file_path = Path(args.extension_file)
|
|
extension_header_path = Path(args.output)
|
|
|
|
update_file(extension_file_path, sorted_extension_file)
|
|
|
|
os.makedirs(extension_header_path.parent, exist_ok=True)
|
|
update_file(extension_header_path, extension_header)
|