Monday, April 25, 2016

Loading Python onto the Zedboard (No libraries)


Starting with the algorithm:

We start with C source code, just a line by line instruction set about some specific topic. Our topic is a charge comparison algorithm that takes in data (CSV files, time & amplitude) from a directory, loops through 3 passes and returns a PSD value (above a certain threshold results in a neutron, below that threshold is a gamma ray). This function can be performed much quicker, with a large number of files in our CSV directory, by programmable logic on an FPGA development board. 

In order to create an executable program, our C program must be compiled.

A compiler is a computer program that transforms source code written in a programming language (C in our case) into another computer language with the latter having a binary called object code. The compiler we use is software called 'Make' a build automation tool that automatically builds executable programs from source code by reading Makefiles.


LOADING PYTHON ONTO THE ZEDBOARD (CROSS-COMPILING)

In addition, if a compiled program can run on a computer whose CPU or operating system is different from the one which the compiler runs, the compiler is known as a cross-compiler. In order to get Python running on the board, I had to cross-compile Python (done on my host-machine, so that it could be used on the ARM processor of the Zedboard). The Makefile and source code for cross-compiling Python on a Zynq processor can be found here (but keep reading first):
https://github.com/imrickysu/PetaLinux-Apps/tree/master/components/apps/python-2.7.3

Follow the detailed instructions from my blog Things We Should All Know (Petalinux) for creating a petalinux project and configuring it if you need help (I will go through them quickly here but less detailed):

1. Create a petalinux-project: 
  • petalinux-create --type project --template zynq --name <Project Name>
  • petalinux-config --get-hw-description=<path to hw description>
    • Select U-boot configuration --> netboot offset
    • Change the offset to 0x200000
    • The offset needs to be changed because it controls where the data is stored/retrieved on the Zedboard itself.  Basically, the image is stored on the SD card (which has 4 GB storage and should be using less than 20MB).  It is then transferred to memory (typically starting at address 0x0000 0000), then is unpacked and loaded at the location 'loadaddr'.  If the compressed image is large enough, then it has data at loadaddr so when the image is unpacked, part of it is overwritten by the uncompressed image and gets compromised.  Changing the loadaddr to a larger number prevents this from happening. 
    • petalinux-config -c kernel
      • deselect networking
2. Navigate to petalinux project directory: Create app: petalinux-create -t apps -n python-2.7.3 --enable

3. Copy all files in this github directory to: <petalinux-project-directory>/components/apps/python-2.7.3


***Note: The Makefile from the link is not correct. There is a PATCH_URL on line 11 that leads to a broken link:


The correct path is:


However, not only can you simply change the PATCH_URL in the Makefile, you have to continue on and let the build FAIL once. There will be an error in Step 3 (next step) do not worry we will fix it).

3. Build the whole image: petalinux-build
4. If any errors occur (there will be) during the build process, the log of the build process can be checked in:  build/build.log 

