Help with synthesis optimizing away one of my bits

L

longbrmb

I am working on a project where synthesis of my design is claiming
that a bit is unused and I'm assuming is optimizing it away. I'm not
sure it is actually being optimized away because the design has timing
problems in another area, so I am unable to test it. But my
experience has been that if a synthesis tool says that something is
unused and you know it isn't, then problems are going to happen :).
First I'll post the relevant section:

-- Not the real declarations, but these are needed to understand the
code below.
signal highbit : unsigned(3 downto 0);
constant inBits : positive := 10;
constant outBits : positive := 4;
...........

architecture behavior of bitselector_1 is
type bit_sel_array is array (0 to inBits - outBits) of
signed(outBits-2 downto 0);
signal bit_selections : bit_sel_array;
begin

............

-- Select the appropriate range of bits based on highbit
process(bit_selections, highbit) is
variable subset_sel : integer range 0 to inBits - outBits;
begin
subset_sel := to_integer(highbit - (outBits-1));
output(outBits-2 downto 0) <= bit_selections(subset_sel);
end process;

............

end behavior;



I'm using an older version of Synplify Pro (8.1). It claims that
highbit(3) is unused. Now my guess is that it looks at the
bit_selections array and sees that there are only 7 elements, meaning
only 3-bits are needed to address the array. Since highbit is 4-bits
wide, it assumes that the most significant bit is unnecessary. The
problem is that highbit ranges from 3 to 9, which means that all four
bits are necessary. The tool doesn't realize that the input is 4-
bits, but is reduced to 3-bits by the subtraction to create
subset_sel.

I'm looking for the best way to modify this so that the tool does not
optimize away necessary hardware. The first thing that popped in my
mind was to modify the array to range from 3 to 9 instead of 0 to 6.
This would eliminate the need for subtraction and highbit could be
used directly. The downside that I see is that you now have a 4-bit
address instead of a 3-bit. Ideally, I would want a 4-bit subtracter
that subtracts 3 from highbit and then only the lower 3 bits are used
to address. I tried this solution once in simulation, but ran into
trouble because highbit is unknown at the beginning of the simulation,
which causes to_integer to return 0, which is outside the range of the
array.

Does my solution make sense and does anyone have any better ideas?

Thanks,
Matt
 
D

Dave

I am working on a project where synthesis of my design is claiming
that a bit is unused and I'm assuming is optimizing it away. I'm not
sure it is actually being optimized away because the design has timing
problems in another area, so I am unable to test it. But my
experience has been that if a synthesis tool says that something is
unused and you know it isn't, then problems are going to happen :).
First I'll post the relevant section:

-- Not the real declarations, but these are needed to understand the
code below.
signal highbit : unsigned(3 downto 0);
constant inBits : positive := 10;
constant outBits : positive := 4;
..........

architecture behavior of bitselector_1 is
type bit_sel_array is array (0 to inBits - outBits) of
signed(outBits-2 downto 0);
signal bit_selections : bit_sel_array;
begin

...........

-- Select the appropriate range of bits based on highbit
process(bit_selections, highbit) is
variable subset_sel : integer range 0 to inBits - outBits;
begin
subset_sel := to_integer(highbit - (outBits-1));
output(outBits-2 downto 0) <= bit_selections(subset_sel);
end process;

...........

end behavior;

I'm using an older version of Synplify Pro (8.1). It claims that
highbit(3) is unused. Now my guess is that it looks at the
bit_selections array and sees that there are only 7 elements, meaning
only 3-bits are needed to address the array. Since highbit is 4-bits
wide, it assumes that the most significant bit is unnecessary. The
problem is that highbit ranges from 3 to 9, which means that all four
bits are necessary. The tool doesn't realize that the input is 4-
bits, but is reduced to 3-bits by the subtraction to create
subset_sel.

I'm looking for the best way to modify this so that the tool does not
optimize away necessary hardware. The first thing that popped in my
mind was to modify the array to range from 3 to 9 instead of 0 to 6.
This would eliminate the need for subtraction and highbit could be
used directly. The downside that I see is that you now have a 4-bit
address instead of a 3-bit. Ideally, I would want a 4-bit subtracter
that subtracts 3 from highbit and then only the lower 3 bits are used
to address. I tried this solution once in simulation, but ran into
trouble because highbit is unknown at the beginning of the simulation,
which causes to_integer to return 0, which is outside the range of the
array.

Does my solution make sense and does anyone have any better ideas?

Thanks,
Matt

