Re: [gem5-dev] [m5-dev] src/dest detection in the ISA descriptions

2011-05-28 Thread Gabriel Michael Black

ping

Quoting Gabe Black :


Ping...

On 05/05/11 10:38, Steve Reinhardt wrote:

On Wed, May 4, 2011 at 2:25 PM, Gabe Black  wrote:


Did that make sense?


I see how that could work... I think I was more puzzled by how you would
figure out that

for (int i = 0; i < 7; i++)
Dest.bytes[i] = Source1.bytes[i] + Source2.bytes[i];

overwrote all of Dest, but

for (int i = 0; i < 4; i++)
Dest.bytes[i] = Source1.bytes[i] + Source2.bytes[i];

wouldn't... but looking back I see now that you'd expect to need manual
annotations in at least one of those cases.



Do you think you'll be able to review those patches
soonish?


I'll try... thanks for the reminder, that definitely increases the
probability :-).

Steve
___
m5-dev mailing list
m5-...@m5sim.org
http://m5sim.org/mailman/listinfo/m5-dev


___
m5-dev mailing list
m5-...@m5sim.org
http://m5sim.org/mailman/listinfo/m5-dev




___
gem5-dev mailing list
gem5-dev@m5sim.org
http://m5sim.org/mailman/listinfo/gem5-dev


Re: [m5-dev] src/dest detection in the ISA descriptions

2011-05-15 Thread Gabe Black
Ping...

On 05/05/11 10:38, Steve Reinhardt wrote:
> On Wed, May 4, 2011 at 2:25 PM, Gabe Black  wrote:
>
>> Did that make sense?
>
> I see how that could work... I think I was more puzzled by how you would
> figure out that
>
> for (int i = 0; i < 7; i++)
> Dest.bytes[i] = Source1.bytes[i] + Source2.bytes[i];
>
> overwrote all of Dest, but
>
> for (int i = 0; i < 4; i++)
> Dest.bytes[i] = Source1.bytes[i] + Source2.bytes[i];
>
> wouldn't... but looking back I see now that you'd expect to need manual
> annotations in at least one of those cases.
>
>
>> Do you think you'll be able to review those patches
>> soonish?
>>
> I'll try... thanks for the reminder, that definitely increases the
> probability :-).
>
> Steve
> ___
> m5-dev mailing list
> m5-dev@m5sim.org
> http://m5sim.org/mailman/listinfo/m5-dev

___
m5-dev mailing list
m5-dev@m5sim.org
http://m5sim.org/mailman/listinfo/m5-dev


Re: [m5-dev] src/dest detection in the ISA descriptions

2011-05-05 Thread Steve Reinhardt
On Wed, May 4, 2011 at 2:25 PM, Gabe Black  wrote:

> Did that make sense?


I see how that could work... I think I was more puzzled by how you would
figure out that

for (int i = 0; i < 7; i++)
Dest.bytes[i] = Source1.bytes[i] + Source2.bytes[i];

overwrote all of Dest, but

for (int i = 0; i < 4; i++)
Dest.bytes[i] = Source1.bytes[i] + Source2.bytes[i];

wouldn't... but looking back I see now that you'd expect to need manual
annotations in at least one of those cases.


> Do you think you'll be able to review those patches
> soonish?
>

I'll try... thanks for the reminder, that definitely increases the
probability :-).

Steve
___
m5-dev mailing list
m5-dev@m5sim.org
http://m5sim.org/mailman/listinfo/m5-dev


Re: [m5-dev] src/dest detection in the ISA descriptions

2011-05-04 Thread Gabe Black
On 04/27/11 22:14, Gabe Black wrote:
> My idea is to be able to inherit from the standard op types like
> IntRegOperand and allow them to install more than one index and/or
> change how they're declared, read, and written. So say for example you
> had a 128 bit wide SIMD instruction operating on four floating point
> registers which are normally accessible as 32 bit, indexed through some
> strange scheme. You could say that operand generates 4 indices,
> determined by whatever weird formula or just sequentially. Then you
> could define a structure which was the union of an array of 4 32 bit
> ints and 4 floats or 2 doubles, or 16 bytes, or ... The constructor
> could take the return of reading the 4 indices with
> readFloatRegOperandBits to fill it's main array, and then the
> instruction could access whatever other representation it needed. The
> other direction would work as well. Then, assuming we get this
> source/dest thing straightened out, you could have an instruction that,
> say, did parallel byte adds defined like this:
>
> for (int i = 0; i < 7; i++)
>Dest.bytes[i] = Source1.bytes[i] + Source2.bytes[i];
>
> And all the other goop would figure itself out. If some other scheme was
> needed (runtime selectable width, selectable float vs. int, etc) then
> the IntRegOperand subclass combined with the composite operand type
> could have the smarts to do the right thing all tidily hidden away after
> it was set up. Note that Dest is just a dest, even though it uses a
> structure field.
>
 I'm not sure how you're envisioning this will work... are you assuming
 there's a full C++ parser like gcc-xml?  How would you know that in this
 case you're overwriting all of Dest, but if the upper bound of the loop
