stephane eranian wrote:
> On Mon, Dec 7, 2009 at 10:46 PM, Corey Ashford
> <cjash...@linux.vnet.ibm.com> wrote:
>> Hi Stephane,
>>
>> stephane eranian wrote:
>>> On Fri, Dec 4, 2009 at 11:16 PM, Corey Ashford
>>> <cjash...@linux.vnet.ibm.com> wrote:
>>>
>>>> I assume this is supposed to be
>>>>                   .uname = "CORE_SELF",\
>>>>
>>>>>                 .udesc = "This core",\
>>>>>                 .ucode = 0x40\
>>>>>               },\
>>>>>               { .uname = "BOTH_CORES",\
>>>> and
>>>>                   .uname = "CORE_BOTH",\
>>>>
>>>>>                 .udesc = "Both cores",\
>>>>>                 .ucode = 0xc0\
>>>>>               }
>>>>>
>>> Yes.
>>>
>>>
>>>>> In this particular case, a reasonable default would be
>>>>>
>>>>> L2_LD:ANY:MESI:CORE_SELF:u=1:k=0:i=0:e=0:c=0
>>>>>
>>>>> I think the only reasonable approach would be for the
>>>>> tool to iterate over all the attributes and query 'default'
>>>>> information. So here, it would return:
>>>>>
>>>>> M: is_dfl=0
>>>>> E: is_dfl=0
>>>>> S: is_dfl=0
>>>>> I: is_dfl=0
>>>>> MESI: is_dfl=1 value=0xf (unit mask value)
>>>>> CORE_BOTH: is_dfl=0
>>>>> CORE_SELF: is_dfl=1
>>>>> u: is_dfl=1 value=1
>>>>> k: is_dfl=0
>>>>> i: is_dfl=0
>>>>> e: is_dfl=0
>>>>> c: is_dfl=0
>>>> Just so I'm certain I understand what you are saying, if I specify
>>>>
>>>> L2_LD:MESI:M=0
>>>>
>>>> would that be an error (because M=0 conflicts with MESI) ?
>>>>
>>> I assume you mean M as in Modified, i.e,, from MESI. In this
>>> case, you would get an error because MESI are managed as
>>> unit masks, not modifiers. You'd get an error because there is
>>> no modifier called M.
>>>
>>> But going back to your example:
>>>   L2_LD:MESI:M
>>>
>>> This would be legal because MESI bits can be combined. That would
>>> be a stupid combination because you would end up measuring MESI.
>>> The library would have to ensure that there is either at least one
>>> unit mask set per group (here the group is M, E, S, I) or it would pick
>>> the default (here MESI).
>> I think I was a bit confused because there was no group description for
>> INTEL_CORE_MESI_UMASKS.
>>
>> I see how it works for unit masks, but what about modifiers with values?
>>
>> Let's say I have a group called DFL_GROUP which, as one of the things it
>> does
>> sets an integer modifier x to 0.  Could I do this:
>>
>> FOO_EVENT:DFL_GROUP:x=8
>>
> I think we need to distinguish between default and hardcoded as part of a
> unit mask.

Correct.  We should not allow the overriding of umasks or modifiers that need 
to 
be set in a certain way to correctly record an event.  My first approach for 
that was simply to make the hard-coded umask/modifiers unavailable for that 
event.

> In your case I suspect x=0 is part of DFL_GROUP, i.e., it is
> necessary for DFL_GROUP to measure what its definition says it measures.
> In that case, x=8, would be illegal. That's different from a default which
> is not part of any specific unit mask definition but it will be used if the
> user omits the modifiers (or unit mask).

To give a more concrete example, in the processor I'm working on, there is a 
class of events for which you can set the mode to level or edge counting, 
depending on what information you want out of it.  However, we generally know 
that most users are going to want, for example, edge counting for these events, 
so we provide that as a default, but will allow that default to be overridden, 
or explicitly specified to be the same as the default value, so that, for 
example:

EVENT
is equivalent to
EVENT:e=1
but can be overridden as
EVENT:e=0

Of course the other way to approach this is that if there's any choice, force 
the user to make a choice rather than assume anything about what he wants.

> 
> Another way of looking at it would be to let the user make mistakes.
> Let the user override x with 8.
> The existing X86 libpfm4 codebase, refuse to set the value of a modifier
> if it is already not zero. But that's specific to X86. It may be that on
> Power, a value of 0 may be required for certain unit masks. 0 is just
> the neutral value on X86, it could be something else on Power. This is
> all in PMU specific code for this reason.
> 
>

Perhaps another way, would be to have an additional flag called is_hard_wired 
which is mutually exclusive with is_dfl.  This way you could display the 
hard-wired umasks and modifier values to the user, but let them know they can't 
change them.

