add suport for the shortreal conversion functions
This commit is contained in:
parent
bc119f96a9
commit
b14c4ca26c
|
|
@ -0,0 +1,40 @@
|
||||||
|
module top;
|
||||||
|
// Test the shortreal conversion functions, but we don't support shortreal
|
||||||
|
// as a type yet so be safe with the actual values that are checked to
|
||||||
|
// avoid any real (double) to shortreal (float) rounding.
|
||||||
|
real in;
|
||||||
|
reg [31:0] irep;
|
||||||
|
real res;
|
||||||
|
reg passed;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
passed = 1'b1;
|
||||||
|
|
||||||
|
in = 0.0;
|
||||||
|
irep = $shortrealtobits(in);
|
||||||
|
res = $bitstoshortreal(irep);
|
||||||
|
if (in != res) begin
|
||||||
|
$display("Input and output value do not match (%f != %f)", in, res);
|
||||||
|
passed = 1'b0;
|
||||||
|
end
|
||||||
|
|
||||||
|
in = 8.0;
|
||||||
|
irep = $shortrealtobits(in);
|
||||||
|
res = $bitstoshortreal(irep);
|
||||||
|
if (in != res) begin
|
||||||
|
$display("Input and output value do not match (%f != %f)", in, res);
|
||||||
|
passed = 1'b0;
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
in = 0.125;
|
||||||
|
irep = $shortrealtobits(in);
|
||||||
|
res = $bitstoshortreal(irep);
|
||||||
|
if (in != res) begin
|
||||||
|
$display("Input and output value do not match (%f != %f)", in, res);
|
||||||
|
passed = 1'b0;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (passed) $display("PASSED");
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
|
@ -14,6 +14,8 @@ bits4 vvp_tests/bits4.json
|
||||||
bitsel11 vvp_tests/bitsel11.json
|
bitsel11 vvp_tests/bitsel11.json
|
||||||
br_gh13a vvp_tests/br_gh13a.json
|
br_gh13a vvp_tests/br_gh13a.json
|
||||||
br_gh13a-vlog95 vvp_tests/br_gh13a-vlog95.json
|
br_gh13a-vlog95 vvp_tests/br_gh13a-vlog95.json
|
||||||
|
br_gh99c vvp_tests/br_gh99c.json
|
||||||
|
br_gh99c-vlog95 vvp_tests/br_gh99c-vlog95.json
|
||||||
br_gh230 vvp_tests/br_gh230.json
|
br_gh230 vvp_tests/br_gh230.json
|
||||||
br_gh383a vvp_tests/br_gh383a.json
|
br_gh383a vvp_tests/br_gh383a.json
|
||||||
br_gh383b vvp_tests/br_gh383b.json
|
br_gh383b vvp_tests/br_gh383b.json
|
||||||
|
|
@ -21,8 +23,7 @@ br_gh383c vvp_tests/br_gh383c.json
|
||||||
br_gh383d vvp_tests/br_gh383d.json
|
br_gh383d vvp_tests/br_gh383d.json
|
||||||
br_gh440 vvp_tests/br_gh440.json
|
br_gh440 vvp_tests/br_gh440.json
|
||||||
br_gh939 vvp_tests/br_gh939.json
|
br_gh939 vvp_tests/br_gh939.json
|
||||||
br_gh99c vvp_tests/br_gh99c.json
|
br_gh1018 vvp_tests/br_gh1018.json
|
||||||
br_gh99c-vlog95 vvp_tests/br_gh99c-vlog95.json
|
|
||||||
ca_time_real` vvp_tests/ca_time_real.json
|
ca_time_real` vvp_tests/ca_time_real.json
|
||||||
case1 vvp_tests/case1.json
|
case1 vvp_tests/case1.json
|
||||||
case2 vvp_tests/case2.json
|
case2 vvp_tests/case2.json
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"type" : "normal",
|
||||||
|
"source" : "br_gh1018.v",
|
||||||
|
"iverilog-args" : [ "-g2005-sv" ]
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2003-2021 Michael Ruff (mruff at chiaro.com)
|
* Copyright (c) 2003-2023 Michael Ruff (mruff at chiaro.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -62,26 +62,70 @@ static void double2bits(double real, PLI_UINT32 bits[2])
|
||||||
conv.rval = real;
|
conv.rval = real;
|
||||||
|
|
||||||
#ifdef WORDS_BIGENDIAN
|
#ifdef WORDS_BIGENDIAN
|
||||||
bits[0] = conv.bval[7]
|
bits[0] = (conv.bval[7] << 0)
|
||||||
| (conv.bval[6] << 8)
|
| (conv.bval[6] << 8)
|
||||||
| (conv.bval[5] << 16)
|
| (conv.bval[5] << 16)
|
||||||
| (conv.bval[4] << 24);
|
| (conv.bval[4] << 24);
|
||||||
bits[1] = conv.bval[3]
|
bits[1] = (conv.bval[3] << 0)
|
||||||
| (conv.bval[2] << 8)
|
| (conv.bval[2] << 8)
|
||||||
| (conv.bval[1] << 16)
|
| (conv.bval[1] << 16)
|
||||||
| (conv.bval[0] << 24);
|
| (conv.bval[0] << 24);
|
||||||
#else
|
#else
|
||||||
bits[0] = conv.bval[0]
|
bits[0] = (conv.bval[0] << 0)
|
||||||
| (conv.bval[1] << 8)
|
| (conv.bval[1] << 8)
|
||||||
| (conv.bval[2] << 16)
|
| (conv.bval[2] << 16)
|
||||||
| (conv.bval[3] << 24);
|
| (conv.bval[3] << 24);
|
||||||
bits[1] = conv.bval[4]
|
bits[1] = (conv.bval[4] << 0)
|
||||||
| (conv.bval[5] << 8)
|
| (conv.bval[5] << 8)
|
||||||
| (conv.bval[6] << 16)
|
| (conv.bval[6] << 16)
|
||||||
| (conv.bval[7] << 24);
|
| (conv.bval[7] << 24);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static float bits2float(PLI_UINT32 bits)
|
||||||
|
{
|
||||||
|
union conv {
|
||||||
|
float rval;
|
||||||
|
unsigned char bval[sizeof(float)];
|
||||||
|
} conv;
|
||||||
|
|
||||||
|
#ifdef WORDS_BIGENDIAN
|
||||||
|
conv.bval[3] = (bits >> 0) & 0xff;
|
||||||
|
conv.bval[2] = (bits >> 8) & 0xff;
|
||||||
|
conv.bval[1] = (bits >> 16) & 0xff;
|
||||||
|
conv.bval[0] = (bits >> 24) & 0xff;
|
||||||
|
#else
|
||||||
|
conv.bval[0] = (bits >> 0) & 0xff;
|
||||||
|
conv.bval[1] = (bits >> 8) & 0xff;
|
||||||
|
conv.bval[2] = (bits >> 16) & 0xff;
|
||||||
|
conv.bval[3] = (bits >> 24) & 0xff;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return conv.rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void float2bits(float real, PLI_UINT32*bits)
|
||||||
|
{
|
||||||
|
union conv {
|
||||||
|
float rval;
|
||||||
|
unsigned char bval[sizeof(float)];
|
||||||
|
} conv;
|
||||||
|
|
||||||
|
conv.rval = real;
|
||||||
|
|
||||||
|
#ifdef WORDS_BIGENDIAN
|
||||||
|
*bits = (conv.bval[3] << 0)
|
||||||
|
| (conv.bval[2] << 8)
|
||||||
|
| (conv.bval[1] << 16)
|
||||||
|
| (conv.bval[0] << 24);
|
||||||
|
#else
|
||||||
|
*bits = (conv.bval[0] << 0)
|
||||||
|
| (conv.bval[1] << 8)
|
||||||
|
| (conv.bval[2] << 16)
|
||||||
|
| (conv.bval[3] << 24);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static void error_message(vpiHandle callh, const char* msg)
|
static void error_message(vpiHandle callh, const char* msg)
|
||||||
{
|
{
|
||||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||||
|
|
@ -97,6 +141,12 @@ static PLI_INT32 sizetf_64 (ICARUS_VPI_CONST PLI_BYTE8*name)
|
||||||
return 64;
|
return 64;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PLI_INT32 sizetf_32 (ICARUS_VPI_CONST PLI_BYTE8*name)
|
||||||
|
{
|
||||||
|
(void)name; /* Parameter is not used. */
|
||||||
|
return 32;
|
||||||
|
}
|
||||||
|
|
||||||
static PLI_INT32 sys_convert_compiletf(ICARUS_VPI_CONST PLI_BYTE8*name)
|
static PLI_INT32 sys_convert_compiletf(ICARUS_VPI_CONST PLI_BYTE8*name)
|
||||||
{
|
{
|
||||||
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
|
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
|
||||||
|
|
@ -112,11 +162,15 @@ static PLI_INT32 sys_convert_compiletf(ICARUS_VPI_CONST PLI_BYTE8*name)
|
||||||
/* In Icarus if we have an argv we have at least one argument. */
|
/* In Icarus if we have an argv we have at least one argument. */
|
||||||
arg = vpi_scan(argv);
|
arg = vpi_scan(argv);
|
||||||
|
|
||||||
/* Validate the argument. Only $bitstoreal for now. */
|
/* Validate the argument. Only $bitstoreal and $bitstoshortreal for now. */
|
||||||
if (!strcmp("$bitstoreal", name) && vpi_get(vpiSize, arg) != 64) {
|
if (!strcmp("$bitstoreal", name) && vpi_get(vpiSize, arg) != 64) {
|
||||||
error_message(callh, "%s requires a 64-bit argument.\n");
|
error_message(callh, "%s requires a 64-bit argument.\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if (!strcmp("$bitstoshortreal", name) && vpi_get(vpiSize, arg) != 32) {
|
||||||
|
error_message(callh, "%s requires a 32-bit argument.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Save the argument away to make the calltf faster. */
|
/* Save the argument away to make the calltf faster. */
|
||||||
vpi_put_userdata(callh, (void *) arg);
|
vpi_put_userdata(callh, (void *) arg);
|
||||||
|
|
@ -153,6 +207,31 @@ static PLI_INT32 sys_bitstoreal_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PLI_INT32 sys_bitstoshortreal_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
|
||||||
|
{
|
||||||
|
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
|
||||||
|
vpiHandle arg = (vpiHandle) vpi_get_userdata(callh);
|
||||||
|
s_vpi_value value;
|
||||||
|
|
||||||
|
PLI_UINT32 bits;
|
||||||
|
|
||||||
|
(void)name; /* Parameter is not used. */
|
||||||
|
|
||||||
|
/* get value */
|
||||||
|
value.format = vpiVectorVal;
|
||||||
|
vpi_get_value(arg, &value);
|
||||||
|
|
||||||
|
/* convert */
|
||||||
|
bits = (value.value.vector[0]).aval;
|
||||||
|
value.value.real = bits2float(bits);
|
||||||
|
value.format = vpiRealVal;
|
||||||
|
|
||||||
|
/* return converted value */
|
||||||
|
vpi_put_value(callh, &value, 0, vpiNoDelay);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static PLI_INT32 sys_itor_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
|
static PLI_INT32 sys_itor_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
|
||||||
{
|
{
|
||||||
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
|
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
|
||||||
|
|
@ -207,6 +286,36 @@ static PLI_INT32 sys_realtobits_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PLI_INT32 sys_shortrealtobits_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
|
||||||
|
{
|
||||||
|
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
|
||||||
|
vpiHandle arg = (vpiHandle) vpi_get_userdata(callh);
|
||||||
|
s_vpi_value value;
|
||||||
|
static struct t_vpi_vecval res[1];
|
||||||
|
|
||||||
|
PLI_UINT32 bits;
|
||||||
|
|
||||||
|
(void)name; /* Parameter is not used. */
|
||||||
|
|
||||||
|
/* get value */
|
||||||
|
value.format = vpiRealVal;
|
||||||
|
vpi_get_value(arg, &value);
|
||||||
|
|
||||||
|
/* convert */
|
||||||
|
float2bits(value.value.real, &bits);
|
||||||
|
|
||||||
|
res[0].aval = bits;
|
||||||
|
res[0].bval = 0;
|
||||||
|
|
||||||
|
value.format = vpiVectorVal;
|
||||||
|
value.value.vector = res;
|
||||||
|
|
||||||
|
/* return converted value */
|
||||||
|
vpi_put_value(callh, &value, 0, vpiNoDelay);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static PLI_INT32 sys_rtoi_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
|
static PLI_INT32 sys_rtoi_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
|
||||||
{
|
{
|
||||||
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
|
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
|
||||||
|
|
@ -258,6 +367,16 @@ void sys_convert_register(void)
|
||||||
res = vpi_register_systf(&tf_data);
|
res = vpi_register_systf(&tf_data);
|
||||||
vpip_make_systf_system_defined(res);
|
vpip_make_systf_system_defined(res);
|
||||||
|
|
||||||
|
tf_data.type = vpiSysFunc;
|
||||||
|
tf_data.sysfunctype = vpiRealFunc;
|
||||||
|
tf_data.user_data = "$bitstoshortreal";
|
||||||
|
tf_data.tfname = tf_data.user_data;
|
||||||
|
tf_data.sizetf = 0;
|
||||||
|
tf_data.compiletf = sys_convert_compiletf;
|
||||||
|
tf_data.calltf = sys_bitstoshortreal_calltf;
|
||||||
|
res = vpi_register_systf(&tf_data);
|
||||||
|
vpip_make_systf_system_defined(res);
|
||||||
|
|
||||||
tf_data.type = vpiSysFunc;
|
tf_data.type = vpiSysFunc;
|
||||||
tf_data.sysfunctype = vpiRealFunc;
|
tf_data.sysfunctype = vpiRealFunc;
|
||||||
tf_data.user_data = "$itor";
|
tf_data.user_data = "$itor";
|
||||||
|
|
@ -278,6 +397,16 @@ void sys_convert_register(void)
|
||||||
res = vpi_register_systf(&tf_data);
|
res = vpi_register_systf(&tf_data);
|
||||||
vpip_make_systf_system_defined(res);
|
vpip_make_systf_system_defined(res);
|
||||||
|
|
||||||
|
tf_data.type = vpiSysFunc;
|
||||||
|
tf_data.sysfunctype = vpiSizedFunc;
|
||||||
|
tf_data.user_data = "$shortrealtobits";
|
||||||
|
tf_data.tfname = tf_data.user_data;
|
||||||
|
tf_data.sizetf = sizetf_32;
|
||||||
|
tf_data.compiletf = sys_convert_compiletf;
|
||||||
|
tf_data.calltf = sys_shortrealtobits_calltf;
|
||||||
|
res = vpi_register_systf(&tf_data);
|
||||||
|
vpip_make_systf_system_defined(res);
|
||||||
|
|
||||||
tf_data.type = vpiSysFunc;
|
tf_data.type = vpiSysFunc;
|
||||||
tf_data.sysfunctype = vpiIntFunc;
|
tf_data.sysfunctype = vpiIntFunc;
|
||||||
tf_data.user_data = "$rtoi";
|
tf_data.user_data = "$rtoi";
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue