Использование значений вместо указателей в качестве аргументов функции

У меня есть эта функция «cost_compare», которую я хотел бы разгрузить на FPGA для некоторых экспериментальных целей. Эта функция, как она вызывается и ее аргументы следующие.

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

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

заранее спасибо Хуман

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];
        }
    }
/* ... */

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

Спасибо @Gerardo Zinno. Когда я запускаю 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.

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

Какой "инструмент синтеза"?

Keith Thompson 31.05.2019 03:44

Замените BASKET **b1, BASKET **b2 любым (*b1)->abs_cost, (*b2)->abs_cost. (например, cost_t cost1, cost_t cost2, а затем сравнить cost1 < cost2 и т. д.) Для начала нет необходимости передавать адрес указателя в эту функцию.

David C. Rankin 31.05.2019 04:33

В сторону: финал return -1; кажется неправильным. Я ожидал return ((*b1)->a->id < (*b2)->a->id )) ? -1 : 0;

chux - Reinstate Monica 31.05.2019 06:54
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
3
183
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 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 вам, вероятно, нужно также рассмотреть случай, когда b1 и b2 равны, и сделать так, чтобы функция возвращала 0.

Gerardo Zinno 31.05.2019 04:06

Спасибо, но код взят из SPEC CPU 2006, RoutePlanning.

Hooman 03.06.2019 01:50

Я попробовал решение @Gerardo Zinno и включил результаты в конец своего вопроса.

Hooman 04.06.2019 04:32

@Hooman попробуйте добавить теги пылинки к вопросу, чтобы сделать его видимым для людей, специализирующихся в этой области. А еще лучше задайте еще вопрос только по новым ошибкам

Gerardo Zinno 04.06.2019 04:40

Поскольку функция 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)

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

Gerardo Zinno 04.06.2019 15:21

@GerardoZinno Итак, вы говорите, что вызов const_compare в spec_qsort нельзя изменить?

Stuart 06.06.2019 02:11

Он может передать любую функцию, которую он хочет spec_qsort, если функция имеет правильную сигнатуру, как обычная qsort из C. Это тип параметра последнего аргумента spec_qsort int (*compar)(const void *, const void *), и вы не можете передать функцию с другая подпись.

Gerardo Zinno 06.06.2019 03:06

Другие вопросы по теме