>>> was
 6 and not 7 then it would be just a partial overwrite?  That's a level of
 compiler analysis I *really* don't want to get into.  (Yes, it is
 theoretically feasible and it would be pretty slick, but I'm sure there
>>> are
 many other things that would have a greater ROI than that.)

 Could we do this with C++ operator overloading?  Seems like you could
>>> just
 say "Dest = Source1 + Source2;" which would be obvious to our code
>>> parser,
 and then have C++ do the magic.  The type extensions could be used as
>>> casts
 to make this more flexible, e.g., "Dest = Source1@bv + Source2@bv" could
>>> do
 byte-by-byte adds while "Source1@fv + Source2@fv" could do it by 32-bit
 floats, or something like that.
>>> The only tricky thing there is determining what is a source and what is
>>> a dest, although it highlights how hard that can be.
>> I still don't really get your proposal, in terms of how the code sample you
>> have parsed above would get turned into a concrete set of source and dest
>> operand indices.
> Very roughly, it would look something like this.
>
> struct SimdData
> {
> union
> {
> uint32_t regBits[4];
> uint8_t bytes[32];
> };
> };
>
> def operand_types {{
> 'SimdData' : 'SimdData'
> }};
>
> class SimdOp(FloatRegOperand):
> def makeConstructor(self):
> return '''
> _srcRegIdx[numSrcRegs++] = %s + 0 + FP_Base_DepTag;
> _srcRegIdx[numSrcRegs++] = %s + 1 + FP_Base_DepTag;
> _srcRegIdx[numSrcRegs++] = %s + 2 + FP_Base_DepTag;
> _srcRegIdx[numSrcRegs++] = %s + 3 + FP_Base_DepTag;
> '''
> def makeRead(self):
> return '''
> %s.regBits[0] = xc->readFloatRegOperandBits(this, %d + 0,
> final_val);
> %s.regBits[1] = xc->readFloatRegOperandBits(this, %d + 1,
> final_val);
> %s.regBits[2] = xc->readFloatRegOperandBits(this, %d + 2,
> final_val);
> %s.regBits[3] = xc->readFloatRegOperandBits(this, %d + 3,
> final_val);
> ''' % (self.base_name, self.idxStart (?))
> def makeWrite(self):
> return '''
> xc->setFloatRegOperandBits(this, %d, %s.regBits[0]);
> xc->setFloatRegOperandBits(this, %d, %s.regBits[1]);
> xc->setFloatRegOperandBits(this, %d, %s.regBits[2]);
> xc->setFloatRegOperandBits(this, %d, %s.regBits[3]);
> ''' % (self.idxStart, self.base_name)
>
> def operands {{
> 'Dest' : ('SimdOp', 'SimdData', 'DEST', 'IsInteger', 1),
> 'Source1' : ('SimdOp', 'SimdData', 'SOURCE1', 'IsInteger', 2),
> 'Source2 : ('SimdOp', 'SimdData', 'SOURCE2', 'IsInteger', 3),
> }};
>

Did that make sense? Do you think you'll be able to review those patches
soonish?

Gabe
___
m5-dev mailing list
m5-dev@m5sim.org
http://m5sim.org/mailman/listinfo/m5-dev


Re: [m5-dev] src/dest detection in the ISA descriptions

2011-04-27 Thread Gabe Black

 My idea is to be able to inherit from the standard op types like
 IntRegOperand and allow them to install more than one index and/or
 change how they're declared, read, and written. So say for example you
 had a 128 bit wide SIMD instruction operating on four floating point
 registers which are normally accessible as 32 bit, indexed through some
 strange scheme. You could say that operand generates 4 indices,
 determined by whatever weird formula or just sequentially. Then you
 could define a structure which was the union of an array of 4 32 bit
 ints and 4 floats or 2 doubles, or 16 bytes, or ... The constructor
 could take the return of reading the 4 indices with
 readFloatRegOperandBits to fill it's main array, and then the
 instruction could access whatever other representation it needed. The
 other direction would work as well. Then, assuming we get this
 source/dest thing straightened out, you could have an instruction that,
 say, did parallel byte adds defined like this:

 for (int i = 0; i < 7; i++)
Dest.bytes[i] = Source1.bytes[i] + Source2.bytes[i];

 And all the other goop would figure itself out. If some other scheme was
 needed (runtime selectable width, selectable float vs. int, etc) then
 the IntRegOperand subclass combined with the composite operand type
 could have the smarts to do the right thing all tidily hidden away after
 it was set up. Note that Dest is just a dest, even though it uses a
 structure field.

>>> I'm not sure how you're envisioning this will work... are you assuming
>>> there's a full C++ parser like gcc-xml?  How would you know that in this
>>> case you're overwriting all of Dest, but if the upper bound of the loop
>> was
>>> 6 and not 7 then it would be just a partial overwrite?  That's a level of
>>> compiler analysis I *really* don't want to get into.  (Yes, it is
>>> theoretically feasible and it would be pretty slick, but I'm sure there
>> are
>>> many other things that would have a greater ROI than that.)
>>>
>>> Could we do this with C++ operator overloading?  Seems like you could
>> just
>>> say "Dest = Source1 + Source2;" which would be obvious to our code
>> parser,
>>> and then have C++ do the magic.  The type extensions could be used as
>> casts
>>> to make this more flexible, e.g., "Dest = Source1@bv + Source2@bv" could
>> do
>>> byte-by-byte adds while "Source1@fv + Source2@fv" could do it by 32-bit
>>> floats, or something like that.
>> The only tricky thing there is determining what is a source and what is
>> a dest, although it highlights how hard that can be.
>
> I still don't really get your proposal, in terms of how the code sample you
> have parsed above would get turned into a concrete set of source and dest
> operand indices.

Very roughly, it would look something like this.

struct SimdData
{
union
{
uint32_t regBits[4];
uint8_t bytes[32];
};
};

def operand_types {{
'SimdData' : 'SimdData'
}};

class SimdOp(FloatRegOperand):
def makeConstructor(self):
return '''
_srcRegIdx[numSrcRegs++] = %s + 0 + FP_Base_DepTag;
_srcRegIdx[numSrcRegs++] = %s + 1 + FP_Base_DepTag;
_srcRegIdx[numSrcRegs++] = %s + 2 + FP_Base_DepTag;
_srcRegIdx[numSrcRegs++] = %s + 3 + FP_Base_DepTag;
'''
def makeRead(self):
return '''
%s.regBits[0] = xc->readFloatRegOperandBits(this, %d + 0,
final_val);
%s.regBits[1] = xc->readFloatRegOperandBits(this, %d + 1,
final_val);
%s.regBits[2] = xc->readFloatRegOperandBits(this, %d + 2,
final_val);
%s.regBits[3] = xc->readFloatRegOperandBits(this, %d + 3,
final_val);
''' % (self.base_name, self.idxStart (?))
def makeWrite(self):
return '''
xc->setFloatRegOperandBits(this, %d, %s.regBits[0]);
xc->setFloatRegOperandBits(this, %d, %s.regBits[1]);
xc->setFloatRegOperandBits(this, %d, %s.regBits[2]);
xc->setFloatRegOperandBits(this, %d, %s.regBits[3]);
''' % (self.idxStart, self.base_name)

def operands {{
'Dest' : ('SimdOp', 'SimdData', 'DEST', 'IsInteger', 1),
'Source1' : ('SimdOp', 'SimdData', 'SOURCE1', 'IsInteger', 2),
'Source2 : ('SimdOp', 'SimdData', 'SOURCE2', 'IsInteger', 3),
}};

>
 Also the operands might be smart enough to change how they set
 themselves up on the fly. Lets say in a particular mode you only need 2
 32 bit floats and the other two spots are zeros. The operand
 initialization code could figure out what mode it's in at construction
 time that it doesn't need all 4 operands and could only fill in 2 spots.
 The next operand would then pack in behind it. This would hopefully make
 it easier to get multiple behaviors without having to define a new
 instruction (or just code blob) for each one.

>>> Are there concrete examples of this

Re: [m5-dev] src/dest detection in the ISA descriptions

2011-04-27 Thread Steve Reinhardt
On Wed, Apr 27, 2011 at 10:14 AM, Gabe Black  wrote:

> On 04/27/11 08:02, Steve Reinhardt wrote:
> > On Wed, Apr 27, 2011 at 1:21 AM, Gabe Black 
> wrote:
> >
> >>> Perhaps the heuristics could simply be extended to deal with
> >>> structure field accesses... if the thing after the symbol is a ".",
> then
> >> you
> >>> look past that to see if there's an equals sign or not, and behave
> >>> appropriately.
> >> "appropriately" isn't clearly defined, really. [...]
> >>
> > "appropriately" was just a placeholder for "stuff I'm sure we can figure
> out
> > later". [...]
>
> My point is that it -is- too complicated to try to figure out if you
> overwrite an entire dest or just part of it. That's why you need to be
> able to say which it is by hand.
>