4a. The build log will tell you that there was only garbage found in the patch (literally that's what it says).

[ALL  ] patch: **** Only garbage was found in the patch input.

4b. To fix, copy the Python-2.7.3-xcompile.patch from https://github.com/sjkingo/python-arm-xcompile/blob/master/files/Python-2.7.3-xcompile.patch (the same path as above in step 2) to the directory (this will replace the old patch file, which is a dead html file because the link to he original path is broken):

<petalinux-project-directory>/build/linux/rootfs/apps/python-2.7.3

4c. The file size will change from 94.5 KB to 11.1 KB, and you are ready to build again.

4d. Run the command petalinux-build -c rootfs/ inside your petalinux project directory once more.

5. Before packaging the bitstream and copying the files to an SD Card there is one more step for python.

5a. Navigate to <petalinux-project-directory/build/linux/rootfs/targetroot/home/root/ and create a file called '.profile' using gedit or VIM. Inside the file, copy the line

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib

5b. Save the file and quit.

5c. Type the command (n petalinux proj directory) petalinux-build -x package


8. Continue on the steps in Things We Should All Know (Petalinux)
  • petalinux-package
  • Copy files onto SD Card
9. Connect to a PuTTy terminal and press enter, type root for UN and root for PW.
10. Python will load just by typing "python" in the command line. The focus now is to load the libraries needed for the PSD algorithm. Because of no internet connectivity and the fact that Petalinux is relatively bare-bones (no yum, apt-get, install), we need to load the libraries into the correct directories before packaging the Petalinux image so that the OS comes pre-loaded with numpy, scipy, etc. In order to do this, we may need to edit the Makefile that comes from the github files. 





Wednesday, April 20, 2016

Writing a C program, Compiling It, MakeFiles

In order to write a C-program you need a text editor. CentOs comes with both VIM and Gedit. I like Gedit better so I will show the instructions for it.

To create a C program, first navigate to a directory in a terminal that you wish to save your program in. Type in the command line:

  • gedit test_program.c
This will open gedit with a blank C-program.
Write your C-program, a "Hello World" program is a good place to start:

int main(int argc, char *argv[])
{
    printf("Hello world.");

    return 0;
}

Save your program.


The next step is to compile your program using 'make' in the command line. In order for 'make' to be used, we first need to create a Makefile called 'Makefile.'  You can use gedit again to create this file and it should be saved in the same directory as your test_program.c. Copy these lines into Makefile:

CFLAGS=-Wall -g

clean:
   rm -f ex1

Save your file.

Go back to your terminal and navigate to the directory where your program and Makefile are saved.

  • Type make test_program to compile the code
  • Type ./testprogram to see the results
The results:
"Hello World"


is written directly in the terminal.

To learn a whole lot more see:





Full C Program Algorithm (for one CSV file (with read-in))

#include <stdio.h>

int main(int argc, char *argv[])
{

/* Pre-Filter */
double time[502]={},amp[502]={};
double var1, var2;
FILE *fp;

fp = fopen("C1mcp&ssd00000.csv","r");

int i=0;
do {
fscanf(fp,"%lf,%lf\n", &var1, &var2);
    time[i] = var1;
    amp[i] = var2;      
    //printf("%i \t Time: %e \t",i, time[i]);
    //printf("Voltage: %f \n", amp[i]);
    i++;
}while(!feof(fp));

//printf("time 3 = %e\n",time[3]);
fclose(fp);

int time_size = sizeof(time)/sizeof(time[0]);
//int amp_size = 6;
/*printf("FIRST Pre - Filtered Time = %e \n", time[0]);

printf("Non-Filtered TIME AND AMPLITUDE: \n");
for(i = 0; i < time_size; i++){
printf("Non - Pre - Filtered Time = %e \n", time[i]);
printf("Non - Pre - Filtered Amp = %f \n", amp[i]);

}*/
//printf("Pre-Filtered TIME AND AMPLITUDE: \n");
double time_2[sizeof(time)/sizeof(time[0])]={};
double amp_2[sizeof(time)/sizeof(time[0])]={};
for(i = 0; i < time_size; i++){
time_2[i]= time[i] - time[0];
amp_2[i] = -amp[i];
//printf("%i \t Pre - Filtered Time = %e \t", i, time_2[i]);
//printf("Pre - Filtered Amp = %f \n", amp_2[i]);

}

/* Pass 1 */
int iStart = 16;

float k1 = 0.25;
float kn = 0.75;
int basePoints = 16;
//int peakPoints = 4;
double v[16]={};
double w[501]={};
float baselineSum;
double mav[502]={};
double Amp_Final[502]={};



for(i=0; i < iStart; i++){
v[i] = amp_2[i];
if(i == 0){
baselineSum = v[i];
mav[i] = baselineSum;
Amp_Final[i] = v[i];

//printf("Mavi = %f \n", mav[0]);
}
else{
if(i<basePoints){
baselineSum = baselineSum + v[i];
}
//printf("Baseline Sum = %f \n", baselineSum);
}
//av[i] = k1*v[i] + kn*mav[0];
//printf("mav [%i] 0 --> 16 = %f \n", i, mav[i]);
}

int length = sizeof(amp_2)/sizeof(amp_2[0]);
//printf("length = %d \n", length);
float baseline = baselineSum/basePoints;
  //printf("Baseline = %f \n", baseline);
//printf("mav [0] = %f \t", mav[0]);
//printf("Final Amplitude [0] = %f \n", Amp_Final[0]);



for(i=1; i < length; i++){
w[i] = amp_2[i] ;
mav[i] = k1*w[i] + kn*mav[i-1];
//printf("mav [%i] = %f \t", i, mav[i]);
if(i < 16){
Amp_Final[i] = w[i];
//printf("Final Amplitude [%i] = %f \n", i, Amp_Final[i]);
}

else{Amp_Final[i] = mav[i] - baseline;
//printf("Final Amplitude [%i] = %f \n", i, Amp_Final[i]);
}
}

double Amp_Final2[502]={};
for(i=0; i<length; i++){
Amp_Final2[i]=Amp_Final[i];
//printf("Post Amp Copy [%i] = %f \n",i, Amp_Final2[i]);
}

double vPeaks[4]={Amp_Final[16],Amp_Final[16],Amp_Final[16],Amp_Final[16]};
int iPeaks[4]={16,16,16,16};
int j=0;
int k=0;
for(j=0; j<4; j++){
for(i=iStart; i < length; i++){
if (Amp_Final[i] > vPeaks[j]){
k=i;
vPeaks[j] = Amp_Final[i];
iPeaks[j] = i;
//Amp_Final[i]=0;
//printf("max [%i] = %f \n", i , max[j]);
//printf("Amp_Final [%i] = %f \n", i , Amp_Final[i]);
}

}


Amp_Final[k]=0;
//printf("Amp_Final = %f \n" , Amp_Final[k]);
/*for(i=iStart; i < length; i++){
printf("Amp_Final [%i] = %f \n", i , Amp_Final[i]);
}*/

printf("vPeaks = %f \t", vPeaks[j]);
printf("iPeaks = %i \n" , iPeaks[j]);
}


float vPeakSum=0;
float iPeakSum=0;
float vPeak;
int iPeak;
int lengthvPeaks = sizeof(vPeaks)/sizeof(vPeaks[0]);
for(j=0; j<lengthvPeaks; j++){
vPeakSum += vPeaks[j];
iPeakSum += iPeaks[j];}
vPeak = vPeakSum/lengthvPeaks;
iPeak = iPeakSum/lengthvPeaks;
printf("Pulse Peak = %f \t", vPeak);
printf("Pulse Peak Index = %i \n", iPeak);

/* Pass 2 */
int part1 = 50;
int part2 = 270;
int iCFD = iStart;
float cfdThresh = 0.25;
float vCFD = vPeak * cfdThresh;
double x[]={};
double y[]={};
float integral1 = 0.0;
float integral2 = 0.0;
int q=0;


for(i=iStart; i<iPeak; i++){
x[i] = Amp_Final2[i];
if(x[i] < vCFD){
if(iCFD<i){
x[i] -= Amp_Final2[iCFD];
integral1 += x[i];
//printf("Integral1 = %f", integral1);
integral2 += x[i];
//printf("Integral2 = %f", integral2);
}
q=i;
iCFD += 1;
//printf("iCFD = %i \t", iCFD);
//printf("vCFD = %f \n", x[i]);
}
else{
if(i < (iCFD + part1)){
integral1 += x[i];}
if(i < (iCFD + part2)){
integral2 += x[i];}
}
}
printf("Threshold Crossing Index = %i \t", iCFD);
printf("Threshold Crossing Value = %f \n", x[q]);
int iPart1 = iCFD + part1;
int iPart2 = iCFD + part2;

for(i=iPeak; i<iPart2; i++){
y[i] = Amp_Final2[i];
if(i<iPart1){
integral1 += y[i];
}
if(i<iPart2){
integral2 += y[i];
}

}
printf("Integral1 = %f \t", integral1);
printf("Integral2 = %f \n", integral2);

return 0;
}

Full Python Algorithm (Stripped Down from Initial NASA Code)

#Important to note that CSV_Files is a manually created directory with an arbitrary number of CSV #files
# -*- coding: utf-8 -*-
# !/usr/bin/python
"""
Created on Thu Mar 17 19:08:58 2016

@author: Mike Englert
"""

import os
import numpy as np
import matplotlib.pyplot as plt
import glob



q=0
int1=[]
int2=[]
vP=[]

#indir = '\Local Disk Storage\CSV_Files'
#for root, dirs, filenames in os.walk(indir):
os.chdir("\Local Disk Storage\CSV_Files")
for file in glob.glob("*.csv"):
        #q++
        q=q+1
        print q
        #filename = '.\C1mcp&ssd00000.csv'
        data = np.loadtxt(file, unpack=True, delimiter = ',', skiprows =5)
        preTime = data[0]
        preAmp = data[1]
        #print preAmp
       
        #Pre-Filter
        preTime -= preTime[0]
        preAmp2 = -preAmp
        #print preAmp2
       
        #Pass 1
        iStart = 16
        postAmp=preAmp2.copy()
        k1 = 0.25
        kn = 0.75
        basePoints = 16
        peakPoints = 4
       
        for i in range (0, iStart):
            v = preAmp2[i]
            if i is 0:
                baselineSum = mav = v
                #print "baseline mav= ", v
            else:
                if (i < basePoints):
                    baselineSum += v
            mav = (k1*v) + (kn*mav)
            #print "mav1: ", mav
       
        #print "baselineSum = ", baselineSum
        baseline = baselineSum/basePoints
        #print "baseline = ", baseline
       
        for i in range(iStart, preAmp2.size):
            mav = (k1*preAmp2[i] + (kn * mav))
            #print "mav = ", mav
            postAmp[i] = v = mav - baseline
           
       
            if i is iStart:
                vPeaks = [v for j in range(peakPoints)]
                #print "VPeaks 1: ", vPeaks
                iPeaks = [i for j in range(peakPoints)]
                #print "IPeaks 1: ", iPeaks
            else:
                for j in range(peakPoints):
                    if v > vPeaks[j]:
                        vPeaks = vPeaks[:j] + [v] + vPeaks[j+1:]
                        #print "VPeaks 1: ", vPeaks
                        iPeaks = iPeaks[:j] + [i] + iPeaks[j+1:]
                        #print "IPeaks 1: ", iPeaks
                        break
        #print "postAmp = ", postAmp
        vPeak = sum(vPeaks)/len(vPeaks)
        #print len(postAmp)
        #print "Pulse Peak = ", vPeak
        iPeak = round(sum(iPeaks)/len(iPeaks))
        #print "Pulse Peak Index = ", iPeak
       
        #Pass 2
        part1 = 24
        part2 = 270
        iCFD = iStart
        cfdThresh = 0.25
        vCFD = vPeak * cfdThresh
        integral1 = 0.0
        integral2 = 0.0
       
        for i in range(iStart, int(iPeak)):
            v = postAmp[i]
            if v < vCFD:
                if iCFD < i:
                    v -= postAmp[iCFD]
                    integral1 += v
                    integral2 += v
                    print "integral1 = ", integral1
                    print "integral2 = ", integral2
                    #integral1=np.array(integral1)
                    #integral2=np.array(integral2)
                iCFD += 1
            else:
                if i <iCFD + part1:
                    integral1 +=v
                    #integral1=np.array(integral1)
                   
                if i <iCFD + part2:
                    integral2 +=v
                   
                    #integral2=np.array(integral2)
        iPart1 = iCFD + part1
        iPart2 = iCFD + part2
       
        for i in range(int(iPeak), max(iPart1, iPart2)):
            v = postAmp[i]
            if i < iPart1:
                integral1 +=v
                #integral1=np.array(integral1)
                 
            if i < iPart2:
                integral2 +=v
                #integral2=np.array(integral2)
               
        int1.append(integral1)
        int2.append(integral2)
        vP.append(vPeaks)
           
i1 = np.array(int1)
i2 = np.array(int2)
vP2 = np.array(vP)
       
       
plt.figure(1)
plt.title('Neutron PSD')
plt.xlabel('Peak Amplitude')
plt.ylabel('Integral Ratio (Long/Short)')      
plt.plot(vP2, i2/i1, '.', markersize=1)

plt.figure(2)
plt.title('Integral Ratio')
plt.xlabel('Short Integral')
plt.ylabel('Long Integral')
plt.plot(i1, i2, '.', markersize=1)

plt.figure(3)
plt.title("Moving Average Smoothing Function")
plt.xlabel('Time (seconds)')
plt.ylabel('Ampitude')
plt.axis([0e0, 1.2e-06, -0.01, 0.07])
plt.plot(preTime, preAmp2, '.r', label = 'pre-Filtered Data')
plt.plot(preTime, postAmp+baseline, label = 'Smoothing Function')
plt.legend(loc = 'upper right')

Pre-Filter C Program (without CSV File read) Needed for Vivado HLS

#include <stdio.h>

int main(){
Pre();

}

int Pre(){


/*Pre-Filter*/
double time[502] = {-2.7e-07,-2.68e-07,-2.66e-07,-2.64e-07,-2.62e-07,-2.6e-07,-2.58e-07,-2.56e-07,-2.54e-07,-2.52e-07,-2.5e-07,-2.48e-07,-2.46e-07,-2.44e-07,-2.42e-07,-2.4e-07,-2.38e-07,-2.36e-07,-2.34e-07,-2.32e-07,-2.3e-07,-2.28e-07,-2.26e-07,-2.24e-07,-2.22e-07,-2.2e-07,-2.18e-07,-2.16e-07,-2.14e-07,-2.12e-07,-2.1e-07,-2.08e-07,-2.06e-07,-2.04e-07,-2.02e-07,-2e-07,-1.98e-07,-1.96e-07,-1.94e-07,-1.92e-07,-1.9e-07,-1.88e-07,-1.86e-07,-1.84e-07,-1.82e-07,-1.8e-07,-1.78e-07,-1.76e-07,-1.74e-07,-1.72e-07,-1.7e-07,-1.68e-07,-1.66e-07,-1.64e-07,-1.62e-07,-1.6e-07,-1.58e-07,-1.56e-07,-1.54e-07,-1.52e-07,-1.5e-07,-1.48e-07,-1.46e-07,-1.44e-07,-1.42e-07,-1.4e-07,-1.38e-07,-1.36e-07,-1.34e-07,-1.32e-07,-1.3e-07,-1.28e-07,-1.26e-07,-1.24e-07,-1.22e-07,-1.2e-07,-1.18e-07,-1.16e-07,-1.14e-07,-1.12e-07,-1.1e-07,-1.08e-07,-1.06e-07,-1.04e-07,-1.02e-07,-1e-07,-9.84e-08,-9.64e-08,-9.44e-08,-9.24e-08,-9.04e-08,-8.84e-08,-8.64e-08,-8.44e-08,-8.24e-08,-8.04e-08,-7.84e-08,-7.64e-08,-7.44e-08,-7.24e-08,-7.04e-08,-6.84e-08,-6.64e-08,-6.44e-08,-6.24e-08,-6.04e-08,-5.84e-08,-5.64e-08,-5.44e-08,-5.24e-08,-5.04e-08,-4.84e-08,-4.64e-08,-4.44e-08,-4.24e-08,-4.04e-08,-3.84e-08,-3.64e-08,-3.44e-08,-3.24e-08,-3.04e-08,-2.84e-08,-2.64e-08,-2.44e-08,-2.24e-08,-2.04e-08,-1.84e-08,-1.64e-08,-1.44e-08,-1.24e-08,-1.04e-08,-8.37e-09,-6.37e-09,-4.37e-09,-2.37e-09,-3.69e-10,1.63e-09,3.63e-09,5.63e-09,7.63e-09,9.63e-09,1.16e-08,1.36e-08,1.56e-08,1.76e-08,1.96e-08,2.16e-08,2.36e-08,2.56e-08,2.76e-08,2.96e-08,3.16e-08,3.36e-08,3.56e-08,3.76e-08,3.96e-08,4.16e-08,4.36e-08,4.56e-08,4.76e-08,4.96e-08,5.16e-08,5.36e-08,5.56e-08,5.76e-08,5.96e-08,6.16e-08,6.36e-08,6.56e-08,6.76e-08,6.96e-08,7.16e-08,7.36e-08,7.56e-08,7.76e-08,7.96e-08,8.16e-08,8.36e-08,8.56e-08,8.76e-08,8.96e-08,9.16e-08,9.36e-08,9.56e-08,9.76e-08,9.96e-08,1.02e-07,1.04e-07,1.06e-07,1.08e-07,1.1e-07,1.12e-07,1.14e-07,1.16e-07,1.18e-07,1.2e-07,1.22e-07,1.24e-07,1.26e-07,1.28e-07,1.3e-07,1.32e-07,1.34e-07,1.36e-07,1.38e-07,1.4e-07,1.42e-07,1.44e-07,1.46e-07,1.48e-07,1.5e-07,1.52e-07,1.54e-07,1.56e-07,1.58e-07,1.6e-07,1.62e-07,1.64e-07,1.66e-07,1.68e-07,1.7e-07,1.72e-07,1.74e-07,1.76e-07,1.78e-07,1.8e-07,1.82e-07,1.84e-07,1.86e-07,1.88e-07,1.9e-07,1.92e-07,1.94e-07,1.96e-07,1.98e-07,2e-07,2.02e-07,2.04e-07,2.06e-07,2.08e-07,2.1e-07,2.12e-07,2.14e-07,2.16e-07,2.18e-07,2.2e-07,2.22e-07,2.24e-07,2.26e-07,2.28e-07,2.3e-07,2.32e-07,2.34e-07,2.36e-07,2.38e-07,2.4e-07,2.42e-07,2.44e-07,2.46e-07,2.48e-07,2.5e-07,2.52e-07,2.54e-07,2.56e-07,2.58e-07,2.6e-07,2.62e-07,2.64e-07,2.66e-07,2.68e-07,2.7e-07,2.72e-07,2.74e-07,2.76e-07,2.78e-07,2.8e-07,2.82e-07,2.84e-07,2.86e-07,2.88e-07,2.9e-07,2.92e-07,2.94e-07,2.96e-07,2.98e-07,3e-07,3.02e-07,3.04e-07,3.06e-07,3.08e-07,3.1e-07,3.12e-07,3.14e-07,3.16e-07,3.18e-07,3.2e-07,3.22e-07,3.24e-07,3.26e-07,3.28e-07,3.3e-07,3.32e-07,3.34e-07,3.36e-07,3.38e-07,3.4e-07,3.42e-07,3.44e-07,3.46e-07,3.48e-07,3.5e-07,3.52e-07,3.54e-07,3.56e-07,3.58e-07,3.6e-07,3.62e-07,3.64e-07,3.66e-07,3.68e-07,3.7e-07,3.72e-07,3.74e-07,3.76e-07,3.78e-07,3.8e-07,3.82e-07,3.84e-07,3.86e-07,3.88e-07,3.9e-07,3.92e-07,3.94e-07,3.96e-07,3.98e-07,4e-07,4.02e-07,4.04e-07,4.06e-07,4.08e-07,4.1e-07,4.12e-07,4.14e-07,4.16e-07,4.18e-07,4.2e-07,4.22e-07,4.24e-07,4.26e-07,4.28e-07,4.3e-07,4.32e-07,4.34e-07,4.36e-07,4.38e-07,4.4e-07,4.42e-07,4.44e-07,4.46e-07,4.48e-07,4.5e-07,4.52e-07,4.54e-07,4.56e-07,4.58e-07,4.6e-07,4.62e-07,4.64e-07,4.66e-07,4.68e-07,4.7e-07,4.72e-07,4.74e-07,4.76e-07,4.78e-07,4.8e-07,4.82e-07,4.84e-07,4.86e-07,4.88e-07,4.9e-07,4.92e-07,4.94e-07,4.96e-07,4.98e-07,5e-07,5.02e-07,5.04e-07,5.06e-07,5.08e-07,5.1e-07,5.12e-07,5.14e-07,5.16e-07,5.18e-07,5.2e-07,5.22e-07,5.24e-07,5.26e-07,5.28e-07,5.3e-07,5.32e-07,5.34e-07,5.36e-07,5.38e-07,5.4e-07,5.42e-07,5.44e-07,5.46e-07,5.48e-07,5.5e-07,5.52e-07,5.54e-07,5.56e-07,5.58e-07,5.6e-07,5.62e-07,5.64e-07,5.66e-07,5.68e-07,5.7e-07,5.72e-07,5.74e-07,5.76e-07,5.78e-07,5.8e-07,5.82e-07,5.84e-07,5.86e-07,5.88e-07,5.9e-07,5.92e-07,5.94e-07,5.96e-07,5.98e-07,6e-07,6.02e-07,6.04e-07,6.06e-07,6.08e-07,6.1e-07,6.12e-07,6.14e-07,6.16e-07,6.18e-07,6.2e-07,6.22e-07,6.24e-07,6.26e-07,6.28e-07,6.3e-07,6.32e-07,6.34e-07,6.36e-07,6.38e-07,6.4e-07,6.42e-07,6.44e-07,6.46e-07,6.48e-07,6.5e-07,6.52e-07,6.54e-07,6.56e-07,6.58e-07,6.6e-07,6.62e-07,6.64e-07,6.66e-07,6.68e-07,6.7e-07,6.72e-07,6.74e-07,6.76e-07,6.78e-07,6.8e-07,6.82e-07,6.84e-07,6.86e-07,6.88e-07,6.9e-07,6.92e-07,6.94e-07,6.96e-07,6.98e-07,7e-07,7.02e-07,7.04e-07,7.06e-07,7.08e-07,7.1e-07,7.12e-07,7.14e-07,7.16e-07,7.18e-07,7.2e-07,7.22e-07,7.24e-07,7.26e-07,7.28e-07,7.3e-07,7.32e-07
};
double amp[502] = {-0.00650676,-0.00330688,-0.00650676,-0.00330688,-0.00490682,-0.00330688,-0.00490682,-0.00490682,-0.00330688,-0.00330688,-0.00650676,-0.00490682,-0.00330688,-0.00330688,-0.00330688,-0.00650676,-0.00170694,-0.00330688,-0.00490682,-0.00490682,-0.00170694,-0.00490682,-0.00650676,-0.00650676,-0.00490682,-0.000107004,-0.00170694,-0.00330688,-0.00650676,-0.00490682,-0.00170694,-0.00330688,-0.00650676,-0.00170694,-0.00170694,-0.00170694,-0.00330688,-0.00330688,-0.00330688,-0.00490682,-0.00490682,-0.00490682,-0.00490682,-0.00170694,-0.00490682,-0.00650676,-0.00490682,-0.00330688,-0.00650676,-0.000107004,-0.000107004,-0.00650676,-0.00330688,-0.00330688,-0.0081067,-0.00650676,-0.00490682,-0.00490682,-0.00330688,-0.00170694,-0.00650676,-0.000107004,-0.00650676,-0.0081067,-0.00650676,-0.00490682,-0.00650676,-0.00490682,-0.00490682,-0.00330688,-0.00490682,-0.00650676,-0.00650676,-0.0081067,-0.00490682,-0.00490682,-0.00490682,-0.00330688,-0.00330688,-0.00650676,-0.0081067,-0.00650676,-0.00490682,-0.00330688,-0.000107004,-0.00330688,-0.00490682,0.00149293,-0.00490682,-0.00330688,-0.00650676,-0.000107004,-0.00330688,-0.00650676,-0.00170694,-0.00490682,-0.00330688,-0.00330688,-0.00330688,-0.00490682,-0.00330688,-0.00490682,-0.00330688,-0.00330688,-0.00650676,-0.00650676,-0.00330688,-0.00330688,-0.00330688,-0.00170694,-0.000107004,-0.00330688,-0.00650676,-0.00490682,-0.00490682,-0.00490682,-0.000107004,-0.00170694,-0.00490682,-0.00490682,-0.0081067,-0.00650676,-0.00650676,-0.0129065,-0.00970664,-0.0129065,-0.0161064,-0.0177063,-0.0193063,-0.0225061,-0.025706,-0.0321058,-0.025706,-0.0337057,-0.0337057,-0.0369056,-0.0353057,-0.0385055,-0.0385055,-0.0433053,-0.0433053,-0.0465052,-0.0481052,-0.051305,-0.051305,-0.0545049,-0.051305,-0.052905,-0.0561049,-0.0545049,-0.0545049,-0.0609047,-0.0609047,-0.0545049,-0.0593047,-0.0593047,-0.0593047,-0.0609047,-0.0577048,-0.0561049,-0.0657045,-0.0561049,-0.0609047,-0.0609047,-0.0609047,-0.0609047,-0.0625046,-0.0609047,-0.0609047,-0.0641045,-0.0577048,-0.0609047,-0.0609047,-0.0609047,-0.0609047,-0.0625046,-0.0577048,-0.0609047,-0.0625046,-0.0593047,-0.0561049,-0.0577048,-0.0561049,-0.051305,-0.0577048,-0.0545049,-0.0577048,-0.0593047,-0.0577048,-0.0545049,-0.052905,-0.051305,-0.0593047,-0.0481052,-0.052905,-0.0497051,-0.052905,-0.051305,-0.0481052,-0.0497051,-0.0481052,-0.0481052,-0.0497051,-0.0433053,-0.0417054,-0.0465052,-0.0449053,-0.0417054,-0.0417054,-0.0417054,-0.0385055,-0.0417054,-0.0433053,-0.0385055,-0.0401055,-0.0353057,-0.0385055,-0.0433053,-0.0401055,-0.0337057,-0.0337057,-0.027306,-0.0337057,-0.0337057,-0.0289059,-0.0305058,-0.0321058,-0.0305058,-0.0289059,-0.027306,-0.027306,-0.025706,-0.0289059,-0.027306,-0.0289059,-0.0241061,-0.0209062,-0.025706,-0.0241061,-0.0241061,-0.027306,-0.0225061,-0.0241061,-0.0225061,-0.0209062,-0.0209062,-0.0209062,-0.0225061,-0.0209062,-0.0193063,-0.0177063,-0.0177063,-0.0177063,-0.0177063,-0.0209062,-0.0161064,-0.0177063,-0.0161064,-0.0177063,-0.0161064,-0.0161064,-0.0177063,-0.0145065,-0.0129065,-0.0161064,-0.0129065,-0.0113066,-0.0113066,-0.0129065,-0.0113066,-0.0129065,-0.0129065,-0.0129065,-0.0113066,-0.0129065,-0.0081067,-0.0129065,-0.0113066,-0.0081067,-0.0129065,-0.0113066,-0.0113066,-0.0113066,-0.0113066,-0.00970664,-0.0113066,-0.0081067,-0.0081067,-0.0113066,-0.0081067,-0.00650676,-0.0081067,-0.00970664,-0.0081067,-0.00650676,-0.00650676,-0.0081067,-0.0081067,-0.0081067,-0.0081067,-0.00970664,-0.00650676,-0.00330688,-0.00970664,-0.00490682,-0.00490682,-0.00490682,-0.00650676,-0.00490682,-0.00170694,-0.0081067,-0.00170694,-0.0081067,-0.00970664,-0.00650676,-0.00650676,-0.00330688,-0.00170694,-0.0081067,-0.00650676,-0.00490682,-0.00650676,-0.00490682,-0.00650676,-0.00650676,-0.0081067,-0.00330688,-0.00970664,-0.00650676,-0.00490682,-0.00650676,-0.00490682,-0.00330688,-0.00490682,-0.00330688,-0.00490682,-0.00650676,-0.000107004,-0.00490682,-0.00650676,-0.00650676,-0.0081067,-0.00490682,-0.00650676,-0.00650676,-0.00170694,-0.00490682,-0.00330688,-0.00490682,-0.00490682,-0.00330688,-0.0081067,-0.00490682,-0.00650676,-0.00330688,-0.00490682,-0.00490682,-0.00330688,-0.00330688,-0.00490682,-0.0081067,-0.00330688,-0.00330688,-0.00490682,-0.00490682,-0.0081067,-0.00170694,-0.00330688,-0.00490682,-0.00330688,-0.00490682,-0.00490682,-0.00650676,-0.00490682,-0.00490682,-0.00490682,-0.00490682,-0.00330688,-0.00650676,-0.00330688,-0.00490682,-0.00330688,-0.00330688,-0.00490682,-0.0081067,-0.00650676,-0.00650676,-0.0081067,-0.00970664,-0.00490682,-0.00650676,-0.00170694,-0.00170694,-0.00170694,-0.00650676,-0.00490682,-0.0081067,-0.00490682,-0.00170694,-0.00330688,-0.00650676,-0.00330688,-0.00650676,-0.00330688,-0.00490682,-0.00490682,-0.00650676,-0.00490682,-0.00970664,-0.00330688,-0.00650676,-0.00490682,-0.00650676,-0.00330688,-0.00490682,-0.00650676,-0.00650676,-0.00490682,-0.00650676,-0.00330688,-0.00170694,-0.00650676,-0.00330688,-0.00650676,-0.00490682,-0.00490682,-0.00490682,-0.00330688,-0.00330688,-0.00490682,-0.00490682,-0.00330688,-0.00650676,-0.00490682,-0.000107004,-0.0081067,-0.00650676,-0.00490682,-0.00650676,-0.00490682,-0.00330688,-0.00650676,-0.0081067,-0.00330688,-0.0081067,-0.00650676,-0.00490682,-0.00490682,-0.00490682,-0.00650676,0.00149293,-0.00490682,-0.00490682,-0.00650676,-0.00490682,-0.00170694,-0.00650676,-0.00650676,-0.00650676,-0.00490682,-0.00170694,-0.00330688,-0.00490682,-0.00170694,-0.00650676,-0.0081067,-0.00490682,-0.00330688,-0.00970664,-0.00970664,-0.000107004,-0.00650676,-0.00490682,-0.00330688,-0.00490682,-0.00650676,-0.00490682,-0.0081067,-0.0081067,-0.00650676,-0.0081067,-0.00650676,-0.00650676,-0.0081067,-0.00650676,-0.00490682,-0.0081067,-0.00490682,-0.0081067,-0.00970664,-0.00490682,-0.00490682,-0.00970664,-0.00650676,-0.00170694,-0.00650676,-0.00490682,-0.00650676,-0.00650676,-0.00170694,-0.00330688,-0.0081067
};
int i=0;
int count = 0;
int time_size = 502;
/*int amp_size = 6;
printf("FIRST Pre - Filtered Time = %e \n", time[0]);
double time [] -= float time[0];*/
printf("Non-Filtered TIME AND AMPLITUDE: \n");
Non: for(i = 0; i < time_size; i++){
printf("Non - Pre - Filtered Time = %e \t", time[i]);
printf("Non - Pre - Filtered Amp = %f \n", amp[i]);
count++;
}
printf("Pre-Filtered TIME AND AMPLITUDE: \n");
double time_2[502]={};
double amp_2[502]={};
for(i = 0; i < time_size; i++){
time_2[i]= time[i] - time[0];
amp_2[i] = -amp[i];
printf("Pre - Filtered Time = %e \t", time_2[i]);
printf("Pre - Filtered Amp = %f \n", amp_2[i]);

}

return 0;
}

Things We Should All Know (Petalinux)

The Xilinx tool-chain, as it pertains to running Petalinux on the Zedboard is as follows:

Vivado HLS --> Vivado  --> Petalinux --> SDCard (Boot on Board).

To fully  understand what is happening at each of these stages I will go through it step by step.

C) Developing Petalinux: an operating system to be installed on the Zedboard

