[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

gEDA-user: Reeling over Reals



Hello again.

I'm completely confused.
Please bear with me.

I have defined with the VPI a task
that computes the square root
of a real input to produce a
real output.

The task is called $FloatSqrt and it
is defined thusly:

     static PLI_INT32 calltf_FloatSqrt(PLI_BYTE8* user)
     {
         vpiHandle   callHandle,
                     argHandles,
                     argHandle;

         s_vpi_value argValue;

         /* get input handle */
         callHandle = vpi_handle(vpiSysTfCall, 0);
         argHandles = vpi_iterate(vpiArgument, callHandle);
         argHandle  = vpi_scan(argHandles);

         /* get input value */
         argValue.format = vpiRealVal;
         vpi_get_value(argHandle, &argValue);

         /* compute square root */
         argValue.value.real = sqrt(argValue.value.real);

         /* get ouput handle */
         argHandle = vpi_scan(argHandles);

         /* set output value */
         vpi_put_value(argHandle, &argValue, 0, vpiNoDelay);

         /* free iterator */
         vpi_free_object(argHandles);

         return 0;
     }

I then make use of this somewhat as follows:

     module FloatSqrt
     (
         input clk,

         input  [63:0] arg1,

         output [63:0] result
     );

         parameter delay = 11;

         real resultReal;

         always @ (arg1) $FloatSqrt($bitstoreal(arg1), resultReal);

         Delay #(.delay(delay), .width(64)) delayResult
         (
             clk,
             $realtobits(resultReal1),
             result
         );

     endmodule

This compiles fine, but I get the following error when it is run:

     VCD info: dumpfile dump.vcd opened for output.
     ../../src/vvp/vpi_tasks.cc:580: failed assertion `vpi_mode_flag  
== VPI_MODE_NONE'
     Abort trap

So, I modified vpi_tasks.cc as follows:

     if (vpip_cur_task->defn->info.calltf) {
		printf("*%d*\n", vpi_mode_flag);
	    assert(vpi_mode_flag == VPI_MODE_CALLTF);
	    vpi_mode_flag = VPI_MODE_CALLTF;
	    vpip_cur_task->defn->info.calltf(vpip_cur_task->defn- 
 >info.user_data);
	    vpi_mode_flag = VPI_MODE_NONE;
       }

which shows that the problem occurs when vpi_mode_flag ==  
VPI_MODE_CALLTF.
Indeed, a further modification:

     if (vpip_cur_task->defn->info.calltf) {
		printf("*===>%s*\n", vpip_cur_task->defn->info.tfname);
	    assert(vpi_mode_flag == VPI_MODE_NONE);
	    vpi_mode_flag = VPI_MODE_CALLTF;
	    vpip_cur_task->defn->info.calltf(vpip_cur_task->defn- 
 >info.user_data);
		printf("*%s===>*\n", vpip_cur_task->defn->info.tfname);
	    vpi_mode_flag = VPI_MODE_NONE;
       }

reveals that $realtobits is being called before $FloatSqrt exits:

     *===>$realtobits*
     *$realtobits===>*
     *===>$dumpvars*
     VCD info: dumpfile dump.vcd opened for output.
     *$dumpvars===>*
     *===>$bitstoreal*
     *$bitstoreal===>*
     *===>$FloatSqrt*
     *===>$realtobits*
     ../../src/vvp/vpi_tasks.cc:581: failed assertion `vpi_mode_flag  
== VPI_MODE_NONE'
     Abort trap

Is this a threading issue?
In any case, I ran gdb and got this backtrace:

     #0  0x900484cc in kill ()
     #1  0x9012e934 in abort ()
     #2  0x0004d760 in __eprintf () at ../../src/vvp/vpi_memory.cc:333
     #3  0x00044ae0 in vpip_execute_vpi_call (thr=0x0, ref=0x0)  
at ../../src/vvp/vpi_tasks.cc:580
     #4  0x0002e318 in vvp_send_real (ptr=@0xbfffece0,  
val=1.7735839421916291) at ../../src/vvp/vvp_net.cc:184
     #5  0x0002e674 in vvp_fun_signal_real::recv_real (this=0x501ac0,  
ptr=@0xbfffed58, bit=1.7735839421916291) at ../../src/vvp/vvp_net.cc: 
1769
     #6  0x0002e318 in vvp_send_real (ptr=@0xbfffedc8,  
val=1.7735839421916291) at ../../src/vvp/vvp_net.cc:184
     #7  0x00042880 in real_var_put_value (ref=0x0, vp=0x0) at ../../ 
src/vvp/vpi_real.cc:76
     #8  0x00040c1c in vpi_put_value (obj=0x5017e0, vp=0xbfffee88,  
when=0xa0004170, flags=9994) at ../../src/vvp/vpi_priv.cc:618
     #9  0x002fcd94 in calltf_FloatSqrt (user=0x0) at FloatSqrt.c:58
     #10 0x00044b00 in vpip_execute_vpi_call (thr=0x0, ref=0x0)  
at ../../src/vvp/vpi_tasks.cc:582
     #11 0x0001c4b4 in of_VPI_CALL (thr=0x503160, cp=0x0) at ../../ 
src/vvp/vthread.cc:3286
     #12 0x0001b8a4 in vthread_run (thr=0x503160) at ../../src/vvp/ 
vthread.cc:330
     #13 0x000279cc in schedule_simulate () at ../../src/vvp/ 
schedule.cc:634
     #14 0x000047a8 in main (argc=6, argv=0xbffff200) at ../../src/ 
vvp/main.cc:279

However, the flow I was getting in the
debugger didn't make much sense to me.

I noticed that my verilog simulation
runs without error (but incorrectly)
when I remove from the VPI code either

     vpi_put_value(...)

or

     the second vpi_scan(...)

Yet, removing the latter simply
assigns the sqrt value to the input,
and even that doesn't actually occur,
because the input handle does not have
the proper put handler; the put is just
swallowed without warning.

Curiously, the problem is completely
bypassed when I unnecessarily assign
the output of $FloatSqrt to a temporary
variable and then use that temporary
variable as the input to delayResult.

     module FloatSqrt
     (
         input clk,

         input  [63:0] arg1,

         output [63:0] result
     );

         parameter delay = 11;

         real resultReal1, resultReal2;

         always @ (arg1)
             begin
                 $FloatSqrt($bitstoreal(arg1), resultReal1);
                 resultReal2 = resultReal1;
             end

         Delay #(.delay(delay), .width(64)) delayResult
         (
             clk,
             $realtobits(resultReal2),
             result
         );

     endmodule

How can I avoid these shenanigans?

Thanks.


_______________________________________________
geda-user mailing list
geda-user@moria.seul.org
http://www.seul.org/cgi-bin/mailman/listinfo/geda-user