I'm working with VHDL, and I'm wondering if there is any way to constrain the string size when declaring it, using initialization. For example, we declare a string as follow:
variable sequence : string(1 to 20) := "AGTAACCAATTCGCATTCGC";
I would like to know if there is any way to do something like:
variable sequence : string := "AGTAACCAATTCGCATTCGC";
Of course, second line isn't valid, because interpreter says:
[VRFC 10-1547] variable cannot be unconstrained
Constants don't have to be constrained, so you could do this:
constant Csequence : string := "AGTAACCAATTCGCATTCGC";
variable Vsequence : string(Csequence'range) := Csequence;
https://www.edaplayground.com/x/r3wK
entity E is
end entity E;
architecture A of E is
begin
process
constant Csequence : string := "AGTAACCAATTCGCATTCGC";
variable Vsequence : string(Csequence'range) := Csequence;
begin
wait;
end process;
end architecture A;
Related
I just started programming on Ada and I was wondering how to code getters and setters to work with classes attributes.
In fact I am interested in obtaining getters and setters of attributes deadline, period and computingTime of the following package:
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Real_Time; use Ada.Real_Time;
package body pkg_tasks is
task body task_a is
deadline : Time_Span := To_Time_Span(25.0);
period : Time_Span := To_Time_Span(25.0);
computingTime : Time_Span := To_Time_Span(10.0);
startingTime : Time;
begin
entry start do
startingTime := Clock;
while (Clock - startingTime) < computingTime loop
end loop;
New_line;
Put_Line("End of task A");
end start;
end task_a;
end pkg_tasks;
In the case of a task, it's quite easy... You can't for the same reason that we answered in your last question, tasks can only have entries which act as a way to synchronize tasks (read part on entries and the followings).
But in fact, you could perform a kind of getters as entries and using selective wait depending on when you want to query your attributes.
Now, about setting attributes on your task, using parameters on your start entry seems to me as the best way to do.
As a note, you are writing about classes attributes but you are currently using no classes at all. Tasks are a first-citizen type in Ada and is not implemented through a class type as it's done in Java. Using object oriented programming is a different beast here.
As said above, generally tasks are not the normal way to do it. Back in Ada83, there were no protected types, so if you needed something like that then you emulated it with a task. That aside, here are some examples using tasks, protected types and classes (or as Ada calls them, Tagged types):
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Real_Time; use Ada.Real_Time;
procedure jdoodle is
------------------------------------------------------
-- Task Example
------------------------------------------------------
task Task_Example is
entry Get(Time : out Time_Span);
entry Set(Time : in Time_Span);
end Task_Example;
task body Task_Example is
Value : Time_Span := To_Time_Span(0.0);
begin
loop
select
accept Get(Time : out Time_Span) do
Time := Value;
end Get;
or
accept Set(Time : in Time_Span) do
Value := Time;
end Set;
or
terminate;
end select;
end loop;
end Task_Example;
------------------------------------------------------
-- Protected type example
------------------------------------------------------
protected type Protected_Example is
procedure Put(Time : Time_Span); -- or use entry
function Get return Time_Span; -- or use procedure or entry
private
Value : Time_Span := To_Time_Span(0.0);
end Protected_Example;
protected body Protected_Example is
procedure Put(Time : Time_Span) is
begin
Value := Time;
end Put;
function Get return Time_Span is
begin
return Value;
end Get;
end Protected_Example;
------------------------------------------------------
-- Class Example
------------------------------------------------------
package Classes is
type Class_Example is tagged limited private;
procedure Put(Self : in out Class_Example; Time : Time_Span);
function Get(Self : in Class_Example) return Time_Span; -- or use procedure
private
type Class_Example is tagged limited record
Value : Time_Span := To_Time_Span(0.0);
end record;
end Classes;
package body Classes is
procedure Put(Self : in out Class_Example; Time : Time_Span) is
begin
Self.Value := Time;
end Put;
function Get(Self : in Class_Example) return Time_Span is
begin
return Self.Value;
end Get;
end Classes;
begin
Put_Line("Starting");
end jdoodle;
Keep in mind the tagged type example is also applicable to regular records and other private types.
I am trying to write a function that will check for the existence of a particular directory on each drive in turn, store the path where it is found as a variable and return true if it exists and false otherwise:
function IsDirPresent(): Boolean;
var
chrDriveLetter: Char;
strMyDir: String;
begin
for chrDriveLetter := 'A' to 'Z' do
begin
if DirExists(chrDriveLetter + ':\MyDir') then
strMyDirPath := chrDriveLetter + ':\MyDir'
end;
if strMyDirPath <> '' then
Result := True;
end;
I get a Type mismatch error on my loop line when compiling this. I am struggling to work out what is wrong with the loop and haven't been able to find any information on how to correctly create a loop from A to Z in Inno Setup.
Your loop is valid for Pascal language because the Char type is ordinal and its range constants are of the same type, so I guess this is a specific limitation of the Pascal Script language notation. I don't know if there's some syntax workaround nor if the Char type is even allowed to be used for the loop control variable.
I can only provide you a workaround working with integer type loop control variable. It uses the Ord and Chr functions. The first returns the ordinal value of a char, the latter ASCII char from the ordinal value:
var
C: Char;
I: Integer;
begin
for I := Ord('A') to Ord('Z') do
begin
C := Chr(I);
...
end;
end;
I have class with integers and string and when i use integers everything is fine but when i use string program is crashing
//class
CatInfoType = class(TRemotable)
private
FcatId: Integer;
FcatName: string;
FcatParent: Integer;
FcatPosition: Integer;
FcatIsProductCatalogueEnabled: Integer;
published
property catId : Integer read FcatId write FcatId;
property catName : string read FcatName write FcatName;
property catParent : Integer read FcatParent write FcatParent;
property catPosition : Integer read FcatPosition write FcatPosition;
property catIsProductCatalogueEnabled: Integer
read FcatIsProductCatalogueEnabled
write FcatIsProductCatalogueEnabled;
end;
//program code
procedure TForm2.Button7Click(Sender: TObject);
var
rc: Integer;
k: CatInfoType;
l:String;
begin
k.catId:=4646;
k.catName:='777';//that crashing the program
end;
No...not quite
k.catId:=4646; // <--- that crashing the program
k.catName:='777';
The error message you could have included would have been something like
Access Violation at address xxxxxxxx in module 'MyProject.exe'. Read of address xxxxxxxx.
Here k is a class of CatInfoType - you haven't yet instantiated it, however. What you want is :
k := CatInfoType.Create;
k.catId := 4646;
//... etc
You failed to instantiate an instance. That would be done with
k := CatInfoType.Create(...);
What I want to do
I want to have a script in python or matlab that creates files which can be read by VHDL / modelsim as a file of real values.
What I've done so far
I've written a small VHDL entity that creates a file of real values so I can find out what format it uses. It looks like this:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
library std;
use std.textio.all;
entity read_arr is
end entity read_arr;
architecture reader of read_arr is
type t_real_arr is array (0 to 1023) of real;
signal real_arr : t_real_arr := (others => 0.0);
signal start : std_logic := '0';
signal filled : std_logic := '0';
type t_real_file is file of t_real_arr;
file real_file : t_real_file;
begin -- architecture reader
start <= '0', '1' after 10 ns;
fill_arr : process (start) is
variable real_fill : real := -10.0;
begin -- process fill_arr
if rising_edge(start) then
for i in real_arr'range loop
real_arr(i) <= real_fill;
real_fill := real_fill + 0.25;
end loop; -- i
filled <= '1';
end if;
end process fill_arr;
wr_arr : process (filled) is
variable filename : string (1 to 10) := "realvc.dat";
variable status : file_open_status := status_error;
begin -- process fill_arr
if rising_edge(filled) then
file_open(status, real_file, filename, write_mode);
write(real_file, real_arr);
file_close(real_file);
end if;
end process wr_arr;
end architecture reader;
What it does is it fills an array of 1024 elements with real values starting from -10.0 and incrementing in steps of 0.25. It then writes this data into the binary file realvc.dat. The content of the file (viewed with a hex editor) can be seen in this gist.
It's easy to see that modelsim uses 64 bit to store each real value, but I haven't figured out what kind of format that is. It isn't ieee double-precision.
The Question
Does anyone know what kind of data format that is and how I can recreate it in a script language such as python or matlab?
The standard VHDL package std.textio makes it possible to read/write real in
literal format to a text file, whereby scripting languages like Python can
easily access it. The binary format is thereby avoided, which improves portability.
An example similar to the question code, doing first write then read of an array of real with std.textio is:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library std;
use std.textio.all;
entity test_arr is
end entity test_arr;
architecture test of test_arr is
begin
process is
type real_arr_t is array (0 to 1023) of real;
variable real_arr_v : real_arr_t := (others => 0.0);
variable real_fill_v : real := -10.0;
procedure real_arr_write(variable real_arr : in real_arr_t) is
file txt_file : text;
variable real_v : real;
variable line_v : line;
begin
file_open(txt_file, "real.txt", write_mode);
for idx in real_arr'range loop
write(line_v, real_arr(idx));
writeline(txt_file, line_v);
end loop;
file_close(txt_file);
end procedure;
procedure real_arr_read(variable real_arr : out real_arr_t) is
file txt_file : text;
variable line_v : line;
variable good_v : boolean;
begin
file_open(txt_file, "real.txt", read_mode);
for idx in real_arr'range loop
readline(txt_file, line_v);
read(line_v, real_arr(idx), good_v);
assert good_v report "Failed convert to real of: " & line_v.all severity FAILURE;
end loop;
file_close(txt_file);
end procedure;
begin
-- Make and write real array to text file
for i in real_arr_v'range loop
real_arr_v(i) := real_fill_v;
real_fill_v := real_fill_v + 0.25;
end loop;
real_arr_write(real_arr_v);
-- Read real array from text file
real_arr_read(real_arr_v);
-- End
wait;
end process;
end architecture test;
The real values in the "real.txt" file are then:
-1.000000e+001
-9.750000e+000
-9.500000e+000
-9.250000e+000
Python 3 can create strings like this with '{:e}'.format(x), and convert from this format using float(s).
Please help, how can i convert a real declared variable into a string one. Is there any function like IntToStr() ? RealToStr() function won't work.
There is a bunch of conversion routines in SysUtils unit, ie FloatToStr and other FloatTo* functions. Also see the Format function.
A really old method uses the 'Str' procedure, which has two parameters: the first is a real or integer, and the second is a string variable, into which the formatted number will be placed.
Examples:
i:= 1;
str (i, a); // a = '1'
r:= 1.5;
str (r:2, a); // a = '1.50'
It depends on the Delphi version you are using.
There is a FloatToStr in newer versions.
I think something like this would work...
procedure TestConversion;
Var
StringValue : String;
RealValue : Real;
begin
RealValue := 1 + 1.95;
Str(RealValue:0:2,StringValue);
// to display it in a label for example, it should be like this:
Label1.Caption := StringValue + ' is a Real Value!';
end;
so the output should be displayed in the Label1.Caption(as example) without problems like this:
2.95 is a Real value!