That's fine... having a system that does the right thing automatically most
of the time (like it does now, ideally with extensions to avoid awkward
workarounds and increase the fraction of time it's automatically right)
coupled with a way to efficiently do manual overrides when it's not right
seems like a fine approach to me.  Extending the heuristics as I said could
still be a part of avoiding workarounds and increasing the number of cases
where it does the right thing automatically.


> >> My idea is to be able to inherit from the standard op types like
> >> IntRegOperand and allow them to install more than one index and/or
> >> change how they're declared, read, and written. So say for example you
> >> had a 128 bit wide SIMD instruction operating on four floating point
> >> registers which are normally accessible as 32 bit, indexed through some
> >> strange scheme. You could say that operand generates 4 indices,
> >> determined by whatever weird formula or just sequentially. Then you
> >> could define a structure which was the union of an array of 4 32 bit
> >> ints and 4 floats or 2 doubles, or 16 bytes, or ... The constructor
> >> could take the return of reading the 4 indices with
> >> readFloatRegOperandBits to fill it's main array, and then the
> >> instruction could access whatever other representation it needed. The
> >> other direction would work as well. Then, assuming we get this
> >> source/dest thing straightened out, you could have an instruction that,
> >> say, did parallel byte adds defined like this:
> >>
> >> for (int i = 0; i < 7; i++)
> >>Dest.bytes[i] = Source1.bytes[i] + Source2.bytes[i];
> >>
> >> And all the other goop would figure itself out. If some other scheme was
> >> needed (runtime selectable width, selectable float vs. int, etc) then
> >> the IntRegOperand subclass combined with the composite operand type
> >> could have the smarts to do the right thing all tidily hidden away after
> >> it was set up. Note that Dest is just a dest, even though it uses a
> >> structure field.
> >>
> > I'm not sure how you're envisioning this will work... are you assuming
> > there's a full C++ parser like gcc-xml?  How would you know that in this
> > case you're overwriting all of Dest, but if the upper bound of the loop
> was
> > 6 and not 7 then it would be just a partial overwrite?  That's a level of
> > compiler analysis I *really* don't want to get into.  (Yes, it is
> > theoretically feasible and it would be pretty slick, but I'm sure there
> are
> > many other things that would have a greater ROI than that.)
> >
> > Could we do this with C++ operator overloading?  Seems like you could
> just
> > say "Dest = Source1 + Source2;" which would be obvious to our code
> parser,
> > and then have C++ do the magic.  The type extensions could be used as
> casts
> > to make this more flexible, e.g., "Dest = Source1@bv + Source2@bv" could
> do
> > byte-by-byte adds while "Source1@fv + Source2@fv" could do it by 32-bit
> > floats, or something like that.
>
> The only tricky thing there is determining what is a source and what is
> a dest, although it highlights how hard that can be.


I still don't really get your proposal, in terms of how the code sample you
have parsed above would get turned into a concrete set of source and dest
operand indices.


> Operator
> overloading seems a little too magical to me, and it wouldn't be obvious
> to somebody looking at the code what's going on. I also don't like
> having to engineer all the possible operations ahead of time and/or
> define a type that does each one. One of the problems I've seen with our
> approach so far is that having a few or even many prepackaged options
> breaks down as you scale it out. I would rather not just push out that
> boundary since we have a better idea of where it needs to be today.
> Granted, the types and operators could be defined as needed, but having
> to make a set for every operation would be pretty cumbersome.
>

I don't think operator overloading would be that confusing in this
particular case, but I agree it's not a general solution.


> >> Also the operands might be smart enough to change how they set
> >> themselves up on the fly. Lets say in a particular mode yo

Re: [m5-dev] src/dest detection in the ISA descriptions

