Is Partial Record Assignment Possible?

S

Sudoer

I often use records within records, or records within records within
records, ad nausea. It's nice that I can currently do the following:

A.A.A <= X;
A.A.B <= Y;
A.A.C <= Z;

However, there's a lot of repetition in my code, so I often prefer the
following:

A <= ( A => ( A => X,
B => Y,
C => Z ) );

The benefit is more noticeable with long and descriptive names for the
elements, but the problem is that if my intention is to set only the
A, B, and C leaf elements and leave any others unchanged it doesn't
seem possible. Is there anything in the 2002 or 2008 standard that
allows this, is there any reason this shouldn't be allowed, or is it
time that I propose an overloaded use of the keyword unaffected, or
another keyword all together (unchanged/same/handsoff?)

A <= ( A => ( A => X,
B => Y,
C => Z,
D => UNAFFECTED ) );

A <= ( A => ( A => X,
B => Y,
C => Z,
OTHERS => UNAFFECTED ) );

Obviously it would be useful for slices as well.

Since I haven't been able to play with 2008 yet, I'm wondering if left-
side aggregates (not sure what they're called) would also simplify the
above. Thanks!
 
S

Sudoer

Funny, I would have expected

A.A <= ( A => X,
                    B => Y,
                    C => Z );
or even

A.A <= (X,Y,Z) ;

to do the job.

- Brian

Me too - in fact that was what I tried first. However, I get the
following error when using XST:

ERROR:HDLCompiler:790 - "*REDACTED*" Line 78: Some record elements are
missing in this aggregate of A_TYPE

Perhaps this is an XST thing and not a VHDL thing? Can anyone else get
the above to work using different synthesis software?
 
S

Sudoer

Ahhh, THAT old problem.  The process in which you assign any elements of
an aggregate signal (record, array, etc) has to be the one in which you
assign all of the elements of it.

Well, that too is annoying, but I'm not quite seeing how that's
related to the behavior I'm taking exception to today. I simply do not
want to change the values of some elements in a record, only
sometimes, and when assigning to the whole record. Frequently this
will happen in some case statement - for some when's I want to assign
some values, and for others I want to assign other values. If I assign
to individual elements of a record I have no issue, but when I try to
assign to the record itself it requires that I provide a value for
every element.

I'll admit right now that what I'm asking for here is pure swizzle-
stick syntax sugar, but the difference between a language like C++ or
Ada and a language like BF is exactly pure swizzle-stick syntax sugar
(who needs named variables anyway?) I've found that unmanageable code
tends to crop up most often when I have to do a lot of copying and
pasting - this issue alone has caused me to create a new emacs macro
that does nothing but copy the character directly above the point
(cursor) to the point, but I do have my macro and so I'll survive if
no one agrees with me that this would be a nice VHDL feature in future
standards, or if no one can point out to me how to do it in any
existing standard...
 
J

Jonathan Bromley

I often use records within records, or records within records within
records, ad nausea. It's nice that I can currently do the following:

A.A.A <= X;
A.A.B <= Y;
A.A.C <= Z;

However, there's a lot of repetition in my code, so I often prefer the
following:

A <= ( A => ( A => X,
B => Y,
C => Z ) );

The benefit is more noticeable with long and descriptive names for the
elements, but the problem is that if my intention is to set only the
A, B, and C leaf elements and leave any others unchanged it doesn't
seem possible.

How about an alias?

alias AA: ABC_record_type is A.A;
...
AA.A <= X;

Doesn't quite do what you asked for (I don't think that's
possible) but it does simplify the naming problem somewhat.

Functions and procedures might be useful too:
procedure tweakJustTheLeafParts(signal T: inout ABC_record_type) is
begin
T.A <= X;
...
end;
...
tweakJustTheLeafParts(A.A); -- does A.A.A <= X;

Watch out for multiple drivers, though, as Rob Gaddi points out.
 
J

Jonathan Bromley