Is it possible that synplify is already performing a translation on
highbit, realizing that it doesn't using the full range of 0-15? Then
it would throw a bit away, since it would never be referenced and
stuck at zero. I guess this would depend on how the signal is used
elsewhere in the code. Does a post-synthesys simulation behave the
same as the pre-synth simulation?
 
A

Andy

I am working on a project where synthesis of my design is claiming
that a bit is unused and I'm assuming is optimizing it away. I'm not
sure it is actually being optimized away because the design has timing
problems in another area, so I am unable to test it. But my
experience has been that if a synthesis tool says that something is
unused and you know it isn't, then problems are going to happen :).
First I'll post the relevant section:

-- Not the real declarations, but these are needed to understand the
code below.
signal highbit : unsigned(3 downto 0);
constant inBits : positive := 10;
constant outBits : positive := 4;
..........

architecture behavior of bitselector_1 is
type bit_sel_array is array (0 to inBits - outBits) of
signed(outBits-2 downto 0);
signal bit_selections : bit_sel_array;
begin

...........

-- Select the appropriate range of bits based on highbit
process(bit_selections, highbit) is
variable subset_sel : integer range 0 to inBits - outBits;
begin
subset_sel := to_integer(highbit - (outBits-1));
output(outBits-2 downto 0) <= bit_selections(subset_sel);
end process;

...........

end behavior;

I'm using an older version of Synplify Pro (8.1). It claims that
highbit(3) is unused. Now my guess is that it looks at the
bit_selections array and sees that there are only 7 elements, meaning
only 3-bits are needed to address the array. Since highbit is 4-bits
wide, it assumes that the most significant bit is unnecessary. The
problem is that highbit ranges from 3 to 9, which means that all four
bits are necessary. The tool doesn't realize that the input is 4-
bits, but is reduced to 3-bits by the subtraction to create
subset_sel.

I'm looking for the best way to modify this so that the tool does not
optimize away necessary hardware. The first thing that popped in my
mind was to modify the array to range from 3 to 9 instead of 0 to 6.
This would eliminate the need for subtraction and highbit could be
used directly. The downside that I see is that you now have a 4-bit
address instead of a 3-bit. Ideally, I would want a 4-bit subtracter
that subtracts 3 from highbit and then only the lower 3 bits are used
to address. I tried this solution once in simulation, but ran into
trouble because highbit is unknown at the beginning of the simulation,
which causes to_integer to return 0, which is outside the range of the
array.

Does my solution make sense and does anyone have any better ideas?

Thanks,
Matt

I dunno, I think the Synplify-pro is pretty smart!

It apparently realizes the valid range of highbits (3 to 9), since
you've told it that highbits minus 3 must fit into the range 0 to 6.
Since it knows values 0 and 1 cannot occur, it maps those values on
the bottom three bits to 8 and 9, so it does not need the MSB to
decode the range 3 to 9.

I've seen synplify do this when decoding counter values with integer
counters (long before 8.1), but I never was quite sure if it was
using reachability analysis on the counter code, or the subrange I
gave it. Your example indicates that it does in fact analyze integer
ranges for unused combinations of bits.

One more excellent reason to use integers rather than vectors; thanks!

Andy
 
A

Andy

I dunno, I think the Synplify-pro is pretty smart!

It apparently realizes the valid range of highbits (3 to 9), since
you've told it that highbits minus 3 must fit into the range 0 to 6.
Since it knows values 0 and 1 cannot occur, it maps those values on
the bottom three bits to 8 and 9, so it does not need the MSB to
decode the range 3 to 9.

I've seen synplify do this when decoding counter values with integer
counters (long before 8.1), but I never was quite sure if it was
using reachability analysis on the counter code, or the subrange I
gave it. Your example indicates that it does in fact analyze integer
ranges for unused combinations of bits.

One more excellent reason to use integers rather than vectors; thanks!

Andy

Actually, depending on what could be controlling highbits in your
design, it could be reaching the conclusion about its range by other
means (i.e. reachability analysis on a counter that drives highbits,
etc.). Did you try synthesizing just what you gave us, with highbits
as a 4 bit primary input port?

Andy
 
K

KJ

I am working on a project where synthesis of my design is claiming
that a bit is unused and I'm assuming is optimizing it away. I'm not
sure it is actually being optimized away because the design has timing
problems in another area, so I am unable to test it. But my
experience has been that if a synthesis tool says that something is
unused and you know it isn't, then problems are going to happen :).

Other times (as is happening in this case), it is your preconceptions that
are incorrect. There is nothing terribly sophisticated going on here, it is
simple boolean logic reduction which can be worked out with Karnaugh maps if
one so chooses. I'll illustrate it with a truth table.

