Unverified Commit 78599578 authored by Karen Xie's avatar Karen Xie Committed by GitHub

Merge pull request #151 from karenx-xilinx/master

XDMA: add sanity test script for memory map mode
parents 6aa83736 8408b626
...@@ -35,7 +35,7 @@ Directory and file description: ...@@ -35,7 +35,7 @@ Directory and file description:
provided kernel module driver and Xilinx PCIe DMA IP. This directory provided kernel module driver and Xilinx PCIe DMA IP. This directory
also contains the following scripts and directories. also contains the following scripts and directories.
- load_driver.sh: - load_driver.sh:
This script loads the kernel module and creates the necissary This script loads the kernel module and creates the necissary
kernel nodes used by the provided software. kernel nodes used by the provided software.
The The kernel device nodes will be created under /dev/xdma*. The The kernel device nodes will be created under /dev/xdma*.
...@@ -43,9 +43,9 @@ Directory and file description: ...@@ -43,9 +43,9 @@ Directory and file description:
more easily differentiate between multiple PCIe DMA enabled more easily differentiate between multiple PCIe DMA enabled
cards. Root permissions will be required to run this script. cards. Root permissions will be required to run this script.
- run_test.sh: - run_test.sh:
- dma_memory_mapped_test.sh, dma_streaming_test.sh: - dma_memory_mapped_test.sh, dma_streaming_test.sh:
- data/: - data/:
run_test.sh runs sample tests on a Xilinx PCIe DMA target and run_test.sh runs sample tests on a Xilinx PCIe DMA target and
returns a pass (0) or fail (1) result. returns a pass (0) or fail (1) result.
This script calls 2 other scripts in the same directory: This script calls 2 other scripts in the same directory:
...@@ -80,6 +80,35 @@ Directory and file description: ...@@ -80,6 +80,35 @@ Directory and file description:
If a AXI-ST design is independent of H2C and C2H, performance If a AXI-ST design is independent of H2C and C2H, performance
number can be generated. number can be generated.
- scripts_mm/
This directory contains a set of scripts to check basic driver
loading/unloading and perform dma operations in memory-mapped
mode.
Compare with dma_memory_mapped_test.sh, the test is more
extensive with more dma size and it also utilizes fio tool in
addition to dma_from/to_device tools.
- xdma_mm.sh
top level script.
- io_sweep.sh, io.sh, unaligned
dma test via dma_from/to_device
- fio_test.sh fio_parse_result.sh
dma test via fio tool
- scripts_mm/ dependency
Some test in script_mm/ requires fio tool and python extension
Install fio:
- Centos/RHEL: yum install fio
- Ubuntu: apt install fio
Install python extension openpyxl, xlrd(version 1.2.0)
python --version
pip2 install openpyxl
pip2 install xlrd=1.2.0
Usage: Usage:
- Change directory to the driver directory. - Change directory to the driver directory.
cd xdma cd xdma
...@@ -96,6 +125,12 @@ Usage: ...@@ -96,6 +125,12 @@ Usage:
./load_driver.sh ./load_driver.sh
- Run the provided test script to generate basic DMA traffic. - Run the provided test script to generate basic DMA traffic.
./run_test.sh ./run_test.sh
For more extensive memory mapped test:
assume the XDMA FGPA is at pci slot 0000:01:00.0
cd scripts_mm
./xdma_mm.sh 0000:01:00.0 | tee /tmp/xdma_mm.log
- Check driver Version number - Check driver Version number
modinfo xdma (or) modinfo xdma (or)
modinfo ../xdma/xdma.ko modinfo ../xdma/xdma.ko
......
#!/bin/bash #!/bin/bash
display_help() {
echo "$0 <xdma id> <io size> <io count> <h2c #> <c2h #>"
echo -e "xdma id:\txdma[N] "
echo -e "io size:\tdma transfer size in byte"
echo -e "io count:\tdma transfer count"
echo -e "h2c #:\tnumber of h2c channels"
echo -e "c2h #:\tnumber of c2h channels"
echo
exit 1
}
transferSize=$1 if [ $# -eq 0 ]; then
transferCount=$2 display_help
h2cChannels=$3 fi
c2hChannels=$4
xid=$1
transferSz=$2
transferCount=$3
h2cChannels=$4
c2hChannels=$5
tool_path=../tools tool_path=../tools
testError=0 testError=0
# Run the PCIe DMA memory mapped write read test # Run the PCIe DMA memory mapped write read test
echo "Info: Running PCIe DMA memory mapped write read test" echo "Info: Running PCIe DMA memory mapped write read test"
echo " transfer size: $transferSize" echo -e "\ttransfer size: $transferSz, count: $transferCount"
echo " transfer count: $transferCount"
# Write to all enabled h2cChannels in parallel # Write to all enabled h2cChannels in parallel
if [ $h2cChannels -gt 0 ]; then if [ $h2cChannels -gt 0 ]; then
# Loop over four blocks of size $transferSize and write to them (in parallel where possible) # Loop over four blocks of size $transferSz and write to them
for ((i=0; i<=3; i++)) for ((i=0; i<=3; i++)); do
do addrOffset=$(($transferSz * $i))
addrOffset=$(($transferSize * $i)) curChannel=$(($i % $h2cChannels))
curChannel=$(($i % $h2cChannels)) echo "Info: Writing to h2c channel $curChannel at address" \
echo "Info: Writing to h2c channel $curChannel at address offset $addrOffset." "offset $addrOffset."
$tool_path/dma_to_device -d /dev/xdma0_h2c_${curChannel} -f data/datafile${i}_4K.bin -s $transferSize -a $addrOffset -c $transferCount & $tool_path/dma_to_device -d /dev/${xid}_h2c_${curChannel} \
# If all channels have active transactions we must wait for them to complete -f data/datafile${i}_4K.bin -s $transferSz \
if [ $(($curChannel+1)) -eq $h2cChannels ]; then -a $addrOffset -c $transferCount &
echo "Info: Wait for current transactions to complete." # If all channels have active transactions we must wait for
wait # them to complete
fi if [ $(($curChannel+1)) -eq $h2cChannels ]; then
done echo "Info: Wait for current transactions to complete."
wait
fi
done
fi fi
# Wait for the last transaction to complete. # Wait for the last transaction to complete.
...@@ -35,20 +53,24 @@ wait ...@@ -35,20 +53,24 @@ wait
# Read from all enabled c2hChannels in parallel # Read from all enabled c2hChannels in parallel
if [ $c2hChannels -gt 0 ]; then if [ $c2hChannels -gt 0 ]; then
# Loop over four blocks of size $transferSize and read from them (in parallel where possible) # Loop over four blocks of size $transferSz and read from them
for ((i=0; i<=3; i++)) for ((i=0; i<=3; i++)); do
do addrOffset=$(($transferSz * $i))
addrOffset=$(($transferSize * $i)) curChannel=$(($i % $c2hChannels))
curChannel=$(($i % $c2hChannels))
rm -f data/output_datafile${i}_4K.bin rm -f data/output_datafile${i}_4K.bin
echo "Info: Reading from c2h channel $curChannel at address offset $addrOffset." echo "Info: Reading from c2h channel $curChannel at " \
$tool_path/dma_from_device -d /dev/xdma0_c2h_${curChannel} -f data/output_datafile${i}_4K.bin -s $transferSize -a $addrOffset -c $transferCount & "address offset $addrOffset."
# If all channels have active transactions we must wait for them to complete $tool_path/dma_from_device -d /dev/${xid}_c2h_${curChannel} \
if [ $(($curChannel+1)) -eq $c2hChannels ]; then -f data/output_datafile${i}_4K.bin -s $transferSz \
echo "Info: Wait for the current transactions to complete." -a $addrOffset -c $transferCount &
wait # If all channels have active transactions we must wait for
fi # them to complete
done if [ $(($curChannel+1)) -eq $c2hChannels ]; then
echo "Info: Wait for current transactions to complete."
wait
fi
done
fi fi
# Wait for the last transaction to complete. # Wait for the last transaction to complete.
...@@ -56,31 +78,36 @@ wait ...@@ -56,31 +78,36 @@ wait
# Verify that the written data matches the read data if possible. # Verify that the written data matches the read data if possible.
if [ $h2cChannels -eq 0 ]; then if [ $h2cChannels -eq 0 ]; then
echo "Info: No data verification was performed because no h2c channels are enabled." echo "Info: No data verification was performed because no h2c " \
"channels are enabled."
elif [ $c2hChannels -eq 0 ]; then elif [ $c2hChannels -eq 0 ]; then
echo "Info: No data verification was performed because no c2h channels are enabled." echo "Info: No data verification was performed because no c2h " \
"channels are enabled."
else else
echo "Info: Checking data integrity." echo "Info: Checking data integrity."
for ((i=0; i<=3; i++)) for ((i=0; i<=3; i++)); do
do cmp data/output_datafile${i}_4K.bin data/datafile${i}_4K.bin \
cmp data/output_datafile${i}_4K.bin data/datafile${i}_4K.bin -n $transferSize -n $transferSz
returnVal=$? returnVal=$?
if [ ! $returnVal == 0 ]; then if [ ! $returnVal == 0 ]; then
echo "Error: The data written did not match the data that was read." echo "Error: The data written did not match the data" \
echo " address range: $(($i*$transferSize)) - $((($i+1)*$transferSize))" " that was read."
echo " write data file: data/datafile${i}_4K.bin" echo -e "\taddress range: " \
echo " read data file: data/output_datafile${i}_4K.bin" "$(($i*$transferSz)) - $((($i+1)*$transferSz))"
testError=1 echo -e "\twrite data file: data/datafile${i}_4K.bin"
else echo -e "\tread data file: data/output_datafile${i}_4K.bin"
echo "Info: Data check passed for address range $(($i*$transferSize)) - $((($i+1)*$transferSize))." testError=1
fi else
done echo "Info: Data check passed for address range " \
"$(($i*$transferSz)) - $((($i+1)*$transferSz))"
fi
done
fi fi
# Exit with an error code if an error was found during testing # Exit with an error code if an error was found during testing
if [ $testError -eq 1 ]; then if [ $testError -eq 1 ]; then
echo "Error: Test completed with Errors." echo "Error: Test completed with Errors."
exit 1 exit 1
fi fi
# Report all tests passed and exit # Report all tests passed and exit
......
File mode changed from 100644 to 100755
#!/bin/bash #!/bin/bash
# set -x
display_help() {
echo "$0 [interrupt mode]"
echo "interrupt mode: optional"
echo "0: auto"
echo "1: MSI"
echo "2: Legacy"
echo "3: MSIx"
echo "4: do not use interrupt, poll mode only"
exit;
}
if [ "$1" == "help" ]; then
display_help
fi;
interrupt_selection=$1
echo "interrupt_selection $interrupt_selection."
device_id=903f
# Make sure only root can run our script # Make sure only root can run our script
if [[ $EUID -ne 0 ]]; then if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root" 1>&2 echo "This script must be run as root" 1>&2
exit 1 exit 1
fi fi
# Remove the existing xdma kernel module # Remove the existing xdma kernel module
lsmod | grep xdma lsmod | grep xdma
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
rmmod xdma rmmod xdma
if [ $? -ne 0 ]; then
echo "rmmod xdma failed: $?"
exit 1
fi
fi fi
echo -n "Loading xdma driver..."
# Use the following command to Load the driver in the default # Use the following command to Load the driver in the default
# or interrupt drive mode. This will allow the driver to use # or interrupt drive mode. This will allow the driver to use
# interrupts to signal when DMA transfers are completed. # interrupts to signal when DMA transfers are completed.
insmod ../xdma/xdma.ko echo -n "Loading driver..."
# Use the following command to Load the driver in Polling case $interrupt_selection in
# mode rather than than interrupt mode. This will allow the "0")
# driver to use polling to determ when DMA transfers are echo "insmod xdma.ko interrupt_mode=1 ..."
# completed. ret=`insmod ../xdma/xdma.ko interrupt_mode=0`
#insmod ../xdma/xdma.ko poll_mode=1 ;;
"1")
if [ ! $? == 0 ]; then echo "insmod xdma.ko interrupt_mode=2 ..."
echo "Error: Kernel module did not load properly." ret=`insmod ../xdma/xdma.ko interrupt_mode=1`
echo " FAILED" ;;
exit 1 "2")
echo "insmod xdma.ko interrupt_mode=3 ..."
ret=`insmod ../xdma/xdma.ko interrupt_mode=2`
;;
"3")
echo "insmod xdma.ko interrupt_mode=4 ..."
ret=`insmod ../xdma/xdma.ko interrupt_mode=3`
;;
"4")
echo "insmod xdma.ko poll_mode=1 ..."
ret=`insmod ../xdma/xdma.ko poll_mode=1`
;;
*)
intp=`sudo lspci -d :${device_id} -v | grep -o -E "MSI-X"`
intp1=`sudo lspci -d :${device_id} -v | grep -o -E "MSI:"`
if [[ ( -n $intp ) && ( $intp == "MSI-X" ) ]]; then
echo "insmod xdma.ko interrupt_mode=0 ..."
ret=`insmod ../xdma/xdma.ko interrupt_mode=0`
elif [[ ( -n $intp1 ) && ( $intp1 == "MSI:" ) ]]; then
echo "insmod xdma.ko interrupt_mode=1 ..."
ret=`insmod ../xdma/xdma.ko interrupt_mode=1`
else
echo "insmod xdma.ko interrupt_mode=2 ..."
ret=`insmod ../xdma/xdma.ko interrupt_mode=2`
fi
;;
esac
if [ ! $ret == 0 ]; then
echo "Error: xdma driver did not load properly"
echo " FAILED"
exit 1
fi fi
# Check to see if the xdma devices were recognized # Check to see if the xdma devices were recognized
...@@ -33,13 +88,13 @@ echo "" ...@@ -33,13 +88,13 @@ echo ""
cat /proc/devices | grep xdma > /dev/null cat /proc/devices | grep xdma > /dev/null
returnVal=$? returnVal=$?
if [ $returnVal == 0 ]; then if [ $returnVal == 0 ]; then
# Installed devices were recognized. # Installed devices were recognized.
echo "The Kernel module installed correctly and the xmda devices were recognized." echo "The Kernel module installed correctly and the xmda devices were recognized."
else else
# No devices were installed. # No devices were installed.
echo "Error: The Kernel module installed correctly, but no devices were recognized." echo "Error: The Kernel module installed correctly, but no devices were recognized."
echo " FAILED" echo " FAILED"
exit 1 exit 1
fi fi
echo " DONE" echo "DONE"
File mode changed from 100644 to 100755
...@@ -20,77 +20,92 @@ transferCount=1 ...@@ -20,77 +20,92 @@ transferCount=1
# Determine if the core is Memory Mapped or Streaming # Determine if the core is Memory Mapped or Streaming
isStreaming=0 isStreaming=0
h2cChannels=0 h2cChannels=0
for ((i=0; i<=3; i++)) for ((i=0; i<=3; i++)); do
do v=`$tool_path/reg_rw /dev/xdma0_control 0x0${i}00 w`
statusRegVal=`$tool_path/reg_rw /dev/xdma0_control 0x0${i}00 w | grep "Read.*:" | sed 's/Read.*: 0x\([a-z0-9]*\)/\1/'` returnVal=$?
channelId=${statusRegVal:0:3} if [ $returnVal -ne 0 ]; then
streamEnable=${statusRegVal:4:1} break;
if [ $channelId == "1fc" ]; then fi
h2cChannels=$((h2cChannels + 1))
if [ $streamEnable == "8" ]; then #v=`echo $v | grep -o '): 0x[0-9a-f]*'`
isStreaming=1 statusRegVal=`$tool_path/reg_rw /dev/xdma0_control 0x0${i}00 w | grep "Read.*:" | sed 's/Read.*: 0x\([a-z0-9]*\)/\1/'`
fi channelId=${statusRegVal:0:3}
fi streamEnable=${statusRegVal:4:1}
if [ $channelId == "1fc" ]; then
h2cChannels=$((h2cChannels + 1))
if [ $streamEnable == "8" ]; then
isStreaming=1
fi
fi
done done
echo "Info: Number of enabled h2c channels = $h2cChannels" echo "Info: Number of enabled h2c channels = $h2cChannels"
# Find enabled c2hChannels # Find enabled c2hChannels
c2hChannels=0 c2hChannels=0
for ((i=0; i<=3; i++)) for ((i=0; i<=3; i++)); do
do v=`$tool_path/reg_rw /dev/xdma0_control 0x1${i}00 w`
$tool_path/reg_rw /dev/xdma0_control 0x1${i}00 w | grep "Read.*: 0x1fc" > /dev/null returnVal=$?
returnVal=$? if [ $returnVal -ne 0 ]; then
if [ $returnVal -eq 0 ]; then break;
c2hChannels=$((c2hChannels + 1)) fi
if [ $streamEnable == "8" ]; then
isStreaming=1 $tool_path/reg_rw /dev/xdma0_control 0x1${i}00 w | grep "Read.*: 0x1fc" > /dev/null
fi statusRegVal=`$tool_path/reg_rw /dev/xdma0_control 0x1${i}00 w | grep "Read.*:" | sed 's/Read.*: 0x\([a-z0-9]*\)/\1/'`
fi channelId=${statusRegVal:0:3}
# there will NOT be a mix of MM & ST channels, so no need to check
# for streaming enabled
if [ $channelId == "1fc" ]; then
c2hChannels=$((c2hChannels + 1))
fi
done done
echo "Info: Number of enabled c2h channels = $c2hChannels" echo "Info: Number of enabled c2h channels = $c2hChannels"
# Report if the PCIe DMA core is memory mapped or streaming # Report if the PCIe DMA core is memory mapped or streaming
if [ $isStreaming -eq 0 ]; then if [ $isStreaming -eq 0 ]; then
echo "Info: The PCIe DMA core is memory mapped." echo "Info: The PCIe DMA core is memory mapped."
else else
echo "Info: The PCIe DMA core is streaming." echo "Info: The PCIe DMA core is streaming."
fi fi
# Check to make sure atleast one channel was identified # Check to make sure atleast one channel was identified
if [ $h2cChannels -eq 0 -a $c2hChannels -eq 0 ]; then if [ $h2cChannels -eq 0 -a $c2hChannels -eq 0 ]; then
echo "Error: No PCIe DMA channels were identified." echo "Error: No PCIe DMA channels were identified."
exit 1 exit 1
fi fi
# Perform testing on the PCIe DMA core. # Perform testing on the PCIe DMA core.
testError=0 testError=0
if [ $isStreaming -eq 0 ]; then if [ $isStreaming -eq 0 ]; then
# Run the PCIe DMA memory mapped write read test # Run the PCIe DMA memory mapped write read test
./dma_memory_mapped_test.sh $transferSize $transferCount $h2cChannels $c2hChannels ./dma_memory_mapped_test.sh xdma0 $transferSize $transferCount $h2cChannels $c2hChannels
returnVal=$? returnVal=$?
if [ $returnVal -eq 1 ]; then if [ $returnVal -eq 1 ]; then
testError=1 testError=1
fi fi
else else
# Run the PCIe DMA streaming test # Run the PCIe DMA streaming test
channelPairs=$(($h2cChannels < $c2hChannels ? $h2cChannels : $c2hChannels)) channelPairs=$(($h2cChannels < $c2hChannels ? $h2cChannels : $c2hChannels))
if [ $channelPairs -gt 0 ]; then if [ $channelPairs -gt 0 ]; then
./dma_streaming_test.sh $transferSize $transferCount $channelPairs ./dma_streaming_test.sh $transferSize $transferCount $channelPairs
returnVal=$? returnVal=$?
if [ $returnVal -eq 1 ]; then if [ $returnVal -eq 1 ]; then
testError=1 testError=1
fi fi
else else
echo "Info: No PCIe DMA stream channels were tested because no h2c/c2h pairs were found." echo "Info: No PCIe DMA stream channels were tested because no h2c/c2h pairs were found."
fi fi
fi fi
# Exit with an error code if an error was found during testing # Exit with an error code if an error was found during testing
if [ $testError -eq 1 ]; then if [ $testError -eq 1 ]; then
echo "Error: Test completed with Errors." echo "Error: Test completed with Errors."
exit 1 exit 1
fi fi
# Report all tests passed and exit # Report all tests passed and exit
......
#!/bin/bash
##############################################################
#
# parse the fio result directory generated by the fio_test.sh
#
##############################################################
function parse_iops() {
eval str="$1"
value=$(echo $str | awk -F "," '{print $1}' | awk -F "=" '{print $2}')
unit=$(echo $value | awk -F '[0-9,.]*' '{print $2}')
value=$(echo $value | sed 's/[^0-9,.]*//g')
# echo -n " iops: ${value}${unit}"
if [ -z "$unit" ];then
value=$(echo "scale=4; $value/1000" | bc -l)
elif [[ "$unit" == "k" ]];then
value=$(echo "scale=4; $value" | bc -l)
elif [[ "$unit" == "m" ]];then
value=$(echo "scale=4; $value*1000" | bc -l)
else
echo "iops: $value$unit, unknown unit $unit."
fi
}
function parse_bw() {
eval str="$1"
value=$(echo $str | awk -F "," '{print $2}')
value=$(echo $value | awk -F "[(,)]" '{print $2}')
unit=$(echo $value | awk -F '[0-9,.]*' '{print $2}')
value=$(echo $value | sed 's/[^0-9,.]*//g')
# echo -n " bw: ${value}${unit}"
if [[ "$unit" == "kB/s" ]];then
value=$(echo "scale=4; $value" | bc -l)
elif [[ "$unit" == "MB/s" ]];then
value=$(echo "scale=4; $value*1024" | bc -l)
elif [[ "$unit" == "gB/s" ]];then
value=$(echo "scale=4; $value*1024*1024" | bc -l)
else
echo "bw: $value$unit, unknown unit $unit."
fi
}
function parse_latency() {
eval str="$1"
value=$(echo $str | awk -F "," '{print $3}' | awk -F "=" '{print $2}')
unit=$(echo $str | awk -F "[(,)]" '{print $2}')
# echo -n " latency: ${value}${unit}"
if [[ "$unit" == "usec" ]];then
value=$(echo "scale=4; $value" | bc -l)
elif [[ "$unit" == "sec" ]];then
value=$(echo "scale=6; $value*1000000" | bc -l)
elif [[ "$unit" == "msec" ]];then
value=$(echo "scale=6; $value*1000" | bc -l)
elif [[ "$unit" == "nsec" ]];then
value=$(echo "scale=4; $value/1000" | bc -l)
else
echo "latency: $value$unit, unknown unit $unit."
fi
}
##############
# Main body
##############
if [ $# -lt 1 ];then
echo "$0 <result directory>"
exit 1
fi
dir=$1
if [[ ! -d $dir ]];then
echo "$dir does NOT exist."
exit 1
fi
declare -a lat_array
resfname=result.csv
rm -f $dir/$resfname
channel_list=`ls $dir`
for channels in $channel_list; do
cd $dir/$channels
rm -f $dir/$channels/$resfname
iodir_list=`ls`
for iodir in $iodir_list; do
cd $dir/$channels/$iodir
rm -f $resfname
echo > $resfname
fio_list=`ls fio*.log`
for fname in $fio_list; do
# fio result file format fio_<io size>_t<# threads>.log
sz=$(echo $fname | cut -d. -f1 | cut -d_ -f2)
thread=$(echo $fname | cut -d. -f1 | cut -d_ -f3)
thread=$(echo $thread | sed 's/[^0-9]*//')
#echo "$dir/$channels/$iodir/$fname:"
value=0;
unit=0
if [ "$iodir" == "h2c" ]; then
#echo -n "$channels h2c:io $sz thread $thread "
ln=$(grep "write:" $fname)
parse_iops "\${ln}"
echo -n $sz,$thread,$value, >> $resfname
parse_bw "\${ln}"
echo -n $value, >> $resfname
ln=$(grep clat $fname | grep avg)
parse_latency "\${ln}"
echo "$value,,,," >> $resfname
elif [ "$iodir" == "c2h" ]; then
#echo -n "$channels c2h:io $sz thread $thread "
ln=$(grep "read:" $fname)
parse_iops "\${ln}"
echo -n $sz,$thread,,,,$value, >> $resfname
parse_bw "\${ln}"
echo -n $value, >> $resfname
ln=$(grep clat $fname | grep avg)
parse_latency "\${ln}"
echo "$value," >> $resfname
elif [ "$iodir" == "bi" ]; then
#echo -n "$channels bidir:io $sz thread $thread "
readarray lat_array < <(grep clat $fname | \
grep avg)
# h2c
#echo -n "h2c "
ln=$(grep "write:" $fname)
parse_iops "\${ln}"
echo -n $sz,$thread,$value, >> $resfname
parse_bw "\${ln}"
echo -n $value, >> $resfname
parse_latency "\${lat_array[1]}"
echo -n $value, >> $resfname
#c2h
#echo -n " c2h "
ln=$(grep "read:" $fname)
parse_iops "\${ln}"
echo -n $value, >> $resfname
parse_bw "\${ln}"
echo -n $value, >> $resfname
parse_latency "\${lat_array[0]}"
echo $value >> $resfname
fi
done
done
done
echo
cd $dir
for channels in $channel_list; do
cd $dir/$channels
echo -n "iosize(B)","Thread #", > $resfname
echo -n "H2C IOPS(K)","H2C BW(KB/s)","H2C Latency(usec)," >> $resfname
echo "C2H IOPS(K)","C2H BW(KB/s)","C2H Latency(usec)," >> $resfname
for iodir in $iodir_list; do
cat $iodir/$resfname | sort -t, -k1,1n >> $resfname
done
echo "$channels channel results: $dir/$channels/$resfname"
done
#!/bin/bash
display_help() {
echo -n "$0 <xdma id> <# ch> <io sz> < runtime> <iodir> <thread #> "
echo "<logdir>"
echo -e "\t<xdma id>: xdmaN"
echo -e "\t<dir>: io direction <h2c|c2h|bi>"
echo -e "\t<# ch>: fio --num_ch"
echo -e "\t<io sz>: fio --io_size"
echo -e "\t<runtime>: fio --runtime"
echo -e "\t<thread #>: fio --threads"
echo -e "\t<logdir>: log directory"
exit;
}
####################
#
# main body
#
####################
if [ $# -ne 7 ]; then
display_help
fi
xid=$1
iodir=$2
num_ch=$3
io_size=$4
runtime=$5
threads=$6
logdir=$7
outfile="${logdir}/fio_${io_size}_t${threads}.log"
exec_cmd=
op_cmd=
engine=sync
cmd_common="fio --allow_file_create=0 --ioengine=${engine} --zero_buffers"
cmd_common="$cmd_common --mem=mmap --runtime=${runtime} --time_based"
for ((i = 0; i < num_ch; i++)); do
if [ ${iodir} == bi ]; then
op_cmd="${op_cmd} --name=write${i} --bs=${io_size}"
op_cmd="${op_cmd} --size=${io_size} --offset=0 --rw=write"
op_cmd="${op_cmd} --filename=/dev/xdma0_h2c_${i}"
op_cmd="${op_cmd} --numjobs=${threads} --group_reporting"
op_cmd="${op_cmd} --name=read${i} --bs=${io_size}"
op_cmd="${op_cmd} --size=${io_size} --offset=0 --rw=read "
op_cmd="${op_cmd} --filename=/dev/xdma0_c2h_${i}"
op_cmd="${op_cmd} --numjobs=${threads} --group_reporting"
elif [ ${iodir} == h2c ]; then
op_cmd="${op_cmd} --name=write${i} --bs=${io_size}"
op_cmd="${op_cmd} --size=${io_size} --offset=0 --rw=write"
op_cmd="${op_cmd} --filename=/dev/xdma0_${iodir}_${i}"
op_cmd="${op_cmd} --numjobs=${threads} --group_reporting"
else
op_cmd="${op_cmd} --name=read${i} --bs=${io_size}"
op_cmd="${op_cmd} --size=${io_size} --offset=0 --rw=read"
op_cmd="${op_cmd} --filename=/dev/xdma0_${iodir}_${i}"
op_cmd="${op_cmd} --numjobs=${threads} --group_reporting"
fi
done
exec_cmd="${cmd_common}${op_cmd}"
echo -e "${exec_cmd}\n\n" > ${outfile}
${exec_cmd} >> ${outfile} &
pid=$!
wait $pid
#!/bin/sh
tool_path=../../tools
logdir=/tmp
if [ $# -lt 9 ]; then
echo -ne "$0 <dmesg log 0|1> <data check 0|1> <sz> <address> <offset> "
echo "<xid> <h2c channel> <c2h channel> <log dir> [data file]"
echo -e "\t<dmesg log>: log test into dmesg"
echo -e "\t<data check 0|1>: read data back and compare"
echo -e "\t<sz>: dma transfer size"
echo -e "\t<address>: "
echo -e "\t<offset>: "
echo -e "\t<xdma id>: xdma<N>"
echo -e "\t<h2c channel>: dma h2c channel #, 0-based"
echo -e "\t\tif >= 4, no traffic will be ran"
echo -e "\t<c2h channel>: dma c2h channel #, 0-based"
echo -e "\t if channel # >= 4 NO dma will be performed"
echo -e "\t\tif >= 4, no traffic will be ran"
echo -e "\t<log dir>: temp. log directory"
echo -e "\t[data file]: data file, size >= io size, "
echo -e "\t optional if <data check>=0"
exit
fi
dmesg=$1
data_check=$2
sz=$3
address=$4
offset=$5
xid=$6
h2cno=$7
c2hno=$8
logdir=$9
if [ $# -gt 9 ]; then
datafile=${10}
fi
if [ ! -d "$logdir" ]; then
mkdir -p $logdir
fi
echo -en "\n===>$0 $xid, channel $h2cno:$c2hno, io $sz, addr $address, "
echo "off $offset, data: $datafile, integrity $data_check, dmesg $dmesg."
if [ "$h2cno" -ge 4 ] && [ "$c2hno" -ge 4 ]; then
echo "$0: NO valid dma channel $h2cno:$c2hno"
exit 1
fi
h2c_cmd="$tool_path/dma_to_device -d /dev/${xid}_h2c_${h2cno}"
c2h_cmd="$tool_path/dma_from_device -d /dev/${xid}_c2h_${c2hno}"
if [ "$address" -ne "0" ]; then
h2c_cmd="$h2c_cmd -a $address"
c2h_cmd="$c2h_cmd -a $address"
fi
if [ "$offset" -ne "0" ]; then
h2c_cmd="$h2c_cmd -o $offset"
c2h_cmd="$c2h_cmd -o $offset"
fi
if [ "$data_check" -ne 0 ]; then
if [ -z "$datafile" ]; then
echo "no datafile specified"
exit 2
fi
if [ ! -s "$datafile" ]; then
echo "missing datafile: $datafile ..."
exit 3
fi
h2c_fname="$logdir/$xid-h2c${h2cno}-io$sz-o$offset-a$address.bin"
rm -f $h2c_fname
h2c_cmd="$h2c_cmd -f $datafile -w $h2c_fname"
c2h_fname="$logdir/$xid-c2h${c2hno}-io$sz-o$offset-a$address.bin"
rm -f $c2h_fname
c2h_cmd="$c2h_cmd -f $c2h_fname"
fi
if [ "$h2cno" -lt 4 ]; then
if [ "$dmesg" -ne "0" ]; then
echo "$h2c_cmd -s $sz -c 1" > /dev/kmsg
fi
echo "$h2c_cmd -s $sz -c 1 ..." > \
${logdir}/h2c-io${sz}-o${offset}-a${address}.log
out=`$h2c_cmd -s $sz -c 1`
echo $out >> ${logdir}/h2c-io${sz}-o${offset}-a${address}.log
if [ "$?" -ne "0" ]; then
echo -e "\tH2C${h2cno}: io $sz, ERROR $?."
exit 4
fi
fi
if [ "$c2hno" -lt 4 ]; then
if [ "$dmesg" -ne "0" ]; then
echo "$c2h_cmd -s $sz -c 1 ..." > /dev/kmsg
fi
echo "$c2h_cmd -s $sz -c 1 ..." > \
${logdir}/c2h-io${sz}-o${offset}-a${address}.log
out=`./$c2h_cmd -s $sz -c 1`
echo $out >> ${logdir}/c2h-io${sz}-o${offset}-a${address}.log
if [ "$?" -ne "0" ]; then
echo -e "\tC2H$channel: io $sz, ERROR $?."
exit 5
fi
fi
if [ "$data_check" -eq 0 ]; then
# no data integrity check needs to be done
exit 0
fi
#md5sum $c2h_fname
#md5sum $h2c_fname
diff -q $c2h_fname $h2c_fname > /dev/null
if [ "$?" -eq "1" ]; then
echo -e "\t$xid $h2cno:$c2hno: io $sz, addr $address, off $offset," \
"data integrity FAILED!."
exit 6
fi
echo -e "\t$xid $h2cno:$c2hno: io $sz, addr $address, off $offset, data match."
rm -f $c2h_fname $h2c_fname
exit 0
#!/bin/sh
delay=5
if [ $# -lt 9 ]; then
echo -ne "$0: <xid> <h2c channel> <c2h channel> <address> <offset> "
echo "<io min> <io max> <data check> <dmesg log> [log dir]"
echo -e "\t<xdma id>: xdma<N>"
echo -e "\th2c channel: H2C channel #, 0-based"
echo -e "\tc2h channel: C2H channel #, 0-based"
echo -e "\t<address>: "
echo -e "\t<offset>: "
echo -e "\t<io min>,<io max>: dma size in byte, io size start from"
echo -e "\t\tio_min, double each time until reaches io_max"
echo -e "\t<data check>: read back the data and compare, 0|1"
echo -e "\t<dmesg log>: log test info. into dmesg, 0|1"
exit 1
fi
xid=$1
h2cno=$2
c2hno=$3
addr=$4
off=$5
io_min=$6
io_max=$7
data_check=$8
dmesg=$9
tmpdir="/tmp/${xid}_h2c${h2cno}c2h${c2hno}"
echo "====>$0 $xid $h2cno:$c2hno, $io_min~$io_max @$addr $off, $data_check, $tmpdir"
if [ "$dmesg" -ne 0 ]; then
echo "$0 $xid $h2cno:$c2hno, $io_min~$io_max @$addr $off, $tmpdir..." \
>> /dev/kmsg
fi
if [ ! -d "$tmpdir" ]; then
mkdir -p $tmpdir
fi
rm -rf ${tmpdir}/*
if [ "$data_check" -ne 0 ]; then
cnt=$(($io_max / 1024))
if [ "$cnt" -eq 0 ]; then
cnt=1
fi
datafile="$tmpdir/datafile-$cnt-K"
cnt=$(($cnt / 65536))
if [ "$cnt" -eq "0" ]; then
cnt=1
fi
if [ ! -f "$datafile" ]; then
echo "creating datafile: $datafile ..."
let cnt=cnt+1
dd if=/dev/urandom of=$datafile bs=64M count=$cnt \
iflag=fullblock
fi
fi
date
sz=$io_min
while [ "$sz" -le "$io_max" ]; do
./io.sh $dmesg $data_check $sz $addr $off $xid $h2cno $c2hno $tmpdir \
$datafile
if [ "$?" -ne "0" ]; then
#echo -e "\t$xid $h2cno:$c2hno, $sz FAILED"
exit 2
fi
if [ "$sz" -eq "$io_max" ]; then
break
fi
sz=$(($sz * 2))
if [ "$sz" -gt "$io_max" ]; then
sz=$io_max
fi
if [ "$delay" -ne "0" ]; then
sleep $delay
fi
done
echo "====>$0 $xid $h2cno:$c2hno, $io_min~$io_max @$addr $off COMPLETED!"
exit 0
tool_path=../../tools
ERR=255
############################
#
# utility functions
#
############################
# Make sure only root can run the script
function check_if_root() {
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root" 1>&2
exit $ERR
fi
}
function check_cmd_exist() {
which $1 > /dev/null 2>&1
if [[ $? -ne 0 ]]; then
echo "$1 NOT found on the system"
return $ERR
fi
return 0
}
# check_rc <error code> <string> <exit if error 0|1>
function check_rc() {
local rc=$1
if [ $rc -ne 0 ]; then
echo "ERR! $2 failed $rc."
if [ $3 -gt 0 ]; then
exit $rc
fi
fi
}
# check_dma_dir <h2c|c2h|bi>
function check_dma_dir() {
if [ "$1" != h2c ] && [ "$1" != c2h ] && [ "$1" != bi ]; then
echo "bad dma direction: $1."
exit $ERR
fi
}
# check_driver_loaded <bdf>
function check_driver_loaded() {
local bdf=$1
lspci -s $bdf -v | grep driver | grep xdma | wc -l
}
# bdf_to_xdmaid <bdf>
function bdf_to_xdmaid() {
cd /sys/bus/pci/devices/$1/
if [ -d "xdma" ]; then
cd xdma/
ls | grep control | cut -d'_' -f1
fi
}
# cfg_reg_read <xid> <reg addr>
function cfg_reg_read() {
local v=`$tool_path/reg_rw /dev/$1_control $2 w | grep "Read.*:" | sed 's/Read.*: 0x\([a-z0-9]*\)/\1/'`
if [ -z "$v" ]; then
return $ERR
else
echo $v
return 0
fi
}
# cfg_reg_write <xid> <reg addr> <reg value>
function cfg_reg_write() {
local v=`$tool_path/reg_rw /dev/$1_control $2 w $3`
return $?
}
# get_streaming_enabled <xid>
function get_streaming_enabled() {
local v=`cfg_reg_read $1 0`
local rc=$?
if [ $rc -ne 0 ]; then
return $rc
fi
local id=${v:0:3}
local stream=${v:4:1}
local st=0
if [ "$id" == "1fc" ]; then
if [ "$stream" == "8" ]; then
st=1
fi
else
echo "$1 reg 0, $v, bad id $id, $stream."
return $ERR
fi
echo $st
return 0
}
# get_h2c_channel_count <xid>
function get_h2c_channel_count() {
local cnt=0
for ((i=0; i<=3; i++)); do
local regval=`cfg_reg_read $1 0x0${i}00`
if [ $? -ne 0 ]; then
break
fi
local id=${regval:0:3}
if [ "$id" == "1fc" ]; then
cnt=$((cnt + 1))
fi
done
echo $cnt
return 0
}
# get_c2h_channel_count <xid>
function get_c2h_channel_count() {
local cnt=0
for ((i=0; i<=3; i++)); do
local regval=`cfg_reg_read $1 0x1${i}00`
if [ $? -ne 0 ]; then
break
fi
local id=${regval:0:3}
if [ "$id" == "1fc" ]; then
cnt=$((cnt + 1))
fi
done
echo $cnt
return 0
}
#############################################################################
#
# test cases
#
#############################################################################
# xdma config bar access
# TC_cfg_reg_rw <xid>
function TC_cfg_reg_rw() {
local reg=0x301c
local val=0
cfg_reg_write $reg $val
local v=$(cfg_reg_read $reg)
let "v = $v + 0"
if [ $v -eq $val ]; then
echo "ERR ${FUNCNAME[0]} reg value mismatch $v, exp $val"
exit $ERR
fi
cfg_reg_write $reg 1
}
# TC_dma_chrdev_open_close <xid> <h2c count> <c2h count>
function TC_dma_chrdev_open_close() {
local xid=$1
local h2c_count=$2
local c2h_count=$3
local err=0
for ((i=0; i<$h2c_count; i++)); do
$tool_path/test_chrdev /dev/${xid}_h2c_$i > /dev/null 2>&1
if [ $? -ne 0 ];then
echo "${FUNCNAME[0]} ${xid}_h2c_$i FAILED"
exit 1
fi
done
for ((i=0; i<$c2h_count; i++)); do
$tool_path/test_chrdev /dev/${xid}_c2h_$i > /dev/null 2>&1
if [ $? -ne 0 ];then
echo "${FUNCNAME[0]} ${xid}_c2h_$i FAILED"
exit 2
fi
done
}
#!/bin/sh
##########################
#
# preset test parameters:
#
##########################
# dma io size
io_list="1 10 127 128 1021 1022 1023 1024 4095 4096 4097 4098 4099 8189 8190 8191 8192"
io_max=8192
# offset
offset_list="1 2 3 4 2045 2046 2047 2048 2049 4091 4092 4093 4094 4095"
# starting address
address=0
# delay(sleep) before moving on to the next channel, if applicable
delay=2
##########################
#
# main
#
##########################
if [ $# -lt 5 ]; then
echo "$0: <xid> <h2c channel> <c2h channel> <data check> <dmesg log>"
echo -e "\t<xid>: xdma<N>"
echo -e "\t<h2c channel>: H2C channel #, 0-based"
echo -e "\t<c2h channel>: C2H channel #, 0-based"
echo -e "\t<data check>: read back the data and compare, 0|1"
echo -e "\t<dmesg log>: log test info. into dmesg, 0|1"
exit
fi
xid=$1
h2cno=$2
c2hno=$3
data_check=$4
dmesg=$5
tmpdir="/tmp/${xid}_h2c${h2cno}_c2h${c2hno}_unaligned"
echo "====>$0 $xid $h2cno:$c2hno, $data_check,$dmesg, $tmpdir"
if [ "$dmesg" -ne 0 ]; then
echo "$0 $xid $h2cno:$c2hno, $tmpdir..." >> /dev/kmsg
fi
if [ ! -d "$tmpdir" ]; then
mkdir -p $tmpdir
fi
rm -rf $tmpdir/*
# generate data file, minimum 64MB
cnt=$(($io_max / 1024))
if [ "$cnt" -eq "0" ]; then
cnt=1
fi
datafile="$tmpdir/datafile-$cnt-K"
cnt=$(($cnt / 65536))
if [ "$cnt" -eq "0" ]; then
cnt=1
fi
if [ ! -f "$datafile" ]; then
echo "creating datafile: $datafile ..."
let cnt=cnt+1
dd if=/dev/urandom of=$datafile bs=64M count=$cnt iflag=fullblock
fi
echo
date
echo "====>$0: $xid $h2cno:$c2hno, addr $address ..." > /dev/kmsg
echo "$0: $xid $h2cno:$c2hno, addr $address ..." > /dev/kmsg
for io in $io_list; do
for offset in $offset_list; do
./io.sh $dmesg $data_check $io $address $offset $xid \
$h2cno $c2hno $tmpdir $datafile
if [ "$?" -ne "0" ]; then
echo -e "\t$xid $h2cno:$c2hno, $io, off $offset FAILED!"
exit 2
fi
done
if [ "$delay" -ne "0" ]; then
sleep $delay
fi
done
date
echo "====>$0: $xid $h2cno:$c2hno, addr $address COMPLETED!"
exit 0
#!/bin/bash
####################
#
# test settings
#
####################
outdir="/tmp"
driver_modes="0 4" ;# driver mode
address=0
offset=0
io_min=64
io_max=$((1 << 30)) ;# 1GB
delay=5 ;# delay between each test
fio_time=30
fio_thread_list="4 8"
fio_iodir_list="h2c c2h bi"
####################
#
# main body
#
####################
display_help() {
echo "$0 <xdma BDF> [log dir]"
echo -e "xdma BDF:\tfpga pci device specified in the format of "
echo -e "\t\t\t<domain>:<bus>:<device>.<func>"
echo -e "log dir:\toptional, default to /tmp"
echo
exit;
}
if [ $# -eq 0 ]; then
display_help
fi
bdf=$1
if [ $# -gt 1 ]; then
outdir=$2
fi
echo "xdma bdf:$bdf, outdir: $outdir"
source ./libtest.sh
check_if_root
curdir=$PWD
for dm in $driver_modes; do
echo -e "\n\n====> xdma mode $dm ...\n"
cd ../../tests
./load_driver.sh $dm
if [ $? -ne 0 ]; then
echo "load_driver.sh failed: $?"
exit 1
fi
cd $curdir
xid=$(bdf_to_xdmaid $bdf)
if [ ! -n "$xid" ]; then
echo "$bdf, no correponding xdma found, driver mode $dm."
exit 1
fi
echo "xdma id: $xid."
h2c_channels=$(get_h2c_channel_count $xid)
check_rc $? get_h2c_channel_count 1
c2h_channels=$(get_c2h_channel_count $xid)
check_rc $? get_c2h_channel_count 1
channel_pairs=$(($h2c_channels < $c2h_channels ? \
$h2c_channels : $c2h_channels))
echo "channels: $h2c_channels,$c2h_channels, pair $channel_pairs"
if [ "$channel_pairs" -eq 0 ]; then
echo "Error: 0 DMA channel pair: $h2c_channels,$c2h_channels."
exit 1
fi
# test cdev
TC_dma_chrdev_open_close $xid $h2c_channels $c2h_channels
#
# run 1 channel at a time
#
for i in {1..80}; do echo -n =; done
echo -e "\nSingle H2C Channel $h2c_channels io test ...\n"
for ((i=0; i<$h2c_channels; i++)); do
# aligned: no data integrity check
./io_sweep.sh $xid $i 4 $address $offset \
$io_min $io_max 0 1
check_rc $? "h2c-$i" 1
./unaligned.sh $xid $i 4 0 1
check_rc $? "h2c-$i-unaligned" 1
done
for i in {1..80}; do echo -n =; done
echo -e "\nSingle C2H Channel $c2h_channels io test ...\n"
for ((i=0; i<$c2h_channels; i++)); do
./io_sweep.sh $xid 4 $i $address $offset \
$io_min $io_max 0 1
check_rc $? "c2h-$i" 1
./unaligned.sh $xid 4 $i 0 1
check_rc $? "c2h-$i-unaligned" 1
done
for i in {1..80}; do echo -n =; done
echo -e "\nh2c/c2h pair $channel_pairs io test with data check ...\n"
for ((i=0; i<$channel_pairs; i++)); do
./io_sweep.sh $xid $i $i $address $offset $io_min $io_max 1 1
check_rc $? "pair-$i" 1
./unaligned.sh $xid $i $i 1 1
check_rc $? "pair-$i-unaligned" 1
done
#
# fio test
#
check_cmd_exist fio
if [ "$?" -ne 0 ]; then
echo "fio test skipped"
continue
fi
for i in {1..80}; do echo -n =; done
echo -e "\nfio test ...\n"
#
# result directory structure:
# - <outdir/fio>
# - <number of channels>
# - <direction: h2c c2h bi>
#
for ((i=1; i<=$channel_pairs; i++)); do
for iodir in $fio_iodir_list; do
out=${outdir}/fio_d${dm}/${i}/${iodir}
mkdir -p ${out}
rm -rf ${out}/*
for (( sz=$io_min; sz<=$io_max; sz=$(($sz*2)) )); do
for thread in $fio_thread_list; do
name=${sz}_t${thread}
echo "$iodir $i: $name ..."
./fio_test.sh $xid $iodir $i ${sz} \
${fio_time} ${thread} ${out}
done
done
done
done
./fio_parse_result.sh ${outdir}/fio_d${dm}
echo -e "\n\n====> xdma mode $dm COMPLETED.\n"
done
echo "$0: COMPLETED."
CC ?= gcc CC ?= gcc
all: reg_rw dma_to_device dma_from_device performance all: reg_rw dma_to_device dma_from_device performance test_chrdev
dma_to_device: dma_to_device.o dma_to_device: dma_to_device.o
$(CC) -lrt -o $@ $< -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -D_LARGE_FILE_SOURCE $(CC) -lrt -o $@ $< -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -D_LARGE_FILE_SOURCE
...@@ -14,9 +14,11 @@ performance: performance.o ...@@ -14,9 +14,11 @@ performance: performance.o
reg_rw: reg_rw.o reg_rw: reg_rw.o
$(CC) -o $@ $< $(CC) -o $@ $<
test_chrdev: test_chrdev.o
$(CC) -o $@ $<
%.o: %.c %.o: %.c
$(CC) -c -std=c99 -o $@ $< -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -D_LARGE_FILE_SOURCE $(CC) -c -std=c99 -o $@ $< -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -D_LARGE_FILE_SOURCE
clean: clean:
rm -rf reg_rw *.o *.bin dma_to_device dma_from_device performance rm -rf reg_rw *.o *.bin dma_to_device dma_from_device performance test_chrdev
...@@ -8,9 +8,6 @@ ...@@ -8,9 +8,6 @@
* LICENSE file in the root directory of this source tree) * LICENSE file in the root directory of this source tree)
*/ */
#define _BSD_SOURCE
#define _XOPEN_SOURCE 500
#include <assert.h>
#include <fcntl.h> #include <fcntl.h>
#include <getopt.h> #include <getopt.h>
#include <stdint.h> #include <stdint.h>
......
...@@ -8,9 +8,6 @@ ...@@ -8,9 +8,6 @@
* LICENSE file in the root directory of this source tree) * LICENSE file in the root directory of this source tree)
*/ */
#define _BSD_SOURCE
#define _XOPEN_SOURCE 500
#include <assert.h>
#include <fcntl.h> #include <fcntl.h>
#include <getopt.h> #include <getopt.h>
#include <stdint.h> #include <stdint.h>
......
#!/bin/bash
#rm hw_log_h2c.txt
#rm hw_log_c2h.txt
h2c=/dev/xdma0_h2c_0
c2h=/dev/xdma0_c2h_0
iter=1
out_h2c=hw_log_h2c.txt
out_c2h=hw_log_c2h.txt
byte=64
for ((j=0; j<=16; j++)) do
echo "** HW H2C = $h2c bytecount = $byte and iteration = $iter" | tee -a $out_h2c
./performance -d $h2c -c $iter -s $byte | tee -a $out_h2c
byte=$(($byte*2))
done
byte=64
for ((j=0; j<=16; j++)) do
echo "** HW C2H = $c2h bytecount = $byte and iteration = $iter" | tee -a $out_c2h
./performance -d $c2h -c $iter -s $byte | tee -a $out_c2h
byte=$(($byte*2))
done
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
/* @TODO During kernel upstreaming, the IOCTL must move into the public user API of the kernel */
#include "../xdma/cdev_sgdma.h" #include "../xdma/cdev_sgdma.h"
struct xdma_performance_ioctl perf; struct xdma_performance_ioctl perf;
......
...@@ -15,16 +15,14 @@ ...@@ -15,16 +15,14 @@
#include <byteswap.h> #include <byteswap.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <signal.h>
#include <fcntl.h> #include <fcntl.h>
#include <ctype.h> #include <ctype.h>
#include <termios.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/mman.h> #include <sys/mman.h>
/* ltoh: little to host */ /* ltoh: little endian to host */
/* htol: little to host */ /* htol: host to little endian */
#if __BYTE_ORDER == __LITTLE_ENDIAN #if __BYTE_ORDER == __LITTLE_ENDIAN
#define ltohl(x) (x) #define ltohl(x) (x)
#define ltohs(x) (x) #define ltohs(x) (x)
...@@ -37,14 +35,14 @@ ...@@ -37,14 +35,14 @@
#define htols(x) __bswap_16(x) #define htols(x) __bswap_16(x)
#endif #endif
#define FATAL do { fprintf(stderr, "Error at line %d, file %s (%d) [%s]\n", __LINE__, __FILE__, errno, strerror(errno)); exit(1); } while(0)
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int fd; int fd;
int err = 0;
void *map; void *map;
uint32_t read_result, writeval; uint32_t read_result, writeval;
off_t target; off_t target;
off_t pgsz, target_aligned, offset;
/* access width */ /* access width */
char access_width = 'w'; char access_width = 'w';
char *device; char *device;
...@@ -63,8 +61,14 @@ int main(int argc, char **argv) ...@@ -63,8 +61,14 @@ int main(int argc, char **argv)
device = strdup(argv[1]); device = strdup(argv[1]);
target = strtoul(argv[2], 0, 0); target = strtoul(argv[2], 0, 0);
printf("device: %s, address: 0x%08x, access %s.\n", /* check for target page alignment */
device, (unsigned int)target, argc >= 4 ? "write" : "read"); pgsz = sysconf(_SC_PAGESIZE);
offset = target & (pgsz - 1);
target_aligned = target & (~(pgsz - 1));
printf("device: %s, address: 0x%lx (0x%lx+0x%lx), access %s.\n",
device, target, target_aligned, offset,
argc >= 4 ? "write" : "read");
/* data given? */ /* data given? */
if (argc >= 4) if (argc >= 4)
...@@ -81,105 +85,95 @@ int main(int argc, char **argv) ...@@ -81,105 +85,95 @@ int main(int argc, char **argv)
access_width = 'w'; access_width = 'w';
} }
if ((fd = open(argv[1], O_RDWR | O_SYNC)) == -1) if ((fd = open(argv[1], O_RDWR | O_SYNC)) == -1) {
FATAL; printf("character device %s opened failed: %s.\n",
argv[1], strerror(errno));
return -errno;
}
printf("character device %s opened.\n", argv[1]); printf("character device %s opened.\n", argv[1]);
fflush(stdout);
map = mmap(0, 4, PROT_READ | PROT_WRITE, MAP_SHARED, fd, target); map = mmap(NULL, offset + 4, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
if (map == (void *)-1) target_aligned);
FATAL; if (map == (void *)-1) {
printf("Memory 0x%lx mapped at address %p.\n", target, map); printf("Memory 0x%lx mapped failed: %s.\n",
fflush(stdout); target, strerror(errno));
err = 1;
goto close;
}
printf("Memory 0x%lx mapped at address %p.\n", target_aligned, map);
map += offset;
/* read only */ /* read only */
if (argc <= 4) { if (argc <= 4) {
switch (access_width) { switch (access_width) {
case 'b': case 'b':
read_result = *((uint8_t *) map); read_result = *((uint8_t *) map);
printf printf
("Read 8-bits value at address 0x%08x (%p): 0x%02x\n", ("Read 8-bits value at address 0x%lx (%p): 0x%02x\n",
(unsigned int)target, map, target, map, (unsigned int)read_result);
(unsigned int)read_result);
break; break;
case 'h': case 'h':
read_result = *((uint16_t *) map); read_result = *((uint16_t *) map);
/* swap 16-bit endianess if host is not little-endian */ /* swap 16-bit endianess if host is not little-endian */
read_result = ltohs(read_result); read_result = ltohs(read_result);
printf printf
("Read 16-bit value at address 0x%08x (%p): 0x%04x\n", ("Read 16-bit value at address 0x%lx (%p): 0x%04x\n",
(unsigned int)target, map, target, map, (unsigned int)read_result);
(unsigned int)read_result);
break; break;
case 'w': case 'w':
read_result = *((uint32_t *) map); read_result = *((uint32_t *) map);
/* swap 32-bit endianess if host is not little-endian */ /* swap 32-bit endianess if host is not little-endian */
read_result = ltohl(read_result); read_result = ltohl(read_result);
printf printf
("Read 32-bit value at address 0x%08x (%p): 0x%08x\n", ("Read 32-bit value at address 0x%lx (%p): 0x%08x\n",
(unsigned int)target, map, target, map, (unsigned int)read_result);
(unsigned int)read_result);
return (int)read_result;
break; break;
default: default:
fprintf(stderr, "Illegal data type '%c'.\n", fprintf(stderr, "Illegal data type '%c'.\n",
access_width); access_width);
exit(2); err = 1;
goto unmap;
} }
fflush(stdout);
} }
/* data value given, i.e. writing? */ /* data value given, i.e. writing? */
if (argc >= 5) { if (argc >= 5) {
writeval = strtoul(argv[4], 0, 0); writeval = strtoul(argv[4], 0, 0);
switch (access_width) { switch (access_width) {
case 'b': case 'b':
printf("Write 8-bits value 0x%02x to 0x%08x (0x%p)\n", printf("Write 8-bits value 0x%02x to 0x%lx (0x%p)\n",
(unsigned int)writeval, (unsigned int)target, (unsigned int)writeval, target, map);
map);
*((uint8_t *) map) = writeval; *((uint8_t *) map) = writeval;
#if 0
if (argc > 4) {
read_result = *((uint8_t *) map);
printf("Written 0x%02x; readback 0x%02x\n",
writeval, read_result);
}
#endif
break; break;
case 'h': case 'h':
printf("Write 16-bits value 0x%04x to 0x%08x (0x%p)\n", printf("Write 16-bits value 0x%04x to 0x%lx (0x%p)\n",
(unsigned int)writeval, (unsigned int)target, (unsigned int)writeval, target, map);
map);
/* swap 16-bit endianess if host is not little-endian */ /* swap 16-bit endianess if host is not little-endian */
writeval = htols(writeval); writeval = htols(writeval);
*((uint16_t *) map) = writeval; *((uint16_t *) map) = writeval;
#if 0
if (argc > 4) {
read_result = *((uint16_t *) map);
printf("Written 0x%04x; readback 0x%04x\n",
writeval, read_result);
}
#endif
break; break;
case 'w': case 'w':
printf("Write 32-bits value 0x%08x to 0x%08x (0x%p)\n", printf("Write 32-bits value 0x%08x to 0x%lx (0x%p)\n",
(unsigned int)writeval, (unsigned int)target, (unsigned int)writeval, target, map);
map);
/* swap 32-bit endianess if host is not little-endian */ /* swap 32-bit endianess if host is not little-endian */
writeval = htoll(writeval); writeval = htoll(writeval);
*((uint32_t *) map) = writeval; *((uint32_t *) map) = writeval;
#if 0
if (argc > 4) {
read_result = *((uint32_t *) map);
printf("Written 0x%08x; readback 0x%08x\n",
writeval, read_result);
}
#endif
break; break;
default:
fprintf(stderr, "Illegal data type '%c'.\n",
access_width);
err = 1;
goto unmap;
} }
fflush(stdout);
} }
if (munmap(map, 4) == -1) unmap:
FATAL; map -= offset;
if (munmap(map, offset + 4) == -1) {
printf("Memory 0x%lx mapped failed: %s.\n",
target, strerror(errno));
}
close:
close(fd); close(fd);
return 0;
return err;
} }
/*
* This file is part of the Xilinx DMA IP Core driver tools for Linux
*
* Copyright (c) 2016-present, Xilinx, Inc.
* All rights reserved.
*
* This source code is licensed under BSD-style license (found in the
* LICENSE file in the root directory of this source tree)
*/
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int fd;
char *filename;
if ( (argc < 2) || (argc >= 3))
{
printf("usage %s <device file>\n",argv[0]);
return -1;
}
filename = argv[1];
fd = open(filename,O_RDWR);
if (fd < 0)
{
perror("Device open Failed");
return fd;
}
printf("%s Device open successfull\n",argv[1]);
if ( close(fd) )
{
perror("Device Close Failed");
return -1;
}
printf("%s Device close successfull\n",argv[1]);
return 0;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment