VHDL recursive component/entity - recursion

I hope this is possible. I want to be able to write recursive code like this:
entity myEntity
generic (
size : natural -- a power of 2
)
port (
-- whatever
);
end;
architecture structural of myEntity is
begin
smallerEntity : entity component.myEntity(structural)
generic map (
size => size/2
);
port map (
...
);
end;
So each architecture instantiates a smaller version of itself. At some value of the generic 'size' I want to have a different implementation however.
Can this be done with configurations? If so, how?
As to why I'd like to be able to do this - so I can build reusable code for computing FFTs/DCTs and similar transforms.

You can use recursion in VHDL. But you need to encapsulate your instantiation in an if-generate statement. Something like:
recursive_structure : if size/2 > 0 generate
smallerEntity : entity <library_name>.myEntity(structural)
generic map (
size => size/2
)
port map (
...
);
end generate recursive_structure;

I use a function like:
-- convert natural to min vector length
function min_len_uns(arg : natural) return natural is
begin
case arg is
when 1 | 0 =>
return 1;
when others =>
return 1 + min_len_uns(arg/2);
end case;
end;

Related

How to use a generic type?

I'm working through the example here: https://www.adahome.com/rm95/rm9x-12-08.html
I've written my generic_stack.ads:
generic
type Item_Type is private;
size : Positive;
package Generic_Stack is
procedure push( item : in Item_Type );
function pop return Item_Type;
function is_Empty return Boolean;
STACK_EMPTY : exception;
STACK_FULL : exception;
end Generic_Stack;
And my generic_stack.adb:
package body Generic_Stack
is
type Stack_Table is array (Positive range <>) of Item_Type;
nodes : Stack_Table( 1..size );
index : Natural := 0;
procedure push( item : in Item_Type )
is
begin
if ( index < size )
then
index := index + 1;
nodes(index) := item;
else
raise STACK_FULL;
end if;
end push;
function pop()
return
Item_Type
is
item : Item_Type;
begin
if ( index > 0 )
then
item := nodes( index );
index := index - 1;
else
raise STACK_EMPTY;
end if;
return item;
end pop;
-- function is_Empty() removed for the sake of brevity
end Generic_Stack;
I don't really understand how to actually use the Generic_Stack.
With the simple generic_stack_test.adb code:
with Generic_Stack;
package Stack_Int_Type is new Generic_Stack( Item_Type => Integer, Size => 32 );
procedure Generic_Stack_Test
is
stack : Stack_Int_Type;
begin
stack.push( 3 );
end Generic_Stack_Test;
Gnat gives me errors on compilation:
# gnat make -gnat95 generic_stack_test.adb -o generic_stack_test
x86_64-linux-gnu-gcc-8 -c -gnat95 generic_stack_test.adb
generic_stack_test.adb:9:08: keyword "body" expected here [see file name]
generic_stack_test.adb:20:24: missing "end Stack_Int_Type;"
x86_64-linux-gnu-gnatmake-8: "generic_stack_test.adb" compilation error
Do I have to declare the Stack_Int_Type or suchlike? I don't understand how to use a declare inside a procedure. If I pass a Stack_Int_Type to another procedure, does it have to declare the type too?
Is it possible to simply declare Stack_Int_Type once in an .ads, and use it as a regular type? My book and web-pages kind of suggest it has to be declared every time, which sounds onerous.
Your test code is actually two library items:
with Generic_Stack;
package Stack_Int_Type is new Generic_Stack( Item_Type => Integer, Size => 32 );
declares a library package Stack_Int_Type, and
procedure Generic_Stack_Test
is
stack : Stack_Int_Type;
begin
stack.push( 3 );
end Generic_Stack_Test;
declares a library procedure which, as it stands, knows nothing about Stack_Int_Type.
We can fix that by adding the necessary with, but (compiling with -gnatl)
1. with Stack_Int_Type;
2. procedure Generic_Stack_Test
3. is
4. stack : Stack_Int_Type;
|
>>> subtype mark required in this context
>>> found "Stack_Int_Type" declared at stack_int_type.ads:2
5. begin
6. stack.push( 3 );
1 2
>>> invalid prefix in selected component "stack"
>>> prefixed call is only allowed for objects of a tagged type
7. end Generic_Stack_Test;
What’s happening here is that Generic_Stack doesn’t declare a type, so you can’t declare an instance of it at line 4; it’s a sort of singleton. (Amongst other things, that means it’s confusingly named: I’d’ve called it Integer_Stack. Never call a package _Type; _Types, maybe.)
Fixing that,
with Generic_Stack;
package Integer_Stack is new Generic_Stack( Item_Type => Integer, Size => 32 );
and
with Integer_Stack;
procedure Generic_Stack_Test
is
begin
Integer_Stack.push( 3 );
end Generic_Stack_Test;
You could have made Integer_Stack local:
with Generic_Stack;
procedure Generic_Stack_Test
is
package Integer_Stack
is new Generic_Stack( Item_Type => Integer, Size => 32 );
begin
Integer_Stack.push( 3 );
end Generic_Stack_Test;
Your Generic_Stack package never defines a stack data type.
The procedure Push and Pop are operations on a stack. You must have a type upon which to operate. There are two general categories of stacks; bounded stacks and unbounded stacks. You must decide which kind of stack you wish to create.
A discussion of both kinds of stacks implemented in Ada can be found at https://sworthodoxy.blogspot.com/2019/02/stack-abstract-data-type-using-ada.html
In the examples referenced in the URL above you will see how to create stack types that can be used multiple times. The example from Adahome is an old and problematic example. You have identified the biggest problem.
As explained elsewhere, no type is defined by your package specification. Otherwise, you would have type ... is somewhere after the package keyword. It's that simple.
But as explained elsewhere too, it's not dramatic. Your package instantiation will define exactly one stack, and not a type to be used in multiple places. In some cases, it's exactly what you need. So, your could call your instantiated package My_Stack, which actually articulates around an object (My_Stack.nodes, accessible only through Push & Pop).
You need to do the instantiation of Generic_Stack from within a unit (procedure, package, ...). Outside of it, it is the "outer space" only with with and use clauses needed to connect with other units.
with Generic_Stack;
procedure Generic_Stack_Test
is
package My_Stack is new Generic_Stack( Item_Type => Integer, Size => 32 );
begin
My_Stack.push( 3 );
end Generic_Stack_Test;

