 # Writing / reading unsigned long long using double channel

## Recommended Posts

I tried to write and read an unsigned long long value over a double channel, using a double value as starting point.

Code snippet:

double d = 3.1415926535897931;

unsigned long long * ullp = (unsigned long long *) &d;

out_port.write(*ullp); // sc_out<double> out_port; connected via sc_signal<double> to in_port

unsigned long long ull = in_port.read(); // sc_in<double> in_port; connected via sc_signal<double> to out_port

double * dp = (double *) &ull;

When I print the values of d, *ullp, ull and *dp, I notice the following:

d:     3.1415926535897931;

*ullp: 4614256656552045848;

ull:   4614256656552045568;

*dp:   3.1415926535896688;

However, plain casting without SystemC (double d -> ull* ullp = (ull*) &d -> ull u = *ullp -> double* dp = (double*) &u -> double d2 = *dp) returns d2 with exactly the same value as d.

Any idea what is happening and why the channel of type double seems to loose a bit of its precision when using it in this way?

--

greetz,

Bas

##### Share on other sites

Hi Bas,

Did you mean to say:

double d = 3.1415926535897931;

unsigned long long * ullp = (unsigned long long *) &d;

out_port.write(*ullp); // sc_out<doubleunsigned long long> out_port; connected via sc_signal<doubleunsigned long long> to in_port

unsigned long long ull = in_port.read(); // sc_in<doubleunsigned long long> in_port; connected via sc_signal<doubleunsigned long long> to out_port

double * dp = (double *) &ull;

Also, what is the output of sizeof(double) and sizeof(unsigned long long) in your case?

##### Share on other sites

Hi Karthick,

Thanks for your reply. I did mean sc_out<double> out_port and sc_in<double> in_port, because I was deliberately using a double channel.

The sizeof() operator returns 8 both for double and unsigned long long on my system.

In the meantime, I found that it is not related to SystemC anyway:

double d = 3.1415926535897931;

unsigned long long *ullp = (unsigned long long *) &d;

unsigned long long ull = *ullp; // ull = 4614256656552045848

double d2 = (double) ull; // d2 = 4614256656552045568.0000000000000000 !!

unsigned long long ull2 = (unsigned long long) d2; // ull2 = 4614256656552045568

double * dp = (double *) &ull2; // *dp = 3.1415926535896688

Hence, the casting of an unsigned long long to a double seems to cause the problem.

--

greetz,

Bas

##### Share on other sites

Hi Bas,

In trying to explain this a bit more, I looked up the double format. As per http://en.wikipedia.org/wiki/Double-precision_floating-point_format, the 8-byte double format can handle 15-17 significant decimal digits without loss of precision.

When assigning,

double d2 = (double) ull;

the width of ull (4614 2566 5655 2045 848) is 19 significant decimal digits, which causes loss in precision.

##### Share on other sites

Hi,

as you mentioned before, casting values is the problem here. If you want to keep the bit representation independent from the data types, you have to rely on casting pointers.

```unsigned long long ull = in_port.read();
```

This line converts the value and changes the bit representation.

```double d = in_port.read();
unsigned long long * ullp = (unsigned long long *)&d;
unsigned long long ull = *ullp;
```

Should work in the same way as before when you did write to the out port.

Greetings

Ralph

##### Share on other sites

I tried to write and read an unsigned long long value over a double channel, using a double value as starting point.

Code snippet:

double d = 3.1415926535897931;

unsigned long long * ullp = (unsigned long long *) &d;

out_port.write(*ullp); // sc_out<double> out_port; connected via sc_signal<double> to in_port

unsigned long long ull = in_port.read(); // sc_in<double> in_port; connected via sc_signal<double> to out_port

double * dp = (double *) &ull;

When I print the values of d, *ullp, ull and *dp, I notice the following:

d:     3.1415926535897931;

*ullp: 4614256656552045848;

ull:   4614256656552045568;

*dp:   3.1415926535896688;

However, plain casting without SystemC (double d -> ull* ullp = (ull*) &d -> ull u = *ullp -> double* dp = (double*) &u -> double d2 = *dp) returns d2 with exactly the same value as d.

Any idea what is happening and why the channel of type double seems to loose a bit of its precision when using it in this way?

--

greetz,

Bas

Hello Sir,

Have you considered the possibility of using bit vectors of sizes specified by

you, instead of using 'long long' etc., After all, in a real world hardware, all

numbers are stored as bit vectors, so although it might appear somewhat

of a low-level approach, it would be far more intuitive, and there would not

be any of the casting issues that you face. Hope that helps.

##### Share on other sites

Basic question: Why are you not just using a port that carries doubles? When modeling, you can assign timing independent of what the data format is. I make the presumption that you are doing high-level modeling rather than RTL.

If your answer is to store it in a memory model that uses unsigned long long int or as its base type, then you should consider:

```// C++ program to test using unsigned long long int to carry data across a connection
#include <iostream>
#include <cassert>
using namespace std;
int main() {

bool success = true; // innocent until proven otherwise

typedef unsigned long long int  data_t; //< generic definition of the data passed over port
assert(sizeof(double)<=sizeof(data_t)); //< ensure it is big enough

for (size_t i=0; i!=1000; ++i) {
// Create a random number
double xmit_double = double(random())/double(1<<(random()%32));

data_t& xmit_data = reinterpret_cast<data_t&>(xmit_double);

// Send the data to the "other" end
data_t  recv_data = xmit_data;

double& recv_double = reinterpret_cast<double&>(recv_data);

success &= (recv_double == xmit_double);
}
cout << (success?"PASSED":"FAILED") << endl;
return success?0:1;
}
```

## Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible. ×   Pasted as rich text.   Paste as plain text instead

Only 75 emoji are allowed.

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×

×