Shop OBEX P1 Docs P2 Docs Learn Events
XBYTE question - Page 4 — Parallax Forums

XBYTE question

12467

Comments

  • cgraceycgracey Posts: 14,133
    Thanks for reporting, Ozpropdev.

    There are currently two SKIP/SKIPF situations in which interrupts are delayed:

    1) On the SKIP/SKIPF instruction, itself.
    2) When the <next> instruction is getting cancelled.

    #2 was just added yesterday to make things work in cases where the first skip bit is 1. I may now be able to get rid of #1. I will try that today.
  • TonyB_TonyB_ Posts: 2,108
    edited 2017-06-22 23:20
    cgracey wrote: »
    I'll make the C/Z writing on XBYTE optional. Maybe bit 9 of the initial SETQ value can be used to enable this.

    Thanks, Chip.

    _______________________________________

    I'm the same person as TonyB but from now on I'll have to be TonyB_
    I forgot my password and registered email address has been shut down!

  • TonyB_TonyB_ Posts: 2,108
    edited 2017-06-22 23:20
    Using SETQ or SETQ2 with Q[9]=1 would seem to be the sensible way to enable CZ writing in XBYTE. This is a bit of a dummy's question: if the D in SETQ/SETQ2 is 9-bit immediate, are the top 23 bits written to Q all zero, ensuring that XBYTE will not modify CZ?

    Something not mentioned so far regarding skipping, I think, is that an interrupt routine could change the skip patterns deliberately by executing SKIPF, for example in response to external events. In theory a skip sequence could be extended ad infinitum but probably not beyond.
  • cgraceycgracey Posts: 14,133
    cgracey wrote: »
    Thanks for reporting, Ozpropdev.

    There are currently two SKIP/SKIPF situations in which interrupts are delayed:

    1) On the SKIP/SKIPF instruction, itself.
    2) When the <next> instruction is getting cancelled.

    #2 was just added yesterday to make things work in cases where the first skip bit is 1. I may now be able to get rid of #1. I will try that today.

    I just spent the last day and a half hunting down a bug involving SKIPF/EXECF/BYTEX and interrupts. The solution was to inhibit skip advancement, rather than delaying interrupts, when the interrupt circuit wants to insert its CALLD into the pipeline. This should make single-stepping more sensible.

    I will post a new Prop123-A9 image later today.

    Ozpropdev, if you could try it out, that would be great.
  • cgracey wrote: »
    Ozpropdev, if you could try it out, that would be great.
    Sure, no worries Chip. (always lurking...)
  • cgraceycgracey Posts: 14,133
    ozpropdev wrote: »
    cgracey wrote: »
    Ozpropdev, if you could try it out, that would be great.
    Sure, no worries Chip. (always lurking...)

    Here it is:

    https://drive.google.com/file/d/0B9NbgkdrupkHTE9aN3hlbTdJYXM/view?usp=sharing

    You should find the single-step behavior to be more sensible now.
  • Chip
    The "dummy" step that appeared in the previous SKIPF tests is now fixed.
    What has remained the same is the first instruction after a SKIP{F} is executed but stepped over.
    The included test runs a SKIP and SKIPF code snippet in COG, HUB and LUT exec modes.
    All actions operate as expected except for the initial first step.

    Code outputs @115200 baud and press "*" to step through code.


  • cgraceycgracey Posts: 14,133
    Ozpropdev,

    Try this one:

    https://drive.google.com/file/d/0B9NbgkdrupkHSXRkSVFaWEpDeWs/view?usp=sharing

    It should not have any weirdness, at all.
  • Chip
    Test code runs fine.
    Looks good. :)

    I'll throw some more test code at it to confirm but i'm pretty confident you've nailed it.

    Test output snippet here shows step after SKIP{F} is correct now.
    -----------------------------------------------------------------------------------------(P2 Debugger)
    SKIP PATTERN (from GETINT D[31:22])  = 0_000000000
    00004: FD643432              SKIPF   #$01A
     -- Expected SKIP(F) action --
    00005: FD644059              DRVH    #$020
    00006: FD644259 <skipped>    DRVH    #$021
    00007: FD644459              DRVH    #$022
    00008: FD644659 <skipped>    DRVH    #$023
    00009: FD644859 <skipped>    DRVH    #$024
    (? for help) >*
    -----------------------------------------------------------------------------------------(P2 Debugger)
    SKIP PATTERN (from GETINT D[31:22])  = 1_000011010
    00005: FD644059              DRVH    #$020
    (? for help) >*
    -----------------------------------------------------------------------------------------(P2 
    
    Thanks! :cool:



  • Oops!
    We now see the instruction after a skip Ok except if the first SKIP bit is '1' in SKIPF a "dummy" step is generated.
    -----------------------------------------------------------------------------------------(P2 Debugger)
    SKIP PATTERN (from GETINT D[31:22])  = 0_000000000
    00004: FD643632              SKIPF   #$01B
     -- Expected SKIP(F) action --
    00005: FD644059 <skipped>    DRVH    #$020
    00006: FD644259 <skipped>    DRVH    #$021
    00007: FD644459              DRVH    #$022
    00008: FD644659 <skipped>    DRVH    #$023
    00009: FD644859 <skipped>    DRVH    #$024
    (? for help) >*
    -----------------------------------------------------------------------------------------(P2 Debugger)
    SKIP PATTERN (from GETINT D[31:22])  = 1_000011011
        *** This Instruction will be skipped/cancelled ****
    00005: FD644059              DRVH    #$020
    (? for help) >*
    -----------------------------------------------------------------------------------------(P2 Debugger)
    SKIP PATTERN (from GETINT D[31:22])  = 1_000000110
    00007: FD644459              DRVH    #$022
    
  • cgraceycgracey Posts: 14,133
    edited 2017-06-25 16:40
    ozpropdev wrote: »
    Oops!
    We now see the instruction after a skip Ok except if the first SKIP bit is '1' in SKIPF a "dummy" step is generated.
    -----------------------------------------------------------------------------------------(P2 Debugger)
    SKIP PATTERN (from GETINT D[31:22])  = 0_000000000
    00004: FD643632              SKIPF   #$01B
     -- Expected SKIP(F) action --
    00005: FD644059 <skipped>    DRVH    #$020
    00006: FD644259 <skipped>    DRVH    #$021
    00007: FD644459              DRVH    #$022
    00008: FD644659 <skipped>    DRVH    #$023
    00009: FD644859 <skipped>    DRVH    #$024
    (? for help) >*
    -----------------------------------------------------------------------------------------(P2 Debugger)
    SKIP PATTERN (from GETINT D[31:22])  = 1_000011011
        *** This Instruction will be skipped/cancelled ****
    00005: FD644059              DRVH    #$020
    (? for help) >*
    -----------------------------------------------------------------------------------------(P2 Debugger)
    SKIP PATTERN (from GETINT D[31:22])  = 1_000000110
    00007: FD644459              DRVH    #$022
    

    I don't think it's possible to improve it. The reason is that in the SKIPF instruction cycle, we must both cancel the next instruction and advance the PC by some variable amount. After that, we just advance the PC variably.

    What I have now looks prettiest for single-stepping, but has caused a critical path that I hope to resolve. If I can't resolve it, we will go back to the way it was just before, where it always pauses on the instruction after SKIPF.
  • jmgjmg Posts: 15,140
    cgracey wrote: »
    What I have now looks prettiest for single-stepping, but has caused a critical path that I hope to resolve. If I can't resolve it, we will go back to the way it was just before, where it always pauses on the instruction after SKIPF.

    As long as the behaviour is predictable, and actually executes correctly, the Debug could fix-up any 1-opcode offsets that result from 'too many balls in the air' ?

    Once you have the complex stuff nailed, and have Spin2 done, for a more lightweight diversion you could try PBASIC bytecodes thru the SKIPF engine ?
    That gives another (simple) language test point, and you can benchmark P2 vs the venerable Stamps.

  • We certainly don't want critical path issues.
    As JMG pointed out, as long as the behaviour is predictable and documented we can make our debuggers adjust accordingly.
    Sorry it's been such a headache.
  • ozpropdev, did you test CALL within a skip sequence?
  • msrobotsmsrobots Posts: 3,701
    edited 2017-06-26 00:15
    jmg wrote: »
    ...Once you have the complex stuff nailed, and have Spin2 done, for a more lightweight diversion you could try PBASIC bytecodes thru the SKIPF engine ?
    That gives another (simple) language test point, and you can benchmark P2 vs the venerable Stamps.

    And could shut up all the questions about the next stamp?

    I really like it. And @Chip is the only one who understands the PBASIC interpreter. Not sure how the language needs to change to accommodate the way bigger Memory, speed and multicore, but even running PBASIC on a P2 would be fantastic.

    And would be a nice way to use smaller P2-Family Variants...

    Enjoy!

    Mike

  • TonyB_ wrote: »
    ozpropdev, did you test CALL within a skip sequence?
    Yes
    I found CALL's seem to be OK within a SKIP sequence but fail in a SKIPF sequence. :(
    That's in real time as well as single step.
    for example
    dat	org
    			bmask	dirb,#15
    			mov	outb,#0
    		'	skip	#%11010		'results in portb = %10000101  'ok
    			skipf	#%11010		'results in portb = %10010010	'incorrect
    			call	#zero
    			call	#one
    			call	#two
    			call	#three
    			call	#four
    			call	#seven
    
    			jmp	#$
    
    zero		_ret_	outh	#32
    one		_ret_	outh	#33
    two		_ret_	outh	#34
    three		_ret_	outh	#35
    four		_ret_	outh	#36
    seven		_ret_	outh	#39
    



  • cgraceycgracey Posts: 14,133
    edited 2017-06-26 16:29
    ozpropdev wrote: »
    TonyB_ wrote: »
    ozpropdev, did you test CALL within a skip sequence?
    Yes
    I found CALL's seem to be OK within a SKIP sequence but fail in a SKIPF sequence. :(
    That's in real time as well as single step.


    Those "CALL #address" instructions are relative. Use the "\" before the address to make them absolute:
    dat	org
    			bmask	dirb,#15
    			mov	outb,#0
    		'	skip	#%11010		'results in portb = %10000101  'ok
    			skipf	#%11010		'results in portb = %10010010	'incorrect
    			call	#\zero
    			call	#\one
    			call	#\two
    			call	#\three
    			call	#\four
    			call	#\seven
    
    			jmp	#$
    
    zero		_ret_	outh	#32
    one		_ret_	outh	#33
    two		_ret_	outh	#34
    three		_ret_	outh	#35
    four		_ret_	outh	#36
    seven		_ret_	outh	#39
    

    It should work, then.

    All calls from the skipped-instruction section must be either "#\" or register, in which either case the address is absolute.
  • Do we have a current functionality / how to in the docs?

    Looks like I've got something I want to try. Have followed thos, but did not write code.

    Also, I'm unclear on interrupts. Where do things stand there? Does XBYTE come first, interrupts first, or first come, first serve?

  • cgraceycgracey Posts: 14,133
    edited 2017-06-26 16:42
    potatohead wrote: »
    Do we have a current functionality / how to in the docs?

    Looks like I've got something I want to try. Have followed thos, but did not write code.

    Also, I'm unclear on interrupts. Where do things stand there? Does XBYTE come first, interrupts first, or first come, first serve?

    XBYTE could be considered a "virtual instruction" that executes when a RET to $1F8..$1FF occurs. It is shielded from interruption, but once its six clocks are done, interrupts can occur. Interrupts now work with XBYTE/SKIP/SKIPF/EXECF code. This was really important for single-stepping. The caveat for XBYTE/SKIP/SKIPF/EXECF code is that CALLs are allowed, but they must be absolute in all cases but "SKIP".

    I need to make a new release and update the Google doc file to reflect the latest functionality. I will do that later this week.
  • Cool, no rush. :D
  • cgracey wrote: »
    they must be absolute in all cases but "SKIP".
    Ok, got it Chip.
    Thanks
  • Besides the SKIPF restriction on relative calls, I've also run into issues with porting self-modifying P1 code and with generating code at run time where calls and jumps have to be absolute.

    Perhaps it makes sense for the absolute form of call/jmp to be the default (as it is in P1) and the relative to be either another opcode or selected via modifying the operand. Personally I'd like a different opcode. I think it would make these kinds of restrictions easier to explain, and also just make the code easier to read.

    (No hardware change proposed here, just an assembler change!)

    Eric
  • jmgjmg Posts: 15,140
    ersmith wrote: »
    Besides the SKIPF restriction on relative calls, I've also run into issues with porting self-modifying P1 code and with generating code at run time where calls and jumps have to be absolute.

    Perhaps it makes sense for the absolute form of call/jmp to be the default (as it is in P1) and the relative to be either another opcode or selected via modifying the operand. Personally I'd like a different opcode. I think it would make these kinds of restrictions easier to explain, and also just make the code easier to read.

    (No hardware change proposed here, just an assembler change!)
    That would be an improvement over what is there now.
    Other MCUs use ACALL for absolute call, and RJMP or SJMP for relative.

    Of course, most every other assembler I've ever seen uses this cleaner form, devoid of the distracting character-chaff
        CALL Label2
        ACALL Label2
    
    Label2:
    
    
  • cgracey wrote: »
    I need to make a new release and update the Google doc file to reflect the latest functionality. I will do that later this week.

    Last digit of SETQ is incorrect in bytecode[7:2] line on p.18 of v19 doc.
    Also MODCZ operand info here needs adding to doc or instructions.
  • cgraceycgracey Posts: 14,133
    TonyB_ wrote: »
    cgracey wrote: »
    I need to make a new release and update the Google doc file to reflect the latest functionality. I will do that later this week.

    Last digit of SETQ is incorrect in bytecode[7:2] line on p.18 of v19 doc.
    Also MODCZ operand info here needs adding to doc or instructions.

    Okay. Thanks. I'll fix that.
  • cgraceycgracey Posts: 14,133
    jmg wrote: »
    ersmith wrote: »
    Besides the SKIPF restriction on relative calls, I've also run into issues with porting self-modifying P1 code and with generating code at run time where calls and jumps have to be absolute.

    Perhaps it makes sense for the absolute form of call/jmp to be the default (as it is in P1) and the relative to be either another opcode or selected via modifying the operand. Personally I'd like a different opcode. I think it would make these kinds of restrictions easier to explain, and also just make the code easier to read.

    (No hardware change proposed here, just an assembler change!)
    That would be an improvement over what is there now.
    Other MCUs use ACALL for absolute call, and RJMP or SJMP for relative.

    Of course, most every other assembler I've ever seen uses this cleaner form, devoid of the distracting character-chaff
        CALL Label2
        ACALL Label2
    
    Label2:
    
    

    I was just reviewing the instructions to see about CALL/ACALL/RCALL. I remember that I've done this in the past, but I'm always stumped because the {#}S-address instructions are absolute for registers and relative for immediates. How to slice this pie with different mnemonics?
  • jmgjmg Posts: 15,140
    edited 2017-06-29 02:00
    cgracey wrote: »

    I was just reviewing the instructions to see about CALL/ACALL/RCALL. I remember that I've done this in the past, but I'm always stumped because the {#}S-address instructions are absolute for registers and relative for immediates. How to slice this pie with different mnemonics?

    Assemblers I'm used to using, appear broadly like this :
        RCALL   Label2     // relative call
        CALL    Label2
        ACALL   Label2     // absolute call
        MOV     Rn,#Label2
        ACALL   @Rn        // indirect call
        ICALL   Rn         
        ICALL   [Rn]
    
    Label2:
    
    ISTR there are issues with the @Rn, but ICALL could be clear enough for Indirect Call , or ICALL [Rn] if it needs to be even more obvious ?

    Most MCUs have separate segments for CODE and REG/DATA, so that tends to make separations clearer for Assemblers to check.

    However, in P2 COGs the CODE and REG space are rather on top of each other, but it may help to introduce the concepts of segments, as REG means explicitly 'place in COG', whilst COG/LUT/HUB exec on P2 means code could sensibly be placed in any, or all, of those areas.

    This becomes like a type check, and ICALL above would only accept a register param, but if someone really did want to use the contents at label 2 as a pointer, they could do something broadly like
    RegAbs     REG   0x15    // address 0x15 as register
    RegInCode  REG   Label2  // Use Label2 as address
    
        CSEG
        
    LoopForever:
        ICALL   RegAbs       // calls to addr in [0x15]
        ICALL   RegInCode    // Calls to addr in Label2, but gives a linker error if final Label2 resolves outside REG space.
        ICALL   LoopForever  // Gives error, as REG expected, but got code label.
    Label2:
        DW      LoopForever  // Fill this code with something legal, but silly
    
    
  • cgraceycgracey Posts: 14,133
    edited 2017-07-01 00:04
    Ozpropdev,

    I made some efficiency changes to the SKIP/SKIPF/EXECF/XBYTE circuitry. Could you please see if this checks out okay on your end?

    https://drive.google.com/file/d/0B9NbgkdrupkHU01ydXdtOWhWdTA/view?usp=sharing

    Thanks.
  • TonyB_ wrote: »
    Using SETQ or SETQ2 with Q[9]=1 would seem to be the sensible way to enable CZ writing in XBYTE. This is a bit of a dummy's question: if the D in SETQ/SETQ2 is 9-bit immediate, are the top 23 bits written to Q all zero, ensuring that XBYTE will not modify CZ?

    Is CZ writing in XBYTE optional now, or is this yet to be done?

    From a previous reply, a RET to $1F8-$1FF always starts a new XBYTE, even if there are '1' bits remaining in the skip pattern. Sometimes this early termination must occur inside a called subroutine. Assuming no nesting, is there any reason why the following shouldn't work?
    ' skipsub is routine called from SKIPF sequence
    
    skipsub		...
    
    ' discard return address and start next XBYTE
    
    	_ret_	pop	temp		
    
  • Looks Ok Chip except that a GETINT D doesn't seem to set D[31] when an active skip pattern is present now.
    SKIP PATTERN (from GETINT D[31:22])  = 0_000011010
    
Sign In or Register to comment.