implementation approach ..

M

ma740988

The member variable addr2 -below- is the address received from a
_vendor_ function (not shown). For discussion purposes lets assume the
address is 0xCFF44000

The code:

typedef unsigned int UINT32;
#define LLSB(x) ((x) & 0xff)
#define LNLSB(x) (((x) >> 8) & 0xff)
#define LNMSB(x) (((x) >> 16) & 0xff)
#define LMSB(x) (((x) >> 24) & 0xff)

UINT32 LongSwap(UINT32 x) {
return (LLSB(x) << 24) |
(LNLSB(x) << 16) |
(LNMSB(x) << 8) | LMSB(x);
}

struct Register {
operator UINT32() {
return *reinterpret_cast<uint32_t *>(this);
}
void set(UINT32 n) {
*reinterpret_cast<uint32_t *>(this)=LongSwap(n);
}
};

// register2 is comprised of two 16 bit values..
struct register2 : public Register{
UINT32 start_vec : 16;
UINT32 stop_vec : 16;
};

// later

UINT32 Bar2Addr;
UINT32 *cReg2Addr;
register2* reg2;

STATUS initialize()
{
STATUS stat;
UINT32 addr2 = 0xCFF44000;

cReg2Addr = (UINT32 *)addr2;
cReg2Addr += 4;
reg2 = (register2*)cReg2Addr ; // map reg2 pointer to addr2
}

void write_to_reg2(
unsigned short val1,
unsigned short val2
)
{
register2 reg;
reg.start_vec = val1;
reg.stop_vec = val2;
reg2->set(UINT32(reg)); // write val1 and val2 to address but first
endian conversion..
}

Prior to modifying the contents of the address (cReg2Addr) provided, I
must perform an endian conversion (hence the longSwap). The question.
Am I on the right track as far as my approach?

Thanks in advance.
 
V

Victor Bazarov

The member variable addr2 -below- is the address received from a
_vendor_ function (not shown). For discussion purposes lets assume
the address is 0xCFF44000

The code:

typedef unsigned int UINT32;

I take it you also need (or assume)

typedef UINT32 uint32_t;
#define LLSB(x) ((x) & 0xff)
#define LNLSB(x) (((x) >> 8) & 0xff)
#define LNMSB(x) (((x) >> 16) & 0xff)
#define LMSB(x) (((x) >> 24) & 0xff)

UINT32 LongSwap(UINT32 x) {
return (LLSB(x) << 24) |
(LNLSB(x) << 16) |
(LNMSB(x) << 8) | LMSB(x);
}

struct Register {
operator UINT32() {
return *reinterpret_cast<uint32_t *>(this);

This is nonsense. You're extracting a 'uint32_t' from something
that is _not_ a 'uint32_t'. Your program has undefined behaviour.
}
void set(UINT32 n) {
*reinterpret_cast<uint32_t *>(this)=LongSwap(n);
}

Your struct Register does not have any memory where you could store
the 'uint32_t' value you get from LongSwap. If you retinterpret_cast
'this' to 'uint32_t*', the storage won't appear from thin air. You
need at least a non-static member variable large enough to contain
a 'uint32_t' value. Hence I have a question: why not have a member
_of_type_ 'uint32_t' and not bother casting anything?

void set(UINT32 n) {
mem_var = LongSwap(n);
}

uint32_t mem_var;

And, of course, the operator UIN32() should look like this:

operator UINT32() const { return mem_var; }

No 'reinterpret_cast' bullshit.
};

// register2 is comprised of two 16 bit values..
struct register2 : public Register{
UINT32 start_vec : 16;
UINT32 stop_vec : 16;
};

// later

UINT32 Bar2Addr;
UINT32 *cReg2Addr;
register2* reg2;

STATUS initialize()
{
STATUS stat;
UINT32 addr2 = 0xCFF44000;

cReg2Addr = (UINT32 *)addr2;

Using C-style cast where you _really_ need 'reinterpret_cast' is
rather strange. Use the proper constructs where they are due.
cReg2Addr += 4;
reg2 = (register2*)cReg2Addr ; // map reg2 pointer to addr2

Again, a C-style cast. Why?
}

void write_to_reg2(
unsigned short val1,
unsigned short val2
)
{
register2 reg;
reg.start_vec = val1;
reg.stop_vec = val2;
reg2->set(UINT32(reg)); // write val1 and val2 to address but first
endian conversion..
}

Prior to modifying the contents of the address (cReg2Addr) provided, I
must perform an endian conversion (hence the longSwap). The question.
Am I on the right track as far as my approach?

What's the ultimate goal? I have to be honest with you, I am losing
track because of all those C-style casts and reinterpret_casts applied
so freely and without merit. And why do you need to perform an endian
conversion on an address? That's something I've never heard of.

V
 
M

ma740988

Hola, Victor,

|| typedef UINT32 uint32_t;
My apologies... All uni32_t should reflect UINT32.

void set(UINT32 n) {
mem_var = LongSwap(n);
}

|| uint32_t mem_var;
|| And, of course, the operator UIN32() should look like this:
|| operator UINT32() const { return mem_var; }
|| No 'reinterpret_cast' bullshit.

Quite vocal there with the use of 'bull..' but I get the point.

|| What's the ultimate goal?

Well here's a synopsis of the current approach. ...... Recall that the
member variable addr2 is obtained from a vendor function. So now

typedef unsigned int UINT32;
UINT32 Bar2Addr;
UINT32 *cReg2Addr;

