How to initialize a bit vector in VHDL - initialization

I want to have a bit vector, I want it to have a value 2. I tried many things but I always get an error. Now I have this :
variable var : bit_vector := B"00000000000000000000000000000100";
I get these errors :
can't match integer literal with type array type "bit_vector"
and
declaration of variable "var" with unconstrained array type
"bit_vector" is not allowed
How can I fix this? Thanks.

You must give var a range (constrain it), like:
variable var : bit_vector(31 downto 0) ...
Then you can assign a constant to it for example with:
library ieee;
use ieee.numeric_bit_unsigned.all;
...
variable var : bit_vector(31 downto 0) := to_bit_vector(2, 32);
or with initial value given as bit string like:
variable var : bit_vector(31 downto 0) := "00000000000000000000000000000010";
The use of to_bit_vector is less error prone, as you can see, since the constant in your example code is not 2 but actually 4 ;-)

A more objective, generic assignment is the following:
var := (1=>'1', others=>'0');

Adding to #MortenZilmer's answer, please note that:
The compiler doesn't have a problem with your original code if you declare a constant instead of a variable:
constant const: bit_vector := b"00000000000000000000000000000100"; -- works OK
You can make the bitstring literal more readable if you write it in base 10. You can also specify the number of bits of the bitstring literal, as per the example below:
variable var: bit_vector(31 downto 0) := 32d"2";

Related

Can a variable passed with 'address attribute to a procedure be modified?