> 
>> and would that differ from
>>
>> FOO_EVENT:x=8:DFL_GROUP
>>
> With the first approach, you would fail DFL_GROUP because it sets a modifier
> already set by the user. With the second approach, DFL_GROUP would override
> x=8.
> 
>> Or perhaps I am misunderstanding how groups work?  Re-reading your proposal,
>> it seems that what a group actually does is not encoded into the data
>> structure, but rather into the libpfm code.  Is that correct?
>>
> I was thinking of groups more in terms of unit masks. A group
> represents a choice of
> unit masks to choose from, where at least one must be set. An event may have
> more than one group, i.e., at least of mask in each group must be set.
> The current
> implementation has one group per event (when they have unit masks). I think we
> need to extend this notion. For instance,
> 
> EVENTA:
>    grp1: A, B, C
>    grp2: D, E, F, G
> 
> That means that you need to set at least one mask in grp1 and one in grp2:
>     EVENTA:A:D        is okay
>     EVENTA:A:B:F     is okay
>     EVENTA:C           is bad
>     EVENTA:FG         is bad
> 
> I think your example adds to this by saying mask A comes from x=0.
> I think this info can be hardcoded as part of the unit mask code. This is how
> it's done on X86. Of course, you need a way to identify the value that means
> 'not set'. If that's not possible, then you need to augment the event 
> structure
> with a field that encodes this.
> 
>> Maybe another way to handle groups is to use "macros" which translate the
>> group name string into lower-level umask and modifier strings processed in
>> the normal way.  As a very simple example:
>>
>> "MESI" -> "M:E:S:I"
>>
>> A more complex case might be:
>>
>> "SOME_GROUP" -> "E:x=0x100:tm=4:k=1:h=1"
>>
> See my answer above about how to hardcode this.

If the hard-coding allows encoding the setting of multiple modifiers/umasks, I 
think this should be fine.  I just don't see how to mix different attributes 
into a single member of a group, given the structure you provided in the 
previous post.

> 
>> All defaults could be done via macros.  If no macro string within list for a
>> specific event is specified, the first one in the list is the default.
>> Something like that.  Doing this would keep you from having to handle all of
>> this in code; the data would drive the translation.  These translations
>> would have to be event-specific, at worst.
> 
> Please show me a concrete example of the macros.

The MESI example was concrete.  The other was a random jumble of umasks and 
modifiers.  I was just looking for a way that could express any combination of 
umasks and modifiers in a clear and simple way, rather than using complex 
structures.

Let me make one that's more complex than MESI and maybe more realistic.  Let's 
say I have an event, call it EVT1, which normally I would want to specify that 
it's for my CPU thread, but in some cases I want to specify a mask which shows 
which CPU threads I want it to measure.  So I set up a group containing three 
macros for EVT1:
"THIS_CPU_THREAD" -> "ethm=0"  // ethm is "enable thread mask"
"ALL_CPU_THREADS" -> "ethm=1:thm=0xff"  // thm is the thread mask, assuming 8 
threads
"SOME_CPU_THREADS" -> "ethm=1" // user must specify thm value now (this macro 
is 
really not that useful)

In addition to this, perhaps I want the event to count level rather than edges, 
but libpfm has determined edges to be the default.  So another group would be 
for this choice:
"EDGES" -> "e=1"
"LEVEL" -> "e=0"

The default for a particular group is the first one in the group.  With these 
two groups, if I specify just "EVT1", I will effectively get "EVT1:ethm=0:e=1". 
  Since I want level counting, I should specify "EVT1:LEVEL" or equivalently 
"EVT1:e=0".

The definition of a group then, is an array of string pointer pairs:
struct attribute_macro {
        const char *name;
        const char *translation;
};

Groups could be associated with events, per-event if necessary, or however the 
libpfm4 arch-dependent implementation best deems.

And since you have potentially more than one group, you also need an array of 
groups.  So there are a couple of levels indirection needed here: 
group[i].macro[j].  A group definition would look something like

struct attribute_macro *group[] = ...

The event string should include one of the members of each group, and if no 
member of a particular group is specified, you take the first one of the group. 
  One other thing comes to mind is that we might want the capability of having 
groups for which there is no default, so we still might need a flag for the 
group which says "0 = has no default, 1 = macro[0] is the default"

These translations could be arbitrarily complex, but I think it would make the 
libpfm code quite easy to read and modify.

To handle the hard-wired case, we'd create a group with a single translation in 
it, which is the hard-wired combination.  We could add another flag to the 
definition of a group that would designate that this macro is hard-wired, and 
not to change any of the attributes set by this macro.  This would add some 
complexity to the libpfm code, because now it has to check for users attempting 
to override attributes specified by the hard-wired default.  How exactly to do 
this check, I don't know.  Perhaps use a bit vector to designate which 
attributes have been set by the hard-wired default, and when you encounter an 
attribute, you check the bit mask to see if this attribute is already 
hard-wired 
for this event.

To flesh out the group definition with the above in mind, perhaps it could look 
like this:

struct attribute_macro {
        const char *name;
        const char *translation;
};

struct macro_group {
        union {
                uint32_t        flags;
                uint32_t        is_hard_wired:1
                                is_dfl:1;
                                reserved:30;
        }
         int ngroups;
        struct attribute_macro *group[];
}


What do you think?

- Corey




------------------------------------------------------------------------------
Return on Information:
Google Enterprise Search pays you back
Get the facts.
http://p.sf.net/sfu/google-dev2dev
_______________________________________________
perfmon2-devel mailing list
perfmon2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/perfmon2-devel

Reply via email to