runners: test: Reworked -P/--powerloss to use another expr-like grammar

This reworks -P/--powerloss to be more consistent with other flexible
flags (-D/--define, -S/--probe, etc):

- Tweaks -P/--powerloss to accept multiple flags (-Pnone -Plinear)
  instead of a comma-separated list (-Pnone,linear)

- Adopts an expr-like grammar similar to -Dx='range(3)', -Sx=123shz, etc
  (see below)

- Generalizes run_powerloss_linear and run_powerloss_log to accept
  start/stop/step conditions, allowing for range and logrange exprs
  with minimal work

---

The new expr-like grammar follows what's worked well for -D/--define,
-S/--probe, etc, in which parens can be used to parameterize some of the
more complex scenarios. This makes the -P/--powerloss grammar more
consistent, less ad-hoc, easier to parse, while also providing
flexibility for future powerloss exprs.

As an example, bounded range/logrange variants of linear/log were easy
to add without each needing their own little syntax:

- none -> none              - Run with no powerlosses
- linear -> linear          - Run with linearly-decreasing powerlosses
- log -> log                - Run with exponentially-decreasing pls
- n -> permute(n)           - Run all permutations of n powerlosses
- exhaustive -> exhaustive  - Run all powerloss permutations
- {1,2,3} -> list(1,2,3)    - Run explicit list of powerlosses
- added range(a,b,s)        - Run explicit range of powerlosses
- added logrange(a,b,s)     - Run explicit range of 2^n powerlosses
- :1248g1 -> :1248g1        - Run custom leb128-encoded set of pls

Note we still keep :-prefixed leb128-encoded powerlosses as is. This is
enough of its own syntax that trying to map it to an expr doesn't really
make sense. And is humorously compatible with most future grammars.
This commit is contained in:
Christopher Haster
2026-02-09 18:30:09 -06:00
parent 4af4cf3212
commit 5a271da7eb
4 changed files with 292 additions and 298 deletions
+9 -9
View File
@@ -52,9 +52,9 @@ void *mappend(void **p,
}
// a quick self-terminating text-safe varint scheme
static void leb16_print(uintmax_t x) {
static void leb16_print(intmax_t x) {
// allow 'w' to indicate negative numbers
if ((intmax_t)x < 0) {
if (x < 0) {
printf("w");
x = -x;
}
@@ -69,7 +69,7 @@ static void leb16_print(uintmax_t x) {
}
}
static uintmax_t leb16_parse(const char *s, char **tail) {
static intmax_t leb16_parse(const char *s, char **tail) {
bool neg = false;
uintmax_t x = 0;
if (tail) {
@@ -392,13 +392,13 @@ intmax_t bench_override_cb(void *data, size_t i) {
if (v->step) {
size_t range_count;
if (v->step > 0) {
range_count = (v->stop-1 - v->start) / v->step + 1;
range_count = (v->stop-1 - v->start) / +v->step + 1;
} else {
range_count = (v->start-1 - v->stop) / -v->step + 1;
}
if (i < range_count) {
return i*v->step + v->start;
return v->start + i*v->step;
}
i -= range_count;
// value?
@@ -903,7 +903,7 @@ int __wrap_vprintf(const char *fmt, va_list args) {
// bench probe/recording state
typedef struct bench_probe {
const char *probe;
const char *name;
size_t step;
double runfreq;
double simfreq;
@@ -1017,7 +1017,7 @@ bench_record_t *bench_find(const char *probe) {
// find probe descriptor, if there is one
bench_probe_t *probe_ = NULL;
for (size_t i = 0; i < bench_probe_count; i++) {
if (strcmp(bench_probes[i].probe, probe) == 0) {
if (strcmp(bench_probes[i].name, probe) == 0) {
probe_ = &bench_probes[i];
break;
}
@@ -2711,7 +2711,7 @@ int main(int argc, char **argv) {
if (*optarg == ',') {
optarg += 1;
step = strtoumax(optarg, &parsed, 0);
// allow empty string for stop=1
// allow empty string for step=1
if (parsed == optarg) {
step = 1;
}
@@ -2814,7 +2814,7 @@ int main(int argc, char **argv) {
// parse into string key/intmax_t value, cannibalizing the
// arg in the process
probe->probe = optarg;
probe->name = optarg;
sep = strchr(optarg, '=');
if (sep) {
*sep = '\0';