From: <sur...@am...> - 2013-06-18 15:28:11
|
From: Suravee Suthikulpanit <sur...@am...> Current libop does not allow named mask to be used as default mask. This causes the tools to fail when user does not specify the named mask of an event and relying on the numerical default unit mask which could have duplication. Signed-off-by: Suravee Suthikulpanit <sur...@am...> --- Example: uops_issued: (counter: all) uops_issued (min count: 2000003) Unit masks (default 0x1) ---------- 0x01: (name=any) Uops that Resource Allocation Table (RAT) issues to Reservation Station (RS) 0x10: (name=flags_merge) Number of flags-merge uops being allocated. Such uops considered perf sensitive; added by GSR u-arch. 0x20: (name=slow_lea) Number of slow LEA uops being allocated. A uop is generally considered SlowLea if it has 3 sources (e.g. 2 sources + immediate) regardless if as a result of LEA instruction or not. 0x40: (name=single_mul) Number of Multiply packed/scalar single precision uops allocated 0x01: (name=stall_cycles) Cycles when Resource Allocation Table (RAT) does not issue Uops to Reservation Station (RS) for the thread 0x01: (name=core_stall_cycles) Cycles when Resource Allocation Table (RAT) does not issue Uops to Reservation Station (RS) for all threads Changes in V4: - Remove "extra" from unit mask entry of ophelp output. - Move "named mask" to the beginning of the output - Modify "word_wrap" function slightly to allow appending space. Changes in V3: - Fix ophelp to properly print out the mask name and default mask name libop/op_events.c | 86 ++++++++++++++++++++++++++++++++++++++++------------- libop/op_events.h | 2 ++ utils/ophelp.c | 42 ++++++++++++-------------- 3 files changed, 87 insertions(+), 43 deletions(-) diff --git a/libop/op_events.c b/libop/op_events.c index 276386d..bba7b43 100644 --- a/libop/op_events.c +++ b/libop/op_events.c @@ -197,7 +197,12 @@ static void parse_um(struct op_unit_mask * um, char const * line) if (seen_default) parse_error("duplicate default: tag"); seen_default = 1; - um->default_mask = parse_hex(tagend); + if (0 != strncmp(tagend, "0x", 2)) { + um->default_mask_name = op_xstrndup( + tagend, valueend - tagend); + } else { + um->default_mask = parse_hex(tagend); + } } else { parse_error("invalid unit mask tag"); } @@ -215,32 +220,50 @@ static void parse_um(struct op_unit_mask * um, char const * line) /* \t0x08 (M)odified cache state */ -/* \t0x08 extra:inv,cmask=... (M)odified cache state */ +/* \t0x08 extra:inv,cmask=... mod_cach_state (M)odified cache state */ static void parse_um_entry(struct op_described_um * entry, char const * line) { char const * c = line; + /* value */ c = skip_ws(c); entry->value = parse_hex(c); - c = skip_nonws(c); + /* extra: */ + c = skip_nonws(c); c = skip_ws(c); + if (!*c) + goto invalid_out; + if (strisprefix(c, "extra:")) { c += 6; entry->extra = parse_extra(c); + /* named mask */ c = skip_nonws(c); - } else - entry->extra = 0; - - if (!*c) - parse_error("invalid unit mask entry"); + c = skip_ws(c); + if (!*c) + goto invalid_out; - c = skip_ws(c); + /* "extra:" !!ALWAYS!! followed by named mask */ + entry->name = op_xstrndup(c, strcspn(c, " \t")); + c = skip_nonws(c); + c = skip_ws(c); + } else { + entry->extra = 0; + } - if (!*c) - parse_error("invalid unit mask entry"); + /* desc */ + if (!*c) { + /* This is a corner case where the named unit mask entry + * only has one word. This should really be fixed in the + * unit_mask file */ + entry->desc = xstrdup(entry->name); + } else + entry->desc = xstrdup(c); + return; - entry->desc = xstrdup(c); +invalid_out: + parse_error("invalid unit mask entry"); } @@ -605,10 +628,18 @@ static int check_unit_mask(struct op_unit_mask const * um, "(%s)\n", um->name, cpu_name); err = EXIT_FAILURE; } - } else { - for (i = 0; i < um->num; ++i) { - if (um->default_mask == um->um[i].value) - break; + } else if (um->unit_type_mask == utm_exclusive) { + if (um->default_mask_name) { + for (i = 0; i < um->num; ++i) { + if (0 == strcmp(um->default_mask_name, + um->um[i].name)) + break; + } + } else { + for (i = 0; i < um->num; ++i) { + if (um->default_mask == um->um[i].value) + break; + } } if (i == um->num) { @@ -708,6 +739,7 @@ static void load_events(op_cpu cpu_type) unit_mask->unit_type_mask = utm_mandatory; unit_mask->um[0].extra = 0; unit_mask->um[0].value = 0; + unit_mask->um[0].name = xstrdup(""); unit_mask->um[0].desc = xstrdup("No unit mask"); unit_mask->used = 1; @@ -1335,10 +1367,18 @@ static void extra_check(struct op_event *e, char *name, unsigned w) } } -static void do_resolve_unit_mask(struct op_event *e, struct parsed_event *pe, u32 *extra) +static void do_resolve_unit_mask(struct op_event *e, + struct parsed_event *pe, u32 *extra) { unsigned i; + /* If not specified um and the default um is name type + * we populate pe unitmask name with default name */ + if ((e->unit->default_mask_name != NULL) && + (pe->unit_mask_name == NULL)) { + pe->unit_mask_name = xstrdup(e->unit->default_mask_name); + } + for (;;) { if (pe->unit_mask_name == NULL) { /* For numerical unit mask */ @@ -1374,9 +1414,15 @@ static void do_resolve_unit_mask(struct op_event *e, struct parsed_event *pe, u3 } else { /* For named unit mask */ for (i = 0; i < e->unit->num; i++) { - int len = strcspn(e->unit->um[i].desc, " \t"); - if (!strncmp(pe->unit_mask_name, e->unit->um[i].desc, - len) && pe->unit_mask_name[len] == '\0') + int len = 0; + + if (e->unit->um[i].name) + len = strlen(e->unit->um[i].name); + + if (len + && (!strncmp(pe->unit_mask_name, + e->unit->um[i].name, len)) + && (pe->unit_mask_name[len] == '\0')) break; } if (i == e->unit->num) { diff --git a/libop/op_events.h b/libop/op_events.h index a437f2a..33114f7 100644 --- a/libop/op_events.h +++ b/libop/op_events.h @@ -56,9 +56,11 @@ struct op_unit_mask { u32 num; /**< number of possible unit masks */ enum unit_mask_type unit_type_mask; u32 default_mask; /**< only the gui use it */ + char * default_mask_name; struct op_described_um { u32 extra; u32 value; + char * name; char * desc; } um[MAX_UNIT_MASK]; struct list_head um_next; /**< next um in list */ diff --git a/utils/ophelp.c b/utils/ophelp.c index 2f83528..c25efe5 100644 --- a/utils/ophelp.c +++ b/utils/ophelp.c @@ -74,8 +74,9 @@ static void word_wrap(int indent, int *column, char *msg) printf("%.*s", wlen, msg); *column += wlen + 1; msg += wlen; - msg += strspn(msg, " "); - if (*msg) + wlen = strspn(msg, " "); + msg += wlen; + if (wlen != 0) putchar(' '); } } @@ -136,34 +137,29 @@ static void help_for_event(struct op_event * event) if (strcmp(event->unit->name, "zero")) { - printf("\tUnit masks (default 0x%x)\n", - event->unit->default_mask); + if (event->unit->default_mask_name) { + printf("\tUnit masks (default %s)\n", + event->unit->default_mask_name); + } else { + printf("\tUnit masks (default 0x%x)\n", + event->unit->default_mask); + } printf("\t----------\n"); for (j = 0; j < event->unit->num; j++) { printf("\t0x%.2x: ", event->unit->um[j].value); column = 14; - word_wrap(14, &column, event->unit->um[j].desc); - if (event->unit->um[j].extra) { - u32 extra = event->unit->um[j].extra; - - word_wrap(14, &column, " (extra:"); - if (extra & EXTRA_EDGE) - word_wrap(14, &column, " edge"); - if (extra & EXTRA_INV) - word_wrap(14, &column, " inv"); - if ((extra >> EXTRA_CMASK_SHIFT) & EXTRA_CMASK_MASK) { - snprintf(buf, sizeof buf, " cmask=%x", - (extra >> EXTRA_CMASK_SHIFT) & EXTRA_CMASK_MASK); - word_wrap(14, &column, buf); - } - if (extra & EXTRA_ANY) - word_wrap(14, &column, " any"); - if (extra & EXTRA_PEBS) - word_wrap(14, &column, " pebs"); - word_wrap(14, &column, ")"); + + /* Named mask */ + if (event->unit->um[j].name) { + word_wrap(14, &column, "(name="); + word_wrap(14, &column, + event->unit->um[j].name); + word_wrap(14, &column, ") "); } + + word_wrap(14, &column, event->unit->um[j].desc); putchar('\n'); } } -- 1.7.10.4 |