I am a new SystemVerilog user and I have faced a strange (from my point of view) behavior of combination of unique method called for fixed array with with operator.
module test();
int arr[12] = '{1,2,1,2,3,4,5,8,9,10,10,8};
int q[$]
initial begin
q = arr.unique() with (item > 5 ? item : 0);
$display("the result is %p",q);
end
I've expected to get queue {8,9,10} but instead I have got {1,8,9,10}.
Why there is a one at the index 0 ?
You are trying to combine the operation of the find method with unique. Unfortunately, it does not work the way you expect. unique returns the element, not the expression in the with clause, which is 0 for elements 1,2,3,4 and 5. The simulator could have chosen any of those elements to represent the unique value for 0(and different simulators do pick different values)
You need to write them separately:
module test();
int arr[$] = '{1,2,1,2,3,4,5,8,9,10,10,8};
int q[$]
initial begin
arr = arr.find() with (item > 5);
q = arr.unique();
$display("the result is %p",q);
end
Update explaining the original results
The with clause generates a list of values to check for uniqueness
'{0,0,0,0,0,0,0,8,9,10,10,8};
^. ^ ^ ^
Assuming the simulator chooses the first occurrence of a replicated value to remain, then it returns {arr[0], arr[7], arr[8], arr[9]} from the original array, which is {1,8,9,10}
Related
If I define my array like this:
array[_, 1..2] of J: A;
where J is a enum, what function can I use to get the length of the first dimension of A? The length function returns 14 (and states that it doesn't work for multiple dimensions). I had it hard-coded like so in my testing, but it won't always be 13:
constraint forall(row in 1..13)(S[A[row, 2]] >= C[A[row, 1]]);
The length function is really only meant for getting the number of elements. When you want the retrieve indexes of an array, you should instead use the index_set function. This returns the actual index set, which you can iterate over: i in index_set(A)
For multidimensional arrays there are specific functions for each index set of the array. For example, to get the first index set from a two-dimensional array (as in your code fragment) you can use the function index_set_1of2
In q, I am trying to call a function f on an incrementing argument id while some condition is not met.
The function f creates a table of random length (between 1 and 5) with a column identifier which is dependent on the input id:
f:{[id] len:(1?1 2 3 4 5)0; ([] identifier:id+til len; c2:len?`a`b`c)}
Starting with id=0, f should be called while (count f[id])>1, i.e. so long until a table of length 1 is produced. The id should be incremented each step.
With the "repeat" adverb I can do the while condition and the starting value:
{(count x)>1} f/0
but how can I keep incrementing the id?
Not entirely sure if this will fix your issue but I was able to get it to work by incrementing id inside the function and returning it with each iteration:
q)g:{[id] len:(1?1 2 3 4 5)0; id[0]:([] identifier:id[1]+til len; c2:len?`a`b`c);#[id;1;1+]}
In this case id is a 2 element list where the first element is the table you are returning (initially ()) and the second item is the id. By amending the exit condition I was able to make it stop whenever the output table had a count of 1:
q)g/[{not 1=count x 0};(();0)]
+`identifier`c2!(,9;,`b)
10
If you just need the table you can run first on the output of the above expression:
q)first g/[{not 1=count x 0};(();0)]
identifier c2
-------------
3 a
The issue with the function f is that when using over and scan the output if each iteration becomes the input for the next. In your case your function is working on a numeric value put on the second pass it would get passed a table.
I noticed this interesting thing about the max() and min() functions in SV LRM (1800-2012) 7.12 (Array manipulation methods). I tried out the max() and min() functions in a dummy SV file
int a[3] = {0,5,5};
int q[$];
int b;
q = a.max(); // legal
b = a.max(); // illegal
The illegal statement error was
Incompatible complex type assignment
Type of source expression is incompatible with type of target expression.
Mismatching types cannot be used in assignments, initializations and
instantiations. The type of the target is 'int', while the type of the
source is 'int$[$]'.
So I commented out the illegal statement and tested it. It compiled and ran fine but I was hoping to get some more insight as to why the function returns a queue and not a single element - I printed out the contents of q and the size, but the size is still 1 and 5 is being printed just once. Kind of redundant then to make the max() and min() functions return a queue ?
The "SystemVerilog for Verification" book by Chris Spear and Greg Tumbush has a good explanation on this topic in Chapter 2.6.2, which I am quoting below:
"The array locator methods find data in an unpacked array. At first
you may wonder why these return a queue of values. After all, there
is only one maximum value in an array. However, SystemVerilog needs a
queue for the case when you ask for a value from an empty queue or
dynamic array."
It returns a queue to deal with empty queues and when the with () conditions have no matches. The the empty queue return is a a way to differentiate a true match from no matches.
Consider the below code. to find the minimum value of a that is greater than 5. a has data but none of its entries have above 5. b is empty, so it will return an empty. c will return 7.
int a[3] = '{0,5,5};
int b[$] = '{};
int c[4] = '{0,15,5,7};
int q[$];
q = a.min() with (item > 5); // no items >5, will return an empty queue
q = b.min(); // queue is empty, will return an empty queue
q = c.min() with (item > 5); // will return a queue of size 1 with value 7
I believe the example results as per Greg's answer is not correct.
As per System Verilog Language:
min() returns the element with the minimum value or whose expression evaluates to a minimum.
max() returns the element with the maximum value or whose expression evaluates to a maximum.
So, when with expression is evaluated, the resultant value will be:
a.min() with (item > 5); {0,0,0} -> Minimum is 0 and corresponding item is 5.
c.min() with (item > 5); {0,1,0,1}-> Minimum is 0 and corresponding item is 5.
Since, example demonstrates the usage of min, the result will be:
q = a.min() with (item > 5); // A queue of size 1 with value 5.
q = c.min() with (item > 5); //A queue of size 1 with value 5.
I am completely new to Max and am struggling to understand how to use arrays and Javascript parameters.
I have one working js object that outputs an array:
var inlets = 1;
var outlets = 1;
function getRandomChordProgression()
{
outlet(0, [1,4,5]);
return [1,4,5];
}
And then later I want to use that array in another js object, that takes an array and an integer:
var inlets = 2;
var outlets = 1;
function getCurrentChord(chords, barNumber)
{
var chord = chords[barNumber % 3];
outlet(0, chord);
return chord;
}
I tried the below, but the js gets undefined inputs.
The first thing to notice is that in Max Msp, in order to assign a list to a single symbol, you need to use the "tosymbol" object. Even if lists are effectively considered mono dimensional arrays in Max Msp, in order to be understood by javascript they first need to be converted. Once the list is converted into a symbol, we can join it with the integer coming from the number box, pack it with the getCurrentChord message and feed it into the getCurrentChord.js object.
You will see that by converting a list into a symbol every character in the array, including the spaces, is seen as part of the array. So using your example, an array composed by 3 integers will have 5 positions occupied, from 0 to 4. In order to make this work, inside the second .js script the modulo operator needs to be set to 5 in order to have a maximum remainder of 4. This means that by setting the number box to 1 or 3 you will have an empty output. So you need to decide how and if to parse the input or the output in order to obtain only the values desired.
var inlets = 2;
var outlets = 1;
function getCurrentChord(chords, barNumber)
{
var chord = chords[barNumber % 5];
outlet(0, chord);
}
Hope that helps!
I want to replace the value of the fields in a structure array. For example, I want to replace all 1's with 3's in the following construction.
a(1).b = 1;
a(2).b = 2;
a(3).b = 1;
a([a.b] == 1).b = 3; % This doesn't work and spits out:
% "Insufficient outputs from right hand side to satisfy comma separated
% list expansion on left hand side. Missing [] are the most likely cause."
Is there an easy syntax for this? I want to avoid ugly for loops for such simple operation.
Credits go to #Slayton, but you actually can do the same thing for assigning values too, using deal:
[a([a.b]==1).b]=deal(3)
So breakdown:
[a.b]
retrieves all b fields of the array a and puts this comma-separated-list in an array.
a([a.b]==1)
uses logical indexing to index only the elements of a that satisfy the constraint. Subsequently the full command above assigns the value 3 to all elements of the resulting comma-separated-list according to this.
You can retrieve that the value of a field for each struct in an array using cell notation.
bVals = {a.b};
bVals = cell2mat( bVals );
AFAIK, you can't do the same thing for inserting values into an array of structs. You'll have to use a loop.