Best way to sort a SystemVerilog associative array? - sorting

I have an associative array and I need to process the items in that array in a certain order. What's the best way to do that?
Here is an example. Suppose I have an associative array of people's names and their ages:
int age[string];
age["bob"] = 32;
age["timmy"] = 4;
age["tyrian"] = 31;
I need to process this array from youngest person to oldest. Currently, I'm creating another array for indexing and sorting that.
string sorted_age[$];
// Is there a more efficient way to do this sort?
foreach (age[i]) begin
bit inserted = 0;
foreach (sorted_age[j]) begin
if (age[i] < age[sorted_age[j]]) begin
sorted_age.insert(j, i);
inserted = 1;
break;
end
end
if (!inserted) begin
sorted_age.push_back(i);
end
end
Full example on EDA Playground: http://www.edaplayground.com/x/2_8

You could add one more queue then use the built in array methods. I haven't done a performance test (which could be simulator dependent), but it is fewer lines of code and easy to read.
string sorted_age[$];
int store_age [$];
store_age = age.unique(); // find all unique ages (no duplicates)
store_age.sort(); // sort by age
foreach(store_age[i]) begin
// multi entry puch_back
sorted_age = {sorted_age, age.find_index with (item==store_age[i])};
end
Full example on EDA Playground

You can use the sort() with functionality:
// Create an aray of people's names
string sorted_age[] = new [age.size()];
int index = 0;
foreach (age[i]) begin
sorted_age[index++] = i;
end
// Sort the array
sorted_age.sort() with (age[item]);
Full example on EDA Playground: http://www.edaplayground.com/x/3Mf

Related

randomizing number of 1's in an array in UVM without using $countones?

In UVM , I want to constraint an array such that I can fix the number of ones in an array to 3, I have written the following code using constraint which uses $countones, but how to do it without using $countones ??
class class_1;
rand bit[31:0] array;
constraint three_ones {
$countones(array) == 3;
}
endclass
What you wrote is equivalent to
constraint three_ones {
int'(array[0]) + int'(array[1]) + int'(array[2]) + ... + int'(array[31]) )
== 3;
}
endclass
Update
To do this programmatically without any functions, you can create another array with a list of indexes that should be set to one. The size of the array is the number of one you want set.
bit [0:255] array;
int countones = 5;
rand int unsigned bitset[];
constraint c_bits { bitset.size == countones;
foreach(bitset[i]) bitset[i] inside {[0;$bits(array)-1];
unique {bitset};
}
function void post_randomize();
array = 0;
foreach(bitset[i]) array[bitset[i]] = 1'b1;
endfunction
Now there is a way to do this without the unique constraint, and without post_randomize, but that's too much work for me.

Insert a map into other map with a unique type key

hello guys i am new to maps in C++ i am having a question regarding copying a particular type map to another map of same kind the details are shown below
I initially declared a map like this
map<string,int> objmap,obj_porcess ;
for(int i = 0; i < 10]; i++) {
obj_process[to_string(i)]=i+10//some processing the to_string is just in case but i have strings with names for all 10 values
}
like
obj_process["today"]=1;
obj_process["yesterday"]=-1;
obj_process["tommorow"]=2;
now i want to define some thing like this just my key word should be added with the process and remaining all can be same for all the keys from obj_process
objmap["process_"+"today"] = obj_process["today"];
instead of defining all 10 can i have a simple code cause in here i took an example of 10 but i have like 200 set of different strings in the key of map
I think this is what you need:
map<string,int> objmap;
map<string,int> obj_porcess;
//
// Fill up the contents of obj_porcess
//
// Copy objects from obj_porcess to objmap using a computed key.
for ( auto& item : obj_process )
{
objmap[std::string("process_") + item.first] = item.second;
}
Could you iterate over the map?
for(auto &i : obj_process)
objmap["process" + i.first] = i.second;

Cilk_for returns wrong data in array

I am new to multi threading programming. Recently, i have a project, which i apply cilk_for into it. Here is the code:.
void myfunction(short *myarray)
{
m128i *array = (m128i*) myarray
cilk_for(int i=0; i<N_LOOP1; i++)
{
for(int z = 0; z<N_LOOP2; z+=8)
{
array[z] = _mm_and_si128(array[z],mym128i);
array[z+1] = _mm_and_si128(array[z+1],mym128i);
array[z+2] = _mm_and_si128(array[z+2],mym128i);
array[z+3] = _mm_and_si128(array[z+3],mym128i);
array[z+4] = _mm_and_si128(array[z+4],mym128i);
array[z+5] = _mm_and_si128(array[z+5],mym128i);
array[z+6] = _mm_and_si128(array[z+6],mym128i);
array[z+7] = _mm_and_si128(array[z+7],mym128i);
array+=8;
}
}
}
After the above code ran, ridiculous thing happens. The data in array isn't updated correctly. For example, if i have an array with 1000 elements, there is a chance that the array will be updated correctly (1000 elements are AND-ed). But there is also a chance that some parts of the array will be omited (first element to 300th element are AND-ed, 301st element to 505th element aren't AND-ed, 506th element to 707th element are AND-ed, etc,...). These omited parts are random in each individual run, so i think the problem here is about cache miss. Am I right? Please tell me, any help is appreciated. :)
The issue is that the array pointer is not synchronized between the threads cilk is spawning and your array variable is incremented in each loop iteration. This works only in a linear execution. In your code snippet multiple threads are accessing the same elements in your array while other parts of the array are not processed at all.
To solve this I would propose to calculate the index within the outer loop so that every thread spawned with Cilk is able to calculate the address independently. Maybe you can do something like:
void myfunction(short *myarray)
{
cilk_for (int i=0; i<N_LOOP1; i++)
{
m128i *array = (m128i*) myarray + i * N_LOOP2 * 8;
for(int z = 0; z<N_LOOP2; z+=8)
{
array[z] = _mm_and_si128(array[z],mym128i);
array[z+1] = _mm_and_si128(array[z+1],mym128i);
array[z+2] = _mm_and_si128(array[z+2],mym128i);
array[z+3] = _mm_and_si128(array[z+3],mym128i);
array[z+4] = _mm_and_si128(array[z+4],mym128i);
array[z+5] = _mm_and_si128(array[z+5],mym128i);
array[z+6] = _mm_and_si128(array[z+6],mym128i);
array[z+7] = _mm_and_si128(array[z+7],mym128i);
array+=8;
}
}
}
BTW: Why do you need to do a manual loop unrolling here? The compiler should do that automatically.

