Is Partial Record Assignment Possible?

S

Sudoer

Guest
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!
 
On Fri, 6 Aug 2010 10:34:38 -0700 (PDT), Sudoer <TheProperNoun@psychophile.com>
wrote:

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.
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
 
On 8/6/2010 2:28 PM, Sudoer wrote:
On Aug 6, 3:33 pm, Brian Drummond<brian_drumm...@btconnect.com
wrote:
On Fri, 6 Aug 2010 10:34:38 -0700 (PDT), Sudoer<TheProperN...@psychophile.com
wrote:





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.

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?
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.

--
Rob Gaddi, Highland Technology
Email address is currently out of order
 
On Fri, 6 Aug 2010 10:34:38 -0700 (PDT), Sudoer
<TheProperNoun@psychophile.com> wrote:

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.
--
Jonathan Bromley
 
On Fri, 6 Aug 2010 10:34:38 -0700 (PDT), Sudoer
<TheProperNoun@psychophile.com> wrote:

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.
--
Jonathan Bromley
 
On Fri, 6 Aug 2010 14:28:47 -0700 (PDT), Sudoer <TheProperNoun@psychophile.com>
wrote:

On Aug 6, 3:33 pm, Brian Drummond <brian_drumm...@btconnect.com
wrote:
On Fri, 6 Aug 2010 10:34:38 -0700 (PDT), Sudoer <TheProperN...@psychophile.com
wrote:

However, there's a lot of repetition in my code, so I often prefer the
following:
A <= ( A => ( A => X,
                   B => Y,
                   C => Z ) );
...if my intention is to set only the
A, B, and C leaf elements and leave any others unchanged it doesn't
seem possible.

Funny, I would have expected
A.A <= (X,Y,Z) ;
to do the job.

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
First : if Modelsim accepts it, it's probably an XST-ism. If not, I have learned
something about VHDL today...

Maybe it's possible to work around the problem using a function?
(or set of functions, overloaded by different parameters)

e.g.
A <= new_A (A, partA => (X,Y,Z));

function new_A (A : in A_type; partA : in partial_A_type) return A_type is
variable temp_A := A;
begin
temp_A.A := partA;
return temp;
end new_A;

- Brian
 
On Aug 6, 3:33 pm, Brian Drummond <brian_drumm...@btconnect.com>
wrote:
On Fri, 6 Aug 2010 10:34:38 -0700 (PDT), Sudoer <TheProperN...@psychophile.com
wrote:





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.

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?
 
On Aug 6, 5:34 pm, Rob Gaddi <rga...@technologyhighland.com> wrote:
On 8/6/2010 2:28 PM, Sudoer wrote:





On Aug 6, 3:33 pm, Brian Drummond<brian_drumm...@btconnect.com
wrote:
On Fri, 6 Aug 2010 10:34:38 -0700 (PDT), Sudoer<TheProperN...@psychophile.com
wrote:

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.

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?

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.

--
Rob Gaddi, Highland Technology
Email address is currently out of order
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...
 
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.
 
On Sat, 7 Aug 2010 10:30:41 -0700 (PDT), Sudoer wrote:

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.
--
Jonathan Bromley
 
On Sun, 08 Aug 2010 12:04:00 +0100, Jonathan Bromley wrote:

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.
--
Jonathan Bromley
 
On Sat, 7 Aug 2010 10:30:41 -0700 (PDT), Sudoer <TheProperNoun@psychophile.com>
wrote:

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.
As Jonathan points out, you can use a full assignment, re-using parts of the
original record, to replace the partial assignment. It looks complex and
confusing - as you say, by adding additional code - but it gets the job jone.

A function can encapsulate that partial assignment via full assignment into a
single - very clean - statement at the point of use, thus making your intention
clear to the reader.

What I don't understand is your objection to using a function because of the
additional code necessary.

The two frequent objections are that a larger program is more complex and harder
to understand; and that adding code increases resource use and decreases
performance.

Using a function, the additional code is written once, and hidden in a package,
so does not interfere with program clarity or understanding. If you have several
patterns of selective update, the package contains several equally simple
functions. They can share a name, overloaded by different parameter types; or
have different names; whichever makes your intent clearer.

The functions will not synthesise to extra hardware; they are just shorthand for
their contents (inlined during synthesis, if you prefer). During simulation, you
may actuallly be able to measure a small increase in simulation time but I'd be
surprised if it was more than a couple of percent.

So I don't believe your objection is either of these - perhaps you can clarify?

- Brian
 
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.
 
On 8/8/2010 5:50 PM, Sudoer wrote:
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
 
On Aug 9, 1:50 am, Sudoer wrote:
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
 
On Fri, 6 Aug 2010 10:34:38 -0700 (PDT), Sudoer
<TheProperNoun@psychophile.com> wrote:

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.
--
Jonathan Bromley
 
On Sat, 30 Jul 2011 14:59:57 +0100, Jonathan Bromley

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


On Fri, 6 Aug 2010 10:34:38 -0700 (PDT), Sudoer
TheProperNoun@psychophile.com> wrote:

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.
 

Welcome to EDABoard.com

Sponsor

Back
Top