lextract/linsert limitations Topic is solved

Technical discussions around xCORE processors (e.g. General Purpose (L/G), xCORE-USB, xCORE-Analog, xCORE-XA).
Ralf.Suckow
New User
Posts: 3
Joined: Sun Nov 01, 2020 10:26 pm

lextract/linsert limitations

Postby Ralf.Suckow » Sun Nov 01, 2020 10:55 pm

Hello,

I was totally excited when discovering these XS2 commands, to be able to quickly get/set bits and bytes in 64 bit operands. Just to find out the position is limited to 31 according to the xs1.h header file, and for linsert also according to the XS2 architecture document (not for lextract, though). What a disappointment!

So, my first question is, what's the point to make this a 64 bit operation, if it generally works only for the first 32 bits?

Then I found by testing, that a position of 32 (i.e. bpw) works, both in simulator and hardware. So I could at least combine two commands like this to extract any 4 bits from a 64 bit value:

Code: Select all

static uint64_t foo = 0x123456789ABCDEF0L;
for (unsigned i = 0; i < 64; i+= 4)
{
  unsigned bar = lextract(lextract(foo, i & 0x20, 32), i & 0x1F, 4);
  printf("%d 0x%08x\n", i, bar);
}
So, the second question is, should I really rely on undocumented behavior?
Any thoughts are higly appreciated.

Yours,
Ralf
View Solution
User avatar
CousinItt
XCore Addict
Posts: 194
Joined: Wed May 31, 2017 6:55 pm

Postby CousinItt » Mon Nov 02, 2020 12:27 pm

I'm not sure your fears are justified, but the spec for the operations is a bit opaque to me.

As far as I can tell the number of bits you can insert/extract is up to 32 (but not any number of bits) and the location is anywhere in the 64-bit register pair (specified by a register). See the full information for the instructions in xCORE-200: The XMOS XS2 Architecture.
Ralf.Suckow
New User
Posts: 3
Joined: Sun Nov 01, 2020 10:26 pm

Postby Ralf.Suckow » Mon Nov 02, 2020 3:44 pm

Hi CousinItt, thanks for your reply.

Interesting enough, the "any position" assumption seems not to hold. Positions above 32 don't work. Here's my test program. Did I something wrong? The document you referred to also mentions this limit for linsert.

Code: Select all

for (int index = -64; index < 64; index++)
{
  unsigned long long data = 0;
  data = linsert(data, 0xF, index, 4);
  unsigned data1 = data >> 32;
  printf("%d 0x%08x%08x\n", index, data1, data);
}
The output is this:

Code: Select all

-64 0x0000000000000000
... <all zeroes here>
-1 0x0000000000000000
0 0x000000000000000f
1 0x000000000000001e
2 0x000000000000003c
3 0x0000000000000078
4 0x00000000000000f0
5 0x00000000000001e0
6 0x00000000000003c0
7 0x0000000000000780
8 0x0000000000000f00
9 0x0000000000001e00
10 0x0000000000003c00
11 0x0000000000007800
12 0x000000000000f000
13 0x000000000001e000
14 0x000000000003c000
15 0x0000000000078000
16 0x00000000000f0000
17 0x00000000001e0000
18 0x00000000003c0000
19 0x0000000000780000
20 0x0000000000f00000
21 0x0000000001e00000
22 0x0000000003c00000
23 0x0000000007800000
24 0x000000000f000000
25 0x000000001e000000
26 0x000000003c000000
27 0x0000000078000000
28 0x00000000f0000000
29 0x00000001e0000000
30 0x00000003c0000000
31 0x0000000780000000
32 0x0000000f00000000
33 0x0000000000000000
... <all zeroes here>
63 0x0000000000000000
So, using this behaviour I could both read and write bits by a combination of linsert/lextract without if statements, and it is still faster by a factor of 1.5..2 compared to 2x32 bit value shifting with logical operations, but still much slower than if locations above 32 would be supported.

Code: Select all

static uint64_t data;

unsigned is_bit_set(unsigned bit_index)
{
  return lextract(lextract(data, bit_index & 0x20, 32), bit_index & 0x1F, 1);
}

void set_bit(unsigned bit_index, unsigned value)
{
  // using the fact that positions <0 and >32 are ignored
  data = linsert(linsert(data,       value, bit_index,      1),
                 linsert(data >> 32, value, bit_index - 32, 1),
                 32, 32);
}
User avatar
CousinItt
XCore Addict
Posts: 194
Joined: Wed May 31, 2017 6:55 pm

Postby CousinItt » Mon Nov 02, 2020 5:48 pm

Yes it looks like you're right: you can only insert a single bit in positions 0..32. It's only if you want to insert a longer bitfield that you can reach further into the upper word of the 64-bit value, for example you can insert a complete 32-bit value anywhere in the 64-bit data.
leobodnar
Member
Posts: 11
Joined: Mon May 07, 2018 9:26 am

Postby leobodnar » Mon Nov 02, 2020 8:20 pm

I hazard a guess that linsert/lextract have been introduced (together with crc32_inc, outpw and a few other instructions) specifically to be able to pull off wirespeed 1000BASE-T traffic. During RGMII transmit/receive you need to be able to insert or extract 32-bit checksum at a non-word boundary.
Leo
Ralf.Suckow
New User
Posts: 3
Joined: Sun Nov 01, 2020 10:26 pm

Postby Ralf.Suckow » Tue Nov 03, 2020 8:54 am

I see, thanks!

Ralf

Who is online

Users browsing this forum: No registered users and 4 guests