From: Martin W. <ic...@ma...> - 2019-10-14 21:03:41
|
I have pushed a fix for the second part of this. Note that you need to create a SFT file to inform the compiler about the different return value and provide the compiler with the path to the VPI module and associated SFT file, e.g. % cat br_ml20191013.sft $pow vpiSysFuncSized 32 signed % iverilog-vpi br_ml20191013.c Compiling br_ml20191013.c... Making br_ml20191013.vpi from br_ml20191013.o... % iverilog -m ./br_ml20191013 br_ml20191013.v % a.out $pow PLI compiletf function. $pow StartOfSim callback. Start simulation pow_test.v $pow(2,3) returns 8 $pow PLI calltf function. $pow(a,b) returns 1 (a=1 b=0) If you don't provide an explicit path, the compiler only searches for VPI modules and their associated SFT files in the iverilog base directory. This is now documented in the iverilog man page. Martin Whitaker wrote: > Hi Yong, > > My apologies. I looked in the test suite for something to adapt to > reproduce the problem, found that, and didn't read it carefully enough! > > If the compiler detects that a system function has constant arguments, it > will try to evaluate it at compile time, using a built-in implementation. > That is why your first call works. We should fix that. > > The second call fails because the compiler is using the return type for the > built-in implementation (real) rather than the return type of the > replacement (32 bits). There is supposed to be a method of fixing that, by > suppling the compiler with a ".sft" file that provides the return types of > user-defined system functions, but that also appears to be broken in this > case. I'll look into that. > > Martin > > > On 14/10/19 08:23, fuyong wrote: >> Hi, Martin, >> >> Finally figure out the reason. In the original example, the 1999 version I >> have, intention of the test is to override the system defined function, >> such as $pow. In your example, you used $my_pow() instead. Guess that in >> Iverilog, system defined function calls could not be overwritten yet. >> Actually I did noticed in my test with $pow(), the first $pow() called the >> system pre-defined function, the second one goes to user defined function. >> This is why the first $pow() passed, and the second one get error. >> >> The version I have is: >> version 11.0 (devel) (s20150603-641-ga8318db2) >> >> Many thanks for the help! >> >> Yong >> >> >> >> On Sun, Oct 13, 2019 at 2:29 AM Martin Whitaker < >> ic...@ma...> wrote: >> >>> I can't reproduce the failure. We have that example in the test suite >>> already - see >>> >>> https://github.com/steveicarus/ivtest/blob/master/vpi/pr1693971.c >>> https://github.com/steveicarus/ivtest/blob/master/vpi/pr1693971.v >>> >>> Please tell us what version of iverilog you are using, and what changes >>> you >>> have made to the example. Just changing the type of 'result' to 'int' made >>> no difference for me. >>> >>> fuyong wrote: >>>> Hi, >>>> >>>> This is a test in Stuart Sutherland's PLI handbook, and it works well >>> with >>>> commercial tools. In Iverilog, we can have compile done, but run time >>> show: >>>> >>>> $pow(2, 3) returns 8 >>>> Unsupported format 6. >>>> vvp: vpi_tasks.cc:179:virtual __vpiHandle* >>>> sysfunc_real::vpi_put_value(p_vpi_value, int): Assertion `0` failed. >>>> >>>> There are two $pow() calls .First one returns correct result, second one >>>> failed. with vpi_print, we find seems like the first pow() did not even >>>> called our defined function (might be using the $pow in build-in >>> $pow()?). >>>> Any way, "result" is defined as int, not sure why the assertion is >>> trigger >>>> in run time. >>>> >>>> >>>> >>>> === Verilog side: >>>> initial >>>> begin >>>> a = 1; >>>> b = 0; >>>> #1 $display("$pow(2,3) returns %d", $pow(2,3)); >>>> #1 result = $pow(a,b); >>>> #1 $display("$pow(a,b) returns %d (a=%d b=%d)", result, a, b); >>>> >>>> === C side: >>>> >>>> tf_data.type = vpiSysFunc; >>>> tf_data.sysfunctype = vpiSysFuncSized; >>>> tf_data.tfname = "$pow"; >>>> tf_data.calltf = PLIbook_PowCalltf; >>>> tf_data.compiletf = PLIbook_PowCompiletf; >>>> tf_data.sizetf = PLIbook_PowSizetf; >>>> vpi_register_systf(&tf_data); >>>> >>>> >>>> int PLIbook_PowCalltf(char *user_data) >>>> { >>>> s_vpi_value value_s; >>>> vpiHandle systf_handle, arg_itr, arg_handle; >>>> int base, exp, result; >>>> >>>> systf_handle = vpi_handle(vpiSysTfCall, NULL); >>>> arg_itr = vpi_iterate(vpiArgument, systf_handle); >>>> if (arg_itr == NULL) { >>>> vpi_printf("ERROR: $pow failed to obtain systf arg handles\n"); >>>> return(0); >>>> } >>>> >>>> /* read base from systf arg 1 (compiletf has already verified) */ >>>> arg_handle = vpi_scan(arg_itr); >>>> value_s.format = vpiIntVal; >>>> vpi_get_value(arg_handle, &value_s); >>>> base = value_s.value.integer; >>>> >>>> /* read exponent from systf arg 2 (compiletf has already verified) */ >>>> arg_handle = vpi_scan(arg_itr); >>>> vpi_free_object(arg_itr); /* not calling scan until returns null */ >>>> vpi_get_value(arg_handle, &value_s); >>>> exp = value_s.value.integer; >>>> >>>> /* calculate result of base to power of exponent */ >>>> result = (int)pow( (double)base, (double)exp ); >>>> >>>> /* write result to simulation as return value $pow */ >>>> value_s.value.integer = result; >>>> vpi_put_value(systf_handle, &value_s, NULL, vpiNoDelay); >>>> return(0); >>>> } >>>> >>>> >>>> >>>> >>>> >>>> _______________________________________________ >>>> Iverilog-devel mailing list >>>> Ive...@li... >>>> https://lists.sourceforge.net/lists/listinfo/iverilog-devel >>>> >>> >>> >>> >>> _______________________________________________ >>> Iverilog-devel mailing list >>> Ive...@li... >>> https://lists.sourceforge.net/lists/listinfo/iverilog-devel >>> >> >> >> >> >> >> _______________________________________________ >> Iverilog-devel mailing list >> Ive...@li... >> https://lists.sourceforge.net/lists/listinfo/iverilog-devel >> > > > > _______________________________________________ > Iverilog-devel mailing list > Ive...@li... > https://lists.sourceforge.net/lists/listinfo/iverilog-devel |