128 lines
4.1 KiB
Python
128 lines
4.1 KiB
Python
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
#
|
|
# Copyright 2022 Paul Elder <paul.elder@ideasonboard.com>
|
|
#
|
|
# Generate tuning file in YAML format
|
|
|
|
from .generator import Generator
|
|
|
|
from numbers import Number
|
|
from pathlib import Path
|
|
|
|
import logging
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
class YamlOutput(Generator):
|
|
def __init__(self):
|
|
super().__init__()
|
|
|
|
def _stringify_number_list(self, listt: list):
|
|
line_wrap = 80
|
|
|
|
line = '[ ' + ', '.join([str(x) for x in listt]) + ' ]'
|
|
if len(line) <= line_wrap:
|
|
return [line]
|
|
|
|
out_lines = ['[']
|
|
line = ' '
|
|
for x in listt:
|
|
x_str = str(x)
|
|
# If the first number is longer than line_wrap, it'll add an extra line
|
|
if len(line) + len(x_str) > line_wrap:
|
|
out_lines.append(line)
|
|
line = f' {x_str},'
|
|
continue
|
|
line += f' {x_str},'
|
|
out_lines.append(line)
|
|
out_lines.append(']')
|
|
|
|
return out_lines
|
|
|
|
# @return Array of lines, and boolean of if all elements were numbers
|
|
def _stringify_list(self, listt: list):
|
|
out_lines = []
|
|
|
|
all_numbers = set([isinstance(x, Number) for x in listt]).issubset({True})
|
|
|
|
if all_numbers:
|
|
return self._stringify_number_list(listt), True
|
|
|
|
for value in listt:
|
|
if isinstance(value, Number):
|
|
out_lines.append(f'- {str(value)}')
|
|
elif isinstance(value, str):
|
|
out_lines.append(f'- "{value}"')
|
|
elif isinstance(value, list):
|
|
lines, all_numbers = self._stringify_list(value)
|
|
|
|
if all_numbers:
|
|
out_lines.append( f'- {lines[0]}')
|
|
out_lines += [f' {line}' for line in lines[1:]]
|
|
else:
|
|
out_lines.append( f'-')
|
|
out_lines += [f' {line}' for line in lines]
|
|
elif isinstance(value, dict):
|
|
lines = self._stringify_dict(value)
|
|
out_lines.append( f'- {lines[0]}')
|
|
out_lines += [f' {line}' for line in lines[1:]]
|
|
|
|
return out_lines, False
|
|
|
|
def _stringify_dict(self, dictt: dict):
|
|
out_lines = []
|
|
|
|
for key in dictt:
|
|
value = dictt[key]
|
|
|
|
if isinstance(value, Number):
|
|
out_lines.append(f'{key}: {str(value)}')
|
|
elif isinstance(value, str):
|
|
out_lines.append(f'{key}: "{value}"')
|
|
elif isinstance(value, list):
|
|
lines, all_numbers = self._stringify_list(value)
|
|
|
|
if all_numbers:
|
|
out_lines.append( f'{key}: {lines[0]}')
|
|
out_lines += [f'{" " * (len(key) + 2)}{line}' for line in lines[1:]]
|
|
else:
|
|
out_lines.append( f'{key}:')
|
|
out_lines += [f' {line}' for line in lines]
|
|
elif isinstance(value, dict):
|
|
lines = self._stringify_dict(value)
|
|
out_lines.append( f'{key}:')
|
|
out_lines += [f' {line}' for line in lines]
|
|
|
|
return out_lines
|
|
|
|
def write(self, output_file: Path, output_dict: dict, output_order: list):
|
|
out_lines = [
|
|
'%YAML 1.1',
|
|
'---',
|
|
'version: 1',
|
|
# No need to condition this, as libtuning already guarantees that
|
|
# we have at least one module. Even if the module has no output,
|
|
# its prescence is meaningful.
|
|
'algorithms:'
|
|
]
|
|
|
|
for module in output_order:
|
|
if module not in output_dict:
|
|
continue
|
|
|
|
out_lines.append(f' - {module.out_name}:')
|
|
|
|
if len(output_dict[module]) == 0:
|
|
continue
|
|
|
|
if not isinstance(output_dict[module], dict):
|
|
logger.error(f'Error: Output of {module.type} is not a dictionary')
|
|
continue
|
|
|
|
lines = self._stringify_dict(output_dict[module])
|
|
out_lines += [f' {line}' for line in lines]
|
|
|
|
with open(output_file, 'w', encoding='utf-8') as f:
|
|
for line in out_lines:
|
|
f.write(f'{line}\n')
|