I got rid of BOTONE and renamed TOPONE to ENCOD. That got rid of a 32-bit mux and other LE's. It's now compiling 6% smaller, overall, which I don't understand. I'll know soon, though, why.
That overlap is superficial, since the OUTx/DIRx instructions automatically index between port A and B. In other words, you only need the pin number.
Yes, I can see the OUT,DIR have a 'reach' of 64 bits but if you give the same pre defined PinName to MOVB/SETB/CLRB/NOTB, the same outcome can result.
I can see if you use a REG, as a bit pointer, OUT can scan all pins on the device in one opcode, whilst _B opcodes have a reach of 32, so can manage a port only, in one opcode.
How often is wanting to pointer-index over 64 pins actually required ?
Those pure CF/ZF opcodes will be in the block of unary functions where SPLITB/MERGEB/etc. are. It will take only 4 bits to cover every logic function for each flag. So, 8 bits of immediate D will handle it. I haven't gotten there yet, but will be there as soon as I get things up again. Right now, after making these changes, some error of mine is causing things not to work. This is typical when a big change is made.
I've got the assembler all updated for the new "d.{#}s" and "!" syntax. I feel funny about how it makes the source code look, as far as knowing that a flag has been modified.
The BITx instructions with "WC" or "WZ" after them were very easy on the eyes, as there was simplicity and visibility for flag effects. This new way, while much more flexible, requires that you slow way down, in order to tell if a flag has been affected. I almost want to require WC/WF where flag writes are occurring. That way, you'd be able to see, at a glance, where flags are being modified.
This new way, while much more flexible, requires that you slow way down, in order to tell if a flag has been affected. I almost want to require WC/WF where flag writes are occurring.
I feel funny about how it makes the source code look, as far as knowing that a flag has been modified.
The BITx instructions with "WC" or "WZ" after them were very easy on the eyes, as there was simplicity and visibility for flag effects. This new way, while much more flexible, requires that you slow way down, in order to tell if a flag has been affected.
That's one of the reasons I favour using the simple and clear C,Z as that makes it very clear 'as far as knowing that a flag has been modified.'
CF,ZF requires users know that CF really means C, and ZF really means Z & not as easy on the eyes
When you use named booleans, the code is further easier to scan - anything with a C or Z Destination in it, modifies Z or C
Can the smart pins capture from a 3rd pin, when Quad counting from 2 others ?
No. The quadrature encoder can work either periodically, reporting the count delta every X clocks, or work in totalizer mode. In its current design, you would have to either watch for the 'zero' pin or use it to generate an interrupt. It would be easy to reset the counter in totalizer mode when 'zero' went high. It seems like this would be troublesome in cases of bidirectional rotation because of hysteresis on the 'zero' detector.
That's probably tolerable, as interrupt can be quite quick, in machine terms.
Most Z designs I've seen have deliberately narrow Z, so it 'fits inside' a single state, and so 'hysteresis' on direction change is not an issue.
I just looked at the smart pin and each mode is limited to two inputs and one output. For PWM in SMPS mode, it can output PWM and simultaneously monitor I and V digital inputs. For quadrature modes, there's no output, but the two inputs get used as A and B.
Chip,
Z is a third channel and is used to reset the counter (totalizer).
You have to distinguish between device and counter module.
-The device eg encoder usually output 90° out of phase pulses on A and B while outputs a single pulse per revolution (same length as A/B) on Z. Here there is no hysteresis issue, the 3 channels are always in sync. If you use your own sensor (eg mechanical switch or proximity sensor) for z signal then you have to manage hysteresis and/or direction issues.
-The counter module updates a totalizer based on pulses of channels A and B and resets it with rising or falling edge on Z channel. Z channel usually have also software enable and a preset value. At Z pulse the counter/totalizer becomes equal to the preset value. The counter module usually, beside updating the totalizer (which gives you position usually), calculates also frequency in 2 modes: counting A/B pulses in given time or counting internal reference frequency pulses in one A/B period. The former is better for high speeds while the latter gives you better resolution at low speeds.
So usually from an industrial counter module you have both position and speed.
Regarding edges evaluation:
- you can for example count pulses on A channel while B gives you the direction.
- you can evaluate rising and falling edge on A and B together with stable state on the opposite channel and thus increasing by 4x the quadrature resolution.
How is the smart pins working: on pulse/direction or edges of A/B?
Regarding edges evaluation:
- you can for example count pulses on A channel while B gives you the direction.
- you can evaluate rising and falling edge on A and B together with stable state on the opposite channel and thus increasing by 4x the quadrature resolution.
How is the smart pins working: on pulse/direction or edges of A/B?
The Quad mode uses every edge, so is a true Quad Counter.
Not sure about support of a DIRN and COUNT mode, some systems do generate that.
The smart pins certainly can do UP/DOWN, and I see inc on A-rise, dec on B-rise but do not see DIRN & COUNT mode ?
Maybe that was missed ?
DOCs have this
%MMMMM: 00000 = smart pin off (default)
00001 = long repository (P[12:10] != %101)
00010 = long repository (P[12:10] != %101)
00011 = long repository (P[12:10] != %101)
00001 = DAC noise (P[12:10] = %101)
00010 = DAC 16-bit dither, noise (P[12:10] = %101)
00011 = DAC 16-bit dither, PWM (P[12:10] = %101)
00100* = pulse/cycle output
00101* = transition output
00110* = NCO frequency
00111* = NCO duty
01000* = PWM triangle
01001* = PWM sawtooth
01010* = PWM switch-mode power supply, V and I feedback
01011 = periodic/continuous, A-B quadrature encoder
01100 = periodic/continuous, inc on A-high
01101 = periodic/continuous, inc on A-rise
01110 = periodic/continuous, inc on A-high, dec on B-high
01111 = periodic/continuous, inc on A-rise, dec on B-rise
10000 = time A states
10001 = time A-high states
10010 = time X A-highs
10011 = for X periods, count time
10100 = for X periods, count states
10101 = for periods in X+ clocks, count time
10110 = for periods in X+ clocks, count states
10111 = for periods in X+ clocks, count periods
11000* = USB host, low-speed (even/odd pin pair = DM/DP)
11001* = USB host, high-speed (even/odd pin pair = DM/DP)
11010* = USB device, low-speed (even/odd pin pair = DM/DP)
11011* = USB device, high-speed (even/odd pin pair = DM/DP)
11100* = sync serial transmit (A-data, B-clock)
11101 = sync serial receive (A-data, B-clock)
11110* = async serial transmit (baudrate)
11111 = async serial receive (baudrate)
I'm not at home to look things up, but I believe the inputs can be preset to 1/0 level I think. So, mode 01110 can do the job of mode 01100, and mode 01111 can do the job of 01101. That would free up a couple of modes.
One mode can then be "periodic/continuous, inc on A-rise (B-low), dec on A-rise (B-high)"
There is no need for every conceivable instruction!
It's nice to have a special instruction for a commonly used set of instructions. However, obscure instruction groups don't need to waste valuable silicon and power.
A couple of years ago I raised the possibility of a generic helper instruction for calculating various CRCC algorithms. However I would rather see silicon.
@cgracey, as long as there is no silicon, people will continue suggesting changes. And as long as you keep implementing those suggestions, there will be no silicon.
I'm not at home to look things up, but I believe the inputs can be preset to 1/0 level I think. So, mode 01110 can do the job of mode 01100, and mode 01111 can do the job of 01101. That would free up a couple of modes.
One mode can then be "periodic/continuous, inc on A-rise (B-low), dec on A-rise (B-high)"
I got that wrong. There is no 1/0 level selector for the smartpin inputs.
D/# = %AAAA_BBBB_FFF_PPPPPPPPPPPPP_TT_MMMMM_0
%BBBB: ‘B’ input selector
0xxx = true (default)
1xxx = inverted
x000 = this pin’s read state (default)
x001 = relative +1 pin’s read state
x010 = relative +2 pin’s read state
x011 = relative +3 pin’s read state
x100 = this pin’s OUT bit from cogs
x101 = relative -3 pin’s read state
x110 = relative -2 pin’s read state
x111 = relative -1 pin’s read state
It can be achieved through an extra step though - Set the above selector mode to 1100, and do an OUTH to that pin so that the forced high is treated as a steady low at the smartpin B input.
I've got the assembler all updated for the new "d.{#}s" and "!" syntax. I feel funny about how it makes the source code look, as far as knowing that a flag has been modified.
The BITx instructions with "WC" or "WZ" after them were very easy on the eyes, as there was simplicity and visibility for flag effects. This new way, while much more flexible, requires that you slow way down, in order to tell if a flag has been affected. I almost want to require WC/WF where flag writes are occurring. That way, you'd be able to see, at a glance, where flags are being modified.
The syntax has been broken. The new bit instruction mnemonics are simple but the operands are not as much as they could be, inconsistent CF & ZF have had to be contrived and WC & WZ have been lost. There must be a better way and I have come up with two options.
CF & ZF & ! ditched and operands reduced from two to one or none. Still room for improvement, though. If the single operand contains "." or MOV/AND/OR/XOR/CLR/SET/NOT have no operand, then 1-bit operation is implicit and B can be eliminated.
MOVC D.S Move C to D.S
MOVN D.S WZ Move Not D.S and write Z
ANDZ D.S And Z with D.S
OR D.S WC Or D.S with C and write C
MOVC WZ Move C and write Z
XORNZ WC Xor Not Z with C and write C
MOVC D.S Move C to D.S
MOVN D.S WZ Move Not D.S and write Z
ANDZ D.S And Z with D.S
OR D.S WC Or D.S with C and write C
MOVC WZ Move C and write Z
XORNZ WC Xor Not Z with C and write C
Err, oops, actually no they do not... Chip's boolean sub group is much easier to read, especially when mixed in with Register opcodes.
Your idea has fragmented what was a clear mnemonic sub-group, and scattered operands into three places, and changed the meaning of WC,WZ.
In all other opcodes, those are optional suffix-only modifiers that control if C,Z are also affected.
CLR D.{#}S WC
By P2 convention, that says Clear the operand, and update C, both the BIT and C change.
The original
CLRB BitName
Clears only the named bit. If BitName is Z or C, it is very clear what single bit is affected.
MOVC D.S Move C to D.S
MOVN D.S WZ Move Not D.S and write Z
ANDZ D.S And Z with D.S
OR D.S WC Or D.S with C and write C
MOVC WZ Move C and write Z
XORNZ WC Xor Not Z with C and write C
Err, oops, actually no they do not... Chip's boolean sub group is much easier to read, especially when mixed in with Register opcodes.
Your idea has fragmented what was a clear mnemonic sub-group, and scattered operands into three places, and changed the meaning of WC,WZ.
In all other opcodes, those are optional suffix-only modifiers that control if C,Z are also affected.
CLR D.{#}S WC
By P2 convention, that says Clear the operand, and update C, both the BIT and C change.
The original
CLRB BitName
Clears only the named bit. If BitName is Z or C, it is very clear what single bit is affected.
CLR D.{#}S WC
By P2 convention, that says Clear the operand, and update C, both the BIT and C change.
The original
CLRB BitName
Clears only the named bit. If BitName is Z or C, it is very clear what single bit is affected.
CLR D.{#}S WC works exactly as before, only the B is missing.
I think you suggested "." and as long as that is somewhere in D it signifies a bit instruction, there will never be confusion with AND D / OR D / XOR D and B is not needed in the mnemonic.
Something like ANDZ for AND with Z is no different to ADDC for ADD with carry. If the usage of WC and WZ changes a little for some esoteric instructions will it really matter very much?
By P1 and P2 convention you can see clearly whenever C or Z are changed through WC and WZ. That was broken and I've fixed it.
If the usage of WC and WZ changes a little for some esoteric instructions will it really matter very much?
Of course it matters, if the premise used for the change/fragmentation was to preserve convention !!
The ideal is to make source code easier to read, not add ever-more variances and sub-rules, and scatter and fragment what was a clear sub group of opcodes, which also fails the stated objective ....
The code Chip already has is perfectly clear, one/two operand assembler, following the simple widely used, core convention of :
Mnemonic Destination,Source
Mnemonic Destination
All of the DOC's use D,S to signify Destination and Source.
I've got the assembler all updated for the new "d.{#}s" and "!" syntax. I feel funny about how it makes the source code look, as far as knowing that a flag has been modified.
The BITx instructions with "WC" or "WZ" after them were very easy on the eyes, as there was simplicity and visibility for flag effects. This new way, while much more flexible, requires that you slow way down, in order to tell if a flag has been affected. I almost want to require WC/WF where flag writes are occurring. That way, you'd be able to see, at a glance, where flags are being modified.
It might be considered a "belt and braces" approach, but given the discussion above it seems that there are (at least) two different code scanning preferences at odds here.
By requiring the WC/WF flags for the operations where these flags are the destination, you can satisfy (and probably upset) both camps simultaneously.
It also makes some code completely clear, that might otherwise be unclear:
ORB CF, !ZF WC
No matter which way you scan the code it is clear that this is a bit OR between the Carry Flag and the complement of the Z Flag, stored into the Carry Flag.
This maintains consistency for the "Destination, Source" paradigm, makes it perfectly clear which operand is complemented, and also uses the WC/WF tags to show the flag modification.
Both (all) camps see what they are looking for in the code, at the expense of (at most) 2 extra keystrokes per line.
Of course, this is a tool issue, not a verilog issue, so shouldn't delay silicon production.
By requiring the WC/WF flags for the operations where these flags are the destination, you can satisfy (and probably upset) both camps simultaneously.
It also makes some code completely clear, that might otherwise be unclear:
ORB CF, !ZF WC
No matter which way you scan the code it is clear that this is a bit OR between the Carry Flag and the complement of the Z Flag, stored into the Carry Flag.
This maintains consistency for the "Destination, Source" paradigm, makes it perfectly clear which operand is complemented, and also uses the WC/WF tags to show the flag modification.
hehe, not sure if that was a serious suggestion, but it works fine for me, combined with a suitably smart assembler.
Of course, I'd make any half-decent assembler allow aliases and support subsets, so this would also be perfectly legal :
; some header.. common Boolean Aliases, if not already inbuilt.
C BIT CF
Z BIT ZF
ORB C, !Z
The assembler also needs to give an error message on these illegal / not valid variants, if you support/tolerate WC suffix : (because the WC WZ rules are not the same as elsewhere, even if the code format may imply it )
By requiring the WC/WF flags for the operations where these flags are the destination, you can satisfy (and probably upset) both camps simultaneously.
It also makes some code completely clear, that might otherwise be unclear:
ORB CF, !ZF WC
No matter which way you scan the code it is clear that this is a bit OR between the Carry Flag and the complement of the Z Flag, stored into the Carry Flag.
This maintains consistency for the "Destination, Source" paradigm, makes it perfectly clear which operand is complemented, and also uses the WC/WF tags to show the flag modification.
hehe, not sure if that was a serious suggestion, but it works fine for me, combined with a suitably smart assembler.
Reasonably serious, but I wouldn't fight anyone for it.
The assembler also needs to give an error message on these illegal / not valid variants, if you support/tolerate WC suffix : (because the WC WZ rules are not the same as elsewhere, even if the code format may imply it )
ORB CF, !ZF WZ
ORB ZF, !CF WC
ORB CF, !ZF WZ WC
Absolutely agree. With these operations the WC and WZ do not represent optional behaviour as they do elsewhere, but would be included to support the humans scanning the code to identify operations that change the flags. The tool can have all it needs without these tags.
Just like supplying an S operand for any D only operation should give an error, so too using WZ with C as the destination or vice versa should give an error.
You guys have been struggling like I have over the syntax of these bit logic instructions. They were really bothering me, as there was no congruous way to meld them into the syntax. I just got rid of them and reverted back to the BITx instructions, harmonizing them with the OUTx/DIRx/DRVx/FLTx instructions.. I'll make logic instructions between C and Z, though.
You guys have been struggling like I have over the syntax of these bit logic instructions. They were really bothering me, as there was no congruous way to meld them into the syntax. I just got rid of them and reverted back to the BITx instructions, harmonizing them with the OUTx/DIRx/DRVx/FLTx instructions.. I'll make logic instructions between C and Z, though.
Noo.....
Are you saying gone is your simple B suffix approach which I thought worked very well, and importantly documents into an easy to grasp and remember block, which is a nice point of difference in the P2, for those new to Boolean coding.
Comments
I can see if you use a REG, as a bit pointer, OUT can scan all pins on the device in one opcode, whilst _B opcodes have a reach of 32, so can manage a port only, in one opcode.
How often is wanting to pointer-index over 64 pins actually required ?
It seems to me there are more bit instruction permutations than available opcodes:
What is the opcode for MOVB CF,ZF for example?
The BITx instructions with "WC" or "WZ" after them were very easy on the eyes, as there was simplicity and visibility for flag effects. This new way, while much more flexible, requires that you slow way down, in order to tell if a flag has been affected. I almost want to require WC/WF where flag writes are occurring. That way, you'd be able to see, at a glance, where flags are being modified.
Can you also declare a NamedBoolean, and use that name ?
Along the lines of
That's one of the reasons I favour using the simple and clear C,Z as that makes it very clear 'as far as knowing that a flag has been modified.'
CF,ZF requires users know that CF really means C, and ZF really means Z & not as easy on the eyes
When you use named booleans, the code is further easier to scan - anything with a C or Z Destination in it, modifies Z or C
Chip,
Z is a third channel and is used to reset the counter (totalizer).
You have to distinguish between device and counter module.
-The device eg encoder usually output 90° out of phase pulses on A and B while outputs a single pulse per revolution (same length as A/B) on Z. Here there is no hysteresis issue, the 3 channels are always in sync. If you use your own sensor (eg mechanical switch or proximity sensor) for z signal then you have to manage hysteresis and/or direction issues.
-The counter module updates a totalizer based on pulses of channels A and B and resets it with rising or falling edge on Z channel. Z channel usually have also software enable and a preset value. At Z pulse the counter/totalizer becomes equal to the preset value. The counter module usually, beside updating the totalizer (which gives you position usually), calculates also frequency in 2 modes: counting A/B pulses in given time or counting internal reference frequency pulses in one A/B period. The former is better for high speeds while the latter gives you better resolution at low speeds.
So usually from an industrial counter module you have both position and speed.
Regarding edges evaluation:
- you can for example count pulses on A channel while B gives you the direction.
- you can evaluate rising and falling edge on A and B together with stable state on the opposite channel and thus increasing by 4x the quadrature resolution.
How is the smart pins working: on pulse/direction or edges of A/B?
The Quad mode uses every edge, so is a true Quad Counter.
Not sure about support of a DIRN and COUNT mode, some systems do generate that.
The smart pins certainly can do UP/DOWN, and I see inc on A-rise, dec on B-rise but do not see DIRN & COUNT mode ?
Maybe that was missed ?
DOCs have this
One mode can then be "periodic/continuous, inc on A-rise (B-low), dec on A-rise (B-high)"
It's nice to have a special instruction for a commonly used set of instructions. However, obscure instruction groups don't need to waste valuable silicon and power.
A couple of years ago I raised the possibility of a generic helper instruction for calculating various CRCC algorithms. However I would rather see silicon.
Here is what I meant for rotating just using the free bits after a CALL has saved the return address & c/z flags. I am presuming that "u[33:32]" gets tested with WC & WZ to determine whether C & Z bits get updated.
ie elsewhere this is performed
Chip, will this do for spin2 too, where you save & restore C & Z ???
Exactly.
@cgracey, as long as there is no silicon, people will continue suggesting changes. And as long as you keep implementing those suggestions, there will be no silicon.
The syntax has been broken. The new bit instruction mnemonics are simple but the operands are not as much as they could be, inconsistent CF & ZF have had to be contrived and WC & WZ have been lost. There must be a better way and I have come up with two options.
Option 1
Syntax fixed.
CF & ZF & ! ditched and operands reduced from two to one or none. Still room for improvement, though. If the single operand contains "." or MOV/AND/OR/XOR/CLR/SET/NOT have no operand, then 1-bit operation is implicit and B can be eliminated.
Option 2
The instructions do what they say:
Sometimes the simplest and most obvious fixes really are the best : Just use C and Z
A more complex 'fix', usually breaks other things, as in ....
Err, oops, actually no they do not... Chip's boolean sub group is much easier to read, especially when mixed in with Register opcodes.
Your idea has fragmented what was a clear mnemonic sub-group, and scattered operands into three places, and changed the meaning of WC,WZ.
In all other opcodes, those are optional suffix-only modifiers that control if C,Z are also affected.
CLR D.{#}S WC
By P2 convention, that says Clear the operand, and update C, both the BIT and C change.
The original
CLRB BitName
Clears only the named bit. If BitName is Z or C, it is very clear what single bit is affected.
+1
CLR D.{#}S WC works exactly as before, only the B is missing.
I think you suggested "." and as long as that is somewhere in D it signifies a bit instruction, there will never be confusion with AND D / OR D / XOR D and B is not needed in the mnemonic.
Something like ANDZ for AND with Z is no different to ADDC for ADD with carry. If the usage of WC and WZ changes a little for some esoteric instructions will it really matter very much?
By P1 and P2 convention you can see clearly whenever C or Z are changed through WC and WZ. That was broken and I've fixed it.
The ideal is to make source code easier to read, not add ever-more variances and sub-rules, and scatter and fragment what was a clear sub group of opcodes, which also fails the stated objective ....
The code Chip already has is perfectly clear, one/two operand assembler, following the simple widely used, core convention of :
Mnemonic Destination,Source
Mnemonic Destination
All of the DOC's use D,S to signify Destination and Source.
It might be considered a "belt and braces" approach, but given the discussion above it seems that there are (at least) two different code scanning preferences at odds here.
By requiring the WC/WF flags for the operations where these flags are the destination, you can satisfy (and probably upset) both camps simultaneously.
It also makes some code completely clear, that might otherwise be unclear:
No matter which way you scan the code it is clear that this is a bit OR between the Carry Flag and the complement of the Z Flag, stored into the Carry Flag.
This maintains consistency for the "Destination, Source" paradigm, makes it perfectly clear which operand is complemented, and also uses the WC/WF tags to show the flag modification.
Both (all) camps see what they are looking for in the code, at the expense of (at most) 2 extra keystrokes per line.
Of course, this is a tool issue, not a verilog issue, so shouldn't delay silicon production.
Regards,
Anthony.
Agreed.
Of course, I'd make any half-decent assembler allow aliases and support subsets, so this would also be perfectly legal :
The assembler also needs to give an error message on these illegal / not valid variants, if you support/tolerate WC suffix :
(because the WC WZ rules are not the same as elsewhere, even if the code format may imply it )
Changing the meaning of WC/WZ for these is a very bad idea.
Explicitly calling out the bits involved is the right thing to do. It's more syntax, but it's more clear and leaves WC/WZ to be consistent all around.
A warning about the absent WC (or WZ) would be of benefit, simply to ensure that the written code matches the programmer's intention.
Absolutely agree. With these operations the WC and WZ do not represent optional behaviour as they do elsewhere, but would be included to support the humans scanning the code to identify operations that change the flags. The tool can have all it needs without these tags.
Just like supplying an S operand for any D only operation should give an error, so too using WZ with C as the destination or vice versa should give an error.
Are you saying gone is your simple B suffix approach which I thought worked very well, and importantly documents into an easy to grasp and remember block, which is a nice point of difference in the P2, for those new to Boolean coding.