2011-04-27 Thread Gabe Black
On 04/27/11 08:02, Steve Reinhardt wrote:
> On Wed, Apr 27, 2011 at 1:21 AM, Gabe Black  wrote:
>
>> The XML thing is an interesting possibility, and it avoids having to
>> make a whole new thing that understands C++. It would still mean we'd
>> have to make a whole new thing that understands XML (which is much
>> easier), but then there's the chicken and egg issue you mention. I don't
>> think we do anything sneaky with deciding what header files to include,
>> though, and we could probably tell the tool about the operands somehow,
>> maybe by making them globals that get thrown away later. The current
>> approach is far from 100% correct in that sense, so if we're a little
>> fuzzy around the edges that should be ok.
>>
> My concern is that parsing C is a much more complex and strictly defined
> thing than what we currently do... the current approach degrades
> "gracefully" in the sense that it might not get the results you want, but it
> never fails completely.  In contrast, if there's a situation where X is a
> type but gcc thinks it's a variable (or vice versa), the parsing could break
> down pretty completely.
>
>
>>  > This is why the ad hoc yet (as you say) surprisingly effective
>> heuristics
>>> were used.  Perhaps the heuristics could simply be extended to deal with
>>> structure field accesses... if the thing after the symbol is a ".", then
>> you
>>> look past that to see if there's an equals sign or not, and behave
>>> appropriately.
>> "appropriately" isn't clearly defined, really. There's an example in ARM
>> where there's a bit broken out of a status register which is set if some
>> condition happens. If you set it, you're really setting the whole thing
>> even though it looks like you're just setting the bitfield. Treating
>> that operand as a source isn't necessary in that case even though it
>> would normally be.
>>
> "appropriately" was just a placeholder for "stuff I'm sure we can figure out
> later".  Maybe there are two classes of fields, one that is a partial field
> (so that writing it means you have a source and a dest) and one that is a
> "complete" field (so that writing it implies just a dest, not a source).  If
> you want to automatically detect that you've written a set of partial fields
> that covers the entire structure and thus you don't need to consider it a
> source, I think you're asking too much... that's a place where either a
> manual override or just using the current approach and adding an extra
> useless assignment to the entire dest would be best, I think.

My point is that it -is- too complicated to try to figure out if you
overwrite an entire dest or just part of it. That's why you need to be
able to say which it is by hand.

>
>> The manual override would get us there, but one thing I worry about is
>> that if BitUnions or composite operands are used often, you might need
>> to have them all over the place. Some sort of inheritance or being able
>> to associate the overrides with a blob of code once that gets reused a
>> lot (like setting condition codes, checking predicates, etc.) would help.
>>
> Those all sound reasonable to me.
>
>
>> My idea is to be able to inherit from the standard op types like
>> IntRegOperand and allow them to install more than one index and/or
>> change how they're declared, read, and written. So say for example you
>> had a 128 bit wide SIMD instruction operating on four floating point
>> registers which are normally accessible as 32 bit, indexed through some
>> strange scheme. You could say that operand generates 4 indices,
>> determined by whatever weird formula or just sequentially. Then you
>> could define a structure which was the union of an array of 4 32 bit
>> ints and 4 floats or 2 doubles, or 16 bytes, or ... The constructor
>> could take the return of reading the 4 indices with
>> readFloatRegOperandBits to fill it's main array, and then the
>> instruction could access whatever other representation it needed. The
>> other direction would work as well. Then, assuming we get this
>> source/dest thing straightened out, you could have an instruction that,
>> say, did parallel byte adds defined like this:
>>
>> for (int i = 0; i < 7; i++)
>>Dest.bytes[i] = Source1.bytes[i] + Source2.bytes[i];
>>
>> And all the other goop would figure itself out. If some other scheme was
>> needed (runtime selectable width, selectable float vs. int, etc) then
>> the IntRegOperand subclass combined with the composite operand type
>> could have the smarts to do the right thing all tidily hidden away after
>> it was set up. Note that Dest is just a dest, even though it uses a
>> structure field.
>>
> I'm not sure how you're envisioning this will work... are you assuming
> there's a full C++ parser like gcc-xml?  How would you know that in this
> case you're overwriting all of Dest, but if the upper bound of the loop was
> 6 and not 7 then it would be just a partial overwrite?  That's a level of
> compiler analysis I *really* don't want to ge

Re: [m5-dev] src/dest detection in the ISA descriptions

2011-04-27 Thread Steve Reinhardt
On Wed, Apr 27, 2011 at 1:21 AM, Gabe Black  wrote:

> The XML thing is an interesting possibility, and it avoids having to
> make a whole new thing that understands C++. It would still mean we'd
> have to make a whole new thing that understands XML (which is much
> easier), but then there's the chicken and egg issue you mention. I don't
> think we do anything sneaky with deciding what header files to include,
> though, and we could probably tell the tool about the operands somehow,
> maybe by making them globals that get thrown away later. The current
> approach is far from 100% correct in that sense, so if we're a little
> fuzzy around the edges that should be ok.
>

My concern is that parsing C is a much more complex and strictly defined
thing than what we currently do... the current approach degrades
"gracefully" in the sense that it might not get the results you want, but it
never fails completely.  In contrast, if there's a situation where X is a
type but gcc thinks it's a variable (or vice versa), the parsing could break
down pretty completely.