Postcondition on a procedure doesn't prove even though the same condition is asserted and true at the end of procedure

The code looks like this:
spec:
type Some_Record_Type is private;
procedure Deserialize_Record_Y(Record: in out Some_Record_Type)
with Post => (
if Status_OK then (
...
other postconditions
...
and then
Record_Field_X_Count(Record) = Record_Field_X_Count(Record'Old)
and then
Record_Field_X(Record) = Record_Field_X(Record'Old)
)
);
function Record_Field_X(Record: Some_Record_Type) return X_Unbounded_Array_Type;
function Record_Field_X_Count(Record: Some_Record_Type) return Natural;
body:
type Some_Record_Type is
record
X_Count: Natural;
X : X_Bounded_Array_Type;
Y_Count: Natural;
Y : Y_Bounded_Array_Type;
...
end record;
function Record_Field_X(Record: Some_Record_Type) return X_Unbounded_Array_Type
is (
...
a bit of logic based on values of other fields of Record
...
)
function Record_Field_X_Count(Record: Some_Record_Type) return Natural
is (Record.X_Count);
procedure Deserialize_Record_Y(Record: in out Some_Record_Type) is
Old_Record: Some_Record_Type := Record with Ghost;
begin
...
-- updates the Y field of the Record.
-- Note that we annot pass Record.Y and have to pass
-- the whole Record because Record is a private type
-- and Deserialize_Record_Y is in public spec
...
pragma Assert_And_Cut (
Status_OK
and then
...
other postconditions
...
and then
Record_Field_X_Count(Record) = Record_Field_X_Count(Record_Old)
and then
Record_Field_X(Record) = Record_Field_X(Record_Old)
)
end Deserialize_Record_Y;
There are no proof errors in the body, the error is only on the spec:
postcondition might fail, cannot prove Record_Field_X(Record) = Record_Field_X(Record'Old)
'other postconditions' are identical between the spec and the Assert_And_Cut at the end of the procedure.
Note the the checks with simpler fields, like X_Count:
Record_Field_X_Count(Record) = Record_Field_X_Count(Record'Old)
do not cause gnatprove to complain.
There's quite a lot of work for the prover inside the procedure, so usually, when there's a problem proving the postcondition it helps to assert that condition at the end of the procedure to 'remind' the prover that this is important facts. Usually, this works, but in one case it doesn't for some reason.
What are my options here?
What might be possible causes of this?
Maybe I should just increase the RAM on the machine where I run the proover, so it won't lose the Record_Field_X(Record) = Record_Field_X(Record_Old) fact between the end of the procedure and its postcondition? (I'm currently doing this on a machine with 32GB ram which is used exclusively to run gnatprove, with --memlimit=32000 --prover=cvc4,altergo --steps=0)
Maybe there are some techniques I don't know?
Maybe the only option I have is the manual proof?
I'm using the spark community 2019 version.
To summarize the comments, adding z3 to the provers with
--prover=cvc4,altergo,z3
helped to solve the problem.

Working with private types in Ada to create a private int

I am trying to implement a private type in Ada like it is used in Java or C++. For example I want to have a "private int" in Ada.
As I have found here http://en.wikibooks.org/wiki/Ada_Programming/Object_Orientation#Encapsulation:_public.2C_private_and_protected_members I have to implement my variable in the package body. So I have tried to implement this like it is described on the example.
My problem is that I can't create a Create function for creating an object and set the values. My second problem is that I want to have children of this type. These children should have a Create function which sets the values for the masterclass and the subclass.
Here is my code which is not working. I have added comments on the points which is not working.
private with Ada.Finalization;
package MasterClass is
type MasterC is tagged private;
type MasterC_Class_Ref is access all MasterC'Class;
procedure printNumObjects;
procedure do( This : in MasterC );
function Make (f1, f2 : Float) return MasterC;
function getVar(This : MasterC) return float;
private
type Private_Part; -- declaration stub
type Private_Part_Pointer is access Private_Part;
type Private_Component is new Ada.Finalization.Controlled with record
P: Private_Part_Pointer;
end record;
overriding procedure Initialize (X: in out Private_Component);
overriding procedure Adjust (X: in out Private_Component);
overriding procedure Finalize (X: in out Private_Component);
type MasterC is tagged record
P : Private_Component;
end record;
end MasterClass;
package body MasterClass is
numObjects : Integer := 0;
type Private_Part is record -- complete declaration
fTest1, fTest2 : float := 0.0;
end record;
overriding procedure Initialize (X: in out Private_Component) is
begin
X.P := new Private_Part'(fTest1=>0.0, fTest2 => 0.0);
end Initialize;
overriding procedure Adjust (X: in out Private_Component) is
begin
X.P := new Private_Part'(fTest1 => X.P.fTest1, fTest2 => X.P.fTest2);
end Adjust;
overriding procedure Finalize (X: in out Private_Component) is
procedure Free is new Ada.Unchecked_Deallocation (Private_Part, Private_Part_Pointer);
begin
Free (X.P);
end Finalize;
function Make (f1, f2 : Float ) return MasterC is
begin
numObjects := numObjects + 1;
return new MasterC'(fTest1=>0.0, fTest2=>0.0); -- This is not working!
end Make;
procedure do( This : in MasterC ) is
begin
Put_Line( "doneMaster");
end do;
function getVar( This : MasterC )
return float is
begin
return This.P.P.fTest1; -- This is not working!
end getVar;
end MasterClass;
with MasterClass; use MasterClass;
package SubClass is
type SubC is new MasterClass.MasterC with
record
fExtra1 : float := 0.0;
fExtra2 : float := 0.0;
end record;
type SubC_Class_Ref is access all SubC'Class;
overriding procedure do(This : SubC);
function Make (f1, f2 : Float) return SubC;
function Make1 (f1, f2 , w, h: Float) return SubC;
end SubClass;
with MasterClass; use MasterClass;
package body SubClass is
function Make ( f1, f2 : Float ) return SubC is
begin
return ((fTest1 => f1, fTest2 => f2, fExtra1 => 0.0, fExtra2 => 0.0));
end Make;
function Make1 ( f1, f2, w, h: Float ) return SubC is
begin
return (fTest1 => f1, fTest2 => f2, fExtra1 => w, fExtra2 => h);
end Make1;
overriding procedure do( This : in SubC ) is
begin
do(MasterC(This));
Put_Line( "doneSub");
end do;
end SubClass;
I cant find any information how to implement this.
The lines which I don't how to implement is the return line in the Make function
return new MasterC'(fTest1=>0.0, fTest2=>0.0); -- This is not working!
Then the line for reading the values
return This.P.P.fTest1; -- This is not working!
And then the line in the Make function for the Subclass.
return ((fTest1 => f1, fTest2 => f2, fExtra1 => 0.0, fExtra2 => 0.0)); -- This is not working!
ajb's answer is very good, but I hope you'll allow me to "work up" to Ada's OOP facilities because they're actually fairly different than the Java equivalents. -- I'm typing off the top of my head here, so the examples might not be compilable, but should do to get the ideas across.
Package Test_1 is
Type Point is record
x, y : Integer;
end record;
-- Some operations
End Test_1;
In the above we are creating a type, but there's a problem here: it exposes the implementation and users can go and change the values directly, which could be disastrous if certain processes/properties need to be ensured. (It also introduces dependance on implementation details.)
In order to address this, we can make the record private and make clients use functions and procedures to alter the internal state -- just like getters and setters (but we haven't touched on any OOP yet).
Package Test_2 is
Type Point is private;
Function Create( x, y : Integer ) return Point;
Function Get_X ( P : Point ) return Integer;
Function Get_Y ( P : Point ) return Integer;
-- Some more operations.
Private
Type Point is record
x, y : Integer;
end record;
-- Ada 2012 expression-functions, for brevity.
Function Create( x, y : Integer ) return Point is ( x => x, y => y );
Function Get_X ( P : Point ) return Integer is ( P.X );
Function Get_Y ( P : Point ) return Integer is ( P.Y );
End Test_2;
In the above the change is made so that the implementation is private, this allows us to change the implementation (see below) without forcing clients to recompile. (We could change Test_3 to Test_2 and it would still work.)
Package Test_3 is
Type Point is private;
Function Create( x, y : Integer ) return Point;
Function Get_X ( P : Point ) return Integer;
Function Get_Y ( P : Point ) return Integer;
-- Some more operations.
Private
Type Point is record
x, y : Float;
end record;
-- Ada 2012 expression-functions, for brevity.
Function Create( x, y : Integer ) return Point is
( x => Float(x), y => Float(y) );
Function Get_X ( P : Point ) return Integer is
( Integer(P.X) );
Function Get_Y ( P : Point ) return Integer is
( Integer(P.Y) );
End Test_3;
So, as you can see private means something different in Ada than it does in Java. Because Ada had this notion of private before OOP was added (in Ada 95) it was carried over to the OOP. (Basically the idea is that changes in a private-type's implementation cannot cause a program to change states becoming legal or illegal as a result.)
As you can see, Ada also had the notion of records and indirected access [private types] and even inheritance [derived types]... but Ada still had the notion of types, and especially distinct types that could be prohibited from interacting (a type for length and another for weight), and subtypes [which were types with added constraints] were different enough that it wouldn't be a good fit, and so they needed some way to distinguish between a type and a "type-or-something-derived-from-it" which is where the 'class attribute comes in: Type_Name'Class denotes a whole branch of an inheritance tree of a tagged-type.
-- Declare an operation that must be overridden in derived types,
-- and which takes the specific type:
Function Operation( Input : Type_Name ) return Boolean is abstract;
-- Declare an operation that takes the whole class:
Function Operation( Input : Type_Name'Class ) return Boolean;
Because of the rule above, a record that had some private components needs to be in the private portion of the spec so that changes to its internal structure don't impact the legality of the clients.
Now we're at a point roughly analogous to what you're used to in Java: class-definitions and inheritance, but with this added idea that private is something dealing with client-use (and packages) rather than, strictly-speaking, the object (or type) itself.
Unlike in Java, you don't need new to create an object. new specifically allocates an object and returns an access to the object. So this:
return new MasterC'(fTest1=>0.0, fTest2=>0.0); -- This is not working!
fails because the function is declared to return a MasterC, not an access MasterC or any type that is declared as access MasterC (or access all MasterC'class or anything of the sort). The function doesn't return an access type at all. So don't use new. Instead, the form will be
return (P => ???); -- keep reading to see what ??? is
The value of P here is a PrivateComponent. This is a subtype of Ada.Finalization.Controlled with an additional component P, so the syntax will look like
return (P => (Ada.Finalization.Controlled with P => ???))
The value of that P will be Private_Part_Pointer, which is an access type (to Private_Part), so that's where you'd use new.
return (P => (Ada.Finalization.Controlled with P =>
new Private_Part' (ftest1=>0.0, ftest2=>0.0)));
It's really not that complicated. To create a value of a record type, put the values in parentheses with component-name => followed by a value for each component. To create a value of an access type, use new.
When returning a SubC, things get interesting. The SubC has the same components as a MasterC, plus the two you've added. Thus, it has three components: P, fExtra1, fExtra2. However, you can't use the name P here, because it's in the private part of MasterClass and is thus invisible to SubClass. To create a SubC, you'll have to call a function to create the MasterC part of the SubC. The result will look something like
return (MasterClass.Make(f1, f2) with fExtra1 => 0.0, fExtra2 => 0.0);
[Note: This is called an extension aggregate.]
This uses MasterClass.Make to create a MasterC, which will have a P component; the SubC function result uses that P component with the fExtra1 and fExtra2 you've specified to create the three components you need for a SubC.
Disclaimer: I haven't tested this (I'm at home and don't have a compiler handy), so I may have gotten some of the syntax wrong, or there may be other subtle errors I missed.
EDIT: Now that I can use a compiler, I've found that the above two changes make your source compile (the second change has to be implemented in two places); except that do is a reserved word and cannot be used as a procedure name, and printNumObjects needs a body. This statement:
return This.P.P.fTest1; -- This is not working!
compiles fine with my compiler.

How to change the range of the range type?

Lets say I have
function x return boolean is
type range0 is range 1..1;
begin
canse x is
when 4=> range0:=firstArray'range;
when 5=> range0:=secondArray'range;
when 6=> range0:=1..100;
end case;
end x;
Basically I would like to change the range of range0 on the go? How may I accomplish this without using the declare block?
Basically I would like to change the range of range0 on the go? How may I accomplish this without using the declare block?
Hm...
In Ada 2012 you can use if- and case-expressions, so you could have something like this:
Type Array_Type is Array(Positive Range <>) of Integer;
Array_1 : Array_Type(1..128);
Array_2 : Array_Type(33..63);
-- your variant-selector
Use_1 : constant Boolean:= True;
-- Your variant-range here:
Subtype Variant_Range is Positive Range
(if Use_1 then Array_1'First else Array_2'First)
..(if Use_1 then Array_1'Last else Array_2'Last);
Array_3 : Array_Type( Variant_Range );
All that said, this probably isn't the best way to go about it and using a declare-block is very likely going to be more easily maintained.
You could technically satisfy the stated requirements by converting the obvious way (declare block) into a local procedure :
function x return boolean is
procedure use_dynamic_range(first,last : in integer) is
type range0 is new integer range first .. last;
begin
null;
end use_dynamic_range;
begin
case z is
when 4=> use_dynamic_range(firstArray'first, firstArray'last);
when 5=> use_dynamic_range(secondArray'first, secondArray'last);
when 6=> use_dynamic_range(1,100);
end case;
end x;
Because it's a local procedure it executes in the same scope as the equivalent declare block, therefore it can access everything visible within X, so you don't need to pass it a huge parameter list.
What about something like :
function x return Boolean is
type Range_Info_Type is
record
First : Integer;
Last : Integer;
end record;
function Get_Range_Info_Type return Range_Info_Type is
begin
case z is
when 4=> return Range_Info_Type'(First => firstArray'First,
Last => FirstArray'Last);
when 5=> return Range_Info_Type'(First => secondArray'First,
Last => secondArray'Last);
when 6=> return Range_Info_Type'(First => 1,
Last => 100);
when others => return Range_Info_Type'(First => 1,
Last => 1);
end case;
end;
MyTypeInfo : constant Range_Info_Type := Get_Range_Info_Type;
-- Now declare the actual type I want to use.
type range0 is new Integer range MyTypeInfo.First .. MyTypeInfo.Last;
begin
return true;
end x;
A declare block might be easier to understand by this should do the trick.
Note that you cannot write type range0 is range <expr>..<expr> in your case since expr should be a static expression (see RM 3.5.4)
Another non declare-block answer from Ada 2012:
Minimum : Integer := Integer'First; --' SO highlight correction
Maximum : Integer := Integer'Last; --' *same*
Function In_Range(X : Integer) return Boolean is
( X in range Minimum..Maximum );
Subtype Variant_Range is Integer Range Integer
with Dynamic_Predicate => In_Range(Variant_Range);
WARNING: Though this should work, I have not tested it.

VHDL bit aggregation

I have a VHDL design question.
I have N similar entities which take some input and each of them generates
an STD_LOGIC output.
Example:
entity example1 is
begin
...
result_1 : out std_logic;
end example1;
entity example2 is
begin
...
result_2 : out std_logic;
end example2;
...
I am looking for a way to aggregate all those single bit results in one UNSIGNED(N - 1 downto 0) result signal V such that V(i) = result_i holds.
Currently, my approach looks like this:
entity ResultAggregation is
port (
result_1 : in std_logic;
result_2 : in std_logic;
aggregate_results : out unsigned(1 downto 0)
);
end ResultAggregation;
architecture Behavioral of ResultAggregation is
begin
aggregate_results <= result_2 & result_1;
end Behavioral;
I find this approach rather clumsy. What I am looking for is a more automated solution,
for example that I can provide the number N such that the appropriate pins are generated.
I know this is a rather generic question, but if somebody knows a clever solution please
let me know.
Thanks in advance,
Sven
My suggestions would be to omit the ResultAggregation entity and only define a aggregate_results signal on the same level as your example1, example2, etc. entities. You could then instantiate these entities as
i_example1 : entity work.example1
port map (
...
result_1 => aggregate_results(0));
i_example2 : entity work.example2
port map (
...
result_2 => aggregate_results(1));
You could make the width of the aggregate_results vector a generic on the level where you instantiate the example1 etc. entities.
The only way you can get a generic number of pins would be to define your ResultsAggregation entity as
entity ResultAggregation is
generic (
N_RESULTS : integer
);
port (
results : in std_logic_vector(N_RESULTS-1 downto 0);
aggregate_results : out std_logic_vector(N_RESULTS-1 downto 0)
);
end ResultAggregation;
But then this entity would only contain the statement aggregate_results <= results which makes this entity pointless.
use a for/generate statement if blocks are identical:
n_examples: for i in 0 to (N-1) generate
inst_example: example_entity
port map(
...
result => V(i);
);
end generate n_examples;
if blocks have similar entity but different funcitonality, you can still use this approach:
...
inst_ex1: example1
port map(
...,
result_1 => V(1)
);
inst_ex2: example2
port map(
...,
result_2 => V(2)
);
....

Resources