Using a Class/record in an other class (subtype mark required in this context) - class

I want to learn ADA and have a problem with the 'class'
I have 2 classes A and B and want that class A can use class B.
Class A
with B;
package A is
type A is tagged
record
varA : INTEGER := 0;
varB : INTEGER := 0;
end record;
procedure DOSMTH(A_In : in out A; B_IN: in out B);
end A;
and Class B
package B is
type B is tagged
record
var1 : INTEGER;
var2 : INTEGER;
end record;
procedure DoSMTH2(B_IN: in out B; var : INTEGER);
end B;
If I want to compile A I get following error message:
subtype mark required in this context
found 'B' declared at b.ads:1
Another problem is my 'Main' File which can't use A and B (declaration)
with Ada.Text_IO, A, B;
procedure Main is
a : A;
b : B;
begin
null;
end Main;
I get following Errors:
object "A" cannot be used before end of its declaration
object "B" cannot be used before end of its declaration
I can't find any solution for that. I have read the ADA 2005 Reference Manual but can't find anything.
OK thx for the help,
finaly it works now.
Solution:
Modify Class A to
with B;
package A is
type A is tagged
record
-- u can use a object VAR with
-- objB : B.B
varA : INTEGER := 0;
varB : INTEGER := 0;
end record;
procedure DOSMTH(A_In : in out A; B_IN: in out B.B);
end A
Modify Main to:
with Ada.Text_IO, A, B;
procedure Main is
myA : A.A; --the old one was stupid ...
myB : B.B; --same here
begin
null;
end Main;

The problem with the main program is that Ada isn’t case-sensitive, so when you say
a : A.A;
the compiler sees as far as a : A and thinks that the second A is the same thing as the first, hence the complaint that object "A" cannot be used before end of its declaration.
You can tell the compiler where to look for the package A by qualifying it. Package A is declared at library level, and there’s a notional package Standard you can use to indicate this:
a : Standard.A.A;
However, it’s much better, if you can, to avoid using the same name for different things in the first place.

You only withed package B in package A - in order to use anything form it you have to use qualified name (that is: for record B you should use B.B). Like:
with B;
package A is
type A is tagged
record
varA : INTEGER := 0;
varB : INTEGER := 0;
end record;
procedure DOSMTH(A_In : in out A; B_IN: in out B.B);
end A;
If you want to use things declared in package B without fully qualifying name you should put use B; right after withing it.
As to whether one should use or only with package is hard question - most of the time most Ada programmers that I know (including myself) prefer to with packages only, rarely using them - for example when working with Lumen library (OpenGL binding with glut-like functionality) I usually use Lumen because then I can type GL.Whatever_GL_Function instead of Lumen.GL.Whatever_GL_Function (but I do not "use" Lumen.GL). If package name is long I prefer to rename it inside procedure and in case of types (for operators if defined) one can use type B.B;
PS: I can elaborate more if some parts of it are unclear.

My guess would be that the compiler sees "B" as the name of the package and not the record. Try naming your package or records differently.
Also, if you want to learn Ada, the reference manual is the last place you want to start at. Get the book by Barnes or get one of the older books used at Amazon. You get good books about Ada 95 for 5$ in the used section.

Related

Converting arrays from signed to integer in VHDL?