>  > This is why the ad hoc yet (as you say) surprisingly effective
> heuristics
> > were used.  Perhaps the heuristics could simply be extended to deal with
> > structure field accesses... if the thing after the symbol is a ".", then
> you
> > look past that to see if there's an equals sign or not, and behave
> > appropriately.
>
> "appropriately" isn't clearly defined, really. There's an example in ARM
> where there's a bit broken out of a status register which is set if some
> condition happens. If you set it, you're really setting the whole thing
> even though it looks like you're just setting the bitfield. Treating
> that operand as a source isn't necessary in that case even though it
> would normally be.
>

"appropriately" was just a placeholder for "stuff I'm sure we can figure out
later".  Maybe there are two classes of fields, one that is a partial field
(so that writing it means you have a source and a dest) and one that is a
"complete" field (so that writing it implies just a dest, not a source).  If
you want to automatically detect that you've written a set of partial fields
that covers the entire structure and thus you don't need to consider it a
source, I think you're asking too much... that's a place where either a
manual override or just using the current approach and adding an extra
useless assignment to the entire dest would be best, I think.


> The manual override would get us there, but one thing I worry about is
> that if BitUnions or composite operands are used often, you might need
> to have them all over the place. Some sort of inheritance or being able
> to associate the overrides with a blob of code once that gets reused a
> lot (like setting condition codes, checking predicates, etc.) would help.
>

Those all sound reasonable to me.


> My idea is to be able to inherit from the standard op types like
> IntRegOperand and allow them to install more than one index and/or
> change how they're declared, read, and written. So say for example you
> had a 128 bit wide SIMD instruction operating on four floating point
> registers which are normally accessible as 32 bit, indexed through some
> strange scheme. You could say that operand generates 4 indices,
> determined by whatever weird formula or just sequentially. Then you
> could define a structure which was the union of an array of 4 32 bit
> ints and 4 floats or 2 doubles, or 16 bytes, or ... The constructor
> could take the return of reading the 4 indices with
> readFloatRegOperandBits to fill it's main array, and then the
> instruction could access whatever other representation it needed. The
> other direction would work as well. Then, assuming we get this
> source/dest thing straightened out, you could have an instruction that,
> say, did parallel byte adds defined like this:
>
> for (int i = 0; i < 7; i++)
>Dest.bytes[i] = Source1.bytes[i] + Source2.bytes[i];
>
> And all the other goop would figure itself out. If some other scheme was
> needed (runtime selectable width, selectable float vs. int, etc) then
> the IntRegOperand subclass combined with the composite operand type
> could have the smarts to do the right thing all tidily hidden away after
> it was set up. Note that Dest is just a dest, even though it uses a
> structure field.
>

I'm not sure how you're envisioning this will work... are you assuming
there's a full C++ parser like gcc-xml?  How would you know that in this
case you're overwriting all of Dest, but if the upper bound of the loop was
6 and not 7 then it would be just a partial overwrite?  That's a level of
compiler analysis I *really* don't want to get into.  (Yes, it is
theoretically feasible and it would be pretty slick, but I'm sure there are
many other things that would have a greater ROI than that.)

Could we do this with C++ operator overloading?  Seems like you could just
say "Dest = Source1 + Source2;" which would be obvious to our code parser,
and 

Re: [m5-dev] src/dest detection in the ISA descriptions

2011-04-27 Thread Gabe Black

>> Before I mentioned using @, and I have a patch that makes that change in
>> the parser and in all the ISA descs. It was less painful than you may
>> assume.
>>
> I haven't looked at your patches yet... is the main point of switching from
> . to @ to allow structure field accesses?

Basically. It could be structure fields or the bitfields of a BitUnion.
This had actually cropped up with the Twin(32|64)_t types SPARC uses,
and to get around it we added clunky parenthesis so the .foo didn't sit
directly next to the operand. gcc figured it out, but it could slip by
the parser.

>
>> I don't think there's a good way to figure out whether operands are a
>> source and/or destination in a setup like this. In the past, I've tried to
>> come up with a scheme that would force gcc/C++ to figure it out for us, but
>> no matter how clever/depraved I allow my solutions to be, they still don't
>> work. It might be possible to use a fancy compiler system like LLVM to build
>> a new tool to do it, but that isn't a near term solution (although I
>> wouldn't rule it out entirely).
>
> One potentially interesting angle to pursue is gcc-xml... I don't know much
> about it except that, as the name implies, it generates an xml
> representation rather than machine code, which should be reasonably
> analyzable.  I bet it's still hairy, but it might be the least hairy
> alternative.
>
> I expect the big problem with most of these approaches is that the final
> compilation context for most of the C snippets is not known at the time the
> code is parsed by the parser for operands etc.  Thus there will be symbols
> that you can't disambiguate as types etc. because the proper include files
> haven't been included (which could be undecidable if the proper include
> files are also being generated in the same isa_parser run, so maybe they
> don't even exist yet at the point where you need them).

