使用数值而不是指针作为函数参数[英] using values instead of pointers as function arguments

本文是小编为大家收集整理的关于使用数值而不是指针作为函数参数的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

我有这个函数"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 中运行时,您的方法(在最后一段中)效果很好.但是,当我使用 Xilinx SDSoC 在 FPGA 上合成"cost_compare"时,它仅适用于

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',我相信问题可能是用硬件综合工具解决.

亲切的问候霍曼

推荐答案

在 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;
    }

本文地址:https://www.itbaoku.cn/post/2090989.html

问题描述

I have this function "cost_compare" that I would like to offload on FPGA for some experimental purposes. This function, how it is called and its arguments are as follows.

The synthesis tool doesn't accept double pointers as arguments for HW functions (in fact it is very picky about using pointers especially to data structures).

How do I get rid of the pointers in the function argument list? In other words, how do I convert pointers in this example to values? How does this possible solution affect the call by reference performed by spec_qsort?

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

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

Thanks @Gerardo Zinno. When I run in SW, your approach (in the last paragraph) works fine. However, when I synthesis 'cost_compare' on FPGA using Xilinx SDSoC, it only works for

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

but not for

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

and the tools gives me this error:

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).'

Also when called by 'qsort' as

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

I receive this warning:

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

I know this error has nothing to do with C programming but if there is any way to get rid of 'b1->a->id' and 'b2->a->id', I believe the problem could be solved with the HW synthesis tool.

Kind regards Hooman

推荐答案

In the int cost_compare( BASKET **b1, BASKET **b2 ) you don't need double pointers since you are just comparing elements and not swapping anything. (In fact notice that you aren't using b1 directly, but you're always dereferencing it)

Just change the function signature to int cost_compare( BASKET *b1, BASKET *b2 ). In the function's body change every (*b1)->abs_const to b1->abs_const.

Also, since spec_qsort expects a function with signature int compare (void *, void *), you could get rid of this cast "(int (*)(const void *, const void *)) cost_compare)" , change the signature of cost_compare to an appropriate one and cast the arguments inside the function, like this:

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;
}

and then call spec_qsort(perm + 1, basket_sizes[thread], sizeof(BASKET*), cost_compare), in this way everything is easier to read.

EDIT: To answer to one point of the last edit you made, change cost_compare to :

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;
    }