Logical equality for two different vector widths - system-verilog

Why does logical equality for two vectors of different widths have an output like below?
module eq_test;
logic check;
logic [3:0] cmp_0;
logic cmp_1 = 1'b0;
initial begin
for (int i = 0; i < 16; i++) begin
cmp_0 = i;
check = (cmp_0 == cmp_1);
$display("%b == %b is %b", cmp_0, cmp_1, check);
end
end
endmodule
With Vivado Simulator
0000 == 0 is 1
0001 == 0 is 0
0010 == 0 is 0
0011 == 0 is 0
0100 == 0 is 0
0101 == 0 is 0
0110 == 0 is 0
0111 == 0 is 0
1000 == 0 is 0
1001 == 0 is 0
1010 == 0 is 0
1011 == 0 is 0
1100 == 0 is 0
1101 == 0 is 0
1110 == 0 is 0
1111 == 0 is 0
I can assume that the variable with smaller width cmp_1 is expanded (unsigned expand) to the larger variable width cmp_0, is that so?

Yes, the variable with smaller width is expanded to the larger variable width.
This is described in IEEE Std 1800-2017, section 11.6.1 Rules for expression bit lengths.
The number of bits of an expression (known as the size of the
expression) shall be determined by the operands involved in the
expression and the context in which the expression is given.
In Table 11-21, the == operator has this comment:
Operands are sized to max(L(i),L(j))
where i and j represent expressions of an operand, and L(i) represents the bit length of the operand represented by i.
This is true for all simulators, not just for Vivado.

Related

Split array of strings into a matrix of numeric digits