I often use records within records, or records within records within
records, ad nausea. It's nice that I can currently do the following:

A.A.A <= X;
A.A.B <= Y;
A.A.C <= Z;

However, there's a lot of repetition in my code, so I often prefer the
following:

A <= ( A => ( A => X,
B => Y,
C => Z ) );

The benefit is more noticeable with long and descriptive names for the
elements, but the problem is that if my intention is to set only the
A, B, and C leaf elements and leave any others unchanged it doesn't
seem possible.

How about an alias?

alias AA: ABC_record_type is A.A;
...
AA.A <= X;

Doesn't quite do what you asked for (I don't think that's
possible) but it does simplify the naming problem somewhat.

Functions and procedures might be useful too:
procedure tweakJustTheLeafParts(signal T: inout ABC_record_type) is
begin
T.A <= X;
...
end;
...
tweakJustTheLeafParts(A.A); -- does A.A.A <= X;

Watch out for multiple drivers, though, as Rob Gaddi points out.
 
S

Sudoer

Neither aliasing nor use of a function quite capture what I want to
do, if only because they require more code just assigning to each
subelement now. The idea is to assign to some, but not all elements,
without writing additional code to do so, in a single assignment
statement. It also occurs to me that this could reduce the number of
signal assignments in total (depending on how the EDA tool author
implements it, and it at least serves as an obvious clue to the
compiler), which is always a good thing for simulation run times. A
very good thing.
 
J

Jonathan Bromley

The idea is to assign to some, but not all elements,
without writing additional code to do so, in a single assignment
statement.

And, as you correctly surmise, the language has (as far
as I know) no direct way to allow you to do that. You
can, of course, use part of the original record in the
aggregate expression:

A <= (X=>55, Y=>'1', Z=>A.Z);

but that still forces you to write out every element
somewhere in the aggregate. I'm sure you can see why
OTHERS=>UNCHANGED is problematic, because the aggregate
doesn't know that it is going to be assigned to A, and
so the aggregate can no longer be just an expression of
the record type; it needs also to incorporate a bunch of
"don't-write" flags. And what would be the meaning
of OTHERS=>UNCHANGED if the aggregate were to appear
in a context other than simple assignment?

So your original question changes from being a
language-syntax problem to being an application problem:
how can you design your data (and code infrastructure)
to do what you want in the clearest possible way?

Your requirement is to update a set of (possibly sub-)
record elements in the cleanest, most concise possible
way. For a single element it's obviously very easy,
and minimally verbose:
R1.R2.R3.E <= value;
But how do you plan to choose your set of record elements,
and what drives that choice? If you have just a small
number of distinct sets of elements, then I would argue
that writing one "update this set" procedure per set of
elements is by far the neatest approach. If, however,
the set of elements you want to update is more fluid,
then I perhaps question your choice of simple records as
an implementation vehicle. Of course, records have the
huge advantage of supporting elements of heterogeneous
data type, so the choice may not be quite so simple;
but I would still argue that the problem is one of
data structure design.
It also occurs to me that this could reduce the number of
signal assignments in total (depending on how the EDA tool author
implements it, and it at least serves as an obvious clue to the
compiler),

Maybe. But I don't see this as a strong argument
in favour of adding a language feature.

On the other hand, your arguments from code conciseness
do seem to me to have some value. But there are many
things that would come way higher up my VHDL wish-list.
 
J

Jonathan Bromley

So your original question changes from being a
language-syntax problem to being an application problem:

A quick postscript: You *can* use OTHERS=> in a
record aggregate, BUT this only works if all the
elements specified by OTHERS are of the same type.
My guess is that this is no use to you, because
your record elements are of various types; and
if the record elements are all of the same type,
then it's probably easier to use an array anyhow.
But I thought I'd mention it because it might
make certain approaches possible in some special
situations.
 
S

Sudoer

Jonathan Bromley pretty much nailed it, I was just looking for code
clarity and conciseness, and in my case I do plan to use many variants
in terms of which subelements I assign to. The code I started this
topic while writing would need five different functions to do the
partial assignments.

