У меня есть эта функция "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.
С уважением, Хуман
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;
}
Поскольку функция 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)
Похожие вопросы
Новые вопросы
c
C - это язык программирования общего назначения, используемый для системного программирования (ОС и встраиваемых), библиотек, игр и кроссплатформенности. Этот тег следует использовать с общими вопросами, касающимися языка C, как это определено в стандарте ISO 9899 (последняя версия 9899: 2018, если не указано иное, а также для запросов, специфичных для версии, с c89, c99, c11 и т. Д.). C отличается от C ++ и не должен сочетаться с тэгом C ++ без разумной причины.