.sum() and .max() not included in Systemverilog? - system-verilog

Why does the error say sum/max "is not declared under this prefix"? I thought Systemverilog had these array reduction functions included. Do I need to add a library or something to use them?
Code below:
module compare_block (clk, result, data, led);
parameter taps = 50; //number of fir filter taps
parameter data_width = 8; //width of data input including sign bit
parameter coeff_width = 32; //width of coefficients including sign bit
parameter size = 4096;
input clk;
input [(data_width + coeff_width + $clog2(taps) - 1):0] result; //from filter
input [(data_width-1):0] data; //precalculated 1 Hz sine wave
output led;
reg [(data_width + coeff_width + $clog2(taps) - 1):0] filt_sig;
reg [(data_width-1):0] comp_sig;
reg [(data_width-1):0] ans_sig;
integer i;
integer ii;
integer sum_array;
integer array_avg;
always #(posedge clk)
begin
filt_sig [(data_width + coeff_width + $clog2(taps) - 1):0]<= result[(data_width + coeff_width + $clog2(taps) - 1):0];
comp_sig [(data_width-1):0]<= data[(data_width-1):0];
end
always #(*)
begin
for (i=0; i < size; i=i+1)
ans_sig[i] = filt_sig[i] - comp_sig[i];
end
assign sum = ans_sig.sum(); //with (int'(item))
assign array_avg = sum >> 'd12; //dividing by 4096 (size) to get mean of signal deviation
integer max_array = ans_sig.max();
integer error_val = 0.5*max_array;
always #(*)
begin
if (array_avg < error_val) begin
led <= 'b1;
end else begin
led <= 'b0;
end
end
endmodule

The array reduction methods are defined for unpacked arrays. Instead of sum(), you can use $countones(ans_sig). I'm not sure what you are trying to compute with max(). Maybe you meant to declare ans_sig as an unpacked array.

Related

system verilog concatenation using values in a variable (type logic)

In system verilog, variables cannot be used as replication constants. Is there any other way to replicate. I need something like:
logic [7:0] value;
logic [4:0] full;
logic [4:0] data_len;
always_comb begin
N= full - data_len ;
output = {N{value}};
end
Thanks in advance.
Concatenations can only handle fixed width expressions. You can do this with a for-loop:
always_comb begin
N= full - data_len ;
output = '0;
for(int i = 0; i < N; i++)
output |= value << i * $bits(value);
end

Efficient import of semi structured text

