Ada Hash_type to integer - hash

im trying to implement my own hash function as a wrapper to Strings.hash
with an upper bound, here is my code:
function hash (k : in tcodigo; b : in positive) return natural is
hash: Ada.Containers.Hash_Type;
begin
hash := Ada.Strings.Hash(String(k));
return integer(hash) mod b;
end hash;
My problem is that i dont know how to cast hash to integer so i can make the mod operation.

According to the Reference Manual (A.18.1) Hash_Type is a modular type. Therefore, a simple Integer(Hash) should work. Actually, I guess you can take directly the mod of the hash by first casting b to Hast_Type and then converting the result to Natural. Remember to add use type Ada.Containers.Hash_Type.

I recommend using the hashing function from the notes; if you don't have it at hand, I'll leave it here:
function hash(k: in string) return natural is
s, p: natural;
begin
s:= 0;
for i in k'range loop
p:= character'pos(k(i)); -- código ASCII
s:= (s+p) mod b;
end loop;
return s;
end hash;
See you on Monday at the exam; good luck and study hard!

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);

The lifetime of systemverilog method in the program block

`define NUM 100
program test;
function automatic int sum(int n);
if(n <= 1)
return n;
else
return n + sum(n-1);
endfunction
initial begin
$display("sum(%0d)=%d",`NUM, sum(`NUM));
end
endprogram
Above is a piece of code that did a recursive exercise of the sum of incremental integers from 1 to NUM. The result is as expected when I ran it in vcs/xcelium/Questa on the EDA playground.
sum(100)= 5050
However, when I tried to make a modify on the lifetime of function int sum(int n):
program test;
function int sum(int n);
if(n <= 1)
return n;
else
return n + sum(n-1);
endfunction
initial begin
$display("sum(%0d)=%d",`NUM, sum(`NUM));
end
endprogram
The results are quite interesting:
VCS : sum(100)= 100
Cadence xcelium: sum(100)= 5050
Questa : sum(100)= 5050
I went back to the IEEE1800-2017 to find out the default lifetime of methods in the program block but I didn't get the explicit description about that. Would someone help me to clarify this?
https://www.edaplayground.com/x/v3gb
The differences you are seeing are not due to the lifetime of the sum method—it's the order of evaluation of function calls within the expression n + sum(n-1), which is indeterminate. If you reverse the expression to sum(n-1) + n, all tools give the correct result for a function with a static lifetime.
BTW, I strongly recommend that you never use program blocks in SystemVerilog. Use modules instead.

Way to have a function like urandom_range(); which will return unique values?

I want to have a urandom_range(); which will not repeat a value once its picked in a simulation ? If it has exhausted its supply of 'available' numbers, then perhaps it can repeat .
Is there any keyword in systemverilog which will help quickly to get around this ?
Not a SV expert here so an example would really help! Thanks
randc does exactly this. (cyclic randomization)
class A;
randc bit[7:0] m;
endclass
Each time you call randomize() on the same object, it will not repeat value for m until all possible values have been given.
Simulators have limits on how large the cyclic value can be, but the standard requires a minimum of 8-bits. If you have a larger value, then you can use the inside operator.
class A;
rand bit[23:0] r;
bit [23:0] list[$];
constraint c { !(r inside {list}); }
function void post_randomize();
list.push_back(r);
endfunction
endclass
If you really expect to cycle through the list, it might be simpler to build the list first, and then shuffle through the list.
bit [7:0] list[20];
for(int i=0;i<20;i++) list[i] = i+10; // range 10-29
list.shuffle();
// cycle through list[0] ... list[29]
list.shuffle();
// cycle through list[0] ... list[29]
You can declare a variable with randc identifier. This is called 'cyclical random' and will ensure exactly what you are requiring.
Note: This requires a license that supports randomization and random variables. Most commercial simulators do provide this but at a higher cost. If you are constrained by this and need to only use the system calls - $urandom or $urandom_range, I would implement something like a queue that tracks all the values returned.
function automatic void find_unique_num();
int c;
int vals[$];
bit found;
do begin
c = $urandom_range(10, 1);
foreach(vals[i])
if (c == vals[i]) found = 1;
end
while (!found);
vals.push_back(c);
return c
endfunction

"operator symbol not allowed for generic subprogram" from Ada

I want to make subprogram for adding array's elements with Ada.
subprogram "Add_Data" have 3 parameters-
first parameter = generic type array (array of INTEGER or array of REAL)
second parameter = INTEGER (size of array)
third parameter = generic type sum (array of INTEGER -> sum will be INTEGER, array of REAL -> sum will be REAL)
I programmed it from ideone.com.
(I want to see just result by array of INTEGER. After that, I will test by array of REAL)
With Ada.Text_IO; Use Ada.Text_IO;
With Ada.Integer_Text_IO; Use Ada.Integer_Text_IO;
procedure test is
generic
type T is private;
type Tarr is array (INTEGER range <>) of T;
--function "+" (A,B : T) return T;
--function "+" (A, B : T) return T is
--begin
-- return (A+B);
--end "+";
procedure Add_Data(X : in Tarr; Y : in INTEGER; Z : in out T);
procedure Add_Data(X : in Tarr; Y : in INTEGER; Z : in out T) is
temp : T;
count : INTEGER;
begin
count := 1;
loop
temp :=temp+ X(count); //<-This is problem.
count := count + 1;
if count > Y then
exit;
end if;
end loop;
Z:=temp;
end Add_Data;
type intArray is array (INTEGER range <>) of INTEGER;
intArr : intArray := (1=>2, 2=>10, 3=>20, 4=>30, 5=>8);
sum : INTEGER;
procedure intAdd is new Add_Data(Tarr=>intArray, T=>INTEGER);
begin
sum := 0;
intAdd(intArr, 5, sum);
put (sum);
end test;
when I don't overload operator "+", It makes error.
"There is no applicable operator "+" for private type "T" defined."
What can I do for this?
If a generic’s formal type is private, then nothing in the generic can assume anything about the type except that it can be assigned (:=) and that it can be compared for equality (=) and inequality (/=). In particular, no other operators (e.g. +) are available in the generic unless you provide them.
The way to do that is
generic
type T is private;
with function "+" (L, R : T) return T is <>;
This tells the compiler that (a) there is a function "+" which takes two T’s and returns a T; and (b) if the actual T has an operator "+" which matches that profile, to allow it as the default.
So, you could say
procedure intAdd is new Add_Data (T => Integer, ...
or, if you didn’t feel like using the default,
procedure intAdd is new Add_Data (T => Integer, "+" => "+", ...
In addition to not knowing how to declare a generic formal subprogram (Wright has shown how to do this for functions), your code has a number of other issues that, if addressed, might help you move from someone who thinks in another language and translates it into Ada into someone who actually uses Ada. Presuming that you want to become such a person, I will point some of these out.
You declare your array types using Integer range <>. It's more common in Ada to use Positive range <>, because people usually refer to positions starting from 1: 1st, 2nd, 3rd, ...
Generics are used for code reuse, and in real life, such code is often used by people other than the original author. It is good practice not to make unstated assumptions about the values clients will pass to your operations. You assume that, for Y > 0, for all I in 1 .. Y => I in X'range and for Y < 1, 1 in X'range. While this is true for the values you use, it's unlikely to be true for all uses of the procedure. For example, when an array is used as a sequence, as it is here, the indices are immaterial, so it's more natural to write your array aggreate as (2, 10, 20, 30, 8). If I do that, Intarr'First = Integer'First and Intarr'Last = Integer'First + 4, both of which are negative. Attempting to index this with 1 will raise Constraint_Error.
Y is declared as Integer, which means that zero and negative values are acceptable. What does it mean to pass -12 to Y? Ada's subtypes help here; if you declare Y as Positive, trying to pass non-positive values to it will fail.
Z is declared mode in out, but the input value is not referenced. This would be better as mode out.
Y is not needed. Ada has real arrays; they carry their bounds around with them as X'First, X'Last, and X'Length. Trying to index an array outside its bounds is an error (no buffer overflow vulnerabilities are possible). The usual way to iterate over an array is with the 'range attribute:
for I in X'range loop
This ensures that I is always a valid index into X.
Temp is not initialized, so it will normally be initialized to "stack junk". You should expect to get different results for different calls with the same inputs.
Instead of
if count > Y then
exit;
end if;
it's more usual to write exit when Count > Y;
Since your procedure produces a single, scalar output, it would be more natural for it to be a function:
generic -- Sum
type T is private;
Zero : T;
type T_List is array (Positive range <>) of T;
with function "+" (Left : T; Right : T) return T is <>;
function Sum (X : T_List) return T;
function Sum (X : T_List) return T is
Result : T := Zero;
begin -- Sum
Add_All : for I in X'range loop
Result := Result + X (I);
end loop Add_All;
return Result;
end Sum;
HTH

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.