Also the protocol description in 3.5 omits the additional headers and footers as described in 3.4. This includes a 2 byte header identifying the switch (which I assume is just the node id?) and the SSCTRL token. A 3 byte header sent back to complete. It seems as if these extra parts should be included with inter-node configuration as opposed to the shorter version in 3.5 for intra-node configuration but its not clear...
Here's my code to write a switch register 3. 'c' is the local channel end used to communicate with the switch which is identified by 'dest'.
Code: Select all
// Write a switch configuration register
void cfgWrite(unsigned c, unsigned dest, unsigned value) {
unsigned v;
// Two byte header identifying dest switch
asm("outt res[%0], %1" :: "r"(c), "r"((dest >> 24) & 0xF));
asm("outt res[%0], %1" :: "r"(c), "r"((dest >> 16) & 0xF));
// SSCTRL token
asm("outct res[%0], %1" :: "r"(c), "r"(XS1_CT_SSCTRL));
// WRITEC token
asm("outct res[%0], %1" :: "r"(c), "r"(XS1_CT_WRITEC));
// NodeId, CoreId, ChanId
asm("outt res[%0], %1" :: "r"(c), "r"((c >> 24) & 0xF));
asm("outt res[%0], %1" :: "r"(c), "r"((c >> 16) & 0xF));
asm("outt res[%0], %1" :: "r"(c), "r"((c >> 8) & 0xF));
// Switch address (register 3)
asm("outt res[%0], %1" :: "r"(c), "r"(0));
asm("outt res[%0], %1" :: "r"(c), "r"(3));
// Data to write
asm("out res[%0], %1" :: "r"(c), "r"(value));
// End of message
asm("outct res[%0], " S(XS1_CT_END) :: "r"(c));
// Receive 3 byte header
asm("int %0, res[%1]" : "=r"(v) : "r"(c));
asm("int %0, res[%1]" : "=r"(v) : "r"(c));
asm("int %0, res[%1]" : "=r"(v) : "r"(c));
// Receive acknowledgement
asm("chkct res[%0], " S(XS1_CT_ACK) :: "r"(c));
asm("chkct res[%0], " S(XS1_CT_END) :: "r"(c));
}
Code: Select all
// Read a switch configuration register
unsigned cfgRead(unsigned c, unsigned dest) {
unsigned value, v;
// Two byte header identifying dest switch
asm("outt res[%0], %1" :: "r"(c), "r"((dest >> 24) & 0xF));
asm("outt res[%0], %1" :: "r"(c), "r"((dest >> 16) & 0xF));
// SSCTRL token
asm("outct res[%0], %1" :: "r"(c), "r"(XS1_CT_SSCTRL));
// READC
asm("outct res[%0], %1" :: "r"(c), "r"(XS1_CT_READC));
// NodeId, CoreId, ChanId
asm("outt res[%0], %1" :: "r"(c), "r"((c >> 24) & 0xF));
asm("outt res[%0], %1" :: "r"(c), "r"((c >> 16) & 0xF));
asm("outt res[%0], %1" :: "r"(c), "r"((c >> 8) & 0xF));
// Switch address (register 3)
asm("outt res[%0], %1" :: "r"(c), "r"(0));
asm("outt res[%0], %1" :: "r"(c), "r"(3));
// End of message
asm("outct res[%0], " S(XS1_CT_END) :: "r"(c));
// Receive 3 byte header
asm("int %0, res[%1]" : "=r"(v) : "r"(c));
asm("int %0, res[%1]" : "=r"(v) : "r"(c));
asm("int %0, res[%1]" : "=r"(v) : "r"(c));
// Receive ACK and data
asm("chkct res[%0], " S(XS1_CT_ACK) :: "r"(c));
asm("in %0, res[%1]" : "=r"(value) : "r"(c));
asm("chkct res[%0], " S(XS1_CT_END) :: "r"(c));
return value;
}
Cheers,
Jamie