I want to convert n integers to base b, and write every digit as a single number in a matrix.
I get the base b representation with:
stringBaseB=dec2base(0:1:1000,b,10)
but don't know how to split every string into a single char
[[0,0,0,0];[0,0,0,1];[0,0,0,2];...]
I can use array2table to split the individual characters:
tableBaseB=array2table(dec2base(stringBaseB,b,10))
but that's not a numeric matrix. Also, in base b>10 I get alphanumeric characters, which I need to convert to numeric by an equivalence like
alphanumeric=["1","A","c","3"]
numericEquivalence=[1,1+i,-3,0]
There is a vectorized way to do it?
For some base b < 11, where the character array from dec2base is always going to be single-digit numeric characters, you can simply do
b = arrayfun( #str2double, stringBaseB );
For some generic base b, you can make a map between the characters and the values (your numericEquivalence)
charMap = containers.Map( {'1','2','3'}, {1,2,3} );
Then you can use arrayfun (not strictly "vectorized" as you requested but it's unclear why that's a requirement)
stringBaseB=dec2base(0:1:1000,b,10);
b = arrayfun( #(x)charMap(x), stringBaseB );
This gives you a numeric output array, for example stringBaseB=dec2base(0:5,3,10) gives
stringBaseB =
6×10 char array
'0000000000'
'0000000001'
'0000000002'
'0000000010'
'0000000011'
'0000000012'
b =
6x10 double array
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0 0 2
0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 1 1
0 0 0 0 0 0 0 0 1 2

assigning rows and columns

I am trying to plot data to a grid that is made up of hexagons. Because of this, the row lengths alternate between two different values.
ie: a grid would look like this with row lengths 4 and 5
0 0 0 0 0
0 0 0 0
0 0 0 0 0
0 0 0 0
Does any one know a clever way to approach this? I thought about using flags to tell you which row you are in, but feel like there can be a more elegant solution
If all you're trying to do is figure out the row length, it's quite simple: Just use modulus of 2.
In your example, assume the top row has an index of 0, and the index increases as you go down.
rowLength = rowIndex % 2 == 0 ? 5 : 4;
0 % 2 == 0 --> 5
1 % 2 == 1 --> 4
2 % 2 == 0 --> 5
3 % 2 == 1 --> 4
Alternatively, you can have the rows always have a length of five, and on every other row store a value (such as null) that indicates the value should be skipped:
0 0 0 0 0
0 0 0 0 (null)
0 0 0 0 0
0 0 0 0 (null)
One solution is to write a "generic" pattern generator:
Takes a pattern, in your case "0 ". This specific pattern uses 2 characters.
Given number of rows, say nR, and number of characters per row, say nC (in your case, nC=5*2-1=9): repeat the pattern into one string that contains this pattern, however, without proper line breaks.
Using number of characters per row nC: insert a line break exactly after nC characters continually throughout your string.
This can be done in a somewhat "swifty functional" manner:
func plotGrid(numRows: Int, numCharsPerRow: Int, myPattern: String) {
let totalNumChars = numRows*numCharsPerRow
let numCharsInPattern = myPattern.characters.count
let gridTemplate = [String](count:totalNumChars/numCharsInPattern + totalNumChars%numCharsInPattern, repeatedValue: myPattern).reduce("", combine: +)
let grid = 0.stride(to: totalNumChars, by: numCharsPerRow)
.map {
i -> String in
let a = gridTemplate.startIndex.advancedBy(i)
let b = a.advancedBy(numCharsPerRow, limit: gridTemplate.endIndex)
return gridTemplate[a..<b] + "\n"
}.reduce("", combine: +)
print(grid)
}
With the results (for your example and another 4-character pattern example, respectively)
plotGrid(5, numCharsPerRow: 9, myPattern: "0 ")
//0 0 0 0 0
// 0 0 0 0
//0 0 0 0 0
// 0 0 0 0
//0 0 0 0 0
plotGrid(4, numCharsPerRow: 10, myPattern: "X O ")
//X O X O X
//O X O X O
//X O X O X
//O X O X O
Note, however, that in the let grid assignment, you create an array that is immediately reduced, so there will be an unnecessary overhead here, especially for large grids. The imperative approach below should be faster, but the above, perhaps, neater.
One possible (among many) classic imperative approach:
let numRows = 5
let numCharsPerRow = 9
let myPattern = "0 "
let totalNumChars = numRows*numCharsPerRow
var grid = "0"
var addZero = false
for i in 2...totalNumChars {
grid += addZero ? "0" : " "
addZero = !addZero
if i%numCharsPerRow == 0 {
grid += "\n"
}
}
print(grid)
//0 0 0 0 0
// 0 0 0 0
//0 0 0 0 0
// 0 0 0 0
//0 0 0 0 0

Convert a matrix of type char to type logical in matlab

Hello I have a char matrix that represents a binary numbers. For example:
0000
1010
0111
.
.
.
1010
How can I convert it to a logical matrix?
You can compare it with character '1'
>> A=['0101';'1011']
A =
0101
1011
>> A=='1'
ans =
0 1 0 1
1 0 1 1
Is this what you want?
a = {'0000'; '1010'; '0111'};
b = logical(double(cell2mat(a)) - 48);
gives,
>> b
b =
0 0 0 0
1 0 1 0
0 1 1 1
>> class(b)
ans =
logical
Try
b_bin = logical(b(:)'-'0')
if b is the name of your matrix.

Improve naive gauss elimination, when zero elements are known

I wrote naive gauss elimination without pivoting:
function [x] = NaiveGaussianElimination(A, b)
N = length(b);
x = zeros(N,1);
mulDivOp = 0;
subAddOp = 0;
for column=1:(N-1)
for row = (column+1):N
mul = A(row,column)/A(column,column);
A(row,:) = A(row,:)-mul*A(column,:);
b(row) = b(row)-mul*b(column);
mulDivOp = mulDivOp+N-column+2;
subAddOp = subAddOp +N-column+1;
end
end
for row=N:-1:1
x(row) = b(row);
for i=(row+1):N
x(row) = x(row)-A(row,i)*x(i);
end
x(row) = x(row)/A(row,row);
mulDivOp = mulDivOp + N-row + 1;
subAddOp = subAddOp + N-row;
end
x = x';
mulDivOp
subAddOp
return
end
but I am curious if I can reduce the number of multiplications/divisions and additions/subtractions in case I know which elements of matrix are 0:
For N = 10:
A =
96 118 0 0 0 0 0 0 0 63
154 -31 -258 0 0 0 0 0 0 0
0 -168 257 -216 0 0 0 0 0 0
0 0 202 24 308 0 0 0 0 0
0 0 0 -262 -36 -244 0 0 0 0
0 0 0 0 287 -308 171 0 0 0
0 0 0 0 0 197 229 -258 0 0
0 0 0 0 0 0 -62 -149 186 0
0 0 0 0 0 0 0 -43 255 -198
-147 0 0 0 0 0 0 0 -147 -220
(non-zero values are from randi). In general, non-zero elements are a_{1, N}, a_{N,1} and a_{i,j} when abs(i-j) <= 1.
Probably not. There are nice algorithms for reducing tridiagonal matrices (which these aren't, but they are close) to diagonal matrices. Indeed, this is one way in which the SVD of a matrix is produced, using orthogonal similarity transformations, not Gaussian elimination.
The problem is that when you use Gaussian elimination to remove the nonzero entries in the first column, you will have introduced additional nonzero entries in the other columns. The further you proceed, the more you destroy the structure of the matrix. It may be that Gaussian elimination is simply the wrong approach for the problem you are trying to solve, at least if you are trying to exploit the structure of the matrix.

Finding consecutive 00's and 11's in a vector

I have a vector a = 1111000011100001110000100100 and I have to compute two values based on it: p00 and p11.
p00 is the number of times 00 is occurring in the vector, divided by the total number of zeros. For example, in the above code then number of times 00 is occurring is 8/16 (total number of zeros).
Similarly, p11 is the number of occurrences of 11 divided by the total number of ones.
How can this be implemented in Matlab?
The safest and most generic way to do it is using regular expressions, because of the way they match runs.
a = [1 1 1 1 0 0 0 0 1 1 1 0 0 0 0 1 1 1 0 0 0 0 1 0 0 1 0 0]
s = char(a + '0');
p00 = numel(regexp(s, '00')) / sum(a == 0)
p11 = numel(regexp(s, '11')) / sum(a == 1)
NOTE:
I was tempted to do something along the following lines:
a = [1 1 1 1 0 0 0 0 1 1 1 0 0 0 0 1 1 1 0 0 0 0 1 0 0 1 0 0]
n = numel(a);
p00 = sum(a(1:n-1) == 0 & a(2:n) == 0) / sum(a == 0)
p11 = sum(a(1:n-1) == 1 & a(2:n) == 1) / sum(a == 1)
But this won't give the correct result, because it counts the sequence 0 0 0 0 as 3, rather than 2.
I would add the vector to itself shifted with one element to the right. The number of two-s will be the number of 11-s. The number of 0-s will be the number of 00-s. I think this is a natural solution in MATLAB.
Alternatively you could implement finite state machines to parse your vector.
a2 = a(2:end)+a(1:end-1);
p11 = length(find(a2 == 2))/length(find(a));
p00 = length(find(a2 == 0))/length(find(a==0));
The proposed solution was wrong!!!
Here is one that should work, but is not very efficient (but faster than the regexp solution):
d0=0; i=1;
while i<length(a)
if (a(i) == 0 & a(i)==a(i+1)) d0 = d0+1; i = i+1; end;
i=i+1;
end
p00 = d0/sum(a == 0)