1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
# SPDX-License-Identifier: GPL-2.0-or-later
#
# Copyright 2022 Paul Elder <paul.elder@ideasonboard.com>
#
# yaml_output.py - Generate tuning file in YAML format
from .generator import Generator
from numbers import Number
from pathlib import Path
import libtuning.utils as utils
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:
out_lines.append(f' - {module.out_name}:')
if len(output_dict[module]) == 0:
continue
if not isinstance(output_dict[module], dict):
utils.eprint(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')
|