PetaLinux is our full Linux distribution which includes the Linux OS as well as a complete configuration, build and deploy environment for Xilinx silicon. Because PetaLinux is fully featured, integrated, tested, and documented, it is the recommended and supported Linux deployment mechanism for our customers.

Steps
  • Install Petalinux if it is not already installed:
  • In a terminal, navigate to the directory where you have saved both your Vivado HLS and Vivado Projects.
    • Type the command:
      • petalinux-create --type project --template zynq --name <Project Name>
      • Where <Project Name> is the name of your project (e.g. Pre_Filter_petalinux)
  • Change to project directory (the one you just created above e.g. Pre_Filter_petalinux)
    • Type the command:
      • petalinux-config --get-hw-description=<path-to-directory-which-contains-hardware-description-file>
    • Note that the hardware description file is typically located in the .sdk/xxx_hw_platform_0 directory.  For example, on my system the directory is '/home/zynquser/Projects/working/HLS_Test/Pre_Filter/Pre_Filter.sdk/Pre_Filter_wrapper_hw_platform_0'     
    • A GUI will appear, choose exit to exit and save the current settings.
  • Enter the kernel configuration program and remove the auto internet configuration. There are problems with connecting the Ethernet cable to the Zedboard, so we remove this functionality
    • Type the command:
      • petalinux-config -c kernel
      • deselect Networking Support --> Networking Options TCP/IP networking
      • Save Settings and Exit GUI
  • Ensure you are in the Petalinux project directory (e.g. Pre_Filter_petalinux):
    • Type the command:
      • petalinux-build
      • wait a few minutes, this takes awhile
  • To generate a boot image for the Zynq system:
    • Type the command:
    • petalinux-package --boot --fsbl <FSBL image> --fpga <FPGA bitstream> --u-boot --force
    • Both files will be located in a directory similar to this:
      • /home/zynquser/Projects/working/HLS_Test/Pre_Filter_peta/images/linux/zynq_fsbl.elf
      • /home/zynquser/Projects/working/HLS_Test/Pre_Filter_peta/images/linux/Pre_Filter_wrapper.bit
  • Copy the following files from /home/zynquser/Projects/working/HLS_Test/Pre_Filter_peta/images/linux/ to an SD card:
    • Boot.BIN
    • Image.ub
  • Place the SD Card inside the Zedboard and turn on the board. Disconnect the Cypress UART cable from the Virtual Machine and connect it  to the Host Machine:
  • Choose PuTTy from Windows Start Menu and choose the correct USB Serial Port (can be found in Device Manager in Control Panel)
  • Press enter and you should see a boot sequence on the terminal
  • Type in username and password:
    • User: root
    • PW: root


    Things We Should All Know (Vivado)

    The Xilinx tool-chain, as it pertains to running Petalinux on the Zedboard is as follows:

    Vivado HLS --> Vivado  --> Petalinux --> SDCard (Boot on Board).

    To fully  understand what is happening at each of these stages I will go through it step by step.

    B) Creating a Block Design in Vivado Design Suite

    Vivado HLS automates  the construction of an IP core (block) that can be inserted into a hardware design (block diagram) to be eventually integrated with Petalinux.

    Steps

    • Open Vivado (on the command line, any directory, type: vivado)
    • Create a new Project --> Pre_Filter as the name
      • Follow the instructions from the Zynq Book Tutorial (part 1 to complete the initialization instructions including adding the processing system to your block design, link to download tutorials below, First Designs in Zynq is the header for where you should start)
      • http://www.zynqbook.com/download-tuts.html
    • Add 3 AXI GPIO Blocks, one for the LEDs, one for the push buttons, and one for the DIPs switches, and run connection automation
    • Add HLS repository --> Choose Project Settings under Project Manager in Flow Navigator
      • Choose IP on the left pane and click the "plus" icon to add a fresh IP repo
      • The repository you want to add is in the HLS directory:
        •  <you choose initial path>/Pre_Filter.prj/solution1/impl/ip
      • Click Apply and OK
    • In your block design window, select Add IP again. This time type "Pre" (or whatever your top function name was in HLS) and select the block that comes from the repository. It will look like this when it is added:
    • Click on the processing system block in your design to open up Re-customize IP:

      • Select IRQ_F2P[15:0] from PL-PS Interrupt Ports. Fabric Interrupts will need to be checked also (see above picture)
    • Connect the interrupt port from the HLS IP block to the  IRQ_F2P[0:0] port of the processing system:
    • Click Regenerate Layout, and your block design should look close to this: 




    • Click Validate Design to ensure no design errors
    • Create HDL wrapper inside the sources tab --> right -click yellow pyramid file, Create HDL wrapper:
    • In the Flow Navigator, click Generate Bitstream. This command Runs Synthesis, Runs Implementation, and Generates the Bitstream (describing the programmable logic)
      • This task will take a while, don't fret
    • Click File --> Export Hardware
    • Click File --> Launch SDK to update the old hardware design
    You have now created a block design that uses a custom IP with interrupt connected to a Zynq processing system. The next step is to integrate the hardware description file (just created in Vivado) into Petalinux so that every module created in Vivado, whether its our module, the LEDs, the buttons, or the switches can be accessed on the Zedboard.

    (see next blog) 



    Things We Should All Know (Vivado HLS)

    The Xilinx tool-chain, as it pertains to running Petalinux on the Zedboard is as follows:

    Vivado HLS --> Vivado  --> Petalinux --> SDCard (Boot on Board).

    To fully  understand what is happening at each of these stages I will go through it step by step.

    A) Developing IP in Vivado High-Level Synthesis

    Vivado HLS is a tool used to accelerate IP creation by enabling C/C++/SystemC programs (in our case I translated the first part of the PSD Python algorithm called Pre-Filter from Python to C, so it could be used in HLS and run on the Zedboard) to be directly targeted into Xilinx Programmable devices (Zedboard) without the need to manually create RTL.

    Steps

    • Open Vivado HLS (on the command line, any directory, type: vivado_hls)
    • Create New Project --> Pre_Filter.prj --> Next
    • Add Source Files --> Pre_Filter.c (can be found on another blog, but great to write your own) --> Next
      • Top Function can be selected from browse (called Pre)
      • The top function is the function that will be synthesized
    • Add TestBench Files --> Pre_Filter.c --> Next
      • Our test bench will be the same as our source file
    • Choose Zedboard in Part Selection --> Finish
      • Solution Name: High-Level Synthesis provides the initial default name solution1 but any name can be specified for the solution. 
      • Clock: The clock period is specified using units of ns. The clock period used for synthesis is the clock period minus the clock uncertainty. High-Level Synthesis uses the timing information in the technology library to create the RTL design. The clock uncertainty value allows a user controllable margin to account for any increases in net delays due to RTL synthesis, place and route. If not specified in ns, the clock uncertainty defaults to 12.5% of the clock period.
    • Run C-Simulation (Project Tab --> Run C - Simulation)
      • Ensure no errors occur during compiling, you would not want to get through the block design without a working code. This would most likely be found during synthesis anyhow, but its good practice to run the simulation as a check. 
    • Insert Directive in Top Function
      • On the right side of the screen, there are two tabs, Outline and Directive. On the Explorer, under Source, be sure to select your Pre_Filter.c file and load it into the main window. Then select Directive on the right side of the screen.
      • Right-click on Pre and insert directive, choosing interface and changing the mode to s_axilite
    • Run C-Synthesis (Project Tab --> Run C - Synthesis)
    • Solution Tab --> Export RTL --> OK
      • Select IP Catalog and VHDL

    You are now ready to import your newly created IP into Vivado and complete your block design! (See next blog)