- First, your observation that the 7 element array requires only three
address bits to get at any element is correct and is the one of the reasons
why you'll only need three 'highbits'. The other reason will be discussed
later on.

- Second, if you step back and look at the transformation from highbits to
subset_sel all that is being done is taking highbits and subtracting off a
constant (in this case '3'). I'm certain you (and the other repliers)
realize this, but what that means to any synthesis tool is that when it is
figuring out the boolean logic needed to implement the equation for the four
bits of subset_sel it will first plop in the equations needed to subtract
two four bit numbers and then do standard logic minimization. The truth
table for that transformation is....
highbits subset_sel
------- -----------
0000 1101
0001 1110
0010 1111
0011 0000
0100 0001
0101 0010
0110 0011
0111 0100
1000 0101
1001 0110
1010 0111
1011 1000
1100 1001
1101 1010
1110 1011
1111 1100

- Third, since you only use the lower 3 bits of subset_sel you're saying
that you don't care about the state of any other bits of subset_sel so they
can be optomized away. That being the case, look at the above truth table
focusing in on the places where the lower three bits happen to be the same.
As an example: highbits = 0000 and highbits = 1000 both produce
subset_sel(2:0) = 101)....pretty much says that highbits(3) is a don't care
to produce the code of 101. Now do that for all of the places where you get
matches on subset_sel(2:0) and you'll see the exact same thing, highbits(3)
will be a don't care to produce all of the needed codes. Therefore
highbits(3) is not needed.

If you ponder a bit more on it, you can probably see that any transformation
between highbits and subset_sel that is a simple addition or subtraction of
some constant value will produce a unique truth table that will have the
same characteristic as the one above in that there will be exactly two spots
in the table where the lower three highbits are the same and those two spots
will occur in one case with highbit(3) = 1, the other with highbit(3) = 0
thus implying highbits(3) is a don't care for each and every output code and
therefore is an unneeded input.

Synplify is not doing anything extraordinary, no fancy analysis, just simple
boolean logic reduction that has been done since day 1 of synthesis
tools....Abel (a language from 20 or so years ago) could have accomplished
the same thing. The higher level constructs available like addition,
multiplication, ranges etc. that we work with to be more productive can
cloud what really goes on under the hood and that we're still fundamentally
working with digital logic and the lessons you learned in Logic 101 still
apply and are the source of all logic minimizations.

Kevin Jennings
 
L

longbrmb

If you ponder a bit more on it, you can probably see that any transformation
between highbits and subset_sel that is a simple addition or subtraction of
some constant value will produce a unique truth table that will have the
same characteristic as the one above in that there will be exactly two spots
in the table where the lower three highbits are the same and those two spots
will occur in one case with highbit(3) = 1, the other with highbit(3) = 0
thus implying highbits(3) is a don't care for each and every output code and
therefore is an unneeded input.


Great post Kevin, I was getting stuck on the assumption that it would
be instantiating an adder to accomplish the subtraction rather than
analyzing all the possibilities and making it a simple combinational
logic problem. And now that I think about it, that makes a lot more
sense for the problem I had. Unfortunately that means that the design
is being synthesized correctly and that it's my fault I am not getting
the correct output. As is typically the case, computer related
problems are usually the fault of the user, not the computer!

Matt
 
A

Andy

Other times (as is happening in this case), it is your preconceptions that
are incorrect. There is nothing terribly sophisticated going on here, it is
simple boolean logic reduction which can be worked out with Karnaugh maps if
one so chooses. I'll illustrate it with a truth table.

- First, your observation that the 7 element array requires only three
address bits to get at any element is correct and is the one of the reasons
why you'll only need three 'highbits'. The other reason will be discussed
later on.

- Second, if you step back and look at the transformation from highbits to
subset_sel all that is being done is taking highbits and subtracting off a
constant (in this case '3'). I'm certain you (and the other repliers)
realize this, but what that means to any synthesis tool is that when it is
figuring out the boolean logic needed to implement the equation for the four
bits of subset_sel it will first plop in the equations needed to subtract
two four bit numbers and then do standard logic minimization. The truth
table for that transformation is....
highbits subset_sel
------- -----------
0000 1101
0001 1110
0010 1111
0011 0000
0100 0001
0101 0010
0110 0011
0111 0100
1000 0101
1001 0110
1010 0111
1011 1000
1100 1001
1101 1010
1110 1011
1111 1100

