Better formatting of Cr<> label for real valued drivers.
Rework the encoding of a real value in the Cr<> label to be similar to the format used by the %loadi/wr instruction. This mantissa-expoment format better carries all the bits of the desired real value with plenty of fidelity and range.
This commit is contained in:
parent
ea1f448300
commit
32d3e5ac46
|
|
@ -22,6 +22,7 @@
|
||||||
# include <malloc.h>
|
# include <malloc.h>
|
||||||
#endif
|
#endif
|
||||||
# include <stdlib.h>
|
# include <stdlib.h>
|
||||||
|
# include <math.h>
|
||||||
# include <string.h>
|
# include <string.h>
|
||||||
# include <inttypes.h>
|
# include <inttypes.h>
|
||||||
# include <assert.h>
|
# include <assert.h>
|
||||||
|
|
@ -468,6 +469,42 @@ static char* draw_C8_to_string(ivl_net_const_t cptr,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char* draw_Cr_to_string(ivl_net_const_t cptr)
|
||||||
|
{
|
||||||
|
char tmp[256];
|
||||||
|
|
||||||
|
double value = ivl_const_real(cptr);
|
||||||
|
uint64_t mant = 0;
|
||||||
|
|
||||||
|
if (isinf(value)) {
|
||||||
|
if (value > 0)
|
||||||
|
snprintf(tmp, sizeof(tmp), "Cr<m0g3fff>");
|
||||||
|
else
|
||||||
|
snprintf(tmp, sizeof(tmp), "Cr<m0g7fff>");
|
||||||
|
return strdup(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sign = 0;
|
||||||
|
if (value < 0) {
|
||||||
|
sign = 0x4000;
|
||||||
|
value *= -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int expo;
|
||||||
|
double fract = frexp(value, &expo);
|
||||||
|
fract = ldexp(fract, 63);
|
||||||
|
mant = fract;
|
||||||
|
expo -= 63;
|
||||||
|
|
||||||
|
int vexp = expo + 0x1000;
|
||||||
|
assert(vexp >= 0);
|
||||||
|
assert(vexp < 0x2000);
|
||||||
|
vexp += sign;
|
||||||
|
|
||||||
|
snprintf(tmp, sizeof(tmp), "Cr<m%" PRIx64 "g%x>", mant, vexp);
|
||||||
|
return strdup(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function takes a nexus and looks for an input functor. It then
|
* This function takes a nexus and looks for an input functor. It then
|
||||||
* draws to the output a string that represents that functor. What we
|
* draws to the output a string that represents that functor. What we
|
||||||
|
|
@ -604,11 +641,7 @@ static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IVL_VT_REAL:
|
case IVL_VT_REAL:
|
||||||
{ char tmp[256];
|
result = draw_Cr_to_string(cptr);
|
||||||
snprintf(tmp, sizeof(tmp),
|
|
||||||
"Cr<%lg>", ivl_const_real(cptr));
|
|
||||||
result = strdup(tmp);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
|
|
@ -815,14 +815,43 @@ void input_connect(vvp_net_t*fdx, unsigned port, char*label)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Handle the Cr<> constant driver, which is a real-value
|
||||||
|
driver. The format is broken into mantissa and
|
||||||
|
exponent. The exponent in turn includes a sign bit.
|
||||||
|
|
||||||
|
The mantissa is a 64bit integer value (encoded in hex).
|
||||||
|
|
||||||
|
The exponent included the sign bit (0x4000) and the binary
|
||||||
|
exponent offset by 0x1000. The actual exponent is the
|
||||||
|
encoded exponent - 0x1000.
|
||||||
|
|
||||||
|
The real value is sign * (mant ** exp). */
|
||||||
if ((strncmp(label, "Cr<", 3) == 0)
|
if ((strncmp(label, "Cr<", 3) == 0)
|
||||||
&& ((tp = strchr(label,'>')))
|
&& ((tp = strchr(label,'>')))
|
||||||
&& (tp[1] == 0)
|
&& (tp[1] == 0)
|
||||||
&& (strspn(label+3, "0123456789.-e")+3 == (unsigned)(tp-label))) {
|
&& (strspn(label+3, "0123456789abcdefmg")+3 == (unsigned)(tp-label))) {
|
||||||
|
|
||||||
|
char*cp = label+3;
|
||||||
|
assert(*cp == 'm');
|
||||||
|
cp += 1;
|
||||||
|
uint64_t mant = strtoull(cp, &cp, 16);
|
||||||
|
assert(*cp == 'g');
|
||||||
|
cp += 1;
|
||||||
|
int exp = strtoul(cp, 0, 16);
|
||||||
|
|
||||||
double tmp;
|
double tmp;
|
||||||
|
if (mant == 0 && exp == 0x3fff) {
|
||||||
|
tmp = INFINITY;
|
||||||
|
} else if (mant == 0 && exp == 0x7fff) {
|
||||||
|
tmp = -INFINITY;
|
||||||
|
} else if (exp == 0x3fff) {
|
||||||
|
tmp = nan("");
|
||||||
|
} else {
|
||||||
|
double sign = (exp & 0x4000)? -1.0 : 1.0;
|
||||||
|
exp &= 0x1fff;
|
||||||
|
|
||||||
sscanf(label+3, "%lg", &tmp);
|
tmp = sign * ldexp((double)mant, exp - 0x1000);
|
||||||
|
}
|
||||||
|
|
||||||
schedule_set_vector(ifdx, tmp);
|
schedule_set_vector(ifdx, tmp);
|
||||||
free(label);
|
free(label);
|
||||||
|
|
|
||||||
|
|
@ -199,7 +199,7 @@
|
||||||
assert(yylval.text);
|
assert(yylval.text);
|
||||||
return T_SYMBOL; }
|
return T_SYMBOL; }
|
||||||
|
|
||||||
"Cr<"[.$_a-zA-Z0-9/,\-]*">" {
|
"Cr<m"[a-f0-9]*"x"[a-f0-9]*">" {
|
||||||
yylval.text = strdup(yytext);
|
yylval.text = strdup(yytext);
|
||||||
assert(yylval.text);
|
assert(yylval.text);
|
||||||
return T_SYMBOL; }
|
return T_SYMBOL; }
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue