Re: [gem5-dev] [m5-dev] src/dest detection in the ISA descriptions
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
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
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
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
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
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
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
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
>> 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
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
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