- Third, since you only use the lower 3 bits of subset_sel you're saying
that you don't care about the state of any other bits of subset_sel so they
can be optomized away. That being the case, look at the above truth table
focusing in on the places where the lower three bits happen to be the same.
As an example: highbits = 0000 and highbits = 1000 both produce
subset_sel(2:0) = 101)....pretty much says that highbits(3) is a don't care
to produce the code of 101. Now do that for all of the places where you get
matches on subset_sel(2:0) and you'll see the exact same thing, highbits(3)
will be a don't care to produce all of the needed codes. Therefore
highbits(3) is not needed.

If you ponder a bit more on it, you can probably see that any transformation
between highbits and subset_sel that is a simple addition or subtraction of
some constant value will produce a unique truth table that will have the
same characteristic as the one above in that there will be exactly two spots
in the table where the lower three highbits are the same and those two spots
will occur in one case with highbit(3) = 1, the other with highbit(3) = 0
thus implying highbits(3) is a don't care for each and every output code and
therefore is an unneeded input.

Synplify is not doing anything extraordinary, no fancy analysis, just simple
boolean logic reduction that has been done since day 1 of synthesis
tools....Abel (a language from 20 or so years ago) could have accomplished
the same thing. The higher level constructs available like addition,
multiplication, ranges etc. that we work with to be more productive can
cloud what really goes on under the hood and that we're still fundamentally
working with digital logic and the lessons you learned in Logic 101 still
apply and are the source of all logic minimizations.

Kevin Jennings

Kevin is right, to a point. The reason the synthesizer knows that only
3 bits are needed to address the array is because it is an array with
an integer index, and is indexed as such. For example, the following
code would not make the same three bit assumption:

For subset_sel in bit_selections'range loop
if unsigned(highbit - 3) = subset_sel then
output(outBits-2 downto 0) <= bit_selections(subset_sel);
exit; -- superfluous for synthesis
end if;
end loop;

But it also would result in a latch for "out of range" values of
highbit.

It has to do with how the description defines behavior for other
values of high_bit. But by constraining the values to fit in the
bounds of the index array, the synthesis tool is given enough
information to optimize it more effectively.

Note that the OP's description did not result in latches, so the
synthesis tool is making some assumptions about legal ranges of input
values. Those values that would result in assertion failures are
ignored, and the simplest way to ignore them is to optimize out the
latch that would be needed to handle them otherwise.

Andy
 
K

KJ

Kevin is right, to a point.
Yes...to the point that I completely explained how the synthesis tool was
able to determine why only 3 of the input bits were needed and not 4 as the
original poster was wondering about. The synthesizer plops down the boolean
equations and optomizes them just as one learned in Logic 101....but either
you seem to have forgotten or don't want to believe that that is what logic
optomization is all about.
The reason the synthesizer knows that only
3 bits are needed to address the array is because it is an array with
an integer index, and is indexed as such. For example, the following
code would not make the same three bit assumption:

For subset_sel in bit_selections'range loop
if unsigned(highbit - 3) = subset_sel then
output(outBits-2 downto 0) <= bit_selections(subset_sel);
exit; -- superfluous for synthesis
end if;
end loop;
The synthesizer makes no assumptions, nor is it prevented from making
assumptions in your example since it doesn't assume in the first place. The
original post defined a combinatorial logic function between 'highbit' and
'subset_sel' whereas you've defined a completely different function that
also infers storage for whatever reason. All four bits of 'highbit' are
needed for your version one simple reason: the mapping from 'highbit' to
'subset_sel' that you've defined does not have a unique functional inverse
whereas the function defined in the original post did (i.e. highbit =
subset_sel + 3). Post an example for any functions f(x) and g(x) where
g(f(x)) = f(g(x)) = x for all x that results in all four bits of highbits
being used...then you'll be on to something...but you won't be able to find
such a function.
It has to do with how the description defines behavior for other
values of high_bit. But by constraining the values to fit in the
bounds of the index array, the synthesis tool is given enough
information to optimize it more effectively.
No, the synthesis tool will simply insert the appropriate boolean logic to
implement the source file description and then do the same Logic 101
optomizations as I outlined in the earlier post.
Note that the OP's description did not result in latches, so the
synthesis tool is making some assumptions about legal ranges of input
values.
No it's not, it is implementing exactly the logic defined by the source file
it is not making assumptions.
Those values that would result in assertion failures are
ignored, and the simplest way to ignore them is to optimize out the
latch that would be needed to handle them otherwise.
No, it simply implements the logic specified....which was take highbits,
subtract 3 and then use the lower three bits of that to index a table and
output a result. No appeal to assertion failures or anything is
required....in fact you're the one making assumption about what you think
the behaviour 'should be' for those input values that 'shouldn't
happen'....and you've coded those assumptions up into....guess what...your
code. Synplify didn't dream up that behaviour you did, it simply turns
source code into boolean logic and memory.

