Ports!

Technical questions regarding the XTC tools and programming with XMOS.
snoopy
Member++
Posts: 28
Joined: Wed Dec 01, 2010 5:46 pm

Ports!

Post by snoopy »

Hi everyone,

I'm trying at the moment to get 40 outputs from an XS1-L1 (128) package while also using the x-links. So if you have a look at the documentation you'll see that my only option is to use X-links C and D and use 16A and 16B along with 1A,B,C,D,E,F,G,H to make up the 40 ports.

The next problem is that I need something that outputs at a frequency of 2.5Mhz. The problem I'm finding is that looking at the timing analysis, the loop takes too long to execute each instruction and the timing is all off.

I'm currently using this to output to the ports

Code: Select all

			for (int i = 0; i < 64; i++){
				C0P16A <: signaltable[i].int16bitA;
				C0P16B <: signaltable[i].int16bitB;
				C0P1A  <: signaltable[i].int1bitA;
				C0P1B  <: signaltable[i].int1bitB;
				C0P1C  <: signaltable[i].int1bitC;
				C0P1D  <: signaltable[i].int1bitD;
				C0P1E  <: signaltable[i].int1bitE;
				C0P1F  <: signaltable[i].int1bitF;
				C0P1G  <: signaltable[i].int1bitG;
				C0P1H  <: signaltable[i].int1bitH;
			}
where I am using buffered ports and a CLKBLK but they are kind of irrelevant cause even if I just output them directly its moving too slow to get the speed i need. I have tried using #pragma unsafe arrays and working on release instead of debug to try reduce the amount of cycles but it still takes too long.


The only way out that I can see is using assembly....

does anyone know if there a way to push to the output faster???


User avatar
bsmithyman
Experienced Member
Posts: 126
Joined: Fri Feb 12, 2010 10:31 pm

Post by bsmithyman »

With 10 separate write statements, and 2.5 MHz, that leaves 4 instructions on average per write, but of course there's a slew involved (all assuming 100 MHz operation). It seems like this should be possible using clocked ports (i.e. page 39 of "Programming XC on XMOS Devices"), but I haven't personally tried it.

Assuming it's possible to put all of the ports on the same clock block, you would take most of the time to load the buffers, and then the clock block should dump them all to the output pins at once. I'm assuming the signaltable is a structure built with a union in C or something similar? The question becomes whether it's possible to get the data out of the structure and into the port buffers in ~3 instructions to leave some cycles for the loop; how does the disassembly look?

Anyway, that's how I'd approach it. I haven't tried it, so I might be totally wrong :)

Edit: The other way might be to have the I/O split across multiple threads, pulling from the same shared memory buffer at different locations. It would be tough to synchronize them though...
snoopy
Member++
Posts: 28
Joined: Wed Dec 01, 2010 5:46 pm

Post by snoopy »

Your absolutely right with the cycles and yes signaltable is a struct. unfortunately at the moment I can only get it down to 6 cycles without going directly into writing assembly.

I thought about splitting it into more threads but at the moment there are 3 going...adding one more is easy but adding anymore could cause the whole thing to slow down slowly.

I am using both buffered ports and clockblocks, problem seems to be accessing an array fast enough to output it to the pin and move to the next instruction....

Looks like i'm going to have to do some crash course reading into the assembly instructions :/

Cheers
User avatar
lilltroll
XCore Expert
Posts: 956
Joined: Fri Dec 11, 2009 3:53 am
Location: Sweden, Eskilstuna

Post by lilltroll »

If you use buffered ports, you cannot bitbang the output at the one bit ports at the same time.
Is the type uint32 of the struct?

Assume the you have stored the value 1 in
signaltable.int1bitA;

and you are using 32-bit FIFO, you will output 1 'HIGH' and 31 'LOW' values.

Can you show a little more of your code regarding the init ?

Would you like all 40bits to change at the same time as well, as a parallell 40 bit port @ 2.5 MHz ?
Probably not the most confused programmer anymore on the XCORE forum.
snoopy
Member++
Posts: 28
Joined: Wed Dec 01, 2010 5:46 pm

Post by snoopy »

The extra set up code:

Code: Select all

//Set up 40 buffered ports ////////////////////////////////////

//2 * 16 bit ports
on stdcore[0] : out buffered port:16 C0P16A = XS1_PORT_16A;
on stdcore[0] : out buffered port:16 C0P16B = XS1_PORT_16B;

//8 * 1 bit ports
on stdcore[0] : out buffered port:1 C0P1A = XS1_PORT_1A;
on stdcore[0] : out buffered port:1 C0P1B = XS1_PORT_1B;
on stdcore[0] : out buffered port:1 C0P1C = XS1_PORT_1C;
on stdcore[0] : out buffered port:1 C0P1D = XS1_PORT_1D;
on stdcore[0] : out buffered port:1 C0P1E = XS1_PORT_1E;
on stdcore[0] : out buffered port:1 C0P1F = XS1_PORT_1F;
on stdcore[0] : out buffered port:1 C0P1G = XS1_PORT_1G;
on stdcore[0] : out buffered port:1 C0P1H = XS1_PORT_1H;
and

Code: Select all

	configure_clock_rate(clk, 100, 80);
	configure_out_port(C0P16A, clk, 1);
	configure_out_port(C0P16B, clk, 1);
	configure_out_port(C0P1A, clk, 1);
	configure_out_port(C0P1B, clk, 1);
	configure_out_port(C0P1C, clk, 1);
	configure_out_port(C0P1D, clk, 1);
	configure_out_port(C0P1E, clk, 1);
	configure_out_port(C0P1F, clk, 1);
	configure_out_port(C0P1G, clk, 1);
	configure_out_port(C0P1H, clk, 1);
Its a single bit buffer for the 1 bit ports and yes I do want all 40 bits to update at once :)

Thanks again
User avatar
Folknology
XCore Legend
Posts: 1274
Joined: Thu Dec 10, 2009 10:20 pm

Post by Folknology »

If you can get away with using a single 2 bit link (Link B in 2bit mode) you could use the 32bit port and either 8C or 8D.

or if using C and D Links in 2 bit mode (rather than 5bit) would free up more than enough of the 32bit port (12bits) 32A0-A2,A7-A12,A17-A19 instead of using the 1 bit ports with your 2x16bit ports

regards
Al
snoopy
Member++
Posts: 28
Joined: Wed Dec 01, 2010 5:46 pm

Post by snoopy »

got more chips on either side of it so a minimum of 2 sets of X-links are needed

Jake
User avatar
Folknology
XCore Legend
Posts: 1274
Joined: Thu Dec 10, 2009 10:20 pm

Post by Folknology »

Can you use them in 2 bit mode?
User avatar
segher
XCore Expert
Posts: 844
Joined: Sun Jul 11, 2010 1:31 am

Post by segher »

You can use 32A[0..19], 16B, and four 1-bit ports (you probably want to avoid
the pins used for SPI boot, if you want to use that).

Then you can use full-width links A and B.

Links have precedence over ports; when both are enabled for a certain pin,
the link gets it, and the port doesn't output on it, and reads as zeroes (but
behaves completely like it would otherwise, otherwise).
snoopy
Member++
Posts: 28
Joined: Wed Dec 01, 2010 5:46 pm

Post by snoopy »

Ye I suppose that would work. Just didn't think it would be wise to use it cause of the X-links. We had a discussion about this within our group but thought we might give it a go with the 8 single bit ports first.