The XML thing is an interesting possibility, and it avoids having to
make a whole new thing that understands C++. It would still mean we'd
have to make a whole new thing that understands XML (which is much
easier), but then there's the chicken and egg issue you mention. I don't
think we do anything sneaky with deciding what header files to include,
though, and we could probably tell the tool about the operands somehow,
maybe by making them globals that get thrown away later. The current
approach is far from 100% correct in that sense, so if we're a little
fuzzy around the edges that should be ok.

> This is why the ad hoc yet (as you say) surprisingly effective heuristics
> were used.  Perhaps the heuristics could simply be extended to deal with
> structure field accesses... if the thing after the symbol is a ".", then you
> look past that to see if there's an equals sign or not, and behave
> appropriately.

"appropriately" isn't clearly defined, really. There's an example in ARM
where there's a bit broken out of a status register which is set if some
condition happens. If you set it, you're really setting the whole thing
even though it looks like you're just setting the bitfield. Treating
that operand as a source isn't necessary in that case even though it
would normally be.

>
>
>> Another solution might be to explicitly list source and destination
>> operands like inline assembly blocks.
>
> I definitely don't like this idea.  One of the main motivations for the
> current implementation was the old SimpleScalar ISA definition macros, which
> required explicit listing of operands... and which as a result had subtle
> bugs that went undetected for years where particular dependencies weren't
> being enforced because someone left an operand out of the list.
>
> As you say, the current approach "works remarkably well most of the time",
> so while I'm all for improving it and addressing its shortcomings, I see no
> need to throw it out and replace it with something that's more manual
> effort, less concise, and more error prone.
>
> An extension that allows you to manually override what the parser finds. to
> deal with those cases where it's getting confused, would be fine though...
> basically sort of what you've been doing already, except that instead of
> "overriding" its heuristics by coming up with awkward code sequences that
> trick it into doing the right thing, you have a more blunt and effective
> path to do that.  That's probably not as big a step forward as you want, but
> to me it's preferable to just switching to a fully manual explicit scheme.

The manual override would get us there, but one thing I worry about is
that if BitUnions or composite operands are used often, you might need
to have them all over the place. Some sort of inheritance or being able
to associate the overrides with a blob of code once that gets reused a
lot (like setting condition codes, checking predicates, etc.) would help.

>
>> Any ideas how we can get this to work better? This is a big stumbling block
>> for this sort of set up, and this will lead to operan

Re: [m5-dev] src/dest detection in the ISA descriptions

2011-04-26 Thread Steve Reinhardt
On Tue, Apr 26, 2011 at 9:45 PM, Gabriel Michael Black <
gbl...@eecs.umich.edu> wrote:

> People not working with the ISA parser can stop here.
>

Here I am :-).


> Before I mentioned using @, and I have a patch that makes that change in
> the parser and in all the ISA descs. It was less painful than you may
> assume.
>

I haven't looked at your patches yet... is the main point of switching from
. to @ to allow structure field accesses?


> I don't think there's a good way to figure out whether operands are a
> source and/or destination in a setup like this. In the past, I've tried to
> come up with a scheme that would force gcc/C++ to figure it out for us, but
> no matter how clever/depraved I allow my solutions to be, they still don't
> work. It might be possible to use a fancy compiler system like LLVM to build
> a new tool to do it, but that isn't a near term solution (although I
> wouldn't rule it out entirely).


One potentially interesting angle to pursue is gcc-xml... I don't know much
about it except that, as the name implies, it generates an xml
representation rather than machine code, which should be reasonably
analyzable.  I bet it's still hairy, but it might be the least hairy
alternative.

I expect the big problem with most of these approaches is that the final
compilation context for most of the C snippets is not known at the time the
code is parsed by the parser for operands etc.  Thus there will be symbols
that you can't disambiguate as types etc. because the proper include files
haven't been included (which could be undecidable if the proper include
files are also being generated in the same isa_parser run, so maybe they
don't even exist yet at the point where you need them).

This is why the ad hoc yet (as you say) surprisingly effective heuristics
were used.  Perhaps the heuristics could simply be extended to deal with
structure field accesses... if the thing after the symbol is a ".", then you
look past that to see if there's an equals sign or not, and behave
appropriately.



> Another solution might be to explicitly list source and destination
> operands like inline assembly blocks.


I definitely don't like this idea.  One of the main motivations for the
current implementation was the old SimpleScalar ISA definition macros, which
required explicit listing of operands... and which as a result had subtle
bugs that went undetected for years where particular dependencies weren't
being enforced because someone left an operand out of the list.

As you say, the current approach "works remarkably well most of the time",
so while I'm all for improving it and addressing its shortcomings, I see no
need to throw it out and replace it with something that's more manual
effort, less concise, and more error prone.

An extension that allows you to manually override what the parser finds. to
deal with those cases where it's getting confused, would be fine though...
basically sort of what you've been doing already, except that instead of
"overriding" its heuristics by coming up with awkward code sequences that
trick it into doing the right thing, you have a more blunt and effective
path to do that.  That's probably not as big a step forward as you want, but
to me it's preferable to just switching to a fully manual explicit scheme.


> Any ideas how we can get this to work better? This is a big stumbling block
> for this sort of set up, and this will lead to operand types which can be
> automatically composited from component values instead of having to have
> hacks that, for instance, retrofit/filter code blobs to build double
> precision floating point values from single precision ones behind the
> scenes, or to merge control and condition code bits everywhere the whole
> control register is needed, etc. I expect that last part to be important for
> x86 to get the control flags dependency issues fixed in O3.
>

Would it help to have a way to explicitly declare compound operand types so
that the parser can treat them intelligently?  Maybe it could be as simple
as declaring "operand foo has fields a, b, and c" and having that
autmoatically turn into separate internal entries for foo, foo.a, foo.b, and
foo.c in the operand-matching code, which are linked together so that the
right inferences are made when any of them are found.

Just a thought...

Steve
___
m5-dev mailing list
m5-dev@m5sim.org
http://m5sim.org/mailman/listinfo/m5-dev


[m5-dev] src/dest detection in the ISA descriptions

2011-04-26 Thread Gabriel Michael Black

People not working with the ISA parser can stop here.

I have my changes out for review which remove the special handling of  
the twin data types which are used for twin loads and stores in SPARC,  
and generally demote integers and floating point values to simply be  
opaque types. That's not quite true, but it mostly is. The idea is  
that other types, which are now just as special as integer and  
floating point types, can be used for operands with no (or only a  
little) special effort.


The next step in making that useful is to not use "." as a way to  
attached a type override to operands. Before I mentioned using @, and  
I have a patch that makes that change in the parser and in all the ISA  
descs. It was less painful than you may assume.


Then after that, I want to start actually taking advantage of this new  
capability in the places where BitUnion types and Twin types were  
being used in awkward ways to pacify the parser. These might look like:


FOO foo = Foo;
foo.a = 1;
Foo = foo;

Here FOO is the BitUnion type, foo is a variable of that type, and Foo  
is the recognized operand. This is more cumbersome than it seems it  
should be in a perfect world.


I started implementing this, but it confuses the parser's detection of  
sources and destinations, partially because of syntax and partially  
because it becomes intrinsically more complicated. The parser assumes  
any operand which is followed by an equal sign is a destination, and  
otherwise it's a source. This works remarkably well most of the time,  
but it can already be confused in certain circumstances.


I have a change that makes Twin type operands first class and which  
allows getting at their values in place with no disambiguating  
parenthesis. This works because the twin types are being used as  
sources.


For other types, things get messier since in "Foo.a = 1", the thing  
after Foo is actually .a, not =. Also, this only partially modifies  
Foo, so really Foo may be a source and a destination from this line.


I don't think there's a good way to figure out whether operands are a  
source and/or destination in a setup like this. In the past, I've  
tried to come up with a scheme that would force gcc/C++ to figure it  
out for us, but no matter how clever/depraved I allow my solutions to  
be, they still don't work. It might be possible to use a fancy  
compiler system like LLVM to build a new tool to do it, but that isn't  
a near term solution (although I wouldn't rule it out entirely).  
Another solution might be to explicitly list source and destination  
operands like inline assembly blocks. This isn't as big a burden as it  
might seem if instructions could be grouped into classes that all  
shared the same or substantially similar set of operands. Then the  
individual instructions could specify their differences instead of the  
whole set of inputs/outputs. This relies on instruction definition  
working differently than it does, but I've been independently hoping  
to move it towards that sort of model at some point.


Any ideas how we can get this to work better? This is a big stumbling  
block for this sort of set up, and this will lead to operand types  
which can be automatically composited from component values instead of  
having to have hacks that, for instance, retrofit/filter code blobs to  
build double precision floating point values from single precision  
ones behind the scenes, or to merge control and condition code bits  
everywhere the whole control register is needed, etc. I expect that  
last part to be important for x86 to get the control flags dependency  
issues fixed in O3.


Gabe
___
m5-dev mailing list
m5-dev@m5sim.org
http://m5sim.org/mailman/listinfo/m5-dev