In my test code below, I am trying to modify a variable by passing it as system.address to another procedure.
with Ada.Text_IO;
with System;
with System.Storage_Elements;
procedure Main is
procedure Modify ( Var : in out System.Address) is
use System.Storage_Elements;
begin
Var := Var + 10;
end Modify;
My_Var : Integer := 10;
begin
-- Insert code here.
Modify (My_Var'Address);
Ada.Text_IO.Put_Line("My_Var is:" & Integer(My_Var)'Image );
end Main;
Compiler is returning an error as below,
17:17 actual for "Var" must be a variable
I could not understand the reason as My_Var(actual for Var) is clearly a variable. What should I change to modify My_Var with system.address?
Note: The context of this trail is that I am trying to understand an interface module in an existing legacy project. While there could be better ways to achieve what I need, I want to understand if it is possible to modify a variable with above method.
It would be helpful if you could show the relevant part of the legacy interface module -- it would help us understand what you need and want to do.
That said, first note that passing a parameter by reference is not usually done in Ada by explicitly passing the 'Address of the actual variable. As you say, there are other and better ways.
If you pass a System.Address value, and then want to read or write whatever data resides at that address, you have to do the read/write through a variable that you force to have that address, or through an access value (the Ada equivalent of "pointer") that you force to point at that addressed location. In both cases, you are responsible for ensuring that the type of the variable, or of the access value, matches the actual type of the data that you want to read or write.
To create an access value that points to memory at a given address, you should use the predefined package System.Address_To_Access_Conversions. That requires some understanding of access values and generics, so I won't show an example here.
To force a variable to have a given address, you declare the variable with the Address aspect set to the given address. The code below shows how that can be done for this example. Note the declaration of the local variable Modify.Var (and note that I changed the name of the parameter from Var to Var_Addr).
with Ada.Text_IO;
with System;
procedure Mod_By_Addr is
procedure Modify (Var_Addr : in System.Address) is
Var : Integer with Address => Var_Addr;
begin
Var := Var + 10;
end Modify;
My_Var : aliased Integer := 10;
begin
Modify (My_Var'Address);
Ada.Text_IO.Put_Line("My_Var is:" & Integer(My_Var)'Image );
end Mod_By_Addr;
Since the Var_Addr parameter is not modified in the Modify procedure, it can be declared with the "in" mode, and so the actual parameter can be an expression (My_Var'Address).
HTH
You modify the address and not the variable. Try to change parameter to Addr : in System.Address and declare Var : Integer with Address => Addr in Modify.
Another way of modifying the variable I have understood using address_to_Access_Conversions is shown below,
with Ada.Text_IO;
with System.Address_To_Access_Conversions;
with System.Storage_Elements;
procedure Main is
procedure Modify ( Var : in System.Address) is
use System.Storage_Elements;
package Convert is new System.Address_To_Access_Conversions (Integer);
begin
Ada.Text_IO.Put_Line(Convert.To_Pointer (Var).all'Img);
end Modify;
My_Var : Integer := 10;
begin
Modify (My_Var'Address);
Ada.Text_IO.Put_Line("My_Var is:" & Integer(My_Var)'Image );
end Main;

Why is Ada not trapping this specified range check?

I am going through the learn.adacore.com tutorial and have hit upon a problem that I am unsure of.
Specifically I understand that Ada is designed to trap attempts to overflow a variable with a specified range definition.
In the case below, the first attempt to do this causes a compiler 'range check failure' which is expected. However the following line doesn't trap it and I am not sure why:
with Ada.Text_IO; use Ada.Text_IO;
procedure Custom_Floating_Types is
type T_Norm is new float range -1.0 .. 1.0;
D : T_Norm := 1.0;
begin
Put_Line("The value of D =" & T_Norm'Image(D));
-- D := D + 1.0; -- This causes a range check failure at run time = completely expected.
Put_Line("The value of D =" & T_Norm'Image(D + 1.0)); -- This doesn't?
end Custom_Floating_Types;
You have a couple of pretty good answers, but I'm going to add another because it's clear that you expect the expression D + 1.0 to raise an exception, and the answers you have don't explain why it doesn't.
A type declaration like
type T_Norm is new float range -1.0 .. 1.0;
is roughly equivalent to
type T_Norm'Base is new Float;
subtype T_Norm is T_Norm'Base range -1.0 .. 1.0;
The type (called the "base type") isn't given a name, though it can often be referenced with the 'Base attribute. The name that is given is to a subtype, called the "first-named subtype".
This distinction is important and is often not given enough attention. As explained by egilhh, T_Norm'Image is defined in terms of T_Norm'Base. This is also true of the arithmetic operators. For example, "+" is defined as
function "+" (Left : in T_Norm'Base; Right : in T_Norm'Base) return T_Norm'Base;
2.0 is clearly in the range of T_Norm'Base, so evaluating D + 1.0 doesn't violate any constraints, nor does passing it to T_Norm'Image. However, when you try to assign the resulting value to D, which has subtype T_Norm, a check is performed that the value is in the range of the subtype, and an exception is raised because the check fails.
This distinction is used in other places to make the language work reasonably. For example, a constrained array type
type A is array (1 .. 10) of C;
is roughly equivalent to
type A'Base is array (Integer range <>) of C;
subtype A is A'Base (1 .. 10);
If you do
V : A;
... V (2 .. 4)
you might expect problems because the slice doesn't have the bounds of A. But it works because the slice doesn't have subtype A but rather the anonymous subtype A'Base (2 ..4).
The definition of 'Image says:
For every scalar subtype S:
S'Image denotes a function with the following specification:
function S'Image(Arg : S'Base)
return String
As you can see, it takes a parameter of the base (unconstrained) type
T_Norm'Image(D + 1.0) neither assigns nor reads an out-of-range value. It asks for the 'Image attribute (string representation) of (D + 1.0), which is the same as asking for (1.0 + 1.0).
I can see two ways the confusion might arise. First, the name "attribute" could be misinterpreted to suggest that 'Image involves something intrinsic to D. It doesn't. The 'Image attribute is just a function, so D is just part of the expression that defines the value of the parameter (in your example = 2.0).
Second, the 'Image attribute comes from Float. Thus, any Float can be its parameter.
You can create a function that accepts only parameters of T_Norm'Range and make that function an attribute of T_Norm. See Ada Reference Manual 4.10.
Because you don't store a value greater than range in D.

Initialize constant variable of record type with all default values

Say I have a type
type Record_T is
record
VAR1 : integer := 1;
VAR2 : string := "";
end record;
If I want to initialize a constant variable of this type, I can do it a few ways:
Null_Record : constant Record_T := (1, "");
Null_Record : constant Record_T := Record_T'(1, "");
but this forces me to specify the default values, when I already previously specified them.
I've tried all of the following, to no avail
Null_Record : constant Record_T := ();
Null_Record : constant Record_T := Record_T'();
Null_Record : constant Record_T;
But there has to be some way to do so? At least, I'd be very surprised if Ada lacked that capability.
It looks like this should be possible in Ada 2005, using the new "default value initialization" for aggregates using the <> operator.
This would look something like
Null_Record : constant Record_T := (others => <>);
I can't see any way to do this pre-Ada 2005. Unfortunately, this isn't a solution for me, being stuck with Ada 95.
The typical way, pre-ISO/IEC 8652:2007, presuming your type is in a package, is to declare a deferred constant in the visible part:
Null_Record : constant Record_T;
and then complete it in the private part with:
Null_Var : Record_T;
Null_Record : constant Record_T := Null_Var;

Ada compiler chooses incorrect overloaded function

I am using avr-ada to compile my program. I want to right shift an unsigned_16 variable twice.
Interfaces.Shift_Right is overloaded and provides for both Unsigned_8 and Unisgned_16.
When I compile, I get the error 'expected type "Interfaces.Unsigned_8"', 'found type "Interfaces.Unsigned_16"'. I have tried to specify that the input is an Unsigned_16, but it won't work. How do I specify the correct function?
with AVR; use AVR;
with AVR.MCU;
with AVR.Timer0;
with AVR.ADC;
with Interfaces;
use Interfaces;
procedure Flash_Led is
adc_result_10 : Unsigned_16 := 0;
adc_result_8 : Unsigned_8 := 0;
begin
-- set OC0A pin as output, required for output toggling
MCU.DDRD_Bits := (others => DD_Output);
-- set all pins low
MCU.PortD := 16#00#;
-- clear register
MCU.TCCR0B := 16#00#;
-- initialize timer to Clear Timer on Compare, scale the input
-- clock and set a value to compare the timer against.
Timer0.Init_CTC (Timer0.Scale_By_1024, Overflow => 1);
-- Toggle the OC0(A)-Pin on compare match
Timer0.Set_Output_Compare_Mode_Toggle;
-- Initialize ADC
ADC.Init(ADC.Scale_By_64, Ref => ADC.Is_Vcc);
loop -- loop forever
adc_result_10 := ADC.Convert_10bit(Ch => 0);
adc_result_10 := Shift_Right(Unsigned_16'(adc_result_10), 2); --'
adc_result_8 := Unsigned_8(adc_result_10);
Timer0.Set_Overflow_At(adc_result_10);
end loop;
end Flash_Led;
The line:
Timer0.Set_Overflow_At(adc_result_10);
Should have been:
Timer0.Set_Overflow_At(adc_result_8);
I didn't look at the line number in the error message closely enough. Oops.
If you are unsure which function is being called (given that it is overloaded) you can always construct a unique name through renames...
function My16_Shift_Right (Item : in Unsigned_16; Amount : Natural) return Unsigned_16
renames Interfaces.Shift_Right;
and then test the way you are thinking about your program.

Ada String Concatenation

I have a function that returns a string for a particular item, and I need to call that function numerous times and combine those strings into one. The combined string is bounded. I've made sure to fill it when space characters when it initializes but I keep getting "length check failed" errors. Is there something basic I'm doing wrong here?
FOR I IN 1..Collection.Size LOOP
Combined_String := combined_string & Tostring(Collection.Book(I));
END LOOP;
Unbounded_String is probably the easiest way to go:
with Ada.Strings.Unbounded;
use Ada.Strings.unbounded;
...
Temp_Unbounded_String : Unbounded_String; -- Is empty by default.
...
for I in 1 .. Collection.Size loop
Append(Temp_Unbounded_String, ToString(Collection.Book(I));
end loop;
If you then need to have the result placed in your fixed length standard string:
declare
Temp_String : constant String := To_String(Temp_Unbounded_String);
begin
-- Beware! If the length of the Temp_String is greater than that of the
-- fixed-length string, a Constraint_Error will be raised. Some verification
-- of source and target string lengths must be performed!
Combined_String(Temp_String'Range) := Temp_String;
end;
Alternatively, you can use the Ada.Strings.Fixed Move() procedure to bring the Unbounded_String into the target fixed-length string:
Ada.Strings.Fixed.Move(To_String(Temp_Unbounded_String), Combined_String);
In this case, if the source string is "too long", by default a Length_Error exception is raised. There are other parameters to Move() that can modify the behavior in that situation, see the provided link on Move for more detail.
In order to assign Combined_String, you must assign the full correct length at once. You can't "build up" a string and assign it that way in Ada.
Without seeing the rest of your code, I think Ada.Strings.Unbounded is probably what you should be using.
I know this is an ancient question, but now that Ada 2012 is out I thought I'd share an idiom I've been finding myself using...
declare
function Concatenate(i: Collection'index)
is
(tostring(Collection(i) &
if (i = Collection'last) then
("")
else
(Concatenate(i+1))
);
s: string := Concatenate(Collection'first);
begin
Put_Line(s);
end;
Typed off the top of my head, so it'll be full of typos; and if you want it to work on empty collections you'll need to tweak the logic (should be obvious).
Ada 2012's expression functions are awesome!
Ada works best when you can use perfectly-sized arrays and strings. This works wonderfully for 99% of string uses, but causes problems any time you need to progressively build a string from something else.
Given that, I'd really like to know why you need that combined string.
If you really need it like that, there are two good ways I know of to do it. The first is to use "unbounded" (dynamically-sized) strings from Ada.Strings.Unbounded, as Dave and Marc C suggested.
The other is to use a bit of functional programming (in this case, recursion) to create your fixed string. Eg:
function Combined_String (String_Collection : in String_Collection_Type) return String is
begin
if String_Collection'length = 1 then
return String_Collection(String_Collection'first);
end if;
return String_Collection(String_Collection'first) &
Combined_String (String_Collection'first + 1 .. String_Collection'last);
end Combined_String;
I don't know what type you used for Collection, so I'm making some guesses. In particular, I'm assuming its an unconstrained array of fixed strings. If it's not, you will need to replace some of the above code with whatever your container uses to return its bounds, access elements, and perform slicing.
From AdaPower.com:
function Next_Line(File : in Ada.Text_IO.File_Type :=
Ada.Text_Io.Standard_Input) return String is
Answer : String(1..256);
Last : Natural;
begin
Ada.Text_IO.Get_Line(File => File,
Item => Answer,
Last => Last);
if Last = Answer'Last then
return Answer & Next_Line(File);
else
return Answer(1..Last);
end if;
end Next_Line;
As you can see, this method builds a string (using Get_Line) of unlimited* length from the file it's reading from. So what you'll need to do, in order to keep what you have is something on the order of:
function Combined_String (String_Collection : in String_Collection_Type)
Return String is
begin
if String_Collection'length = 1 then
Return String_Collection(String_Collection'First).All;
end if;
Recursion:
Declare
Data : String:= String_Collection(String_Collection'First).All;
SubType Constraint is Positive Range
Positive'Succ(String_Collection'First)..String_Collection'Last;
Begin
Return Data & Combined_String( String_Collection(Constraint'Range) );
End Recursion;
end Combined_String;
Assuming that String_Collection is defined as:
Type String_Collection is Array (Positive Range <>) of Access String;
*Actually limited by Integer'Range, IIRC

Resources