Sometimes I forget that VHDL has a formal syntactic definition that
causes even small changes like I suggested to have large consequences.
That said, one way to do this would be to have "OTHERS =>
UNAFFECTED" (or UNCHANGED - I'm not sure of the policy of overloading
keywords, or of introducing keywords that are very likely to be in
existing code...) simply mean that each element "assigned" UNAFFECTED
would be assigned it's current value. This does away with the "bit-
flag" problem.

As I'm a bit of a VHDL neophyte I was more hoping an expert would
point out that I was missing an obvious way to do this more than I was
hoping to propose a feature which would take years to ratify, further
years to implement, and even innumerable years to make it into
synthesis tools.
 
M

Mike Treseler

Jonathan Bromley pretty much nailed it, I was just looking for code
clarity and conciseness, and in my case I do plan to use many variants
in terms of which subelements I assign to. The code I started this
topic while writing would need five different functions to do the
partial assignments.

I also prefer structures with descriptive element names -- if the
dimensions are small enough that words don't confuse the issue.
In this case, an array of records, where the array index is a type
enumeration, often does the trick for me.
As I'm a bit of a VHDL neophyte I was more hoping an expert would
point out that I was missing an obvious way to do this more than I was
hoping to propose a feature which would take years to ratify, further
years to implement, and even innumerable years to make it into
synthesis tools.

On the other hand, a question without an obvious answer is interesting.

-- Mike Treseler
 
J

Jonathan Bromley

one way to do this would be to have "OTHERS => UNAFFECTED"
simply mean that each element "assigned" UNAFFECTED
would be assigned it's current value. This does away with the "bit-
flag" problem.

As we all agree, this discussion is academic anyway, but....

It doesn't "do away with" any such problem. In a simple
assignment TARGET:=(some aggregate), the notion of "its current
value" makes some sense (although it would be a new idea in
VHDL for a right-hand-side expression to obtain values from
an assignment target). But I'm at a loss even to guess what
UNAFFECTED might mean in any other context - for example,
if you were passing the aggregate to a function as an
input argument.

There are other peripheral problems too.
Should the UNAFFECTED assignment cause a transaction on
the unaffected elements of a record signal?

I do agree, though, that it is exceedingly tedious that
you can't write a record aggregate with only a few of
its elements specified, leaving the others with their
default values. In fact, that would open the door to
some neat approaches to solving your problem. But you
can't do it, so I won't waste my time and yours by
describing how it might be done!

cheers

Jonathan Bromley
 
J

Jonathan Bromley

I often use records within records, or records within records within
records, ad nausea. It's nice that I can currently do the following:

A.A.A <= X;
A.A.B <= Y;
A.A.C <= Z;

However, there's a lot of repetition in my code, so I often prefer the
following:

A <= ( A => ( A => X,
B => Y,
C => Z ) );

The benefit is more noticeable with long and descriptive names for the
elements, but the problem is that if my intention is to set only the
A, B, and C leaf elements and leave any others unchanged it doesn't
seem possible.

How about an alias?

alias AA: ABC_record_type is A.A;
...
AA.A <= X;

Doesn't quite do what you asked for (I don't think that's
possible) but it does simplify the naming problem somewhat.

Functions and procedures might be useful too:
procedure tweakJustTheLeafParts(signal T: inout ABC_record_type) is
begin
T.A <= X;
...
end;
...
tweakJustTheLeafParts(A.A); -- does A.A.A <= X;

Watch out for multiple drivers, though, as Rob Gaddi points out.
 
J

Jonathan Bromley

On Sat, 30 Jul 2011 14:59:57 +0100, Jonathan Bromley

..... sent a long-dead post by mistake. Sorry, please ignore.
 

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

Forum statistics

Threads
473,996
Messages
2,570,237
Members
46,825
Latest member
VernonQuy6

Latest Threads

Top