I have multiple text files saved from a Tekscan pressure mapping system. I'm am trying to find the most efficient method for importing the multiple comma delimited matrices into one 3-d matrix of type uint8. I have developed a solution, which makes repeated calls to the MATLAB function dlmread. Unfortunately, it takes roughly 1.5 min to import the data. I have included the code below.
This code makes calls to two other functions I wrote, metaextract and framecount which I have not included as they aren't truly relevant to answering the question at hand.
Here are two links to samples of the files I am using.
The first is a shorter file with 90 samples
The second is a longer file with 3458 samples
Any help would be appreciated
function pressureData = tekscanimport
% Import TekScan data from .asf file to 3d matrix of type double.
[id,path] = uigetfile('*.asf'); %User input for .asf file
if path == 0 %uigetfile returns zero on cancel
error('You must select a file to continue')
end
path = strcat(path,id); %Concatenate path and id to full path
% function calls
pressureData.metaData = metaextract(path);
nLines = linecount(path); %Find number of lines in file
nFrames = framecount(path,nLines);%Find number of frames
rowStart = 25; %Default starting row to read from tekscan .asf file
rowEnd = rowStart + 41; %Frames are 42 rows long
colStart = 0;%Default starting col to read from tekscan .asf file
colEnd = 47;%Frames are 48 rows long
pressureData.frames = zeros([42,48,nFrames],'uint8');%Preallocate for speed
f = waitbar(0,'1','Name','loading Data...',...
'CreateCancelBtn','setappdata(gcbf,''canceling'',1)');
setappdata(f,'canceling',0);
for i = 1:nFrames %Loop through file skipping frame metadata
if getappdata(f,'canceling')
break
end
waitbar(i/nFrames,f,sprintf('Loaded %.2f%%', i/nFrames*100));
%Make repeated calls to dlmread
pressureData.frames(:,:,i) = dlmread(path,',',[rowStart,colStart,rowEnd,colEnd]);
rowStart = rowStart + 44;
rowEnd = rowStart + 41;
end
delete(f)
end
I gave it a try. This code opens your big file in 3.6 seconds on my PC. The trick is to use sscanf instead of the str2double and str2number functions.
clear all;tic
fid = fopen('tekscanlarge.txt','rt');
%read the header, stop at frame
header='';
l = fgetl(fid);
while length(l)>5&&~strcmp(l(1:5),'Frame')
header=[header,l,sprintf('\n')];
l = fgetl(fid);
if length(l)<5,l(end+1:5)=' ';end
end
%all data at once
dat = fread(fid,inf,'*char');
fclose(fid);
%allocate space
res = zeros([48,42,3458],'uint8');
%get all line endings
LE = [0,regexp(dat','\n')];
i=1;
for ct = 2:length(LE)-1 %go line by line
L = dat(LE(ct-1)+1:LE(ct)-1);
if isempty(L),continue;end
if all(L(1:5)==['Frame']')
fr = sscanf(L(7:end),'%u');
i=1;
continue;
end
% sscan can only handle row-char with space seperation.
res(:,i,fr) = uint8(sscanf(strrep(L',',',' '),'%u'));
i=i+1;
end
toc
Does anyone knows of a faster way to convert than sscanf? Because it spends the majority of time on this function (2.17 seconds). For a dataset of 13.1MB I find it very slow compared to the speed of the memory.
Found a way to do it in 0.2 seconds that might be usefull for others as well.
This mex-file scans through a list of char values for numbers and reports them back. Save it as mexscan.c and run mex mexscan.c.
#include "mex.h"
/* The computational routine */
void calc(unsigned char *in, unsigned char *out, long Sout, long Sin)
{
long ct = 0;
int newnumber=0;
for (int i=0;i<Sin;i+=2){
if (in[i]>=48 && in[i]<=57) { //it is a number
out[ct]=out[ct]*10+in[i]-48;
newnumber=1;
} else { //it is not a number
if (newnumber==1){
ct++;
if (ct>Sout){return;}
}
newnumber=0;
}
}
}
/* The gateway function */
void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
unsigned char *in; /* input vector */
long Sout; /* input size of output vector */
long Sin; /* size of input vector */
unsigned char *out; /* output vector*/
/* check for proper number of arguments */
if(nrhs!=2) {
mexErrMsgIdAndTxt("MyToolbox:arrayProduct:nrhs","two input required.");
}
if(nlhs!=1) {
mexErrMsgIdAndTxt("MyToolbox:arrayProduct:nlhs","One output required.");
}
/* make sure the first input argument is type char */
if(!mxIsClass(prhs[0], "char")) {
mexErrMsgIdAndTxt("MyToolbox:arrayProduct:notDouble","Input matrix must be type char.");
}
/* make sure the second input argument is type uint32 */
if(!mxIsClass(prhs[0], "char")) {
mexErrMsgIdAndTxt("MyToolbox:arrayProduct:notDouble","Input matrix must be type char.");
}
/* get dimensions of the input matrix */
Sin = mxGetM(prhs[0])*2;
/* create a pointer to the real data in the input matrix */
in = (unsigned char *) mxGetPr(prhs[0]);
Sout = mxGetScalar(prhs[1]);
/* create the output matrix */
plhs[0] = mxCreateNumericMatrix(1,Sout,mxUINT8_CLASS,0);
/* get a pointer to the real data in the output matrix */
out = (unsigned char *) mxGetPr(plhs[0]);
/* call the computational routine */
calc(in,out,Sout,Sin);
}
Now this script runs in 0.2 seconds and returns the same result as the previous script.
clear all;tic
fid = fopen('tekscanlarge.txt','rt');
%read the header, stop at frame
header='';
l = fgetl(fid);
while length(l)>5&&~strcmp(l(1:5),'Frame')
header=[header,l,sprintf('\n')];
l = fgetl(fid);
if length(l)<5,l(end+1:5)=' ';end
end
%all data at once
dat = fread(fid,inf,'*char');
fclose(fid);
S=[48,42,3458];
d = mexscan(dat,uint32(prod(S)+3458));
d(1:prod(S(1:2))+1:end)=[];%remove frame numbers
d = reshape(d,S);
toc

Logistic regression Macro

%macro intercept(i1= ,i2= );
%let n = %sysfunc(countw(&i1));
%do i = 1 %to &n;
%let val_i1 = %scan(&i1,&i,'');
%let val_i2 = %scan(&i2,&i,'');
data scores;
set repeat_score2;
/* Segment 1 probablity score */
p1 = 0;
z1 = &val_i1 +
a * 0.03 +
r * -0.0047841 +
p * -0.000916081 ;
p1 = 1/(1+2.71828**-z1);
/* Segment 2 probablity score */
p2 = 0;
z2 = &val_i2 +
r * 0.09 +
m * 0.012786245 +
c * -0.00179618 +
p2 = 1/(1+2.71828**-z2);
logit_score = 0;
if max(p1,p2) = p1 then logit_score = 1;
else if max(p1,p2) = p2 then logit_score = 2;
run;
proc freq data = scores;
table logit_score * clu_ /nocol norow nopercent;
run;
%end;
%mend;
%intercept (i1=-0.456491042, i2=-3.207379842, i3=-1.380627318 , i4=0.035684096, i5=-0.855283373);
%intercept (i1=-0.456491042 0, i2=-3.207379842 -3.207379842, i3=-1.380627318 -1.380627318, i4=0.035684096 0.035684096,
i5=-0.855283373 -0.855283373);
I have the above macro which takes the intercept for the two of the above models and then calculates the probablity score and then assigns a a value to to a segment based on that probablity score.
The first problem with above macro is when I execute the macro with one argument each it's resolving macro variable 'n' to 2 and executing twice. First iteration, it's giving the right results while for second it's wrong.
For the second implementation(macro with two aruguments each) n is resolving to 3 and scan is resolving to both of those values together at a time (eg. i1 for the iteration itself is -0.45 and 0), If I remove the space, then it taking '.' to be the delimiter and resolving that to ( 0,45,0 - one for each iteration). I don't get any results for this case.
How do I get this to work the right way?
Thanks!!!
%SCAN and COUNTW function by default consider punctuation symbols and blanks as delimiters. Since your arguments include decimal points, you need to state explicitly that delimiter should be blank for both COUNTW and %SCAN. Which you have done for %SCAN, but not for COUNTW.
So the 2nd line of the code should be:
%let n = %sysfunc(countw(&i1,' '))
And I'm not sure if it's a typo or just formatting thing, but in your %SCAN functions third argument looks like two quotes together '', not quote-blank-quote ' ' as it should be.

Simpson's Composite Rule GUI

I got this problem while doing the Simpson's composite rule
Attempted to access funcion(1.2); index must be a positive integer or logical.
Error in Simpson_Comp>Calcular_Callback (line 185)
sum_even = sum_even + funcion(x(i)); "
funcion=get(handles.funcion,'string');
b=str2num(get(handles.b,'string'));
a=str2num(get(handles.a,'string'));
n=str2num(get(handles.n,'string'));
h = (b-a)/n;
sum_even = 0;
for i = 1:n/2-1
x(i) = a + 2*i*h;
sum_even = sum_even + funcion(x(i));
end
sum_odd = 0;
for i = 1:n/2
x(i) = a + (2*i-1)*h;
sum_odd = sum_odd + funcion(x(i));
end
integral = h*(funcion(a)+ 2*sum_even + 4*sum_odd +funcion(b))/3
fprintf('el valor aproximado de la integral es: %10.15f\n\n',integral);
set(handles.solucion,'string',num2str(integral));
I'm testing it with x^2 and [0,3]
I don't know why x(i) must be an integer ?
You're getting an error because handles.funcion is a string but you are assuming that it's an actual function - as noted in your comments. Therefore, MATLAB is interpreting this as indexing into a string. Try doing using the str2func which converts a string to a function handle that is defined by the contents of that string. Also, because str2func accepts in a string that is formatted like an anonymous function, you need to prepend #(x) before the actual string.
As such, either add this into your string in your GUI widget, or prepend the string once you grab the string after the capture event triggers.
Let's do the second way because I'm assuming you don't want the user to type in more text than they need to. Therefore, after your get call, use str2func:
funcion=get(handles.funcion,'string');
funcion = str2func(['#(x)' funcion]); %// New

matlab program to check whether the given input number is prime number or not

I need to find whether the given input number in MAT-LAB command window is prime number or not. I need to code without using the inbuilt command in matlab.
Am I programming your homework?
function result = isprime2(number)
result=true;
%% check if number is a nonnegative integer
if floor(number)~=number || number<0
result=false;
return
end
%% check if number can be divided by another integer
for k=2:(number/2)
if rem(number,k)==0
result=false;
return
end
end
The above answer is not correct....it consider 9 as prime number which is not
function result=myprime(n)
%result=true;
%check if number is a nonnegative integer
if floor(n)~=n || n<0
result=false;
return
end
% check if number can be divided by another integer
for k=2:(n/2)
if rem(n,k)==0
result=false;
return
end
end
result=true;
return
end
Calculation
a = input('Enter a value: ');
b = input ('Enter b value: ');
for(x = a : b)
if (isprime(x)==1)
fprintf('%d is prime number \n',x)
end
end
My program goes this way
function tf = isprim(n)
%this function will check whether the number is prime or not
tf = true;
for i = 2:n-1
if rem(n,i) == 0
tf = false;
break
end
end