yowasp-yosys 0.55.0.3.post946.dev0__py3-none-any.whl → 0.56.0.0.post964__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- yowasp_yosys/sby.py +39 -8
- yowasp_yosys/share/include/kernel/constids.inc +1 -0
- yowasp_yosys/share/include/kernel/io.h +382 -8
- yowasp_yosys/share/include/kernel/json.h +2 -2
- yowasp_yosys/share/include/kernel/register.h +42 -4
- yowasp_yosys/share/include/kernel/rtlil.h +5 -1
- yowasp_yosys/share/include/kernel/satgen.h +3 -1
- yowasp_yosys/share/include/kernel/yosys_common.h +9 -0
- yowasp_yosys/share/include/passes/techmap/libparse.h +235 -0
- yowasp_yosys/share/python3/sby_autotune.py +1 -1
- yowasp_yosys/share/python3/sby_cmdline.py +13 -0
- yowasp_yosys/share/python3/sby_core.py +208 -85
- yowasp_yosys/share/python3/sby_design.py +4 -0
- yowasp_yosys/share/python3/sby_engine_abc.py +15 -4
- yowasp_yosys/share/python3/sby_engine_aiger.py +14 -9
- yowasp_yosys/share/python3/sby_engine_btor.py +15 -4
- yowasp_yosys/share/python3/sby_engine_smtbmc.py +40 -27
- yowasp_yosys/share/python3/sby_status.py +388 -115
- yowasp_yosys/yosys.wasm +0 -0
- {yowasp_yosys-0.55.0.3.post946.dev0.dist-info → yowasp_yosys-0.56.0.0.post964.dist-info}/METADATA +1 -1
- {yowasp_yosys-0.55.0.3.post946.dev0.dist-info → yowasp_yosys-0.56.0.0.post964.dist-info}/RECORD +24 -23
- {yowasp_yosys-0.55.0.3.post946.dev0.dist-info → yowasp_yosys-0.56.0.0.post964.dist-info}/WHEEL +0 -0
- {yowasp_yosys-0.55.0.3.post946.dev0.dist-info → yowasp_yosys-0.56.0.0.post964.dist-info}/entry_points.txt +0 -0
- {yowasp_yosys-0.55.0.3.post946.dev0.dist-info → yowasp_yosys-0.56.0.0.post964.dist-info}/top_level.txt +0 -0
yowasp_yosys/sby.py
CHANGED
|
@@ -22,7 +22,7 @@ import json, os, sys, shutil, tempfile, re
|
|
|
22
22
|
from sby_cmdline import parser_func
|
|
23
23
|
from sby_core import SbyConfig, SbyTask, SbyAbort, SbyTaskloop, process_filename, dress_message
|
|
24
24
|
from sby_jobserver import SbyJobClient, process_jobserver_environment
|
|
25
|
-
from sby_status import SbyStatusDb
|
|
25
|
+
from sby_status import SbyStatusDb, remove_db, FileInUseError
|
|
26
26
|
import time, platform, click
|
|
27
27
|
|
|
28
28
|
release_version = 'unknown SBY version'
|
|
@@ -54,6 +54,7 @@ dump_taskinfo = args.dump_taskinfo
|
|
|
54
54
|
dump_files = args.dump_files
|
|
55
55
|
reusedir = False
|
|
56
56
|
setupmode = args.setupmode
|
|
57
|
+
linkmode = args.linkmode
|
|
57
58
|
autotune = args.autotune
|
|
58
59
|
autotune_config = args.autotune_config
|
|
59
60
|
sequential = args.sequential
|
|
@@ -61,8 +62,17 @@ jobcount = args.jobcount
|
|
|
61
62
|
init_config_file = args.init_config_file
|
|
62
63
|
status_show = args.status
|
|
63
64
|
status_reset = args.status_reset
|
|
65
|
+
status_cancels = args.status_cancels
|
|
66
|
+
task_status = args.task_status
|
|
67
|
+
status_live_formats = args.live_formats
|
|
68
|
+
status_format = args.status_format
|
|
69
|
+
status_latest = args.status_latest
|
|
70
|
+
|
|
71
|
+
if autotune and linkmode:
|
|
72
|
+
print("ERROR: --link flag currently not available with --autotune")
|
|
73
|
+
sys.exit(1)
|
|
64
74
|
|
|
65
|
-
if status_show or status_reset:
|
|
75
|
+
if status_show or status_reset or task_status or status_format:
|
|
66
76
|
target = workdir_prefix or workdir or sbyfile
|
|
67
77
|
if target is None:
|
|
68
78
|
print("ERROR: Specify a .sby config file or working directory to use --status.")
|
|
@@ -85,15 +95,29 @@ if status_show or status_reset:
|
|
|
85
95
|
|
|
86
96
|
status_db = SbyStatusDb(status_path, task=None)
|
|
87
97
|
|
|
88
|
-
if status_show:
|
|
89
|
-
status_db.print_status_summary()
|
|
90
|
-
sys.exit(0)
|
|
91
|
-
|
|
92
98
|
if status_reset:
|
|
93
99
|
status_db.reset()
|
|
100
|
+
elif status_db.test_schema():
|
|
101
|
+
print(f"ERROR: Status database does not match expected format. Use --statusreset to reset.")
|
|
102
|
+
sys.exit(1)
|
|
103
|
+
|
|
104
|
+
if status_show:
|
|
105
|
+
status_db.print_status_summary(status_latest)
|
|
106
|
+
|
|
107
|
+
if status_format:
|
|
108
|
+
status_db.print_status_summary_fmt(tasknames, status_format, status_latest)
|
|
109
|
+
|
|
110
|
+
if task_status:
|
|
111
|
+
status_db.print_task_summary()
|
|
94
112
|
|
|
95
113
|
status_db.db.close()
|
|
114
|
+
|
|
115
|
+
if status_live_formats:
|
|
116
|
+
print(f"WARNING: --live option found but not used.")
|
|
117
|
+
|
|
96
118
|
sys.exit(0)
|
|
119
|
+
elif status_latest:
|
|
120
|
+
print(f"WARNING: --latest flag found but not used.")
|
|
97
121
|
|
|
98
122
|
|
|
99
123
|
if sbyfile is not None:
|
|
@@ -369,6 +393,7 @@ if dump_taskinfo:
|
|
|
369
393
|
"mode": cfg.options.get("mode"),
|
|
370
394
|
"engines": cfg.engines,
|
|
371
395
|
"script": cfg.script,
|
|
396
|
+
"cancelledby": cfg.cancelledby,
|
|
372
397
|
}
|
|
373
398
|
print(json.dumps(taskinfo, indent=2))
|
|
374
399
|
sys.exit(0)
|
|
@@ -450,6 +475,12 @@ def start_task(taskloop, taskname):
|
|
|
450
475
|
print("*", file=gitignore)
|
|
451
476
|
with open(f"{my_workdir}/status.path", "w") as status_path:
|
|
452
477
|
print(my_status_db, file=status_path)
|
|
478
|
+
if os.path.exists(f"{my_workdir}/{my_status_db}") and opt_force:
|
|
479
|
+
try:
|
|
480
|
+
remove_db(f"{my_workdir}/{my_status_db}")
|
|
481
|
+
except FileInUseError:
|
|
482
|
+
# don't delete an open database
|
|
483
|
+
pass
|
|
453
484
|
|
|
454
485
|
junit_ts_name = os.path.basename(sbyfile[:-4]) if sbyfile is not None else workdir if workdir is not None else "stdin"
|
|
455
486
|
junit_tc_name = taskname if taskname is not None else "default"
|
|
@@ -465,7 +496,7 @@ def start_task(taskloop, taskname):
|
|
|
465
496
|
else:
|
|
466
497
|
junit_filename = "junit"
|
|
467
498
|
|
|
468
|
-
task = SbyTask(sbyconfig, my_workdir, early_logmsgs, reusedir, taskloop)
|
|
499
|
+
task = SbyTask(sbyconfig, my_workdir, early_logmsgs, reusedir, status_cancels, taskloop, name=taskname, live_formats=status_live_formats)
|
|
469
500
|
|
|
470
501
|
for k, v in exe_paths.items():
|
|
471
502
|
task.exe_paths[k] = v
|
|
@@ -495,7 +526,7 @@ def start_task(taskloop, taskname):
|
|
|
495
526
|
task.exit_callback = exit_callback
|
|
496
527
|
|
|
497
528
|
if not autotune:
|
|
498
|
-
task.setup_procs(setupmode)
|
|
529
|
+
task.setup_procs(setupmode, linkmode)
|
|
499
530
|
task.task_local_abort = not throw_err
|
|
500
531
|
|
|
501
532
|
return task
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#include <string>
|
|
2
2
|
#include <stdarg.h>
|
|
3
|
+
#include <type_traits>
|
|
3
4
|
#include "kernel/yosys_common.h"
|
|
4
5
|
|
|
5
6
|
#ifndef YOSYS_IO_H
|
|
@@ -50,18 +51,391 @@ inline std::string vstringf(const char *fmt, va_list ap)
|
|
|
50
51
|
#endif
|
|
51
52
|
}
|
|
52
53
|
|
|
53
|
-
|
|
54
|
+
enum ConversionSpecifier : uint8_t
|
|
55
|
+
{
|
|
56
|
+
CONVSPEC_NONE,
|
|
57
|
+
// Specifier not understood/supported
|
|
58
|
+
CONVSPEC_ERROR,
|
|
59
|
+
// Consumes a "long long"
|
|
60
|
+
CONVSPEC_SIGNED_INT,
|
|
61
|
+
// Consumes a "unsigned long long"
|
|
62
|
+
CONVSPEC_UNSIGNED_INT,
|
|
63
|
+
// Consumes a "double"
|
|
64
|
+
CONVSPEC_DOUBLE,
|
|
65
|
+
// Consumes a "const char*" or other string type
|
|
66
|
+
CONVSPEC_CHAR_PTR,
|
|
67
|
+
// Consumes a "void*"
|
|
68
|
+
CONVSPEC_VOID_PTR,
|
|
69
|
+
};
|
|
54
70
|
|
|
55
|
-
|
|
71
|
+
constexpr ConversionSpecifier parse_conversion_specifier(char ch, char prev_ch)
|
|
56
72
|
{
|
|
57
|
-
|
|
58
|
-
|
|
73
|
+
switch (ch) {
|
|
74
|
+
case 'd':
|
|
75
|
+
case 'i':
|
|
76
|
+
return CONVSPEC_SIGNED_INT;
|
|
77
|
+
case 'o':
|
|
78
|
+
case 'u':
|
|
79
|
+
case 'x':
|
|
80
|
+
case 'X':
|
|
81
|
+
case 'm':
|
|
82
|
+
return CONVSPEC_UNSIGNED_INT;
|
|
83
|
+
case 'c':
|
|
84
|
+
if (prev_ch == 'l' || prev_ch == 'q' || prev_ch == 'L') {
|
|
85
|
+
// wchar not supported
|
|
86
|
+
return CONVSPEC_ERROR;
|
|
87
|
+
}
|
|
88
|
+
return CONVSPEC_UNSIGNED_INT;
|
|
89
|
+
case 'e':
|
|
90
|
+
case 'E':
|
|
91
|
+
case 'f':
|
|
92
|
+
case 'F':
|
|
93
|
+
case 'g':
|
|
94
|
+
case 'G':
|
|
95
|
+
case 'a':
|
|
96
|
+
case 'A':
|
|
97
|
+
return CONVSPEC_DOUBLE;
|
|
98
|
+
case 's':
|
|
99
|
+
if (prev_ch == 'l' || prev_ch == 'q' || prev_ch == 'L') {
|
|
100
|
+
// wchar not supported
|
|
101
|
+
return CONVSPEC_ERROR;
|
|
102
|
+
}
|
|
103
|
+
return CONVSPEC_CHAR_PTR;
|
|
104
|
+
case 'p':
|
|
105
|
+
return CONVSPEC_VOID_PTR;
|
|
106
|
+
case '$': // positional parameters
|
|
107
|
+
case 'n':
|
|
108
|
+
case 'S':
|
|
109
|
+
return CONVSPEC_ERROR;
|
|
110
|
+
default:
|
|
111
|
+
return CONVSPEC_NONE;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
59
114
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
115
|
+
enum class DynamicIntCount : uint8_t {
|
|
116
|
+
NONE = 0,
|
|
117
|
+
ONE = 1,
|
|
118
|
+
TWO = 2,
|
|
119
|
+
};
|
|
63
120
|
|
|
64
|
-
|
|
121
|
+
// Describes a printf-style format conversion specifier found in a format string.
|
|
122
|
+
struct FoundFormatSpec
|
|
123
|
+
{
|
|
124
|
+
// The start offset of the conversion spec in the format string.
|
|
125
|
+
int start;
|
|
126
|
+
// The end offset of the conversion spec in the format string.
|
|
127
|
+
int end;
|
|
128
|
+
ConversionSpecifier spec;
|
|
129
|
+
// Number of int args consumed by '*' dynamic width/precision args.
|
|
130
|
+
DynamicIntCount num_dynamic_ints;
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
// Ensure there is no format spec.
|
|
134
|
+
constexpr void ensure_no_format_spec(std::string_view fmt, int index, bool *has_escapes)
|
|
135
|
+
{
|
|
136
|
+
int fmt_size = static_cast<int>(fmt.size());
|
|
137
|
+
// A trailing '%' is not a format spec.
|
|
138
|
+
while (index + 1 < fmt_size) {
|
|
139
|
+
if (fmt[index] != '%') {
|
|
140
|
+
++index;
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
if (fmt[index + 1] != '%') {
|
|
144
|
+
YOSYS_ABORT("More format conversion specifiers than arguments");
|
|
145
|
+
}
|
|
146
|
+
*has_escapes = true;
|
|
147
|
+
index += 2;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Returns the next format conversion specifier (starting with '%').
|
|
152
|
+
// Returns CONVSPEC_NONE if there isn't a format conversion specifier.
|
|
153
|
+
constexpr FoundFormatSpec find_next_format_spec(std::string_view fmt, int fmt_start, bool *has_escapes)
|
|
154
|
+
{
|
|
155
|
+
int index = fmt_start;
|
|
156
|
+
int fmt_size = static_cast<int>(fmt.size());
|
|
157
|
+
while (index < fmt_size) {
|
|
158
|
+
if (fmt[index] != '%') {
|
|
159
|
+
++index;
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
int p = index + 1;
|
|
163
|
+
uint8_t num_dynamic_ints = 0;
|
|
164
|
+
while (true) {
|
|
165
|
+
if (p == fmt_size) {
|
|
166
|
+
return {0, 0, CONVSPEC_NONE, DynamicIntCount::NONE};
|
|
167
|
+
}
|
|
168
|
+
if (fmt[p] == '%') {
|
|
169
|
+
*has_escapes = true;
|
|
170
|
+
index = p + 1;
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
if (fmt[p] == '*') {
|
|
174
|
+
if (num_dynamic_ints >= 2) {
|
|
175
|
+
return {0, 0, CONVSPEC_ERROR, DynamicIntCount::NONE};
|
|
176
|
+
}
|
|
177
|
+
++num_dynamic_ints;
|
|
178
|
+
}
|
|
179
|
+
ConversionSpecifier spec = parse_conversion_specifier(fmt[p], fmt[p - 1]);
|
|
180
|
+
if (spec != CONVSPEC_NONE) {
|
|
181
|
+
return {index, p + 1, spec, static_cast<DynamicIntCount>(num_dynamic_ints)};
|
|
182
|
+
}
|
|
183
|
+
++p;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return {0, 0, CONVSPEC_NONE, DynamicIntCount::NONE};
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
template <typename... Args>
|
|
190
|
+
constexpr typename std::enable_if<sizeof...(Args) == 0>::type
|
|
191
|
+
check_format(std::string_view fmt, int fmt_start, bool *has_escapes, FoundFormatSpec*, DynamicIntCount)
|
|
192
|
+
{
|
|
193
|
+
ensure_no_format_spec(fmt, fmt_start, has_escapes);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Check that the format string `fmt.substr(fmt_start)` is valid for the given type arguments.
|
|
197
|
+
// Fills `specs` with the FoundFormatSpecs found in the format string.
|
|
198
|
+
// `int_args_consumed` is the number of int arguments already consumed to satisfy the
|
|
199
|
+
// dynamic width/precision args for the next format conversion specifier.
|
|
200
|
+
template <typename Arg, typename... Args>
|
|
201
|
+
constexpr void check_format(std::string_view fmt, int fmt_start, bool *has_escapes, FoundFormatSpec* specs,
|
|
202
|
+
DynamicIntCount int_args_consumed)
|
|
203
|
+
{
|
|
204
|
+
FoundFormatSpec found = find_next_format_spec(fmt, fmt_start, has_escapes);
|
|
205
|
+
if (found.num_dynamic_ints > int_args_consumed) {
|
|
206
|
+
// We need to consume at least one more int for the dynamic
|
|
207
|
+
// width/precision of this format conversion specifier.
|
|
208
|
+
if constexpr (!std::is_convertible_v<Arg, int>) {
|
|
209
|
+
YOSYS_ABORT("Expected dynamic int argument");
|
|
210
|
+
}
|
|
211
|
+
check_format<Args...>(fmt, fmt_start, has_escapes, specs,
|
|
212
|
+
static_cast<DynamicIntCount>(static_cast<uint8_t>(int_args_consumed) + 1));
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
switch (found.spec) {
|
|
216
|
+
case CONVSPEC_NONE:
|
|
217
|
+
YOSYS_ABORT("Expected format conversion specifier for argument");
|
|
218
|
+
break;
|
|
219
|
+
case CONVSPEC_ERROR:
|
|
220
|
+
YOSYS_ABORT("Found unsupported format conversion specifier");
|
|
221
|
+
break;
|
|
222
|
+
case CONVSPEC_SIGNED_INT:
|
|
223
|
+
if constexpr (!std::is_convertible_v<Arg, long long>) {
|
|
224
|
+
YOSYS_ABORT("Expected type convertible to signed integer");
|
|
225
|
+
}
|
|
226
|
+
*specs = found;
|
|
227
|
+
break;
|
|
228
|
+
case CONVSPEC_UNSIGNED_INT:
|
|
229
|
+
if constexpr (!std::is_convertible_v<Arg, unsigned long long>) {
|
|
230
|
+
YOSYS_ABORT("Expected type convertible to unsigned integer");
|
|
231
|
+
}
|
|
232
|
+
*specs = found;
|
|
233
|
+
break;
|
|
234
|
+
case CONVSPEC_DOUBLE:
|
|
235
|
+
if constexpr (!std::is_convertible_v<Arg, double>) {
|
|
236
|
+
YOSYS_ABORT("Expected type convertible to double");
|
|
237
|
+
}
|
|
238
|
+
*specs = found;
|
|
239
|
+
break;
|
|
240
|
+
case CONVSPEC_CHAR_PTR:
|
|
241
|
+
if constexpr (!std::is_convertible_v<Arg, const char *> &&
|
|
242
|
+
!std::is_convertible_v<Arg, const std::string &> &&
|
|
243
|
+
!std::is_convertible_v<Arg, const std::string_view &>) {
|
|
244
|
+
YOSYS_ABORT("Expected type convertible to char *");
|
|
245
|
+
}
|
|
246
|
+
*specs = found;
|
|
247
|
+
break;
|
|
248
|
+
case CONVSPEC_VOID_PTR:
|
|
249
|
+
if constexpr (!std::is_convertible_v<Arg, const void *>) {
|
|
250
|
+
YOSYS_ABORT("Expected pointer type");
|
|
251
|
+
}
|
|
252
|
+
*specs = found;
|
|
253
|
+
break;
|
|
254
|
+
}
|
|
255
|
+
check_format<Args...>(fmt, found.end, has_escapes, specs + 1, DynamicIntCount::NONE);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Emit the string representation of `arg` that has been converted to a `long long'.
|
|
259
|
+
void format_emit_long_long(std::string &result, std::string_view spec, int *dynamic_ints,
|
|
260
|
+
DynamicIntCount num_dynamic_ints, long long arg);
|
|
261
|
+
|
|
262
|
+
// Emit the string representation of `arg` that has been converted to a `unsigned long long'.
|
|
263
|
+
void format_emit_unsigned_long_long(std::string &result, std::string_view spec, int *dynamic_ints,
|
|
264
|
+
DynamicIntCount num_dynamic_ints, unsigned long long arg);
|
|
265
|
+
|
|
266
|
+
// Emit the string representation of `arg` that has been converted to a `double'.
|
|
267
|
+
void format_emit_double(std::string &result, std::string_view spec, int *dynamic_ints,
|
|
268
|
+
DynamicIntCount num_dynamic_ints, double arg);
|
|
269
|
+
|
|
270
|
+
// Emit the string representation of `arg` that has been converted to a `const char*'.
|
|
271
|
+
void format_emit_char_ptr(std::string &result, std::string_view spec, int *dynamic_ints,
|
|
272
|
+
DynamicIntCount num_dynamic_ints, const char *arg);
|
|
273
|
+
|
|
274
|
+
// Emit the string representation of `arg` that has been converted to a `std::string'.
|
|
275
|
+
void format_emit_string(std::string &result, std::string_view spec, int *dynamic_ints,
|
|
276
|
+
DynamicIntCount num_dynamic_ints, const std::string &arg);
|
|
277
|
+
|
|
278
|
+
// Emit the string representation of `arg` that has been converted to a `std::string_view'.
|
|
279
|
+
void format_emit_string_view(std::string &result, std::string_view spec, int *dynamic_ints,
|
|
280
|
+
DynamicIntCount num_dynamic_ints, std::string_view arg);
|
|
281
|
+
|
|
282
|
+
// Emit the string representation of `arg` that has been converted to a `double'.
|
|
283
|
+
void format_emit_void_ptr(std::string &result, std::string_view spec, int *dynamic_ints,
|
|
284
|
+
DynamicIntCount num_dynamic_ints, const void *arg);
|
|
285
|
+
|
|
286
|
+
// Emit the string representation of `arg` according to the given `FoundFormatSpec`,
|
|
287
|
+
// appending it to `result`.
|
|
288
|
+
template <typename Arg>
|
|
289
|
+
inline void format_emit_one(std::string &result, std::string_view fmt, const FoundFormatSpec &ffspec,
|
|
290
|
+
int *dynamic_ints, const Arg& arg)
|
|
291
|
+
{
|
|
292
|
+
std::string_view spec = fmt.substr(ffspec.start, ffspec.end - ffspec.start);
|
|
293
|
+
DynamicIntCount num_dynamic_ints = ffspec.num_dynamic_ints;
|
|
294
|
+
switch (ffspec.spec) {
|
|
295
|
+
case CONVSPEC_SIGNED_INT:
|
|
296
|
+
if constexpr (std::is_convertible_v<Arg, long long>) {
|
|
297
|
+
long long s = arg;
|
|
298
|
+
format_emit_long_long(result, spec, dynamic_ints, num_dynamic_ints, s);
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
break;
|
|
302
|
+
case CONVSPEC_UNSIGNED_INT:
|
|
303
|
+
if constexpr (std::is_convertible_v<Arg, unsigned long long>) {
|
|
304
|
+
unsigned long long s = arg;
|
|
305
|
+
format_emit_unsigned_long_long(result, spec, dynamic_ints, num_dynamic_ints, s);
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
break;
|
|
309
|
+
case CONVSPEC_DOUBLE:
|
|
310
|
+
if constexpr (std::is_convertible_v<Arg, double>) {
|
|
311
|
+
double s = arg;
|
|
312
|
+
format_emit_double(result, spec, dynamic_ints, num_dynamic_ints, s);
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
break;
|
|
316
|
+
case CONVSPEC_CHAR_PTR:
|
|
317
|
+
if constexpr (std::is_convertible_v<Arg, const char *>) {
|
|
318
|
+
const char *s = arg;
|
|
319
|
+
format_emit_char_ptr(result, spec, dynamic_ints, num_dynamic_ints, s);
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
if constexpr (std::is_convertible_v<Arg, const std::string &>) {
|
|
323
|
+
const std::string &s = arg;
|
|
324
|
+
format_emit_string(result, spec, dynamic_ints, num_dynamic_ints, s);
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
if constexpr (std::is_convertible_v<Arg, const std::string_view &>) {
|
|
328
|
+
const std::string_view &s = arg;
|
|
329
|
+
format_emit_string_view(result, spec, dynamic_ints, num_dynamic_ints, s);
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
break;
|
|
333
|
+
case CONVSPEC_VOID_PTR:
|
|
334
|
+
if constexpr (std::is_convertible_v<Arg, const void *>) {
|
|
335
|
+
const void *s = arg;
|
|
336
|
+
format_emit_void_ptr(result, spec, dynamic_ints, num_dynamic_ints, s);
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
break;
|
|
340
|
+
default:
|
|
341
|
+
break;
|
|
342
|
+
}
|
|
343
|
+
YOSYS_ABORT("Internal error");
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// Append the format string `fmt` to `result`, assuming there are no format conversion
|
|
347
|
+
// specifiers other than "%%" and therefore no arguments. Unescape "%%".
|
|
348
|
+
void format_emit_unescaped(std::string &result, std::string_view fmt);
|
|
349
|
+
std::string unescape_format_string(std::string_view fmt);
|
|
350
|
+
|
|
351
|
+
inline void format_emit(std::string &result, std::string_view fmt, int fmt_start,
|
|
352
|
+
bool has_escapes, const FoundFormatSpec*, int*, DynamicIntCount)
|
|
353
|
+
{
|
|
354
|
+
fmt = fmt.substr(fmt_start);
|
|
355
|
+
if (has_escapes) {
|
|
356
|
+
format_emit_unescaped(result, fmt);
|
|
357
|
+
} else {
|
|
358
|
+
result += fmt;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
// Format `args` according to `fmt` (starting at `fmt_start`) and `specs` and append to `result`.
|
|
362
|
+
// `num_dynamic_ints` in `dynamic_ints[]` have already been collected to provide as
|
|
363
|
+
// dynamic width/precision args for the next format conversion specifier.
|
|
364
|
+
template <typename Arg, typename... Args>
|
|
365
|
+
inline void format_emit(std::string &result, std::string_view fmt, int fmt_start, bool has_escapes,
|
|
366
|
+
const FoundFormatSpec* specs, int *dynamic_ints, DynamicIntCount num_dynamic_ints,
|
|
367
|
+
const Arg &arg, const Args &... args)
|
|
368
|
+
{
|
|
369
|
+
if (specs->num_dynamic_ints > num_dynamic_ints) {
|
|
370
|
+
// Collect another int for the dynamic width precision/args
|
|
371
|
+
// for the next format conversion specifier.
|
|
372
|
+
if constexpr (std::is_convertible_v<Arg, int>) {
|
|
373
|
+
dynamic_ints[static_cast<uint8_t>(num_dynamic_ints)] = arg;
|
|
374
|
+
} else {
|
|
375
|
+
YOSYS_ABORT("Internal error");
|
|
376
|
+
}
|
|
377
|
+
format_emit(result, fmt, fmt_start, has_escapes, specs, dynamic_ints,
|
|
378
|
+
static_cast<DynamicIntCount>(static_cast<uint8_t>(num_dynamic_ints) + 1), args...);
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
std::string_view str = fmt.substr(fmt_start, specs->start - fmt_start);
|
|
382
|
+
if (has_escapes) {
|
|
383
|
+
format_emit_unescaped(result, str);
|
|
384
|
+
} else {
|
|
385
|
+
result += str;
|
|
386
|
+
}
|
|
387
|
+
format_emit_one(result, fmt, *specs, dynamic_ints, arg);
|
|
388
|
+
format_emit(result, fmt, specs->end, has_escapes, specs + 1, dynamic_ints, DynamicIntCount::NONE, args...);
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
template <typename... Args>
|
|
392
|
+
inline std::string format_emit_toplevel(std::string_view fmt, bool has_escapes, const FoundFormatSpec* specs, const Args &... args)
|
|
393
|
+
{
|
|
394
|
+
std::string result;
|
|
395
|
+
int dynamic_ints[2] = { 0, 0 };
|
|
396
|
+
format_emit(result, fmt, 0, has_escapes, specs, dynamic_ints, DynamicIntCount::NONE, args...);
|
|
397
|
+
return result;
|
|
398
|
+
}
|
|
399
|
+
template <>
|
|
400
|
+
inline std::string format_emit_toplevel(std::string_view fmt, bool has_escapes, const FoundFormatSpec*)
|
|
401
|
+
{
|
|
402
|
+
if (!has_escapes) {
|
|
403
|
+
return std::string(fmt);
|
|
404
|
+
}
|
|
405
|
+
return unescape_format_string(fmt);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// This class parses format strings to build a list of `FoundFormatSpecs` in `specs`.
|
|
409
|
+
// When the compiler supports `consteval` (C++20), this parsing happens at compile time and
|
|
410
|
+
// type errors will be reported at compile time. Otherwise the parsing happens at
|
|
411
|
+
// runtime and type errors will trigger an `abort()` at runtime.
|
|
412
|
+
template <typename... Args>
|
|
413
|
+
class FmtString
|
|
414
|
+
{
|
|
415
|
+
public:
|
|
416
|
+
// Implicit conversion from const char * means that users can pass
|
|
417
|
+
// C string constants which are automatically parsed.
|
|
418
|
+
YOSYS_CONSTEVAL FmtString(const char *p) : fmt(p)
|
|
419
|
+
{
|
|
420
|
+
check_format<Args...>(fmt, 0, &has_escapes, specs, DynamicIntCount::NONE);
|
|
421
|
+
}
|
|
422
|
+
std::string format(const Args &... args)
|
|
423
|
+
{
|
|
424
|
+
return format_emit_toplevel(fmt, has_escapes, specs, args...);
|
|
425
|
+
}
|
|
426
|
+
private:
|
|
427
|
+
std::string_view fmt;
|
|
428
|
+
bool has_escapes = false;
|
|
429
|
+
FoundFormatSpec specs[sizeof...(Args)] = {};
|
|
430
|
+
};
|
|
431
|
+
|
|
432
|
+
template <typename T> struct WrapType { using type = T; };
|
|
433
|
+
template <typename T> using TypeIdentity = typename WrapType<T>::type;
|
|
434
|
+
|
|
435
|
+
template <typename... Args>
|
|
436
|
+
inline std::string stringf(FmtString<TypeIdentity<Args>...> fmt, Args... args)
|
|
437
|
+
{
|
|
438
|
+
return fmt.format(args...);
|
|
65
439
|
}
|
|
66
440
|
|
|
67
441
|
int readsome(std::istream &f, char *s, int n);
|
|
@@ -23,27 +23,62 @@
|
|
|
23
23
|
#include "kernel/yosys_common.h"
|
|
24
24
|
#include "kernel/yosys.h"
|
|
25
25
|
|
|
26
|
+
#ifdef YOSYS_ENABLE_HELP_SOURCE
|
|
27
|
+
#include <version>
|
|
28
|
+
# if __cpp_lib_source_location == 201907L
|
|
29
|
+
#include <source_location>
|
|
30
|
+
using std::source_location;
|
|
31
|
+
#define HAS_SOURCE_LOCATION
|
|
32
|
+
# elif defined(__has_include)
|
|
33
|
+
# if __has_include(<experimental/source_location>)
|
|
34
|
+
#include <experimental/source_location>
|
|
35
|
+
using std::experimental::source_location;
|
|
36
|
+
#define HAS_SOURCE_LOCATION
|
|
37
|
+
# endif
|
|
38
|
+
# endif
|
|
39
|
+
#endif
|
|
40
|
+
|
|
41
|
+
#ifndef HAS_SOURCE_LOCATION
|
|
42
|
+
struct source_location { // dummy placeholder
|
|
43
|
+
int line() const { return 0; }
|
|
44
|
+
int column() const { return 0; }
|
|
45
|
+
const char* file_name() const { return "unknown"; }
|
|
46
|
+
const char* function_name() const { return "unknown"; }
|
|
47
|
+
static const source_location current(...) { return source_location(); }
|
|
48
|
+
};
|
|
49
|
+
#endif
|
|
50
|
+
|
|
26
51
|
YOSYS_NAMESPACE_BEGIN
|
|
27
52
|
|
|
28
53
|
struct Pass
|
|
29
54
|
{
|
|
30
55
|
std::string pass_name, short_help;
|
|
31
|
-
|
|
56
|
+
source_location location;
|
|
57
|
+
Pass(std::string name, std::string short_help = "** document me **",
|
|
58
|
+
source_location location = source_location::current());
|
|
32
59
|
// Prefer overriding 'Pass::on_shutdown()' if possible
|
|
33
60
|
virtual ~Pass();
|
|
34
61
|
|
|
62
|
+
// Makes calls to log() to generate help message
|
|
35
63
|
virtual void help();
|
|
64
|
+
// Uses PrettyHelp::get_current() to produce a more portable formatted help message
|
|
65
|
+
virtual bool formatted_help();
|
|
36
66
|
virtual void clear_flags();
|
|
37
67
|
virtual void execute(std::vector<std::string> args, RTLIL::Design *design) = 0;
|
|
38
68
|
|
|
39
69
|
int call_counter;
|
|
40
70
|
int64_t runtime_ns;
|
|
41
71
|
bool experimental_flag = false;
|
|
72
|
+
bool internal_flag = false;
|
|
42
73
|
|
|
43
74
|
void experimental() {
|
|
44
75
|
experimental_flag = true;
|
|
45
76
|
}
|
|
46
77
|
|
|
78
|
+
void internal() {
|
|
79
|
+
internal_flag = true;
|
|
80
|
+
}
|
|
81
|
+
|
|
47
82
|
struct pre_post_exec_state_t {
|
|
48
83
|
Pass *parent_pass;
|
|
49
84
|
int64_t begin_ns;
|
|
@@ -81,7 +116,8 @@ struct ScriptPass : Pass
|
|
|
81
116
|
RTLIL::Design *active_design;
|
|
82
117
|
std::string active_run_from, active_run_to;
|
|
83
118
|
|
|
84
|
-
ScriptPass(std::string name, std::string short_help = "** document me **"
|
|
119
|
+
ScriptPass(std::string name, std::string short_help = "** document me **", source_location location = source_location::current()) :
|
|
120
|
+
Pass(name, short_help, location) { }
|
|
85
121
|
|
|
86
122
|
virtual void script() = 0;
|
|
87
123
|
|
|
@@ -99,7 +135,8 @@ struct Frontend : Pass
|
|
|
99
135
|
static std::string last_here_document;
|
|
100
136
|
|
|
101
137
|
std::string frontend_name;
|
|
102
|
-
Frontend(std::string name, std::string short_help = "** document me **"
|
|
138
|
+
Frontend(std::string name, std::string short_help = "** document me **",
|
|
139
|
+
source_location location = source_location::current());
|
|
103
140
|
void run_register() override;
|
|
104
141
|
~Frontend() override;
|
|
105
142
|
void execute(std::vector<std::string> args, RTLIL::Design *design) override final;
|
|
@@ -115,7 +152,8 @@ struct Frontend : Pass
|
|
|
115
152
|
struct Backend : Pass
|
|
116
153
|
{
|
|
117
154
|
std::string backend_name;
|
|
118
|
-
Backend(std::string name, std::string short_help = "** document me **"
|
|
155
|
+
Backend(std::string name, std::string short_help = "** document me **",
|
|
156
|
+
source_location location = source_location::current());
|
|
119
157
|
void run_register() override;
|
|
120
158
|
~Backend() override;
|
|
121
159
|
void execute(std::vector<std::string> args, RTLIL::Design *design) override final;
|
|
@@ -23,6 +23,9 @@
|
|
|
23
23
|
#include "kernel/yosys_common.h"
|
|
24
24
|
#include "kernel/yosys.h"
|
|
25
25
|
|
|
26
|
+
#include <string_view>
|
|
27
|
+
#include <unordered_map>
|
|
28
|
+
|
|
26
29
|
YOSYS_NAMESPACE_BEGIN
|
|
27
30
|
|
|
28
31
|
namespace RTLIL
|
|
@@ -122,7 +125,7 @@ struct RTLIL::IdString
|
|
|
122
125
|
} destruct_guard;
|
|
123
126
|
|
|
124
127
|
static std::vector<char*> global_id_storage_;
|
|
125
|
-
static
|
|
128
|
+
static std::unordered_map<std::string_view, int> global_id_index_;
|
|
126
129
|
#ifndef YOSYS_NO_IDS_REFCNT
|
|
127
130
|
static std::vector<int> global_refcount_storage_;
|
|
128
131
|
static std::vector<int> global_free_idx_list_;
|
|
@@ -1368,6 +1371,7 @@ struct RTLIL::Design
|
|
|
1368
1371
|
std::string scratchpad_get_string(const std::string &varname, const std::string &default_value = std::string()) const;
|
|
1369
1372
|
|
|
1370
1373
|
void sort();
|
|
1374
|
+
void sort_modules();
|
|
1371
1375
|
void check();
|
|
1372
1376
|
void optimize();
|
|
1373
1377
|
|
|
@@ -101,7 +101,9 @@ struct SatGen
|
|
|
101
101
|
else
|
|
102
102
|
vec.push_back(bit == (undef_mode ? RTLIL::State::Sx : RTLIL::State::S1) ? ez->CONST_TRUE : ez->CONST_FALSE);
|
|
103
103
|
} else {
|
|
104
|
-
std::string
|
|
104
|
+
std::string wire_name = RTLIL::unescape_id(bit.wire->name);
|
|
105
|
+
std::string name = pf +
|
|
106
|
+
(bit.wire->width == 1 ? wire_name : stringf("%s [%d]", wire_name.c_str(), bit.offset));
|
|
105
107
|
vec.push_back(ez->frozen_literal(name));
|
|
106
108
|
imported_signals[pf][bit] = vec.back();
|
|
107
109
|
}
|
|
@@ -134,6 +134,15 @@
|
|
|
134
134
|
# define YS_COLD
|
|
135
135
|
#endif
|
|
136
136
|
|
|
137
|
+
#ifdef __cpp_consteval
|
|
138
|
+
#define YOSYS_CONSTEVAL consteval
|
|
139
|
+
#else
|
|
140
|
+
// If we can't use consteval we can at least make it constexpr.
|
|
141
|
+
#define YOSYS_CONSTEVAL constexpr
|
|
142
|
+
#endif
|
|
143
|
+
|
|
144
|
+
#define YOSYS_ABORT(s) abort()
|
|
145
|
+
|
|
137
146
|
#include "kernel/io.h"
|
|
138
147
|
|
|
139
148
|
YOSYS_NAMESPACE_BEGIN
|