Converting an if code into forloop statement

Right now i have to write a code that will print out "*" for each collectedDots, however if it doesn't collect any collectedDots==0 then it print out "". Using too many if statements look messy and i was wandering how you would implement the forloop in this case.
As a general principle the kind of rearrangement you've done here is good. You have found a way to express the rule in a general way rather than as a sequence of special cases. This is much easier to reason about and to check, and it's obviously extensible to cases where you have more than 3 dots.
You probably have made an error in confusing your target number and the iteration value, I assume that collectedDots contains the number of dots you have (as per your if statement) and so you need to introduce a variable to count up to that value
for (int i =0; i <= collectedDots; i++)
{
stars = "*";
System.out.print(stars);
}
Ok, so you already have a variable called collectedDots that is a number which tells you how many stars to print?
So your loop would be something like
for every collected dot
print *
But you can't just print it out, you need to return a string that will be printed out. So it's more like
for every collected dot
add a * to our string
return the string
They key difference between this and your attempt so far is that you were assigning a star to be your string each time through the loop, then at the end of it, you return that string–no matter how many times you assign a star to the string, the string will always just be one star.
You also need a separate variable to keep track of your loop, this should do the trick:
String stars = "";
for(int i = 0; i < collectedDots; i++)
{
stars = stars + "*";
}
return stars;
You are almost correct. Just need to change range limit of looping. Looping initial value is set to 1. So whenever you have collectedDots = 0, it will not go in loop and will return "", as stars is intialized with "" before loop.
String stars = "";
for (int i =1; i <= collectedDots; i++)
{
stars = "*";
System.out.print(stars);
}
return stars;

Array List looping for a duplicate value

I am looking if there is an "easy" or simple way to make an array of something, Lets say Icecreams.. this would be a class of icecream with various Attributes (ID, flavour, Size, scoops), i would like to run an array that gathers every ice cream ordered and then searches through this list for any duplicate values (2+ same size)
First idea i had was a for loop that creates the array than grabs the ice cream ID for the first instance, and checks its "flavour" against the array, if no duplicate is found the ID is increased by 1 (ID++) and then that Ice creams flavour is ran in the array, if a match is found i would set a Boolean to true.
Every approach i seem to take appears to be rather long winded and i haven't got one working as of yet. hoping some fresh/more experienced eyes would help on this.
In answer to below;
The XML would hold something like below
<iceCream id=1>
<flavour>chocolate</flavour>
<scoops>5</scoops>
</iceCream>
<iceCream id=2>
<flavour>banana</flavour>
<scoops>2</scoops>
</iceCream>
I would want to use drools (probably an array list?) to gather each icecream tag and allow me to check if any of the icecreams have the same flavour and output something (set a boolean to true) if a match is found, My understand was to make an array then run each icecream though the array by using its ID to identify it and inside each loop do ID +1 (int ID = 1) then in the lopp ID++. Aswell as search through the flavour childtag.
int ID = 0;
boolean match = false;
ArrayList iceCreams = new ArrayList($cont.getIceCreams());
for(iceCream $Flavour: (ArrayList<iceCream>)iceCreams)
{
ID++
if($Flavour.getFlavour().equals(icecream with id of (ID variable).getFlavour)
{
match = true;
}
}
if(match)
{etc etc etc}
Something along these lines if this helps?
1) If you have control over the first array creation, why dont you make sure that while insertion, you insert only the icecreams that are unique. So, while you are inserting into the array say ID=1, first iterate through the array and check if there is an icecream in the array with ID as 1, if not you put this into the array and do other stuff.
2) Searching part: now while inserting, make sure that you are doing so based on the ascending oder of IDs, so you can perform binary search for the same.
Note: I dont know drools, i have just posted a logic as per my understanding of the problem.
I don't know drools either, but I'll post the some pseudo code for what I think you are trying to accomplish:
for(i = 0; i < len(ice_cream_array); i++)
{
for(j = (i + 1); j < len(ice_cream_array); j++)
{
if (ice_cream_array[i] == ice_cream_array[j])
break from inner loop
else
there is no match
}
}
You may also want to look up bubble sorts and binary searches.

Resources