I have declared an array
type datastream is array(0 to 10) of signed (5 downto 0);
For simulation, I want to display the array as integer-numbers
So I created
type datastream_int is array(0 to 10) of integer;
and
signal DIN_ARRAY: datastream;
signal DIN_ARRAY_int: datastream_int;
...
DIN_ARRAY_real <= datastream_int(DIN_ARRAY);
But it fails. How to convert it? Dont want to use a for loop
The numeric_std package, that I assume you are using, provides a to_integer function to convert from a single signed value to a single integer object. For an array, you're going to have to use a for loop. Something like this:
for i in DIN_ARRAY'range loop
DIN_ARRAY_int <= to_integer(DIN_ARRAY(i));
end loop;
You could also provide a conversion function (it will also contain a for loop)
function datastream_to_datastream_int( d : datastream ) return datastream_int is
variable r : datastream_int;
begin
for i in d'range loop
r(i) := to_integer(d(i));
end loop;
return r;
end function;
....
--no loop required
DIN_ARRAY_int <= datastream_to_datastream_int(DIN_ARRAY);
So, there will be a for loop somewhere.
Your code fails because you have attempted a type conversion, which is only allowed between similar types - ie. array or record types where the element types match between the two types.
PS. VHDL 2008 provides an integer_vector type in the std.standard library (which is included by default) which may help by allowing you to do this:
signal DIN_ARRAY_int: integer_vector(DIN_ARRAY'range);
If you did decide to keep datastream_int as per your original, you could type convert it to an integer_vector, because the types are similar:
my_iv <= integer_vector(DIN_ARRAY_int);

Why can't I import a let definition from a package, in a SystemVerilog module?

I would like to put the following definitions in a default package, which I include in all my other SystemVerilog modules:
let max(a,b) = a > b ? a : b;
But, when I try to use the imported let definition in a module, I'm told that I'm attempting to use a non-local function definition and VCS errors out.
Why?
The simple example works with no issues. Make sure that the package is always compiled before it is imported. Do correct import from the package either as pkg::* or pkg::max. Or use it as pkg::max(a,b) directly without import. And yes, use the compiler which supports this syntax.
package pkg;
let max(a,b) = a > b ? a : b;
endpackage:pkg
module top();
import pkg::*;
int a = 1,b = 2;
initial begin
$display("max of %d and %d is %d", a, b, max(a,b));
end
endmodule

Conditional declaration by array of records

I try to create many components depending on the value of constant elements. These elements are organized in an array of records.
Dymola prints the translation log for the example below:
But I'm sure to use fixed conditions because I only perform allowed operations on constant values.
Here is the simple example of what I wantet to do:
model ConditionalComponent
type Enum = enumeration(one,two,three);
record Tmp
parameter Integer ID;
parameter Boolean active;
end Tmp;
record TmpNamed
parameter Enum name;
extends Tmp;
end TmpNamed;
function reorder
input TmpNamed inp[:];
output Tmp out[size(inp,1)];
algorithm
for elem in inp loop
out[elem.name] := Tmp(elem.ID, elem.active);
end for;
end reorder;
constant TmpNamed testIn[:] = {
TmpNamed(Enum.two,20,true),
TmpNamed(Enum.one,10,true),
TmpNamed(Enum.three,30,true)};
constant Tmp testOut1[:] = reorder({
TmpNamed(Enum.two,20,true),
TmpNamed(Enum.one,10,true),
TmpNamed(Enum.three,30,true)});
constant Tmp testOut2[:] = reorder(testIn);
constant Boolean active1 = testOut1[Enum.one].active;
constant Boolean active2 = testOut2[Enum.one].active;
Real t1=0 if testOut1[Enum.one].active;
//Real t2=0 if testOut2[Enum.one].active;
//Real t3=0 if active1;
//Real t4=0 if active2;
end ConditionalComponent;
The function reorder is intended to ease the management of large lists of named active components. Normally the constant testOut2 is used and created within the package ConditionalComponent. But for testing purposes ConditionalComponent is a model here. Actually I only want to use the line
Real t2=0 if testOut2[choice].active;
parameter Enum choice = Enum.one;
within other components, that have a parameter of type Enum. The declarations for t1, t3, t4 are only some tests that work, depending on what is left uncommented.
For example leaving the declaration for t1 and t3 uncommented works. But if one uses only the declaration for t1, it is not translated by Dymola.
The difference between t1 and t2 is, that the argument for reorder is passed directly or via the constant testIn.
I'm sure, that most parameter and constant prefixes are unnecessary and I tried hard to figure out the problem. But unfortunately I cannot decide whether Dymola is not working correctly or I did something wrong. And I've got no idea how to debug the translation process to figure it out by myself.
Can anyone tell me, what am I doing wrong?
Not something wrong, but it's just currently seen as too complicated and not handled.
A work-around is to split subscripting and element access:
constant Tmp testOut1_one=testOut1[Enum.one];
Real t1=0 if testOut1_one.active;

If a variable is passed as a constant does it get passed by reference?

If I pass a variable as a constant does it automatically get passed by reference?
procedure foo(const x : integer)
I can already pass a variable by reference like this:
procedure foo(var y : integer);
Ideally I'd want something like the code below:
procedure foo(const var z : integer)
const does not guarantee that the value is actually passed by reference.
Free Pascal supports
procedure foo(constref z : integer);
for this purpose: z is always passed by reference in this case. I'am not aware of something similiar in other pascal compiler.

Illegal type conversion VHDL

I was trying to return type std_logic_vector by type conversion in vhdl.
Here is my code:
function mul(num1,num2 : in std_logic_vector(7 DOWNTO 0)) return std_logic_vector is
variable v_TEST_VARIABLE1 : integer;
variable v_TEST_VARIABLE2 : integer;
variable n_times: integer:=1;
variable product: integer:=0;
begin
for n_times in 1 to v_TEST_VARIABLE2 loop
product:=product + v_TEST_VARIABLE1;
end loop;
return std_logic_vector(product);
end mul;
It gives "Illegal type conversion from std.standard.integer to ieee.std_logic_1164.std_logic_vector (numeric to array)." on compilation.
How do I return std_logic_vector in such a code?
See Russell's post first. If you use the VHDL-2008, numeric_std_unsigned package, then you can use just one conversion:
use ieee.numeric_std_unsigned.all ;
...
return to_std_logic_vector(product, length) ; -- long form
-- alternate short form
return to_slv(product, length) ;
Usage warning: for synthesis, I consider VHDL-2008 items to be on the bleeding edge of support. Hence, while I use VHDL-2008 frequently in my testbenches, I try to limit the usage of it in my RTL code to what can't be done using other methods. However, if you ever want to use code like this, it is it is important to try it out in your synthesis tool and submit a bug report against it if it does not work - that is the only way change happens.
You must first convert it to an unsigned. I hope you're using numeric_std? If so, your code looks like this. Note that to use to_unsigned you must know the length of your output std_logic_vector. So this either needs to be an input to your function or you can bound the return vector:
return std_logic_vector(to_unsigned(product, length));
More information about how to convert std_logic_vector to integer.