Running IXP sample code in Unoptimized mode
I saw another variant of this problem (reported by Francis Chang for the the
example in Chapter 5 of the IXP book). When run in unoptmized mode, the
compiler generates the following code (My comments start with //*** )
For:
buf_handle = receive_packet(0, 5, &cur_pkt_len);
Code generated:
/******/ buf_handle = receive_packet(0, 5, &cur_pkt_len);
l_8#:
immed[port_num_96_V$bc$2$5:a4, 0, <<0] //*** USES SAME REGISTER a4
immed[rfifo_num_96_V$bd$2$5:a4, 5, <<0] //*** USES SAME REGISTER a4
br[_receive_packet#], defer[1]
load_addr[a2, l_55#]
------------------
The same register is being used for both the in parameters.
-----------------
If I change the function receive_packet to use temporary variables:
buffer_handle_t receive_packet( unsigned int port_num ,
unsigned int rfifo_num ,
unsigned int *pkt_length)
{
unsigned int a = 0, b = 0; //*** temp variables
rcv_state_t rcv_state = { 0 };
rcv_cntl_reg_t rcv_control;
__declspec(sdram) void *buf_data_ptr;
a = port_num; //*** temp variables
b = rfifo_num; //*** temp variables
do
{
rcv_control = get_mpacket(a, b); //*** use temp variables instead of
original code: rcv_control = get_mpacket(port_num, rfifo_num); ***
...
...
}
-------------
This produces the following code:
immed[port_num_96_V$bc$2$5:a0, 0, <<0] //*** USES different register a0
***
immed[rfifo_num_96_V$bd$2$5:a4, 5, <<0] //*** USES different register a4
***
br[_receive_packet#], defer[1]
load_addr[b3, l_55#]
/******/ scratch_incr(cntr, no_signal);
l_55#:
scratch[incr, --, cntr_105$2$4:b0, 0, 1], no_signal
/******/ *byte_count += cur_pkt_len;
scratch[read, $0, byte_count_105$2$4:a2, 0, 1], ctx_swap
sram[read, $1, pkt_length_96_V$be$2$5:b3, 0, 1], ctx_swap
.....
.....
----------------
On return from the function call, the value of cntr is overwritten by code
within the function (that writes the out value pkt_lenth to the same
register b0). I can send more detailed code if required. Is there a
workaround/fix for this, (where the registers do not get corrupted in Debug
mode)?
Thanks,
Deepa
From: "Francis"
Hi, another variant of false register allocation occured in SDK 2.01a but this time using optimizations for speed. Below you will find the generated code and two workarounds: /**************************************************************** The compiler falsely reuses sram_write_register $0. $0 is first used to hold swrtmp and then is used to hold swrtmp2 Therefore, both writes to scratch write the same value : the value of swrtmp2. ****************************************************************/ immed[$0, -1, 0] //swrtmp = 0xffffffff; scratch[write, $0, _myTID:a2, 17, 1] //scratch_write(&swrtmp, BASE_THREAD_SLOTS + myTID, 1, sync_none); alu[$0, --, B, _myCTX:b1] //swrtmp2 = myTID; scratch[write, $0, rc_sop_seq_315_V$99$1$0:b0, 0, 1], ctx_swap //scratch_write(&swrtmp2, rc_sop_seq, 1, ctx_swap); /* Workarounds: 1. context swap after first scratch write By adding a ctx_swap after the second command the context will be swapped and when awakened it will be able to reuse the $0 (not a good solution though....) 2. Change the order of the commands. (PREFFERED) First do the assignments and then do the intrinsic function calls. This way the compiler produces the following code which is correct: //swrtmp = 0xffffffff; //swrtmp2 = myTID; //scratch_write(&swrtmp, (__declspec(scratch) void *) (BASE_THREAD_SLOTS + myTID), 1, sync_none); //scratch_write(&swrtmp2, (__declspec(scratch) void *) rc_sop_seq, 1, ctx_swap); immed[$0, -1, 0] alu[$1, --, B, _myCTX:b1] scratch[write, $0, _myTID:a2, 17, 1] scratch[write, $1, rc_sop_seq_315_V$99$1$0:b0, 0, 1], ctx_swap Yannis Charitakis haritak@ics.forth.gr Foundation of Research and Technology Heraklion Crete Greece On Thu, 29 Aug 2002, Deepa Srinivasan wrote:
I saw another variant of this problem (reported by Francis Chang for the the example in Chapter 5 of the IXP book). When run in unoptmized mode, the compiler generates the following code (My comments start with //*** )
For: buf_handle = receive_packet(0, 5, &cur_pkt_len);
Code generated: /******/ buf_handle = receive_packet(0, 5, &cur_pkt_len); l_8#: immed[port_num_96_V$bc$2$5:a4, 0, <<0] //*** USES SAME REGISTER a4 immed[rfifo_num_96_V$bd$2$5:a4, 5, <<0] //*** USES SAME REGISTER a4 br[_receive_packet#], defer[1] load_addr[a2, l_55#] ------------------ The same register is being used for both the in parameters. -----------------
If I change the function receive_packet to use temporary variables:
buffer_handle_t receive_packet( unsigned int port_num , unsigned int rfifo_num , unsigned int *pkt_length) { unsigned int a = 0, b = 0; //*** temp variables rcv_state_t rcv_state = { 0 }; rcv_cntl_reg_t rcv_control; __declspec(sdram) void *buf_data_ptr;
a = port_num; //*** temp variables b = rfifo_num; //*** temp variables
do { rcv_control = get_mpacket(a, b); //*** use temp variables instead of original code: rcv_control = get_mpacket(port_num, rfifo_num); *** ... ... } ------------- This produces the following code:
immed[port_num_96_V$bc$2$5:a0, 0, <<0] //*** USES different register a0 *** immed[rfifo_num_96_V$bd$2$5:a4, 5, <<0] //*** USES different register a4 *** br[_receive_packet#], defer[1] load_addr[b3, l_55#] /******/ scratch_incr(cntr, no_signal); l_55#: scratch[incr, --, cntr_105$2$4:b0, 0, 1], no_signal /******/ *byte_count += cur_pkt_len;
scratch[read, $0, byte_count_105$2$4:a2, 0, 1], ctx_swap sram[read, $1, pkt_length_96_V$be$2$5:b3, 0, 1], ctx_swap ..... .....
---------------- On return from the function call, the value of cntr is overwritten by code within the function (that writes the out value pkt_lenth to the same register b0). I can send more detailed code if required. Is there a workaround/fix for this, (where the registers do not get corrupted in Debug mode)?
Thanks, Deepa
From: "Francis"
To: Subject: [ixp1200] IXA SDK Bug Date: Mon, 12 Aug 2002 07:58:52 -0700 There seems to be a bug in the uEngine C Compiler, when run in unoptimized mode. I was wondering if anyone's seen this behaviour before, and if they can suggest work-arounds.
One of the sample IXA applications (single-threaded-packet counter) I'm looking at exhibits this bug. It works on the "optimize for speed" settings, but when I put it into the non-optimized mode, it generates questionable micro-engine assembly output.
The compiler seems to want to use GPR a0 to store both a pointer into scratch memory, as well as function return address. Predictably, this causes problems :)
This behaviour is consistent in the Intel IXA Software Developers Kit for IXP1200, versions 2.0, 2.01 and 2.01a.
-- Francis
From owner-ixp1200@upright.CS.Princeton.EDU Tue Aug 13 19:13:22 2002 Received: (from daemon@localhost) by upright.CS.Princeton.EDU (8.11.6/8.11.6) id g7DND3w21081; Tue, 13 Aug 2002 19:13:03 -0400 (EDT) Mailbox-Line: From vkrish@cs.ucr.edu Tue Aug 13 16:12:57 2002 Date: Tue, 13 Aug 2002 16:12:56 -0700 (PDT) From: Vaishnavi Krishnamurthy
To: Subject: [ixp1200] Optimization Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII X-Spam-Status: No, hits=0.0 required=5.0 tests=none version=2.31 X-Spam-Level: X-Virus-Scanned: by AMaViS perl-11 Sender: owner-ixp1200@CS.Princeton.EDU Reply-To: ixp1200@CS.Princeton.EDU Hi Francis, I have had the same problem as you..when optimized for size or speed there are no errors but when the program is made to run without any optimization it gives some error. Is there any way to remove these errors? Please let me know. Thanks, vaish.
From owner-ixp1200@upright.CS.Princeton.EDU Tue Aug 13 19:42:01 2002 Received: (from daemon@localhost) by upright.CS.Princeton.EDU (8.11.6/8.11.6) id g7DNfvN25523; Tue, 13 Aug 2002 19:41:57 -0400 (EDT) From: "Francis"
To: Subject: RE: [ixp1200] IXA SDK Bug Date: Tue, 13 Aug 2002 16:41:36 -0700 Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset="US-ASCII" Content-Transfer-Encoding: 7bit X-Priority: 3 (Normal) X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook IMO, Build 9.0.2416 (9.0.2911.0) Importance: Normal X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2600.0000 Sender: owner-ixp1200@CS.Princeton.EDU Reply-To: ixp1200@CS.Princeton.EDU It's been suggested that I should provide some more details on this particular problem, so here goes :)
The sample code I have is from "IXP1200 Programming" by Erik J. Johnson and Aaron R. Kunze. It's chapter 5's sample, the single-threaded packet counter.
This is an excerpt of the uC compiler output. // My comments will in C++ style
// Initialize the cntr variable, as GPR a0 ;****** cntr = (__declspec(scratch) unsigned int *)0; immed[cntr_109$2$4:a0, 0, <<0] // Write "0" into the scratchpad memory ;****** *cntr = 0; immed[$0, 0, <<0] scratch[write, $0, cntr_109$2$4:a0, 0, 1], ctx_swap // Call the receive_packet function. Load the return address into a0 ;****** buf_handle = receive_packet(0, 5, &cur_pkt_len); immed[port_num_100_V$ca$2$5:b2, 0, <<0] immed[rfifo_num_100_V$cb$2$5:a2, 5, <<0] br[_receive_packet#], defer[1] load_addr[a0, l_55#] // Increment the packet count in scratch memory. Notice, however, that a0, // the pointer to scratch memory a0 now contains the return address of // label 1_55#, and not a valid pointer into scratch memory. l_55#: ;****** scratch_incr(cntr, no_signal); scratch[incr, --, cntr_109$2$4:a0, 0, 1], no_signal
-- Francis
participants (2)
-
Deepa Srinivasan
-
Yannis Haritakis