Kevin Jennings
 
A

Andy

Yes...to the point that I completely explained how the synthesis tool was
able to determine why only 3 of the input bits were needed and not 4 as the
original poster was wondering about. The synthesizer plops down the boolean
equations and optomizes them just as one learned in Logic 101....but either
you seem to have forgotten or don't want to believe that that is what logic
optomization is all about.



The synthesizer makes no assumptions, nor is it prevented from making
assumptions in your example since it doesn't assume in the first place. The
original post defined a combinatorial logic function between 'highbit' and
'subset_sel' whereas you've defined a completely different function that
also infers storage for whatever reason. All four bits of 'highbit' are
needed for your version one simple reason: the mapping from 'highbit' to
'subset_sel' that you've defined does not have a unique functional inverse
whereas the function defined in the original post did (i.e. highbit =
subset_sel + 3). Post an example for any functions f(x) and g(x) where
g(f(x)) = f(g(x)) = x for all x that results in all four bits of highbits
being used...then you'll be on to something...but you won't be able to find
such a function.


No, the synthesis tool will simply insert the appropriate boolean logic to
implement the source file description and then do the same Logic 101
optomizations as I outlined in the earlier post.


No it's not, it is implementing exactly the logic defined by the source file
it is not making assumptions.


No, it simply implements the logic specified....which was take highbits,
subtract 3 and then use the lower three bits of that to index a table and
output a result. No appeal to assertion failures or anything is
required....in fact you're the one making assumption about what you think
the behaviour 'should be' for those input values that 'shouldn't
happen'....and you've coded those assumptions up into....guess what...your
code. Synplify didn't dream up that behaviour you did, it simply turns
source code into boolean logic and memory.

Kevin Jennings

KJ,

Your argument certainly has merit, so I simplified things to see what
would happen:

ENTITY integer_test IS
PORT(CLK : IN std_logic;
highbits : IN unsigned(3 DOWNTO 0);
output : OUT boolean);
END integer_test;

ARCHITECTURE rtl OF integer_test IS
BEGIN
PROCESS (clk) IS
VARIABLE subset_sel : natural RANGE 0 TO 6;
VARIABLE reg : unsigned(highbits'range);
ATTRIBUTE syn_preserve OF reg : VARIABLE IS TRUE;
BEGIN
IF rising_edge(clk) THEN
subset_sel := to_integer(reg - 3);
output <= subset_sel = 6;
reg := highbits;
END IF;
END PROCESS;
END rtl;

The results are as you (indirectly) predicted, it still uses three
bits of reg to decode the output. If it had been looking at the
subrange of subset_sel, it could have only used two (since the lsb
would be don't care if the value 7 was known not to be possible).

However, the "RTL view" (showing initial optimizations, but not all)
showed only a three bit adder with a constant -3 addend. The final
"technology view" showed a lut configured as a three input AND gate
with two inverted inputs. I then changed subset_sel to an unsigned(2
downto 0), and got the same RTL and technology view optimizations.

Other than the type change, this line changed to:

subset_sel := resize(reg - 3, subset_sel'length)

From this we cannot tell if Synplify performed a numeric optimization
(based solely on bit size, not integer subrange) on the range of
values first (it did not present 4 bits to a 4 bit adder in its
initial optimization), and then a boolean optimization later to get
down to a simple 3lut. Even at the "RTL view" it knew enough to bypass
the LSB of the adder, since it was a simple inversion.

In other words, the RTL view in both cases looked more like:

temp(2 downto 0) := reg(2 downto 0) - 3;
output <= temp(2) and temp(1) and reg(0);

I do know that Synplify does not simply munge code to boolean
equations and optimize those; it starts at a higher level first and
does some resource pruning and sharing before final optimizations.
Whether it uses higher-level numerical or simple boolean optimizations
for pruning, we just cannot tell from this example. However, given
that it does not appear to do numerical optimizations on integer
subranges, your boolean optimization argument seems more likely.

Also, my earlier experience with such an optimization decoding an
integer counter (range 0 to 5), needing only two bits for some values,
must have been due to a state reachability analysis on the counter,
and not due to the use of an integer subrange.

Thanks for your persistence in keeping me honest.

Andy
 

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,756
Messages
2,569,533
Members
45,007
Latest member
OrderFitnessKetoCapsules

Latest Threads

Top