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>
|
||||
#endif
|
||||
# include <stdlib.h>
|
||||
# include <math.h>
|
||||
# include <string.h>
|
||||
# include <inttypes.h>
|
||||
# include <assert.h>
|
||||
|
|
@ -468,6 +469,42 @@ static char* draw_C8_to_string(ivl_net_const_t cptr,
|
|||
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
|
||||
* 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;
|
||||
|
||||
case IVL_VT_REAL:
|
||||
{ char tmp[256];
|
||||
snprintf(tmp, sizeof(tmp),
|
||||
"Cr<%lg>", ivl_const_real(cptr));
|
||||
result = strdup(tmp);
|
||||
}
|
||||
result = draw_Cr_to_string(cptr);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -815,14 +815,43 @@ void input_connect(vvp_net_t*fdx, unsigned port, char*label)
|
|||
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)
|
||||
&& ((tp = strchr(label,'>')))
|
||||
&& (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;
|
||||
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);
|
||||
free(label);
|
||||
|
|
|
|||
|
|
@ -199,7 +199,7 @@
|
|||
assert(yylval.text);
|
||||
return T_SYMBOL; }
|
||||
|
||||
"Cr<"[.$_a-zA-Z0-9/,\-]*">" {
|
||||
"Cr<m"[a-f0-9]*"x"[a-f0-9]*">" {
|
||||
yylval.text = strdup(yytext);
|
||||
assert(yylval.text);
|
||||
return T_SYMBOL; }
|
||||
|
|
|
|||
Loading…
Reference in New Issue