Alternative "rep" syntax?
Seairth
Posts: 2,474
I realize that this topic has been discussed in the past. However, I think it's worth revisiting.
@moderators: Can you move the rep-related comment I made (and follow-up comments) in "Propr2 FPGA files!!!" to this thread?
Edit: never mind. I moved my own comment.
@moderators: Can you move the rep-related comment I made (and follow-up comments) in "Propr2 FPGA files!!!" to this thread?
Edit: never mind. I moved my own comment.
Comments
From that, it looks to me like:
1. The instruction immediately following REP is executed.
2. The first REP parameter is N-1 instructions that you want to repeat
3. The second REP parameter is N-1 times you want to repeat the loop
Is that correct? If so, for #2 and #3, I wish there were a better way of setting the parameters. Immediate thoughts are to change the second parameter to have #0 mean "forever" (if that's still possible) and have any positive value indicate the count.
I know the first parameter could also be done like:
But the expression is... well... ugly. You might be able to do something like:
which is a bit better. But what I'd really like is something like:
where the compiler will do the work for me.
The repeat value is the true count value.
Let's leave pnut.exe to whatever is easy for Chip.
I would like to see the compiler...
1. Determine the count based on the label ":rep_bits" because it's a local label.
For me, I would prefer ":rep" or ":rep_end" or ":rep_last".
2. Automatically deduct the "1" from the no. of repeats. So if we want 8 we say #8 and the compiler substitutes #7.
3. For an endless repeat, I would prefer no repeat count. ie "rep"
So here are the code examples... Note we may need a number after ":rep_last" ie ":rep_lastn". The compiler will just use the ":rep_last" section closest to the rep instruction.
Agreed. I made such a note it my original comment. #0 can mean "forever" (if that function still exists).
That may be true for the instruction count, but I think the proposed change for repeat count would require an FPGA change.
The first "rep" sets the loop count and the second "rep" sets the instruction count. This would be similar to instructions like AUGDS that augment the second instruction. In this case, though, the second instruction is really augmenting the first one. Of course, the mnemonics could be changed. And, of course, this could all be hidden by the assembler as a single instruction.
Note also that this places the "waitx" back before the "rep", which is in keeping with all other branch-like instructions. Now that we no longer have delayed branches, this characteristic of "rep" sticks out a bit. An approach like the one above would take care of that!
we point the start, and the compiler automatically seeks for the "*_end" tag in a way that's sort of mimicking call/ret behavior ?
Hmm... well the label is always $+2, so I guess it's a bit redundant.
Otherwise, we only point the end explicitly, and the compiler makes the rest. Two parameters makes the rep more readable IMHO, expecially if the loop is large.
Interesting idea, as it saves needing the Rep_Start label to make it clear where the loop actually is.
It does make placing labels trickier tho, as the 'pull-up' creates out-of-order ASM.
Maybe that can be managed with more tool-support:
In the above case, a jump from elsewhere to any Label_InValid would be flagged, but a jump to Label_Valid is ok.
To avoid out-of-order ASM, code clarity would need two labels :
The tools can now catch common by-line paste/comment code changes that may break the loop structure.
May be better to let the compiler reduce the count by 1, and disallow using a register and only allow the count to be immediate.
BTW if the operands are swapped to rep #count,#instructions would this get rid of executing the following instruction before the rep starts? This operand order makes more sense even though the destination (count) is not decremented.
We can always change the count using movd rep_instr,S/#.
IMHO I would rather a restriction if it means the rep instruction is simpler to understand.
There is no out-of-order instructions in what I was proposing. Moving the "waitx" before "rep" does nothing but free up the delayed slot after "rep". The thought was to use the second instruction slot (after the rep) to augment the rep. Or, put another way, "rep" would take two instruction slots. This could be handled in number of ways:
* Use the same "rep" syntax as we currently do, but have the assembler expand it to two instructions.
* Have back-to-back "rep" instructions which each take a single operand, like I showed above.
* Have two separate opcodes (and mnemonics), but otherwise it looks like what I showed above.
As for your code above, "Label_Invalid" would still be a valid address to jump to. Similarly, "Label_Invalid2" would be valid if you are conditionally switching between "1 or n" repeats.
Actually, chip doesn't really need to delay the instruction. He could have treated it like a "JMP @1" (i.e. flush pipeline and re-fetch the next instruction). That too would simplify the instruction usage. And keep it more consistent with all other instructions. I'd take this over the recommendation I made above.
Edit: Changed the @4 to an @1. With all of the byte vs. long addressing discussion, I can't remember if the relative operator returns bytes or longs. It should be bytes to be consistent with all other instruction addressing. But it should be longs to avoid losing two bits range. So confusing...
Making code larger seems a significant backward step, which means stretching the opcode time is the only realistic alternative. That makes the code slower, but it does avoid the ease-of-break-on-edit, that the present direct binary form suffers from.
To me, the two label approach has none of these larger/slower drawbacks, and is a syntax already in use by Analog Devices.
ie Simplicity and clarity, with no down sides.
I see where you are coming from.
Personally, I think it's more important to be consistent with the rest of the ISA than to save an instruction or couple of clock cycles. Treating rep as a delayed instruction made sense in the context of the P2-hot ISA. Now, however, there are no other instructions that behave this way. From my perspective, the delayed instruction slot is a relic of an old design and therefore inconsistent with the current ISA. By stalling a few clock cylces (instead of supporting a delayed slot), you get something simple like:
To me, that is about as simple and readable as you can get.
Thinking some more about labels, and coding styles, I think the two label version would be clearest as
This slight Rep_Exit change makes it clear the repeated code is inside the labels, which is a very similar block-form to High level language repeats, and safely allows labels on separate lines (ie removes possible context confusion)
ASM code pivots on labels, so this is ASM consistent.
Two labels means this form is also safely legal
(This may be generated by HLL compilers )
If that's it, then for all the others I have to remember more.
Someone recommended something like:
Repr D ... for number of Repeats (total iterations)
Repi D ... for number of Instructions to iterate.
etc. etc. would be fine, but I think it confuses the brain, which is expecting to be one step away from an actual opcode...not that there is anything wrong with that:)
This would be another example of a "compound" instruction... which could be dealt with in a documentation section listing instruction variants.
That's easily handled in the two label version I gave above, and I expect the non-merged form to be more commonly generated by HLL, and maybe by someone who knows they do not need to optimize size or speed.
Let the assembler do the simple housekeeping, and there is no need for two opcodes/macros.
The user has total control of one opcode.
Now, there is no spacer instruction needed.
Also, the repeat count from S is now 1-based and 0 means infinite repeat.
The instruction count from D is still 0-based, but I changed the assembler so that by using @address, it figures the 0-based constant to go into D.
Here's what REP use looks like now:
I don't think we can have it any simpler than that.
I'm recompiling for the Prop123 and the DE2-115 right now. I will put up new files as soon as they're ready.
Thank you all for thinking about this REP syntax. This resulted in a needed improvement. The new REP circuitry is slightly larger than before, since it has to resolve more on the initial REP cycle, but this is going to be a lot easier for people to work with.
Great
Is it still 2 cycles to 'get started' ?
I think the above can still be improved, and made more edit tolerant.
consider this code someone may write :
Problem: Which opcodes are actually within the REP loop ?
To me, clearer/simpler/safer is this variant
This follows assembler convention, which has labels as block delimiters.
I think this is just an assembler change, not a verilog change.
You're right. That would be easier to deal with when making edits. Okay, I'll make it work that way.
The REP instruction takes two clocks.
jmg said:
I think so too. It is really encouraging
Now, we have a label that works differently from all other labels. Seems to me, that's a thing a user needs to know, not unlike say, understanding that rep starts from 0 on it's line count.
Worse, given the label has to have the word exit in it, there is this special complication in the assembler, a backward reference where no other label is a backward reference.
So a user learns how labels work, understands that putting them on lines by themselves is ambiguous practice, except for jmg style labels. Of course, they will ask, "who is jmg?" among many other things.
If we are going to support a label based use, which I agree with as an alternative to simply including a line count, then the label shouldn't add any other complexity.
The above use example does that. And a user doesn't have to remember a specific word, nor understand that a rep label is different from every other label ever written for a Propeller either.
@cgracey, can we consider the above use instead? It's consistent with all past behavior.
Secondly, we got rid of special labels with the elimination of call / ret, with the P2 stack. Why add them back? A label should be a label, unless we've got a really sweet case for making that not true, and this one just doesn't seem like that kind of case.
REP @label,repeatcount
'label' is just a label. It needn't be local or have any special name. It's just like any other label. That label needs to come after the code to be repeated. The @ could become some other character for this use case.
There is nothing strange or special about this label, you seem to have locked into some unusual interpretation ?
If you think of the label as an exit destination, the code is simple to follow.
ie the label is where the code goes, when done, just like any other exit or destination label, or block delimiter in HLL.
Code that comes after the label, is not within the block.
It is edit safe, and tolerates conditional, and will tolerate 64b opcodes.
???? Who said the label has to have the word exit in it ?
It is just a label, the root exit was used to try and make the flow clear to a reader. Use Rep_Done if you prefer, or Post_rep or Do_After_Rep or anything you like.