R1 = absolute cog address
#r2 = immediate, some say literal here
...
Jmp r1
Jmp *r1
These example are quite confusing, in that you use rN for all cases.
Most ASM manuals would instead use a clearer
mov r1, #Immed
and
Label:
jmp Label
or some variant of
jmp $-2
for relative
and jmp @Rn or jmp [Rn] or jmp *Rn for register-indirect cases.
Care is usually taken to use Rn only when the element really is a register, not an Immed or Label.
Yeah, if moving an address, its #r2, and if immediate or literal value, its #5.
In the COG, one can think of it as a register or just memory. This also means it really is a register when people want to treat it like one. In PASM, a label is an address. One can say that address is just COG RAM, meaning a memory to memory design, or COG ram is all registers.
In that sense, mov there, here or mov r1, r5 aren't any different from mov 5, 7. We dont mean to reassign addresses, nor will the physical memory be moved, and that leaves contents of, which are what moves.
Need a few snippets to makr it more clear.
Then, mov pointer, #label+5 starts to make sense as does your jmp $-2, which would load the PC with the contents found at $-2. Probably want address as value to be loaded into the PC jmp #$-2, right?
Maybe this is all we need, as DIR/OUT instructions go:
EEEE 1101011 CZL DDDDDDDDD 001011000 DRVL {#}D {WC,WZ} OUT bit of pin D[5:0] = 0, DIR bit = 1, C/!Z = IN bit.
EEEE 1101011 CZL DDDDDDDDD 001011001 DRVH {#}D {WC,WZ} OUT bit of pin D[5:0] = 1, DIR bit = 1, C/!Z = IN bit.
EEEE 1101011 CZL DDDDDDDDD 001011010 DRVC {#}D {WC,WZ} OUT bit of pin D[5:0] = C, DIR bit = 1, C/!Z = IN bit.
EEEE 1101011 CZL DDDDDDDDD 001011011 DRVNC {#}D {WC,WZ} OUT bit of pin D[5:0] = !C, DIR bit = 1, C/!Z = IN bit.
EEEE 1101011 CZL DDDDDDDDD 001011100 DRVZ {#}D {WC,WZ} OUT bit of pin D[5:0] = Z, DIR bit = 1, C/!Z = IN bit.
EEEE 1101011 CZL DDDDDDDDD 001011101 DRVNZ {#}D {WC,WZ} OUT bit of pin D[5:0] = !Z, DIR bit = 1, C/!Z = IN bit.
EEEE 1101011 CZL DDDDDDDDD 001011110 DRVN {#}D {WC,WZ} OUT bit of pin D[5:0] = !bit, DIR bit = 1, C/!Z = IN bit.
EEEE 1101011 CZL DDDDDDDDD 001011111 FLT {#}D {WC,WZ} OUT bit of pin D[5:0] = 0, DIR bit = 0, C/!Z = IN bit.
Right now, its basically ready for synthesis. We really need to exercise a lot of things before doing that. The synthesis is super expensive.
Seems to me a brief test period, with SPIN and C initial, core development as part of that, is prudent.
Yes, but that doesn't mean that we have to design a new language. We could get the current Spin (with perhaps "obvious" extensions for the new instructions) up and running very quickly. The big changes (new language features) can wait until the chip is going out to synthesis.
I understand the desire to make the P2 as good as possible, but that needs to be balanced against time to market -- the P2 is already late in that regard. And really, at this point the P2 has all the instructions needed to implement any language. Spin has already been run on the P2 (via fastspin and Cluso's Spin1 port). So has C (via Dave Hein's Taz C). The problem with making more changes is that trying to implement a compiler/interpreter for an architecture that keeps changing is an exercise in frustration.
My suggestion would be to reserve some opcodes for future expansion in case there are any last minute additions discovered, and set the rest of the instruction set in stone. We can then start development on assemblers, compilers, linkers, etc. and start testing in earnest.
Ken has said before that they won't launch the P2 chip without software such as Spin and C, and probably now he'd like Blockly on it too. He also wants it to have cross platform support from the start instead of only windows like with P1.
Yes, but even if the P2 is declared "finished" right now, samples aren't going to arrive for a long time.
They need the software ready for launch in order to be able to actually sell it. Spending a pile of money on a chip right now, that they then have to sit on for months while software is made is bad for business.
Sure. But we can't write software without a platform. In particular it's very hard to write a compiler or assembler for a target that keeps changing. I know I gave up a while ago on trying to keep fastspin up to date, because I knew that whatever changes I made would just need to be re-done later.
The P2 as it stands now is perfectly capable of running any language we can throw at it. Perhaps some small changes could yield a faster interpreter; we don't know for sure. On the other hand the P2 is never going to be the "fastest" chip on any benchmarks; its strength lies elsewhere. A P2 available "now" (end of 2017, realistically) is much better than a P2 that's not available for another year but which can run Spin 10% faster. At least, that's my opinion.
Once the instruction set is set in stone then we can start developing tools. I definitely agree with you that there need to be good quality tools available when the chip is available. But tapeout can be done in parallel with language development.
My suggestion: freeze the instruction set and get Spin1 working on the P2 now. There are lots of paths available for this: we could update openspin and fastspin for P2, for example. Then incrementally add features to the Spin compiler and interpreter, so that at each stage there's a working language and toolchain. Then whenever the chip comes back there's something available.
Maybe this is all we need, as DIR/OUT instructions go:
EEEE 1101011 CZL DDDDDDDDD 001011000 DRVL {#}D {WC,WZ} OUT bit of pin D[5:0] = 0, DIR bit = 1, C/!Z = IN bit.
EEEE 1101011 CZL DDDDDDDDD 001011001 DRVH {#}D {WC,WZ} OUT bit of pin D[5:0] = 1, DIR bit = 1, C/!Z = IN bit.
EEEE 1101011 CZL DDDDDDDDD 001011010 DRVC {#}D {WC,WZ} OUT bit of pin D[5:0] = C, DIR bit = 1, C/!Z = IN bit.
EEEE 1101011 CZL DDDDDDDDD 001011011 DRVNC {#}D {WC,WZ} OUT bit of pin D[5:0] = !C, DIR bit = 1, C/!Z = IN bit.
EEEE 1101011 CZL DDDDDDDDD 001011100 DRVZ {#}D {WC,WZ} OUT bit of pin D[5:0] = Z, DIR bit = 1, C/!Z = IN bit.
EEEE 1101011 CZL DDDDDDDDD 001011101 DRVNZ {#}D {WC,WZ} OUT bit of pin D[5:0] = !Z, DIR bit = 1, C/!Z = IN bit.
EEEE 1101011 CZL DDDDDDDDD 001011110 DRVN {#}D {WC,WZ} OUT bit of pin D[5:0] = !bit, DIR bit = 1, C/!Z = IN bit.
EEEE 1101011 CZL DDDDDDDDD 001011111 FLT {#}D {WC,WZ} OUT bit of pin D[5:0] = 0, DIR bit = 0, C/!Z = IN bit.
Would that be complete?
There are some cases, like i2c, where you want to operate an Open-Drain port pin, and read that pin.
Can you code i2c cleanly with the above opcodes ?
I note these bit-pointer opcodes can reach above port pins - does it make sense to implement a few buried bits, that these can reach ?
Thinking more, there are valid uses for all the current DIR/OUT instructions. For example, the FLTxx instructions clear the DIR bit and write a value to the OUT bit. Seems kind of pointless, but you may have the bit to output at that time, so, later, you just set the DIR bit. For completeness, it's useful to have the OUT instructions, as well. It would only save two 32-bit muxes per cog to get rid of half of these. I'll just keep them. Carry on.
Maybe this is all we need, as DIR/OUT instructions go:
EEEE 1101011 CZL DDDDDDDDD 001011000 DRVL {#}D {WC,WZ} OUT bit of pin D[5:0] = 0, DIR bit = 1, C/!Z = IN bit.
EEEE 1101011 CZL DDDDDDDDD 001011001 DRVH {#}D {WC,WZ} OUT bit of pin D[5:0] = 1, DIR bit = 1, C/!Z = IN bit.
EEEE 1101011 CZL DDDDDDDDD 001011010 DRVC {#}D {WC,WZ} OUT bit of pin D[5:0] = C, DIR bit = 1, C/!Z = IN bit.
EEEE 1101011 CZL DDDDDDDDD 001011011 DRVNC {#}D {WC,WZ} OUT bit of pin D[5:0] = !C, DIR bit = 1, C/!Z = IN bit.
EEEE 1101011 CZL DDDDDDDDD 001011100 DRVZ {#}D {WC,WZ} OUT bit of pin D[5:0] = Z, DIR bit = 1, C/!Z = IN bit.
EEEE 1101011 CZL DDDDDDDDD 001011101 DRVNZ {#}D {WC,WZ} OUT bit of pin D[5:0] = !Z, DIR bit = 1, C/!Z = IN bit.
EEEE 1101011 CZL DDDDDDDDD 001011110 DRVN {#}D {WC,WZ} OUT bit of pin D[5:0] = !bit, DIR bit = 1, C/!Z = IN bit.
EEEE 1101011 CZL DDDDDDDDD 001011111 FLT {#}D {WC,WZ} OUT bit of pin D[5:0] = 0, DIR bit = 0, C/!Z = IN bit.
Would that be complete?
There are some cases, like i2c, where you want to operate an Open-Drain port pin, and read that pin.
Can you code i2c cleanly with the above opcodes ?
I note these bit-pointer opcodes can reach above port pins - does it make sense to implement a few buried bits, that these can reach ?
I don't know what we'd with more bits. We can reach everything directly with these instructions, already. Thanks for thinking about this, anyway.
I think we've got all the instructions we need to do anything, as Eric said. It's not worth, I agree, more delay to ensure what are probably only minor improvements, at this point.
I want to say it's frozen, barring any bugs that might be discovered. I think it would be useful to get high-level languages going to shake out any latent problems before we commit to synthesis.
Thinking more, there are valid uses for all the current DIR/OUT instructions. For example, the FLTxx instructions clear the DIR bit and write a value to the OUT bit. Seems kind of pointless, but you may have the bit to output at that time, so, later, you just set the DIR bit. For completeness, it's useful to have the OUT instructions, as well. It would only save two 32-bit muxes per cog to get rid of half of these. I'll just keep them. Carry on.
For i2c, you want to ideally operate open-drain, so CY can do DRIVL when CY=0 and FLT when CY=1
There is a way to copy-CY to a CMOS drive port (DRVC), but it's less clear if you can copy CY to a OpenDrain port ?
You may also want to WAIT on a Pin, for clock stretching cases, and for finite-slew BUS cases.
Thinking more, there are valid uses for all the current DIR/OUT instructions. For example, the FLTxx instructions clear the DIR bit and write a value to the OUT bit. Seems kind of pointless, but you may have the bit to output at that time, so, later, you just set the DIR bit. For completeness, it's useful to have the OUT instructions, as well. It would only save two 32-bit muxes per cog to get rid of half of these. I'll just keep them. Carry on.
For i2c, you want to ideally operate open-drain, so CY can do DRIVL when CY=0 and FLT when CY=1
There is a way to copy-CY to a CMOS drive port (DRVC), but it's less clear if you can copy CY to a OpenDrain port ?
You can separately configure each I/O pin's 'low' and 'high' states with 3-bit fields. You can pick: normal/1.5k/15k/150k/1ma/100ua/10ua/float for each state. To keep things simple for I2C, you could just set the OUT bit low and control the DIR bit for drive-low/float-high.
Are there any instruction encoding differences between V15 and V16 other than the new instructions that were added?
I had to move stuff around in the block that begins with SETNIB, in order to get the new ALTxx instructions in which allow nibble/byte/word access. Changes will be flagged in the instructions.txt file.
BTW: I2C is extremely slow (3.2 MHz max) compared to 80 MIPS of one cog. Don't think you need any special instructions for it...
i2c also has i3c derivatives, that says :
" The I3C bus supports a mixture of message types including: I2C-like single data rate (SDR) messages which use SCL clock speeds of up to 12.5MHz, and HDR messages at higher data rates...
A bus to which only I3C devices are connected is called a pure I3C bus, and supports speeds from 8.8 to 26.7Mbit/s. Typically, the SCL clock frequency in a pure I3C bus is 12.5MHz."
Are there any instruction encoding differences between V15 and V16 other than the new instructions that were added?
I had to move stuff around in the block that begins with SETNIB, in order to get the new ALTxx instructions in which allow nibble/byte/word access. Changes will be flagged in the instructions.txt file.
Okay, thanks. I won't start until you post the V16 instructions.txt then. I won't need the highlighting because everything will be new to me at this point! :-)
One thing I'd like to do before getting this out is maybe clear up some name-space conflicts.
NOT, AND, and OR are both PASM instructions and boolean operators. This is going to cause headaches.
How about if, for PASM, we renamed these instructions to NOTF, ANDF, ORF and XORF (F for 'function', let's say)? XORF is just there for consistency.
Is that really necessary? Those keywords have had dual meanings in Spin/PASM for 11 years, and they've never caused any trouble. In PASM, the context (instruction vs. operand) is more than sufficient to distinguish between meanings.
Comments
Yeah, if moving an address, its #r2, and if immediate or literal value, its #5.
In the COG, one can think of it as a register or just memory. This also means it really is a register when people want to treat it like one. In PASM, a label is an address. One can say that address is just COG RAM, meaning a memory to memory design, or COG ram is all registers.
In that sense, mov there, here or mov r1, r5 aren't any different from mov 5, 7. We dont mean to reassign addresses, nor will the physical memory be moved, and that leaves contents of, which are what moves.
Need a few snippets to makr it more clear.
Then, mov pointer, #label+5 starts to make sense as does your jmp $-2, which would load the PC with the contents found at $-2. Probably want address as value to be loaded into the PC jmp #$-2, right?
Would that be complete?
Yes, but that doesn't mean that we have to design a new language. We could get the current Spin (with perhaps "obvious" extensions for the new instructions) up and running very quickly. The big changes (new language features) can wait until the chip is going out to synthesis.
I understand the desire to make the P2 as good as possible, but that needs to be balanced against time to market -- the P2 is already late in that regard. And really, at this point the P2 has all the instructions needed to implement any language. Spin has already been run on the P2 (via fastspin and Cluso's Spin1 port). So has C (via Dave Hein's Taz C). The problem with making more changes is that trying to implement a compiler/interpreter for an architecture that keeps changing is an exercise in frustration.
My suggestion would be to reserve some opcodes for future expansion in case there are any last minute additions discovered, and set the rest of the instruction set in stone. We can then start development on assemblers, compilers, linkers, etc. and start testing in earnest.
Eric
Sure. But we can't write software without a platform. In particular it's very hard to write a compiler or assembler for a target that keeps changing. I know I gave up a while ago on trying to keep fastspin up to date, because I knew that whatever changes I made would just need to be re-done later.
The P2 as it stands now is perfectly capable of running any language we can throw at it. Perhaps some small changes could yield a faster interpreter; we don't know for sure. On the other hand the P2 is never going to be the "fastest" chip on any benchmarks; its strength lies elsewhere. A P2 available "now" (end of 2017, realistically) is much better than a P2 that's not available for another year but which can run Spin 10% faster. At least, that's my opinion.
Once the instruction set is set in stone then we can start developing tools. I definitely agree with you that there need to be good quality tools available when the chip is available. But tapeout can be done in parallel with language development.
My suggestion: freeze the instruction set and get Spin1 working on the P2 now. There are lots of paths available for this: we could update openspin and fastspin for P2, for example. Then incrementally add features to the Spin compiler and interpreter, so that at each stage there's a working language and toolchain. Then whenever the chip comes back there's something available.
There are some cases, like i2c, where you want to operate an Open-Drain port pin, and read that pin.
Can you code i2c cleanly with the above opcodes ?
I note these bit-pointer opcodes can reach above port pins - does it make sense to implement a few buried bits, that these can reach ?
I don't know what we'd with more bits. We can reach everything directly with these instructions, already. Thanks for thinking about this, anyway.
I want to say it's frozen, barring any bugs that might be discovered. I think it would be useful to get high-level languages going to shake out any latent problems before we commit to synthesis.
It's your decision I think.
For i2c, you want to ideally operate open-drain, so CY can do DRIVL when CY=0 and FLT when CY=1
There is a way to copy-CY to a CMOS drive port (DRVC), but it's less clear if you can copy CY to a OpenDrain port ?
You may also want to WAIT on a Pin, for clock stretching cases, and for finite-slew BUS cases.
Completely agreed here, and perhaps was just not clear.
Looks like we have a lock proposed for instructions.
I'm in favor of moving to bug fix only.
You can separately configure each I/O pin's 'low' and 'high' states with 3-bit fields. You can pick: normal/1.5k/15k/150k/1ma/100ua/10ua/float for each state. To keep things simple for I2C, you could just set the OUT bit low and control the DIR bit for drive-low/float-high.
THE VERILOG IS FINISHED.
I will get v16 out for everybody, hopefully, by the end of tomorrow.
Is there an opcode that does !CY -> DIR ? (like the one that does !CY -> OUT)
And there was much rejoicing!
BTW: I2C is extremely slow (3.2 MHz max) compared to 80 MIPS of one cog. Don't think you need any special instructions for it...
I had to move stuff around in the block that begins with SETNIB, in order to get the new ALTxx instructions in which allow nibble/byte/word access. Changes will be flagged in the instructions.txt file.
i2c also has i3c derivatives, that says :
" The I3C bus supports a mixture of message types including: I2C-like single data rate (SDR) messages which use SCL clock speeds of up to 12.5MHz, and HDR messages at higher data rates...
A bus to which only I3C devices are connected is called a pure I3C bus, and supports speeds from 8.8 to 26.7Mbit/s. Typically, the SCL clock frequency in a pure I3C bus is 12.5MHz."
or
NOT, AND, and OR are both PASM instructions and boolean operators. This is going to cause headaches.
How about if, for PASM, we renamed these instructions to NOTF, ANDF, ORF and XORF (F for 'function', let's say)? XORF is just there for consistency.
Any better idea?
I think I3C will be fine if we have cogs running at 160MHz.
Other MCUs use a 'b' suffix where there is name space confusion.
-Phil