I am trying to create a bin in my coverage group to sample values that are multiple of n (where n is a constant integer in my case 15). So far, I have came
up with the following code:
class rx_port;
int unsigned rx_rates[];
...
covergroup rx_cov with function sample (int unsigned rate);
coverpoint rate{
bins no_rate = {0};
bins mul_of_15 = {SOME_PRE_DEFINED_PATTERN};
}
endgroup;
....
endclass
Where SOME_PRE_DEFINED_PATTERN is an array of int from 0 to a system macro with the step of 15. I am not sure if this is the correct/best way of generating this bin. Any better suggestion?
How about writing some helper functions:
module FIFTEEN;
class rx_port;
typedef enum {IS_ZERO, IS_DIVISIBLE_BY_15, IS_NOT_DIVISIBLE_BY_15} rate_type;
function new;
rx_cov=new;
endfunction
local function rate_type covergroup_helper(input int unsigned i);
if (i==0) return IS_ZERO;
if (i%15==0) return IS_DIVISIBLE_BY_15;
return IS_NOT_DIVISIBLE_BY_15;
endfunction
function sample (input int unsigned i);
rx_cov.sample(covergroup_helper(i));
endfunction
covergroup rx_cov with function sample (rate_type rate);
coverpoint rate;
endgroup;
endclass
rx_port R = new;
initial
begin
void'(R.sample(0));
void'(R.sample(30));
void'(R.sample(31));
$display("coverage R.rx_cov.get_coverage= %f", R.rx_cov.get_coverage);
end
endmodule
https://www.edaplayground.com/x/65v7
Here I've written a function that determines whether its input is divisible by 15 or not and another function which calls that to do the sampling. You could combine those functions together, but I like the division of labour in my example.
It turns out that there is a better way:
module FIFTEEN;
class rx_port;
function new;
rx_cov=new;
endfunction
function sample (input int unsigned i);
rx_cov.sample(i);
endfunction
covergroup rx_cov with function sample (int unsigned rate);
coverpoint rate {
bins IS_ZERO = {0};
bins IS_DIVISIBLE_BY_15 = {[1:$]} with ((item % 15)==0);
bins IS_NOT_DIVISIBLE_BY_15 = {[1:$]} with ((item % 15)!=0);
}
endgroup;
endclass
rx_port R = new;
initial
begin
void'(R.sample(0));
void'(R.sample(30));
void'(R.sample(31));
$display("coverage R.rx_cov.get_coverage= %f", R.rx_cov.get_coverage);
end
endmodule
https://www.edaplayground.com/x/3T5v
You can use with to specify bins. So
bins IS_DIVISIBLE_BY_15 = {[1:$]} with ((item % 15)==0);
gives you a bin that is hit whenever the value is divisible by 15 (but not 0) and
bins IS_NOT_DIVISIBLE_BY_15 = {[1:$]} with ((item % 15)!=0);
gives you a bin that is hit whenever the value is not divisible by 15.
Related
I want to instrument my system verilog model for collecting functional coverage on the packets it processes. Specifically, I want to see of the distribution of the packet length in the incoming packet. However, my naive attempt gives "null reference" on sample method below. What is the way to do this?
class packet;
rand bit[7:0] len;
covergroup packet_len_cg;
coverpoint len;
endgroup
endclass
class model;
// Scoreboard calls this to process the input packet
function void run(packet p1);
p1.packet_len_cg.sample(); //FAILS WITH NULL REFERENCE!!
endfunction
endclass
module test;
model m1;
packet p1;
initial begin
m1 = new();
p1 = new();
assert(p1.randomize());
m1.run(p1);
end
endmodule
My code on edaplayground https://www.edaplayground.com/x/2VPm
You need to construct the covergroup.
class packet;
rand bit[7:0] len;
covergroup packet_len_cg;
coverpoint len;
endgroup
function new;
packet_len_cg = new;
endfunction
endclass
Let's say I have an array of parameters I want to use in a covergroup.
In order to interate over all the parameters in the array I tried to use a for loop in this manner:
array [5];
covergroup param;
coefficient: coverpoint array[i]{
bin low = {0:50};
bins high = {51:100};
}
for (i=0;i<5;i++)
param = new(i);
for (i=0;i<5;i++)
param.sample(i);
I'm not really sure how to solve this rather than creating a coverpoint for every cell in the array, but that's just messy and wrong.
Pass the input argument to the covergroup.
int array [5];
covergroup param (ref int a);
coefficient: coverpoint a{
bin low = {0:50};
bins high = {51:100};
}
endgroup
for (i=0;i<5;i++)
param = new(array[i]);
for (i=0;i<5;i++)
param.sample();
How to convert this part of Matlab code to Delphi?
for i=1:popsize
fi=rand(1,dimension); % Generate a vector of uniform random numbers
p=pbest(i,:);
pbest(i,:)=x(i,:);
end
My code:
for i:= 1 to popsize do
begin
fi:= // which function generates vector of uniform random numbers in Delphi?
for k :=1 to popsize do
begin
p:=pbest(i,k);
pbest(i,k):=x(i,k);
end;
end;
You can call Random function to generate a uniformly distributed random value. Calling Randomize once makes Random generate different values in each run.
var
fi: array of Double;
J: Integer;
begin
Randomize;
for J := 0 to dimension - 1 do
fi[J] := Random;
end;
I have a 900×1 vector of values (in MATLAB). Each 9 consecutive values should be averaged -without overlap- result in a 100×1 vector of values. The problem is that the averaging should be weighted based on a weighting vector of [1 2 1;2 4 2;1 2 1]. Is there any efficient way to do that averaging? I’ve heard about conv function in MATLAB; Is it helpful?
conv works by sliding a kernel through your data. But in your case, you need the mask to be jumping through your data, so I don't think conv will work for you.
If you want to use existing MATLAB function, you can do this (I have to assume your weighting matrix has only one dimension) :
kernel = [1;2;1;2;4;2;1;2;1];
in_matrix = reshape(in_matrix, 9, 100);
base = sum(kernel);
out_matrix = bsxfun(#times, in_matrix, kernel);
result = sum(out_matrix,1)/base;
I don't know if there is any clever way to speed this up. bsxfun allows singleton expansion, but maybe not dimension reduction.
A faster way would be to use mex. Open a new file in editor, paste the following code and save file as weighted_average.c.
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
double *in_matrix, *kernel, *out_matrix, base;
int niter;
size_t nrows_data, nrows_kernel;
/* Get number of element along first dimension of input matrix. */
nrows_kernel = mxGetM(prhs[1]);
nrows_data = mxGetM(prhs[0]);
/* Create output matrix*/
plhs[0] = mxCreateDoubleMatrix((mwSize)nrows_data/nrows_kernel,1,mxREAL);
/* Get a pointer to the real data */
in_matrix = mxGetPr(prhs[0]);
kernel = mxGetPr(prhs[1]);
out_matrix = mxGetPr(plhs[0]);
/* Sum the elements in weighting array */
base = 0;
for (int i = 0; i < nrows_kernel; i +=1)
{
base += kernel[i];
}
/* Perform calculation */
niter = nrows_data/nrows_kernel;
for (int i = 0; i < niter ; i += 1)
{
for (int j = 0; j < nrows_kernel; j += 1)
{
out_matrix[i] += in_matrix[i*nrows_kernel+j]*kernel[j];
}
out_matrix[i] /= base;
}
}
Then in command window , type in
mex weighted_average.c
To use it:
result = weighted_average(input, kernel);
Note that both input and kernel have to be M x 1 matrix. On my computer, the first method took 0.0012 second. The second method took 0.00007 second. That's an order of magnitude faster than the first method.
I have a wire vector with 64 bits;
wire [63:0] sout;
I want to compute the sum of these bits or, equivalently, count the number of ones.
What is the best way to do this? (it should be synthesizable)
I prefer using for-loops as they are easier to scale and require less typing (and thereby less prone to typos).
SystemVerilog (IEEE Std 1800):
logic [$clog2($bits(sout)+1)-1:0] count_ones;
always_comb begin
count_ones = '0;
foreach(sout[idx]) begin
count_ones += sout[idx];
end
end
Verilog (IEEE Std 1364-2005):
parameter WIDTH = 64;
// NOTE: $clog2 was added in 1364-2005, not supported in 1364-1995 or 1364-2001
reg [$clog2(WIDTH+1)-1:0] count_ones;
integer idx;
always #* begin
count_ones = {WIDTH{1'b0}};
for( idx = 0; idx<WIDTH; idx = idx + 1) begin
count_ones = count_ones + sout[idx];
end
end
The $countones system function can be used. Refer to the IEEE Std 1800-2012, section "20.9 Bit vector system functions". It might not be synthesizable, but you did not list that as a requirement.
"Best" is rather subjective, but a simple and clear formulation would just be:
wire [6:0] sout_sum = sout[63] + sout[62] + ... + sout[1] + sout[0];
You might be able to think hard and come up with something that produces better synthesized results, but this is probably a good start until a timing tool says it's not good enough.
The following solution uses a function to calculate the total number of set (to High) bits in a 64-bits wide bus:
function logic [6:0] AddBitsOfBus (
input [63:0] InBus
);
AddBitsOfBus[2:0] = '0;
for (int k = 0; k < 64; k += 1) begin // for loop
AddBitsOfBus[6:0] += {6'b00_0000, InBus[k]};
end
endfunction
The following synthesizable SystemVerilog functions do this for you:
$countbits(sout,'1); // Counts the # of 1's
$countbits(sout,'0); // Counts the # of 0's
$countones(sout); // equivalent to $countbits(sout,'1)
The logic the synthesis tools will produce is a different story.
Ref: IEEE Std 1800-2012, Section 20.9