How to concatenate two arrays in VHDL - arrays

I have some types like this :
Type MyCharacters is ('0', '1' ... '9', 'A', 'B', ... 'Z');
Type CharArray_8 is array(1 to 8) of MyCharacters;
Type CharArray_16 is array(1 to 16) of MyCharacters;
Type CharArray_32 is array(1 to 32) of MyCharacters;
and 4 Signals with this types :
Signal S1, S2 : CharArray_8;
Signal S3 : CharArray_16;
Signal S : CharArray_32;
I want to concatinate S1, S2 and S3 and assign the result to S, like this :
S <= S1 & S2 & S3;
but this code is wrong and have error, how I should concatenate them ?
Should Array types be declared as SubType of MyCharacters ?

but this code is wrong and have error, how I should concatenate them ?
There isn't an implicitly declared concatenation operator (&) defined for multiple array types. You need to either declare an overload operator allowing different types with the same element types to be concatenated (which is burdensome, requiring at least three functions for each possible combination) or make the array values the same type either by using type conversion or as in these first two answers declaring a single unbound array type. The array types are eligible for type conversion, having index ranges compatible with type S3 and the same element type.
Should Array types be declared as SubType of MyCharacters ?
In addiition to named subtypes object declarations shown by Renaud Pacalet subtypes can be defined through subtype indications (a type mark and a constraint) in object declarations:
type mychararray is array(natural range <>) of MyCharacters;
signal S1, S2: mychararray(1 to 8);
signal S3: mychararray(1 to 16);
signal S: mychararray(1 to 32);
The & operator is implicitly declared following the type declaration (a one dimensional array type).
See IEEE Std 1076-2008 6.4 Objects, 6.3 Subtype declarations, 5.3.2 Array types (mychararray is an unbounded array type) and 9.2.5 Adding operators (& concatenation operator).
The Mycharacters type is a scalar enumerated character type (discrete values), mychararray is an array type (elements, here the scalar type Mycharacters).
Renaud Pacalet asks about the use of the string type, your 36 value MyCharacters type requires 6 bit binary values to represent after synthesis, three quarters of the way to the std.STANDARD character type (requiring 8 bit binary values). On the other hand you can convert to ASCII values by adding the position value of a MyCharacters to "110000" (16#30# or 48, noting the 'LEFT index position of your array type is '0') if you include the :, ;, <, =, >, ?, and# characters before A:
30 0 31 1 32 2 33 3 34 4 35 5 36 6 37 7
38 8 39 9 3a : 3b ; 3c < 3d = 3e > 3f ?
40 # 41 A 42 B 43 C 44 D 45 E 46 F 47 G
48 H 49 I 4a J 4b K 4c L 4d M 4e N 4f O
50 P 51 Q 52 R 53 S 54 T 55 U 56 V 57 W
58 X 59 Y 5a Z
Instead of declaring type MyCharacters you could use type character with appropriate index constraints in your object declarations:
subtype MyCharacters is character('0' to 'Z');
type mychararray is array(natural range <>) of MyCharacters;
signal S1, S2: mychararray(1 to 8);
signal S3: mychararray(1 to 16);
signal S: mychararray(1 to 32);
Bundle that into a Minimal, Complete and Verifiable example:
entity mychar_concat is
end entity;
architecture foo of mychar_concat is
subtype MyCharacters is character range '0' to 'Z'; -- 16#30# to 16#5A#
type mychararray is array (natural range <>) of
character range '0' to 'Z';
signal S1: mychararray (1 to 8) := "01234567";
signal S2: mychararray (1 to 8) := "89:;<=>?";
signal S3: mychararray (1 to 16) := "#ABCDEFGHIJKLMNO";
signal S: mychararray (1 to 32);
function valuehex (inp: MyCharacters) return string is
variable retval: string (1 to 2);
variable hexval: integer;
variable remainder: integer;
begin
hexval := character'pos(inp) / 16;
retval(1) := character'val(hexval + 48); -- where '0' 'pos is 48.
-- expects inp is less than 'Z', (9 * 16 > 'Z')
remainder := character'pos(inp) rem 16;
if remainder < 10 then
retval(2) := character'val(remainder + 48); -- offset to '0'
else
retval(2) := character'val(remainder + 48 + 7); -- offset to 'A'
end if;
return retval;
end function;
begin
S <= S1 & S2 & S3; -- & implicity declared for mychararray
MONITOR:
process
begin
wait on S;
wait for 0 ns; -- skip "00000000000000000000000000000000" default S
report "S = " & string(S);
report "valuehex(MyCharacters'LEFT) = " &
valuehex(MyCharacters'LEFT) & "H";
report "valuehex(MyCharacters'RIGHT) = " &
valuehex(MyCharacters'RIGHT) & "H";
end process;
end architecture;
ghdl -r mychar_concat
mychar_concat.vhdl:37:9:#0ms:(report note): S = 0123456789:;<=>?#ABCDEFGHIJKLMNO
mychar_concat.vhdl:38:9:#0ms:(report note): valuehex(MyCharacters'LEFT) = 30H
mychar_concat.vhdl:40:9:#0ms:(report note): valuehex(MyCharacters'RIGHT) = 5AH
Where 30H is a '0' and 5AH is a 'Z'. Additionally see 16.2.2 Predefined attributes of types and objects.
We see that we derive 7 bit ASCII or 8 bit ISO/IEC 8859-1 character values (See 15.2 Character set) from MyCharacters values with little effort.
In either case the concatenation operators (array & array, element & array, array & element) are implicitly declared following the declaration of a single dimensional array type (mychararray here).

No, your array types cannot be declared as subtypes of MyCharacters, which is an enumerated type, not an array type.
Your 3 array types are different and independent types. The concatenation operator (&) is not defined on the combination of them that you use. You could overload it for this specific case but the simplest is probably be to use a common base type, that is, a parent unconstrained array type and declare subtypes of it with fixed ranges:
type mychararray is array(natural range <>) of MyCharacters;
subtype CharArray_8 is mychararray(1 to 8);
subtype CharArray_16 is mychararray(1 to 16);
subtype CharArray_32 is mychararray(1 to 32);
This way, they would all have the same base type and the implicit concatenation operator that is automatically declared with the mychararray type would work on any combination of them (assuming the size of the result is the same as the size of the variable it is assigned to, of course).
Note: I guess that you already know the string type (array of characters)?

Related

Does MATLAB support truly 1d arrays?

It would really help me reason about my MATLAB code if I didn't have to worry about accidental 2d operations. For instance, if I want to do element-wise multiplication of 1d arrays, but one is a row and another is a column, I end up with a 2d result.
>> a = 1:8;
>> a = a(:);
>> a .* cumsum(ones(8))
ans =
1 1 1 1 1 1 1 1
4 4 4 4 4 4 4 4
9 9 9 9 9 9 9 9
16 16 16 16 16 16 16 16
25 25 25 25 25 25 25 25
36 36 36 36 36 36 36 36
49 49 49 49 49 49 49 49
64 64 64 64 64 64 64 64
I'd like to prevent this type of thing, and likely other problems that I can't foresee, by keeping all my arrays 1d wherever I can. But every time I check the size() of vector, I get at least 2 elements back:
>> size(1:1:6)
ans =
1 6
>> size(linspace(0, 5, 10))
ans =
1 10
I've tried the suggestions at How to create single dimensional array in matlab? and some of the options here (PDF download), and I can't get a "truly" 1d array. How would you deal with this type of issue?
There is no such thing as 1D array. The documentation says (emphasis mine):
All MATLAB variables are multidimensional arrays, no matter what type of data. A matrix is a two-dimensional array often used for linear algebra.
You may use isvector, isrow and iscolumn to identify vectors, row vectors and column vectors respectively.
#Sardar has already said the last word. Another clue is ndims:
N = ndims(A) returns the number of dimensions in the array A. The
number of dimensions is always greater than or equal to 2. ...
But about your other question:
How would you deal with this type of issue?
There's not much you can do. Debug, find the mistake and fix it. If it's some one-time script, you are done. But if you are writing functions that may be used later, it's better to protect them from accepting arguments with unequal dimensions:
function myFunc(A, B)
if ndims(A)~=ndims(B) || any(size(A)~=size(B))
error('Matrix dimensions must agree.');
end
% ...
end
Or, if your function really needs them to be vectors:
function myFunc(A, B)
if ~isvector(A) || ~isvector(B) || any(size(A)~=size(B))
error('A and B must be vectors with same dimensions.');
end
% ...
end
You can also validate different attributes of arguments using validateattributes:
function myFunc(A, B)
validateattributes(A, {'numeric'},{'vector'}, 'myFunc', 'A')
validateattributes(B, {'numeric'},{'size', size(A)}, 'myFunc', 'B')
% ...
end
Edit:
Also, if the function only needs the inputs to be vectors and their orientation does not matter, you can modify them inside the function (thanks to #CrisLuengo for commenting).
function myFunc(A, B)
if ~isvector(A) || ~isvector(B) || length(A)~=length(B)
error('A and B must be vectors with the same length.');
end
A = A(:);
B = B(:);
% ...
end
However, this is not recommended when the output of the function is also a vector with the same size as the inputs. This is because the caller expects the output to be in the same orientation as the inputs, and if this is not the case, problems may arise.

How to get the list of indices connecting two 1-d arrays?

Suppose A and B are two 1d arrays of different sizes such that pythonically B = A[C] where C is a particular list of indices meeting some specific but otherwise known condition. How to get C if A and B are both known? I tried C = np.where(np.close(A, B)) but I get the following error message:
File "/home/username/../my_script.py", line 897, in get_histogram
i0, i1 = np.where(np.isclose(hist_xs, vals1)), np.where(np.isclose(hist_ys, vals2))
File "<__array_function__ internals>", line 6, in isclose
File "/usr/local/anaconda3/lib/python3.7/site-packages/numpy/core/numeric.py", line 2260, in isclose
return within_tol(x, y, atol, rtol)
File "/usr/local/anaconda3/lib/python3.7/site-packages/numpy/core/numeric.py", line 2246, in within_tol
return less_equal(abs(x-y), atol + rtol * abs(y))
ValueError: operands could not be broadcast together with shapes (722,) (1536,)
In other words, I am trying to get only those elements of A whose right indices would correspond to the known B array.
Are you looking for this?:
sorti = np.argsort(A)
C_inv = sorti[np.searchsorted(A,B,sorter=sorti)]
sample code (it works on any sortable array, if your array elements do not have comparison operator, you could write your own. If (less/greater) comparison is not applicable, you would need a for loop to find elements which seems to easy to include here):
A: [89 28 86 73 29 71 37 46 15 52]
B: [86 52 15]
C: [2 9 8]
C_inv: [2 9 8]

Best practices for mapping structure members in an Ada-C binding application

In an Ada-C binding application where the structures(records) need to be passed and read/written between functions defined in C and Ada, what is the best way to declare structers at C and Ada side to ensure correct mapping of members between both the languages. For an example, I declared a structure in C (without using bit fields here), but at Ada side while declaring the same structures(record in Ada) I also used use representation clause to map it bitwise and then used the Convention C pragma. What I saw is that Ada was not reading the structure properly which probably I reckon could be because of wrong bitwise mapping of members.
Just wanted to know what is the best way to ensure correct declaration of same structure at Ada and C side. Should at the C side, the structure be declared using bit fields and then use the same bit scheme to decalre the same structure/record at Ada side using use representation clause?
For Example in C,
/* Position Data Structure */
typedef struct {
float lat;
float lon;
} POSITION_TYPE;
/* Fix Data Structure */
typedef struct {
int32_t fix_id;
char fix_type[20];
char leg_type[7];
char ident[8];
char ident_code[11];
char fix_descriptor[30];
char way_ident[7];
char ref_pt[8];
char ref_pt_code[11];
POSITION_TYPE position;
} FIX_DATA_TYPE;
I declared the same structure in Ada as:
-- Position Record --------------------------------------------------------
type Pos_Rec_Type is
record
Lat : C.C_float;
Lon : C.C_float;
end record;
for Pos_Rec_Type use
record
Lat at 0 range 0..31;
Lon at 0 range 32..63;
end record;
pragma Convention (Convention => C, Entity => Pos_Rec_Type);
-- Fix Data Record --------------------------------------------------------
type Fix_Data_Rec_Type is
record
Fix_Id : C.int;
Fix_Type : C.char_array(1..20);
Leg_Type : C.char_array(1..7);
Ident : C.char_array(1..8);
Ident_Code : C.char_array(1..11);
Fix_Desc : C.char_array(1..30);
Way_Ident : C.char_array(1..7);
Ref_Pt : C.char_array(1..8);
Ref_Pt_Code : C.char_array(1..11);
Position : Pos_Rec_Type;
end record;
for Fix_Data_Rec_Type use
record
Fix_Id at 0 range 0..31;
Fix_Type at 0 range 32..191;
Leg_Type at 0 range 192..247;
Ident at 0 range 248..311;
Ident_Code at 0 range 312..399;
Fix_Desc at 0 range 400..639;
Way_Ident at 0 range 640..695;
Ref_Pt at 0 range 696..759;
Ref_Pt_Code at 0 range 760..847;
Position at 0 range 848..911;
end record;
pragma Convention (Convention => C, Entity => Fix_Data_Rec_Type);
But when I populated this structure at Ada side and transferred it to C functions, I saw that the position record was not decoded correctly. When I disabled the representation clause for Fix_Data_Rec_Type, it worked properly.
If you use -gnatR to print representation info for types, you’ll find that
with rep clause:
for Pos_Rec_Type'Size use 64;
for Pos_Rec_Type'Alignment use 4;
for Pos_Rec_Type use record
Lat at 0 range 0 .. 31;
Lon at 4 range 0 .. 31;
end record;
for Fix_Data_Rec_Type'Object_Size use 928;
for Fix_Data_Rec_Type'Value_Size use 912;
for Fix_Data_Rec_Type'Alignment use 4;
for Fix_Data_Rec_Type use record
Fix_Id at 0 range 0 .. 31;
Fix_Type at 4 range 0 .. 159;
Leg_Type at 24 range 0 .. 55;
Ident at 31 range 0 .. 63;
Ident_Code at 39 range 0 .. 87;
Fix_Desc at 50 range 0 .. 239;
Way_Ident at 80 range 0 .. 55;
Ref_Pt at 87 range 0 .. 63;
Ref_Pt_Code at 95 range 0 .. 87;
Position at 106 range 0 .. 63;
end record;
without rep clause:
for Pos_Rec_Type'Size use 64;
for Pos_Rec_Type'Alignment use 4;
for Pos_Rec_Type use record
Lat at 0 range 0 .. 31;
Lon at 4 range 0 .. 31;
end record;
for Fix_Data_Rec_Type'Size use 928;
for Fix_Data_Rec_Type'Alignment use 4;
for Fix_Data_Rec_Type use record
Fix_Id at 0 range 0 .. 31;
Fix_Type at 4 range 0 .. 159;
Leg_Type at 24 range 0 .. 55;
Ident at 31 range 0 .. 63;
Ident_Code at 39 range 0 .. 87;
Fix_Desc at 50 range 0 .. 239;
Way_Ident at 80 range 0 .. 55;
Ref_Pt at 87 range 0 .. 63;
Ref_Pt_Code at 95 range 0 .. 87;
Position at 108 range 0 .. 63;
end record;
With the rep clause, the Position component is in fact misaligned (106 isn’t divisible by 4).

Can characters be used as indices?

Let's define, for example,
x = 10:10:2000;
As is well known, integer values can be used as indices:
>> x(9)
ans =
90
In Matlab, characters can often be used where a number would be expected, with Matlab doing the conversion automatically. For example, since the ASCII code of 'a' is 97,
>> 'a'+1
ans =
98
Can characters be also used as indices? Does Matlab convert them into integers?
They can be used... but careful if the index is a single colon!
Let's define
>> x = 10:10:2000;
Indexing with 'a' produces the 97-th element of x, as expected:
>> x('a')
ans =
970
However, indexing with ':' is a special case. The string ':' acts as a : index, thus producing a column vector of all values of x. That is, x(':') is the same as x(:):
>> x(':')
ans =
10
20
30
...
1990
2000
This means that the index ':' is being evaluated (x(':') acts like x(:)), whereas other character arrays used as indices are not evaluated (x('a') doesn't act like x(a)):
>> a = 1;
>> x('a')
ans =
970
This also implies that with ':', converting to a numeric type before indexing does matter, unlike with other characters used as indices:
>> x(double('abc'))
ans =
970 980 990
>> x('abc')
ans =
970 980 990
>> x(double(':'))
ans =
580
>> x(':')
ans =
10
20
30
...
1990
2000
The "evaluated" behaviour of ':' used as index was already known. What's surprising is the contrast with other characters or character arrays used as indices (which are not evaluated).
The examples have used a single dimension for simplicity, but the described behaviour also applies to multidimensional indexing. The same behaviour is observed in Octave too.

Decode table construction for base64

I am reading this libb64 source code for encoding and decoding base64 data.
I know the encoding procedure but i can't figure out how the following decoding table is constructed for fast lookup to perform decoding of encoded base64 characters. This is the table they are using:
static const char decoding[] = {62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-2,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51};
Can some one explain me how the values in this table are used for decoding purpose.
It's a shifted and limited ASCII translating table. The keys of the table are ASCII values, the values are base64 decoded values. The table is shifted such that the index 0 actually maps to the ASCII character + and any further indices map the ASCII values after +. The first entry in the table, the ASCII character +, is mapped to the base64 value 62. Then three characters are ignored (ASCII ,-.) and the next character is mapped to the base64 value 63. That next character is ASCII /.
The rest will become obvious if you look at that table and the ASCII table.
It's usage is something like this:
int decode_base64(char ch) {
if (ch < `+` or ch > `z`) {
return SOME_INVALID_CH_ERROR;
}
/* shift range into decoding table range */
ch -= `+`;
int base64_val = decoding[ch];
if (base64_val < 0) {
return SOME_INVALID_CH_ERROR;
}
return base64_val;
}
As know, each byte has 8 bits, possible 256 combinations with 2 symbols (base2).
With 2 symbols is need to waste 8 chars to represent a byte, for example '01010011'.
With base 64 is possible to represent 64 combinations with 1 char...
So, we have a base table:
A = 000000
B = 000001
C = 000010
...
If you have the word 'Man', so you have the bytes:
01001101, 01100001, 01101110
and so the stream:
011010110000101101110
Break in group of six bits: 010011 010110 000101 101110
010011 = T
010110 = W
000101 = F
101110 = u
So, 'Man' => base64 coded = 'TWFu'.
As saw, this works perfectly to streams whith length multiple of 6.
If you have a stream that isn't multiple of 6, for example 'Ma' you have the stream:
010011 010110 0001
you need to complete to have groups of 6:
010011 010110 000100
so you have the coded base 64:
010011 = T
010110 = W
000100 = E
So, 'Ma' => 'TWE'
After to decode the stream, in this case you need to calc the last multiple length to be multiple of 8 and so remove the extra bits to obtain the original stream:
T = 010011
W = 010110
E = 000100
1) 010011 010110 000100
2) 01001101 01100001 00
3) 01001101 01100001 = 'Ma'
In really, when we put the trailing 00s, we mark the end of Base64 string with '=' to each trailing '00 added ('Ma' ==> Base64 'TWE=')
See too the link: http://www.base64decode.org/
Images represented on base 64 is a good option to represent with strings in many applications where is hard to work directly with a real binary stream. Real binary stream is better because is a base256, but is difficult inside HTML for example, there are 2 ways, minor traffic, or more easy to work with strings.
See ASCII codes too, the chars of base 64 is from range '+' to 'z' on table ASCII but there are some values between '+' and 'z' that isn't base 64 symbols
'+' = ASCII DEC 43
...
'z' = ASCII DEC 122
from DEC 43 to 122 are 80 values but
43 OK = '+'
44 isn't a base 64 symbols so the decoding index is -1 (invalid symbol to base64)
45 ....
46 ...
...
122 OK = 'z'
do the char needed to decode, decremented of 43 ('+') to be index 0 on vector to quick access by index so, decoding[80] = {62, -1, -1 ........, 49, 50,51};
Roberto Novakosky
Developer Systems
Considering these 2 mapping tables:
static const char decodingTab[] = {62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-2,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51};
static unsigned char encodingTab[64]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
decodingTab is the reverse mapping table of encondingTab.
So decodingTab[i] should never be -1.
In fact, only 64 values are expected. However decodingTab size is 128.
So, in decodingTab,unexpected index values are set to -1 (an arbitrary number which is not in [0,63])
char c;
unsigned char i;
...
encoding[decoding[c]]=c;
decoding[encoding[i]=i;
Hope it helps.

Resources