XMOS Port Max Sampling Rate

Technical discussions around xCORE processors (e.g. xcore-200 & xcore.ai).
User avatar
fabriceo
XCore Addict
Posts: 255
Joined: Mon Jan 08, 2018 4:14 pm

Post by fabriceo »

Hello,
here is an example of assembly code embedded in a XC function which is optimized to store a port-input into a circular buffer. it take 4 core cycles only to read, store, increment, compare, reset and loop.

Code: Select all

[[dual_issue]] void circularbuff(buffered in port:4 p, unsigned &ptr, unsigned max){
    unsigned idx,val,test;
    asm volatile("#allocate reg %0 %1 %2":"=r"(idx),"=r"(val),"=r"(test));
    asm volatile(
            ".Looop_%=:"
            "\n  { in %4,res[%0] ; and %3,%3,%5 }"
            "\n  stw %4,%1[%3]"
            "\n  { lsu %5,%3,%2 ; add %3,%3,1 }"
            "\n  { neg %5,%5 ; bu .Looop_%= }"
              // %0      %1       %2       %3       %4        %5
            ::"r"(p),"r"(ptr),"r"(max),"r"(idx),"r"(val),"r"(test));
}
this means that a port can be read and stored at say 600/5/4 = 30mhz.
if this is a 4 bits ports configured in buffered mode (as in this example) then the theoretical sampling frequency could be 240mhz (30 x 32/4).
if it is 8 bits port, the routine should be ok up to 120mhz (default reference clock here).

fyi some tips here:
the first asm volatile is used to fool the compiler and to effectively allocate 3 temporary registers, used in the next asm statement.
the lsu instruction returns 1 as long as the idx is below max, then the neg instruction provides FFFFFFFF
when idx==max, lsu return 0 and then neg will return 0 as well, which will reset idx with the and instruction bundled with in.
max should be size of buffer - 1

remark : the only way to stop this loop is to use an event from a timer or a channel.
if this is needed, then this routine can be called in the default case of a select statement.
but then it is required to add

Code: Select all

asm volatile("setsr 1"); 
at the beginning of the default code, to keep the event enabled before entering in the fast acquisition loop.
hope this helps
User avatar
Ross
Verified
XCore Legend
Posts: 1203
Joined: Thu Dec 10, 2009 9:20 pm
Location: Bristol, UK

Post by Ross »

Jcvc wrote: Fri Jun 27, 2025 8:57 am Yeah, I tried changing it to a for loop instead, but no difference. I'll see then if I can improve it.
What compile options are you using?
Technical Director @ XMOS. Opinions expressed are my own
Joe
Verified
Experienced Member
Posts: 120
Joined: Sun Dec 13, 2009 1:12 am

Post by Joe »

Ran up a quick example in c:
portfastsample.zip
Compiles to:

0x00080230: c4 b6: in (2r) r1, res[r0]
0x00080232: ff 17: nop (0r)
0x00080234: ff 17: nop (0r)
0x00080236: 4f 54: stw (ru6) r1, sp[0xf]
0x00080238: c4 b6: in (2r) r1, res[r0]

The nops are due to dual issue so actually this loop take 2 cycles.

Obviously fabriceo's circular buffer more flexible but shows a basic implementation of highest speed port sampling.

Joe
You do not have the required permissions to view the files attached to this post.
XMOS hardware grey beard.