abc-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
fxuSelect.c
Go to the documentation of this file.
1 /**CFile****************************************************************
2 
3  FileName [fxuSelect.c]
4 
5  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
6 
7  Synopsis [Procedures to select the best divisor/complement pair.]
8 
9  Author [MVSIS Group]
10 
11  Affiliation [UC Berkeley]
12 
13  Date [Ver. 1.0. Started - February 1, 2003.]
14 
15  Revision [$Id: fxuSelect.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $]
16 
17 ***********************************************************************/
18 
19 #include "fxuInt.h"
20 
22 
23 
24 ////////////////////////////////////////////////////////////////////////
25 /// DECLARATIONS ///
26 ////////////////////////////////////////////////////////////////////////
27 
28 #define MAX_SIZE_LOOKAHEAD 20
29 
30 static int Fxu_MatrixFindComplement( Fxu_Matrix * p, int iVar );
31 
35 
37  int piVarsC1[], int piVarsC2[], int nVarsC1, int nVarsC2 );
39  int piVarsC1[], int piVarsC2[], int * pnVarsC1, int * pnVarsC2 );
40 
41 
42 ////////////////////////////////////////////////////////////////////////
43 /// FUNCTION DEFINITIONS ///
44 ////////////////////////////////////////////////////////////////////////
45 
46 /**Function*************************************************************
47 
48  Synopsis [Selects the best pair (Single,Double) and returns their weight.]
49 
50  Description []
51 
52  SideEffects []
53 
54  SeeAlso []
55 
56 ***********************************************************************/
57 int Fxu_Select( Fxu_Matrix * p, Fxu_Single ** ppSingle, Fxu_Double ** ppDouble )
58 {
59  // the top entries
60  Fxu_Single * pSingles[MAX_SIZE_LOOKAHEAD] = {0};
61  Fxu_Double * pDoubles[MAX_SIZE_LOOKAHEAD] = {0};
62  // the complements
63  Fxu_Double * pSCompl[MAX_SIZE_LOOKAHEAD] = {0};
64  Fxu_Single * pDComplS[MAX_SIZE_LOOKAHEAD] = {0};
65  Fxu_Double * pDComplD[MAX_SIZE_LOOKAHEAD] = {0};
66  Fxu_Pair * pPair;
67  int nSingles;
68  int nDoubles;
69  int i;
70  int WeightBest;
71  int WeightCur;
72  int iNum, fBestS;
73 
74  // collect the top entries from the queues
75  for ( nSingles = 0; nSingles < MAX_SIZE_LOOKAHEAD; nSingles++ )
76  {
77  pSingles[nSingles] = Fxu_HeapSingleGetMax( p->pHeapSingle );
78  if ( pSingles[nSingles] == NULL )
79  break;
80  }
81  // put them back into the queue
82  for ( i = 0; i < nSingles; i++ )
83  if ( pSingles[i] )
84  Fxu_HeapSingleInsert( p->pHeapSingle, pSingles[i] );
85 
86  // the same for doubles
87  // collect the top entries from the queues
88  for ( nDoubles = 0; nDoubles < MAX_SIZE_LOOKAHEAD; nDoubles++ )
89  {
90  pDoubles[nDoubles] = Fxu_HeapDoubleGetMax( p->pHeapDouble );
91  if ( pDoubles[nDoubles] == NULL )
92  break;
93  }
94  // put them back into the queue
95  for ( i = 0; i < nDoubles; i++ )
96  if ( pDoubles[i] )
97  Fxu_HeapDoubleInsert( p->pHeapDouble, pDoubles[i] );
98 
99  // for each single, find the complement double (if any)
100  for ( i = 0; i < nSingles; i++ )
101  if ( pSingles[i] )
102  pSCompl[i] = Fxu_MatrixFindComplementSingle( p, pSingles[i] );
103 
104  // for each double, find the complement single or double (if any)
105  for ( i = 0; i < nDoubles; i++ )
106  if ( pDoubles[i] )
107  {
108  pPair = pDoubles[i]->lPairs.pHead;
109  if ( pPair->nLits1 == 1 && pPair->nLits2 == 1 )
110  {
111  pDComplS[i] = Fxu_MatrixFindComplementDouble2( p, pDoubles[i] );
112  pDComplD[i] = NULL;
113  }
114 // else if ( pPair->nLits1 == 2 && pPair->nLits2 == 2 )
115 // {
116 // pDComplS[i] = NULL;
117 // pDComplD[i] = Fxu_MatrixFindComplementDouble4( p, pDoubles[i] );
118 // }
119  else
120  {
121  pDComplS[i] = NULL;
122  pDComplD[i] = NULL;
123  }
124  }
125 
126  // select the best pair
127  WeightBest = -1;
128  for ( i = 0; i < nSingles; i++ )
129  {
130  WeightCur = pSingles[i]->Weight;
131  if ( pSCompl[i] )
132  {
133  // add the weight of the double
134  WeightCur += pSCompl[i]->Weight;
135  // there is no need to implement this double, so...
136  pPair = pSCompl[i]->lPairs.pHead;
137  WeightCur += pPair->nLits1 + pPair->nLits2;
138  }
139  if ( WeightBest < WeightCur )
140  {
141  WeightBest = WeightCur;
142  *ppSingle = pSingles[i];
143  *ppDouble = pSCompl[i];
144  fBestS = 1;
145  iNum = i;
146  }
147  }
148  for ( i = 0; i < nDoubles; i++ )
149  {
150  WeightCur = pDoubles[i]->Weight;
151  if ( pDComplS[i] )
152  {
153  // add the weight of the single
154  WeightCur += pDComplS[i]->Weight;
155  // there is no need to implement this double, so...
156  pPair = pDoubles[i]->lPairs.pHead;
157  WeightCur += pPair->nLits1 + pPair->nLits2;
158  }
159  if ( WeightBest < WeightCur )
160  {
161  WeightBest = WeightCur;
162  *ppSingle = pDComplS[i];
163  *ppDouble = pDoubles[i];
164  fBestS = 0;
165  iNum = i;
166  }
167  }
168 /*
169  // print the statistics
170  printf( "\n" );
171  for ( i = 0; i < nSingles; i++ )
172  {
173  printf( "Single #%d: Weight = %3d. ", i, pSingles[i]->Weight );
174  printf( "Compl: " );
175  if ( pSCompl[i] == NULL )
176  printf( "None." );
177  else
178  printf( "D Weight = %3d Sum = %3d",
179  pSCompl[i]->Weight, pSCompl[i]->Weight + pSingles[i]->Weight );
180  printf( "\n" );
181  }
182  printf( "\n" );
183  for ( i = 0; i < nDoubles; i++ )
184  {
185  printf( "Double #%d: Weight = %3d. ", i, pDoubles[i]->Weight );
186  printf( "Compl: " );
187  if ( pDComplS[i] == NULL && pDComplD[i] == NULL )
188  printf( "None." );
189  else if ( pDComplS[i] )
190  printf( "S Weight = %3d Sum = %3d",
191  pDComplS[i]->Weight, pDComplS[i]->Weight + pDoubles[i]->Weight );
192  else if ( pDComplD[i] )
193  printf( "D Weight = %3d Sum = %3d",
194  pDComplD[i]->Weight, pDComplD[i]->Weight + pDoubles[i]->Weight );
195  printf( "\n" );
196  }
197  if ( WeightBest == -1 )
198  printf( "Selected NONE\n" );
199  else
200  {
201  printf( "Selected = %s. ", fBestS? "S": "D" );
202  printf( "Number = %d. ", iNum );
203  printf( "Weight = %d.\n", WeightBest );
204  }
205  printf( "\n" );
206 */
207  return WeightBest;
208 }
209 
210 
211 /**Function*************************************************************
212 
213  Synopsis []
214 
215  Description []
216 
217  SideEffects []
218 
219  SeeAlso []
220 
221 ***********************************************************************/
223 {
224 // int * pValue2Node = p->pValue2Node;
225  int iVar1, iVar2;
226  int iVar1C, iVar2C;
227  // get the variables of this single div
228  iVar1 = pSingle->pVar1->iVar;
229  iVar2 = pSingle->pVar2->iVar;
230  iVar1C = Fxu_MatrixFindComplement( p, iVar1 );
231  iVar2C = Fxu_MatrixFindComplement( p, iVar2 );
232  if ( iVar1C == -1 || iVar2C == -1 )
233  return NULL;
234  assert( iVar1C < iVar2C );
235  return Fxu_MatrixFindDouble( p, &iVar1C, &iVar2C, 1, 1 );
236 }
237 
238 /**Function*************************************************************
239 
240  Synopsis []
241 
242  Description []
243 
244  SideEffects []
245 
246  SeeAlso []
247 
248 ***********************************************************************/
250 {
251 // int * pValue2Node = p->pValue2Node;
252  int piVarsC1[10], piVarsC2[10];
253  int nVarsC1, nVarsC2;
254  int iVar1, iVar2, iVarTemp;
255  int iVar1C, iVar2C;
256  Fxu_Single * pSingle;
257 
258  // get the variables of this double div
259  Fxu_MatrixGetDoubleVars( p, pDouble, piVarsC1, piVarsC2, &nVarsC1, &nVarsC2 );
260  assert( nVarsC1 == 1 );
261  assert( nVarsC2 == 1 );
262  iVar1 = piVarsC1[0];
263  iVar2 = piVarsC2[0];
264  assert( iVar1 < iVar2 );
265 
266  iVar1C = Fxu_MatrixFindComplement( p, iVar1 );
267  iVar2C = Fxu_MatrixFindComplement( p, iVar2 );
268  if ( iVar1C == -1 || iVar2C == -1 )
269  return NULL;
270 
271  // go through the queque and find this one
272 // assert( iVar1C < iVar2C );
273  if ( iVar1C > iVar2C )
274  {
275  iVarTemp = iVar1C;
276  iVar1C = iVar2C;
277  iVar2C = iVarTemp;
278  }
279 
280  Fxu_MatrixForEachSingle( p, pSingle )
281  if ( pSingle->pVar1->iVar == iVar1C && pSingle->pVar2->iVar == iVar2C )
282  return pSingle;
283  return NULL;
284 }
285 
286 /**Function*************************************************************
287 
288  Synopsis []
289 
290  Description []
291 
292  SideEffects []
293 
294  SeeAlso []
295 
296 ***********************************************************************/
298 {
299 // int * pValue2Node = p->pValue2Node;
300  int piVarsC1[10], piVarsC2[10];
301  int nVarsC1, nVarsC2;
302  int iVar11, iVar12, iVar21, iVar22;
303  int iVar11C, iVar12C, iVar21C, iVar22C;
304  int RetValue;
305 
306  // get the variables of this double div
307  Fxu_MatrixGetDoubleVars( p, pDouble, piVarsC1, piVarsC2, &nVarsC1, &nVarsC2 );
308  assert( nVarsC1 == 2 && nVarsC2 == 2 );
309 
310  iVar11 = piVarsC1[0];
311  iVar12 = piVarsC1[1];
312  iVar21 = piVarsC2[0];
313  iVar22 = piVarsC2[1];
314  assert( iVar11 < iVar21 );
315 
316  iVar11C = Fxu_MatrixFindComplement( p, iVar11 );
317  iVar12C = Fxu_MatrixFindComplement( p, iVar12 );
318  iVar21C = Fxu_MatrixFindComplement( p, iVar21 );
319  iVar22C = Fxu_MatrixFindComplement( p, iVar22 );
320  if ( iVar11C == -1 || iVar12C == -1 || iVar21C == -1 || iVar22C == -1 )
321  return NULL;
322  if ( iVar11C != iVar21 || iVar12C != iVar22 ||
323  iVar21C != iVar11 || iVar22C != iVar12 )
324  return NULL;
325 
326  // a'b' + ab => a'b + ab'
327  // a'b + ab' => a'b' + ab
328  // swap the second pair in each cube
329  RetValue = piVarsC1[1];
330  piVarsC1[1] = piVarsC2[1];
331  piVarsC2[1] = RetValue;
332 
333  return Fxu_MatrixFindDouble( p, piVarsC1, piVarsC2, 2, 2 );
334 }
335 
336 
337 /**Function*************************************************************
338 
339  Synopsis []
340 
341  Description []
342 
343  SideEffects []
344 
345  SeeAlso []
346 
347 ***********************************************************************/
349 {
350  return iVar ^ 1;
351 /*
352 // int * pValue2Node = p->pValue2Node;
353  int iVarC;
354  int iNode;
355  int Beg, End;
356 
357  // get the nodes
358  iNode = pValue2Node[iVar];
359  // get the first node with the same var
360  for ( Beg = iVar; Beg >= 0; Beg-- )
361  if ( pValue2Node[Beg] != iNode )
362  {
363  Beg++;
364  break;
365  }
366  // get the last node with the same var
367  for ( End = iVar; ; End++ )
368  if ( pValue2Node[End] != iNode )
369  {
370  End--;
371  break;
372  }
373 
374  // if one of the vars is not binary, quit
375  if ( End - Beg > 1 )
376  return -1;
377 
378  // get the complements
379  if ( iVar == Beg )
380  iVarC = End;
381  else if ( iVar == End )
382  iVarC = Beg;
383  else
384  {
385  assert( 0 );
386  }
387  return iVarC;
388 */
389 }
390 
391 
392 /**Function*************************************************************
393 
394  Synopsis []
395 
396  Description []
397 
398  SideEffects []
399 
400  SeeAlso []
401 
402 ***********************************************************************/
404  int piVarsC1[], int piVarsC2[], int * pnVarsC1, int * pnVarsC2 )
405 {
406  Fxu_Pair * pPair;
407  Fxu_Lit * pLit1, * pLit2;
408  int nLits1, nLits2;
409 
410  // get the first pair
411  pPair = pDouble->lPairs.pHead;
412  // init the parameters
413  nLits1 = 0;
414  nLits2 = 0;
415  pLit1 = pPair->pCube1->lLits.pHead;
416  pLit2 = pPair->pCube2->lLits.pHead;
417  while ( 1 )
418  {
419  if ( pLit1 && pLit2 )
420  {
421  if ( pLit1->iVar == pLit2->iVar )
422  { // ensure cube-free
423  pLit1 = pLit1->pHNext;
424  pLit2 = pLit2->pHNext;
425  }
426  else if ( pLit1->iVar < pLit2->iVar )
427  {
428  piVarsC1[nLits1++] = pLit1->iVar;
429  pLit1 = pLit1->pHNext;
430  }
431  else
432  {
433  piVarsC2[nLits2++] = pLit2->iVar;
434  pLit2 = pLit2->pHNext;
435  }
436  }
437  else if ( pLit1 && !pLit2 )
438  {
439  piVarsC1[nLits1++] = pLit1->iVar;
440  pLit1 = pLit1->pHNext;
441  }
442  else if ( !pLit1 && pLit2 )
443  {
444  piVarsC2[nLits2++] = pLit2->iVar;
445  pLit2 = pLit2->pHNext;
446  }
447  else
448  break;
449  }
450  *pnVarsC1 = nLits1;
451  *pnVarsC2 = nLits2;
452 }
453 
454 
455 /**Function*************************************************************
456 
457  Synopsis []
458 
459  Description []
460 
461  SideEffects []
462 
463  SeeAlso []
464 
465 ***********************************************************************/
467  int piVarsC1[], int piVarsC2[], int nVarsC1, int nVarsC2 )
468 {
469  int piVarsC1_[100], piVarsC2_[100];
470  int nVarsC1_, nVarsC2_, i;
471  Fxu_Double * pDouble;
472  Fxu_Pair * pPair;
473  unsigned Key;
474 
475  assert( nVarsC1 > 0 );
476  assert( nVarsC2 > 0 );
477  assert( piVarsC1[0] < piVarsC2[0] );
478 
479  // get the hash key
480  Key = Fxu_PairHashKeyArray( p, piVarsC1, piVarsC2, nVarsC1, nVarsC2 );
481 
482  // check if the divisor for this pair already exists
483  Key %= p->nTableSize;
484  Fxu_TableForEachDouble( p, Key, pDouble )
485  {
486  pPair = pDouble->lPairs.pHead;
487  if ( pPair->nLits1 != nVarsC1 )
488  continue;
489  if ( pPair->nLits2 != nVarsC2 )
490  continue;
491  // get the cubes of this divisor
492  Fxu_MatrixGetDoubleVars( p, pDouble, piVarsC1_, piVarsC2_, &nVarsC1_, &nVarsC2_ );
493  // compare lits of the first cube
494  for ( i = 0; i < nVarsC1; i++ )
495  if ( piVarsC1[i] != piVarsC1_[i] )
496  break;
497  if ( i != nVarsC1 )
498  continue;
499  // compare lits of the second cube
500  for ( i = 0; i < nVarsC2; i++ )
501  if ( piVarsC2[i] != piVarsC2_[i] )
502  break;
503  if ( i != nVarsC2 )
504  continue;
505  return pDouble;
506  }
507  return NULL;
508 }
509 
510 
511 
512 
513 
514 /**Function*************************************************************
515 
516  Synopsis []
517 
518  Description []
519 
520  SideEffects []
521 
522  SeeAlso []
523 
524 ***********************************************************************/
525 int Fxu_SelectSCD( Fxu_Matrix * p, int WeightLimit, Fxu_Var ** ppVar1, Fxu_Var ** ppVar2 )
526 {
527 // int * pValue2Node = p->pValue2Node;
528  Fxu_Var * pVar1;
529  Fxu_Var * pVar2, * pVarTemp;
530  Fxu_Lit * pLitV, * pLitH;
531  int Coin;
532  int CounterAll;
533  int CounterTest;
534  int WeightCur;
535  int WeightBest;
536 
537  CounterAll = 0;
538  CounterTest = 0;
539 
540  WeightBest = -10;
541 
542  // iterate through the columns in the matrix
543  Fxu_MatrixForEachVariable( p, pVar1 )
544  {
545  // start collecting the affected vars
547 
548  // go through all the literals of this variable
549  for ( pLitV = pVar1->lLits.pHead; pLitV; pLitV = pLitV->pVNext )
550  {
551  // for this literal, go through all the horizontal literals
552  for ( pLitH = pLitV->pHNext; pLitH; pLitH = pLitH->pHNext )
553  {
554  // get another variable
555  pVar2 = pLitH->pVar;
556  CounterAll++;
557  // skip the var if it is already used
558  if ( pVar2->pOrder )
559  continue;
560  // skip the var if it belongs to the same node
561 // if ( pValue2Node[pVar1->iVar] == pValue2Node[pVar2->iVar] )
562 // continue;
563  // collect the var
564  Fxu_MatrixRingVarsAdd( p, pVar2 );
565  }
566  }
567  // stop collecting the selected vars
569 
570  // iterate through the selected vars
571  Fxu_MatrixForEachVarInRing( p, pVar2 )
572  {
573  CounterTest++;
574 
575  // count the coincidence
576  Coin = Fxu_SingleCountCoincidence( p, pVar1, pVar2 );
577  assert( Coin > 0 );
578 
579  // get the new weight
580  WeightCur = Coin - 2;
581 
582  // compare the weights
583  if ( WeightBest < WeightCur )
584  {
585  WeightBest = WeightCur;
586  *ppVar1 = pVar1;
587  *ppVar2 = pVar2;
588  }
589  }
590  // unmark the vars
591  Fxu_MatrixForEachVarInRingSafe( p, pVar2, pVarTemp )
592  pVar2->pOrder = NULL;
594  }
595 
596 // if ( WeightBest == WeightLimit )
597 // return -1;
598  return WeightBest;
599 }
600 
601 
602 ////////////////////////////////////////////////////////////////////////
603 /// END OF FILE ///
604 ////////////////////////////////////////////////////////////////////////
605 
606 
608 
void Fxu_HeapSingleInsert(Fxu_HeapSingle *p, Fxu_Single *pSingle)
Definition: fxuHeapS.c:204
Definition: fxuInt.h:213
Fxu_ListLit lLits
Definition: fxuInt.h:219
#define Fxu_MatrixForEachVarInRingSafe(Matrix, Var, Var2)
Definition: fxuInt.h:412
Fxu_Pair * pHead
Definition: fxuInt.h:117
static Llb_Mgr_t * p
Definition: llb3Image.c:950
int iVar
Definition: fxuInt.h:215
#define Fxu_MatrixRingVarsReset(Matrix)
Definition: fxuInt.h:392
Fxu_Single * Fxu_HeapSingleGetMax(Fxu_HeapSingle *p)
Definition: fxuHeapS.c:293
Fxu_Lit * pHead
Definition: fxuInt.h:109
Fxu_ListPair lPairs
Definition: fxuInt.h:260
#define Fxu_MatrixForEachVarInRing(Matrix, Var)
Definition: fxuInt.h:407
#define Fxu_MatrixForEachSingle(Matrix, Single)
Definition: fxuInt.h:312
int Fxu_SelectSCD(Fxu_Matrix *p, int WeightLimit, Fxu_Var **ppVar1, Fxu_Var **ppVar2)
Definition: fxuSelect.c:525
Fxu_Lit * pHNext
Definition: fxuInt.h:233
Fxu_Double * Fxu_HeapDoubleGetMax(Fxu_HeapDouble *p)
Definition: fxuHeapD.c:291
Fxu_Var * pVar2
Definition: fxuInt.h:273
Fxu_Lit * pVNext
Definition: fxuInt.h:235
static Fxu_Single * Fxu_MatrixFindComplementDouble2(Fxu_Matrix *p, Fxu_Double *pDouble)
Definition: fxuSelect.c:249
Fxu_Cube * pCube1
Definition: fxuInt.h:245
#define Fxu_MatrixForEachVariable(Matrix, Var)
Definition: fxuInt.h:303
unsigned Fxu_PairHashKeyArray(Fxu_Matrix *p, int piVarsC1[], int piVarsC2[], int nVarsC1, int nVarsC2)
Definition: fxuPair.c:137
#define Fxu_MatrixRingVarsStart(Matrix)
Definition: fxuInt.h:386
Fxu_ListLit lLits
Definition: fxuInt.h:206
#define ABC_NAMESPACE_IMPL_END
Definition: abc_global.h:108
#define MAX_SIZE_LOOKAHEAD
DECLARATIONS ///.
Definition: fxuSelect.c:28
#define Fxu_MatrixRingVarsAdd(Matrix, Var)
Definition: fxuInt.h:395
int nLits2
Definition: fxuInt.h:242
#define Fxu_TableForEachDouble(Matrix, Key, Div)
Definition: fxuInt.h:321
int iVar
Definition: fxuInt.h:228
#define ABC_NAMESPACE_IMPL_START
Definition: abc_global.h:107
Fxu_Double * Fxu_MatrixFindDouble(Fxu_Matrix *p, int piVarsC1[], int piVarsC2[], int nVarsC1, int nVarsC2)
Definition: fxuSelect.c:466
Fxu_Cube * pCube2
Definition: fxuInt.h:246
int Fxu_SingleCountCoincidence(Fxu_Matrix *p, Fxu_Var *pVar1, Fxu_Var *pVar2)
Definition: fxuSingle.c:241
static Fxu_Double * Fxu_MatrixFindComplementSingle(Fxu_Matrix *p, Fxu_Single *pSingle)
Definition: fxuSelect.c:222
Fxu_Var * pVar1
Definition: fxuInt.h:272
void Fxu_MatrixGetDoubleVars(Fxu_Matrix *p, Fxu_Double *pDouble, int piVarsC1[], int piVarsC2[], int *pnVarsC1, int *pnVarsC2)
Definition: fxuSelect.c:403
static int Fxu_MatrixFindComplement(Fxu_Matrix *p, int iVar)
Definition: fxuSelect.c:348
int Weight
Definition: fxuInt.h:258
int Weight
Definition: fxuInt.h:271
Fxu_Var * pVar
Definition: fxuInt.h:231
Fxu_Var * pOrder
Definition: fxuInt.h:222
void Fxu_HeapDoubleInsert(Fxu_HeapDouble *p, Fxu_Double *pDiv)
Definition: fxuHeapD.c:201
int Fxu_Select(Fxu_Matrix *p, Fxu_Single **ppSingle, Fxu_Double **ppDouble)
FUNCTION DEFINITIONS ///.
Definition: fxuSelect.c:57
#define Fxu_MatrixRingVarsStop(Matrix)
Definition: fxuInt.h:389
#define assert(ex)
Definition: util_old.h:213
int nLits1
Definition: fxuInt.h:241
typedefABC_NAMESPACE_HEADER_START struct FxuMatrix Fxu_Matrix
INCLUDES ///.
Definition: fxuInt.h:63
Definition: fxuInt.h:226
static Fxu_Double * Fxu_MatrixFindComplementDouble4(Fxu_Matrix *p, Fxu_Double *pDouble)
Definition: fxuSelect.c:297