bool initialize()
{
UINT32 addr2 = 0xCFF44000; // well assume addr2 is 0xCFF44000
cReg2Addr = (UINT32 *)addr2;
cReg2Addr += 4; // at this point cReg2Addr is
'alive and well'.
}

// later
void write_to_reg2(UINT32 start_vec, UINT32 stop_vec)
{
UINT32 reg2;
reg2 = start_vec & 0xffff;
reg2 |= ((stop_vec + start_vec) & 0xffff) <<16;

*cReg2Addr = LongSwap (reg2); // [1] Write a 32 bit value to the
'address'.
// First we must
LongSwap the value because of endian differences..
}

The line inidicated by [1] will set the address with the desired 'start
and stop' vector values. Before I do that I must convert the value
prior to writing the value to the address. In effect, I have a local
variable (reg2) which gets converted then the converted value gets
written to/stored at cReg2Addr. This approach works but becomes a real
pain in the rear. The shifting and anding is enough to make my head
spin.

The 'documentation' has a defintion for register2. So why not do:
struct register2 {
unsigned int start_vec;
unsigned int stop_vec;
};

Within the initialize function. I could now do:
register2 *ptr_reg2;

bool initialize()
{
UINT32 addr2 = 0xCFF44000;
cReg2Addr = (UINT32 *)addr2;
cReg2Addr += 4;

ptr_reg2 = (register2*)cReg2Addr; // watch this line... Just map
the struct (register2) definition to the address.
// I suspect
placement new would work here but that's seems like overkill
}

The write_to_reg2 function then becomes:

void write_to_reg2(UINT32 start_vec, UINT32 stop_vec)
{
register2 reg;
reg.start_vec = start_vec;
reg.stop_vec = stop_vec;

//ptr_reg2 = reg;
}

The commented out line above brings up an interesting dilema. I must
first LongSwap (reg) then assign it to ptr_reg2, hence my previous
solution which I suspect is convoluted. Your thougths.
Thanks Vic.
 
V

Victor Bazarov

Hola, Victor,
Well here's a synopsis of the current approach. ...... Recall that
the member variable addr2 is obtained from a vendor function. So
now

typedef unsigned int UINT32;
UINT32 Bar2Addr;
UINT32 *cReg2Addr;

bool initialize()
{
UINT32 addr2 = 0xCFF44000; // well assume addr2 is 0xCFF44000
cReg2Addr = (UINT32 *)addr2;
cReg2Addr += 4; // at this point cReg2Addr is
'alive and well'.
}

// later
void write_to_reg2(UINT32 start_vec, UINT32 stop_vec)
{
UINT32 reg2;
reg2 = start_vec & 0xffff;
reg2 |= ((stop_vec + start_vec) & 0xffff) <<16;

*cReg2Addr = LongSwap (reg2); // [1] Write a 32 bit value to the
'address'.
// First we must
LongSwap the value because of endian differences..
}

This particular thing makes me shudder. If you get an address, it's
gotta be for the same system. If it's for the same system, how can
it have different endian-ness? And if it's not from the same system,
why is _an address_ passed around?

If it's not an address, then why are you treating it as one?
The line inidicated by [1] will set the address with the desired
'start and stop' vector values.

So, it _is_ an address? Is this whole thing an emulator of some kind?
Before I do that I must convert the
value prior to writing the value to the address. In effect, I have a
local variable (reg2) which gets converted then the converted value
gets written to/stored at cReg2Addr. This approach works but becomes
a real pain in the rear. The shifting and anding is enough to make
my head spin.

The 'documentation' has a defintion for register2. So why not do:
struct register2 {
unsigned int start_vec;
unsigned int stop_vec;
};

Within the initialize function. I could now do:
register2 *ptr_reg2;

Why a _pointer_? This is another part where you lose me.
bool initialize()
{
UINT32 addr2 = 0xCFF44000;
cReg2Addr = (UINT32 *)addr2;
cReg2Addr += 4;

You're adding _16_ bytes offset here. Is that intentional?
ptr_reg2 = (register2*)cReg2Addr; // watch this line... Just map
the struct (register2) definition to the address.
// I suspect
placement new would work here but that's seems like overkill
}

The write_to_reg2 function then becomes:

void write_to_reg2(UINT32 start_vec, UINT32 stop_vec)
{
register2 reg;
reg.start_vec = start_vec;
reg.stop_vec = stop_vec;

//ptr_reg2 = reg;
}

The commented out line above brings up an interesting dilema. I must
first LongSwap (reg) then assign it to ptr_reg2, hence my previous
solution which I suspect is convoluted. Your thougths.

I've really got none. First, it's too late on Sunday night. Second,
if you got it to work, leave it. If it doesn't work, then start to
worry. 'Nough thinking. Time to go to bed.

V
 
M

ma740988

|| Is this whole thing an emulator of some kind?
Part of this, I suspect is my terminology is all over the place. What
it amounts to is I have an address that's mapped across PCI space. The
address that I'm writing to is _really_ an FPGA address (the
documentation calls it register). The vendor function (not shown in
my earlier posts) returns to me the address. So in my local memory I
'fiddle with things'. I LongSwap (becasue of endian differences) the
value then update the contents of the FPGA address/register.


Thanks Vic. You gave me some clues.. I could certainly simply the
register struct to rid/eliminate the reinterpret_casts. As always I
tend to over do it with all the reinterpret_cast mayhem i was doing.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top