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:
Stephen Williams 2008-01-19 16:27:09 -08:00
parent ea1f448300
commit 32d3e5ac46
3 changed files with 70 additions and 8 deletions

View File

@ -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:

View File

@ -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);

View File

@ -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; }