У меня есть эта функция "cost_compare", которую я хотел бы разгрузить на ПЛИС для некоторых экспериментальных целей. Эта функция, как она называется, и ее аргументы таковы.

Инструмент синтеза не принимает двойные указатели в качестве аргументов для функций HW (на самом деле он очень требователен к использованию указателей, особенно к структурам данных).

Как избавиться от указателей в списке аргументов функции? Другими словами, как мне преобразовать указатели в этом примере в значения? Как это возможное решение влияет на вызов по ссылке, выполняемый spec_qsort?

Заранее спасибо Hooman

typedef struct arc *arc_p;
typedef LONG cost_t;

typedef struct basket
{
    arc_t *a;
    cost_t cost;
    cost_t abs_cost;
    LONG number;
} BASKET;
/* ... */
typedef struct arc
{
    int id;
    cost_t cost;
    node_p tail, head;
    short ident;
    arc_p nextout, nextin;
    flow_t flow;
    cost_t org_cost;
} arc;
/* ... */
extern int cost_compare( BASKET **b1, BASKET **b2 );
/* ... */
int cost_compare( BASKET **b1, BASKET **b2 )
{
    if( (*b1)->abs_cost < (*b2)->abs_cost )
        return 1;
    if( (*b1)->abs_cost > (*b2)->abs_cost )
        return -1;
    if( (*b1)->a->id > (*b2)->a->id )
        return 1;
    else
        return -1;
}
/* ... */
spec_qsort(perm + 1, basket_sizes[thread], sizeof(BASKET*),
           (int (*)(const void *, const void *))cost_compare);
/* ... */
BASKET* max, *act;
for (j = 1; j < num_threads; j++) {
    act = *perm_p[j];
    if (act->number >= 0) {
        if (!max || cost_compare(&act, &max) < 0) {
            max = act;
            max_pos = j;
        }
    }
    /* ... */
    BASKET*     max_basket;
    static BASKET    **opt_basket;

    for (i = 0; i< num_threads; i++) {
        if ((!max_basket && opt_basket[i]) || (opt_basket[i] && 
                                               cost_compare(&opt_basket[i], &max_basket) < 0)) {
            max_basket = opt_basket[i];
        }
    }
/* ... */

=========================================

Спасибо @ Герардо Зинно. Когда я запускаю в SW, ваш подход (в последнем абзаце) работает нормально. Однако, когда я синтезирую 'cost_compare' на FPGA с использованием Xilinx SDSoC, он работает только для

if(b1->abs_cost < b2->abs_cost)

Но не для

if( b1->a->id > b2->a->id )

И инструменты дают мне эту ошибку:

ERROR: [SYNCHK 200-61] /home/a1083898/Xilinx_examples/original_routeplanning/src/pbeampp.c:85: unsupported memory access on variable 'x' which is (or contains) an array with unknown size at compile time.

ERROR: [SYNCHK 200-41] /home/a1083898/Xilinx_examples/original_routeplanning/src/pbeampp.c:89: unsupported pointer reinterpretation from type 'i8*' to type '%struct.arc.1.4.6 = type { i32, i64, %struct.node.0.3.5*, %s...' on variable 'x'.

ERROR: [SYNCHK 200-11] /home/a1083898/Xilinx_examples/original_routeplanning/src/pbeampp.c:89: Argument 'x' has an unsynthesizable type 'i8*' (possible cause(s): pointer to pointer or global pointer).

ERROR: [SYNCHK 200-11] /home/a1083898/Xilinx_examples/original_routeplanning/src/pbeampp.c:89: Argument 'x' has an unsynthesizable type 'i8*' (possible cause(s): structure variable cannot be decomposed due to (1) unsupported type conversion; (2) memory copy operation; (3) function pointer used in struct; (4) unsupported pointer comparison).'

Также когда вызывается 'qsort' как

qsort(perm + 1, basket_sizes[thread], sizeof(BASKET*), cost_compare); 

Я получаю это предупреждение:

warning: incompatible pointer types passing 'int (void *, void *)' to parameter of type '__compar_fn_t' (aka 'int (*)(const void *, const void *)') [-Wincompatible-pointer-types]

Я знаю, что эта ошибка не имеет ничего общего с программированием на C, но если есть какой-либо способ избавиться от 'b1-> a-> id' и 'b2-> a-> id', я считаю, что проблему можно решить с помощью Инструмент синтеза HW.

С уважением, Хуман

3
Hooman 31 Май 2019 в 04:33

2 ответа

Лучший ответ

В int cost_compare( BASKET **b1, BASKET **b2 ) вам не нужны двойные указатели, поскольку вы просто сравниваете элементы и ничего не меняете местами. (На самом деле обратите внимание, что вы не используете b1 напрямую, но вы всегда разыменовываете его)

Просто измените сигнатуру функции на int cost_compare( BASKET *b1, BASKET *b2 ). В теле функции измените каждый (*b1)->abs_const на b1->abs_const.

Кроме того, поскольку spec_qsort ожидает функцию с подписью int compare (void *, void *), вы можете избавиться от этого приведения "(int (*) (const void *, const void *)) cost_compare)", измените подпись cost_compare к соответствующему и приведите аргументы внутри функции, например так:

int cost_compare( void *a, void *b ){
 BASKET *b1 = a;
 BASKET *b2 = b;
 if(b1->abs_cost < b2->abs_cost){
   return 1;
 }
 ...
 else return -1;
}

И затем вызовите spec_qsort(perm + 1, basket_sizes[thread], sizeof(BASKET*), cost_compare), таким образом все будет легче читать.

РЕДАКТИРОВАТЬ: Чтобы ответить на один момент последнего внесенного вами изменения, измените cost_compare на:

int cost_compare( const void *a, const void *b ){
     BASKET b1 = *(BASKET *)a;
     BASKET b2 = *(BASKET *)b;
     if(b1.abs_cost < b2.abs_cost){
       return 1;
     }
     ...
     if(*(b1.a).id > *(b2.a).id)
         return 1;
     else return -1;
    }
2
Gerardo Zinno 4 Июн 2019 в 02:58

Поскольку функция cost_compare просто сравнивает abs_cost и id, почему бы вам не передать их напрямую, как это.

int cost_compare(cost_t abs_cost1, int id1, cost_t abs_cost2, int id2)
{
    if( abs_cost1 < abs_cost2 )
        return 1;
    if( abs_cost1 > abs_cost2 )
        return -1;
    if( id1 > id2 )
        return 1;
    else
        return -1;
}

А потом ты называешь это так

const_compare(act->abs_cost, act->a->id, max->abs_cost, max->a->id)
0
Stuart 4 Июн 2019 в 03:46