From dee66e136e9c24ad52684a72ee77762627b4eaa7 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 27 Jun 2015 13:55:33 +0200 Subject: [PATCH] Added "make table.txt" vivado scripts --- README.md | 20 +++++++ scripts/vivado/.gitignore | 1 + scripts/vivado/Makefile | 12 +++- scripts/vivado/table.sh | 17 ++++++ scripts/vivado/tabtest.sh | 71 +++++++++++++++++++++++ scripts/vivado/tabtest.v | 116 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 236 insertions(+), 1 deletion(-) create mode 100644 scripts/vivado/table.sh create mode 100644 scripts/vivado/tabtest.sh create mode 100644 scripts/vivado/tabtest.v diff --git a/README.md b/README.md index 2c8e8b9..be295f9 100644 --- a/README.md +++ b/README.md @@ -311,6 +311,26 @@ makes it easy to install them side-by-side with the regular riscv-tools, which are using the name prefix `riscv64-unknown-elf-` by default. +Evaluation: Timing on Xilinx 7-Series FPGAs +------------------------------------------- + +The following table lists the maximum clock speeds that PicoRV32 can run at on +Xilinx 7-Series FPGAs. This are the values reported by Vivado 2015.1 post +place&route static timing analysis (report_timing). + +| Device | Speedgrade | Clock Period (Freq.) | +|:-------------------- |:----------:| --------------------:| +| Xilinx Artix-7T | -1 | 5.1 ns (196 MHz) | +| Xilinx Artix-7T | -2 | 4.1 ns (243 MHz) | +| Xilinx Artix-7T | -3 | 3.6 ns (277 MHz) | +| Xilinx Kintex-7T | -1 | 3.3 ns (303 MHz) | +| Xilinx Kintex-7T | -2 | 2.6 ns (384 MHz) | +| Xilinx Kintex-7T | -3 | 2.5 ns (400 MHz) | +| Xilinx Virtex-7T | -1 | 3.1 ns (322 MHz) | +| Xilinx Virtex-7T | -2 | 2.6 ns (384 MHz) | +| Xilinx Virtex-7T | -3 | 2.4 ns (416 MHz) | + + Todos: ------ diff --git a/scripts/vivado/.gitignore b/scripts/vivado/.gitignore index 884ba06..6103060 100644 --- a/scripts/vivado/.gitignore +++ b/scripts/vivado/.gitignore @@ -2,3 +2,4 @@ synth_*.log synth_*.mmi synth_*.bit synth_*.v +tab_*/ diff --git a/scripts/vivado/Makefile b/scripts/vivado/Makefile index aa41132..9ca46a9 100644 --- a/scripts/vivado/Makefile +++ b/scripts/vivado/Makefile @@ -1,5 +1,5 @@ -VIVADO = /opt/Xilinx/Vivado/2014.4/bin/vivado +export VIVADO = /opt/Xilinx/Vivado/2015.1/bin/vivado help: @echo "Usage: make {synth_speed|synth_area|synth_soc}" @@ -8,3 +8,13 @@ synth_%: $(VIVADO) -nojournal -log $@.log -mode batch -source $@.tcl rm -rf .Xil fsm_encoding.os synth_*.backup.log usage_statistics_webtalk.* +tab_%/results.txt: + bash tabtest.sh $@ + +table.txt: tab_small_xc7a_1/results.txt tab_small_xc7a_2/results.txt tab_small_xc7a_3/results.txt +table.txt: tab_small_xc7k_1/results.txt tab_small_xc7k_2/results.txt tab_small_xc7k_3/results.txt +table.txt: tab_small_xc7v_1/results.txt tab_small_xc7v_2/results.txt tab_small_xc7v_3/results.txt + +table.txt: + bash table.sh > table.txt + diff --git a/scripts/vivado/table.sh b/scripts/vivado/table.sh new file mode 100644 index 0000000..9e8b9d1 --- /dev/null +++ b/scripts/vivado/table.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +dashes="----------------------------------------------------------------" +printf '| %-20s | %-10s | %-20s |\n' "Device" "Speedgrade" "Clock Period (Freq.)" +printf '|:%.20s |:%.10s:| %.20s:|\n' $dashes $dashes $dashes + +for x in $( grep -H . tab_*/results.txt ) +do + read _ size device grade _ speed < <( echo "$x" | tr _/: ' ' ) + case "$device" in + xc7a) d="Xilinx Artix-7T" ;; + xc7k) d="Xilinx Kintex-7T" ;; + xc7v) d="Xilinx Virtex-7T" ;; + esac + speedtxt=$( printf '%s.%s ns (%d MHz)' ${speed%?} ${speed#?} $((10000 / speed)) ) + printf '| %-20s | %-10s | %20s |\n' "$d" "-$grade" "$speedtxt" +done diff --git a/scripts/vivado/tabtest.sh b/scripts/vivado/tabtest.sh new file mode 100644 index 0000000..f9e03ed --- /dev/null +++ b/scripts/vivado/tabtest.sh @@ -0,0 +1,71 @@ +#!/bin/bash + +set -e +read _ ip dev grade _ < <( echo $* | tr '_/' ' '; ) + +# rm -rf tab_${ip}_${dev}_${grade} +mkdir -p tab_${ip}_${dev}_${grade} +cd tab_${ip}_${dev}_${grade} + +best_speed=99 +speed=30 +step=16 + +synth_case() { + if [ -f test_${1}.txt ]; then + echo "Reusing cached tab_${ip}_${dev}_${grade}/test_${1}." + return + fi + + case "${dev}" in + xc7a) xl_device="xc7a15t-fgg484-${grade}" ;; + xc7k) xl_device="xc7k70t-fbg676-${grade}" ;; + xc7v) xl_device="xc7v585t-ffg1761-${grade}" ;; + esac + + cat > test_${1}.tcl <<- EOT + read_verilog ../tabtest.v + read_verilog ../../../picorv32.v + read_xdc test_${1}.xdc + synth_design -flatten_hierarchy full -part ${xl_device} -top top + opt_design -sweep -remap + place_design -directive Explore + phys_opt_design -retime -rewire -critical_pin_opt -placement_opt -critical_cell_opt + route_design -directive Explore + place_design -post_place_opt + phys_opt_design -retime + route_design -directive NoTimingRelaxation + report_utilization + report_timing + EOT + + cat > test_${1}.xdc <<- EOT + create_clock -period ${speed%?}.${speed#?} [get_ports clk] + EOT + + echo "Running tab_${ip}_${dev}_${grade}/test_${1}.." + if ! $VIVADO -nojournal -log test_${1}.log -mode batch -source test_${1}.tcl > /dev/null 2>&1; then + cat test_${1}.log + exit 1 + fi + mv test_${1}.log test_${1}.txt +} + +while [ $step -gt 0 ]; do + synth_case $speed + + if grep -q '^Slack.*(VIOLATED)' test_${speed}.txt; then + [ $speed -eq 38 ] || step=$((step / 2)) + speed=$((speed + step)) + elif grep -q '^Slack.*(MET)' test_${speed}.txt; then + [ $speed -lt $best_speed ] && best_speed=$speed + step=$((step / 2)) + speed=$((speed - step)) + else + echo "ERROR: No slack line found in $PWD/test_${speed}.txt!" + exit 1 + fi +done + +echo $best_speed > results.txt + diff --git a/scripts/vivado/tabtest.v b/scripts/vivado/tabtest.v new file mode 100644 index 0000000..3a7677f --- /dev/null +++ b/scripts/vivado/tabtest.v @@ -0,0 +1,116 @@ + +module top ( + input clk, io_resetn, + output io_trap, + + output io_mem_axi_awvalid, + input io_mem_axi_awready, + output [31:0] io_mem_axi_awaddr, + output [ 2:0] io_mem_axi_awprot, + + output io_mem_axi_wvalid, + input io_mem_axi_wready, + output [31:0] io_mem_axi_wdata, + output [ 3:0] io_mem_axi_wstrb, + + input io_mem_axi_bvalid, + output io_mem_axi_bready, + + output io_mem_axi_arvalid, + input io_mem_axi_arready, + output [31:0] io_mem_axi_araddr, + output [ 2:0] io_mem_axi_arprot, + + input io_mem_axi_rvalid, + output io_mem_axi_rready, + input [31:0] io_mem_axi_rdata, + + input [31:0] io_irq, + output [31:0] io_eoi +); + wire resetn; + wire trap; + wire mem_axi_awvalid; + wire mem_axi_awready; + wire [31:0] mem_axi_awaddr; + wire [2:0] mem_axi_awprot; + wire mem_axi_wvalid; + wire mem_axi_wready; + wire [31:0] mem_axi_wdata; + wire [3:0] mem_axi_wstrb; + wire mem_axi_bvalid; + wire mem_axi_bready; + wire mem_axi_arvalid; + wire mem_axi_arready; + wire [31:0] mem_axi_araddr; + wire [2:0] mem_axi_arprot; + wire mem_axi_rvalid; + wire mem_axi_rready; + wire [31:0] mem_axi_rdata; + wire [31:0] irq; + wire [31:0] eoi; + + delay4 #( 1) delay_resetn (clk, io_resetn , resetn ); + delay4 #( 1) delay_trap (clk, trap , io_trap ); + delay4 #( 1) delay_mem_axi_awvalid (clk, mem_axi_awvalid, io_mem_axi_awvalid); + delay4 #( 1) delay_mem_axi_awready (clk, io_mem_axi_awready, mem_axi_awready); + delay4 #(32) delay_mem_axi_awaddr (clk, mem_axi_awaddr , io_mem_axi_awaddr ); + delay4 #( 3) delay_mem_axi_awprot (clk, mem_axi_awprot , io_mem_axi_awprot ); + delay4 #( 1) delay_mem_axi_wvalid (clk, mem_axi_wvalid , io_mem_axi_wvalid ); + delay4 #( 1) delay_mem_axi_wready (clk, io_mem_axi_wready , mem_axi_wready ); + delay4 #(32) delay_mem_axi_wdata (clk, mem_axi_wdata , io_mem_axi_wdata ); + delay4 #( 4) delay_mem_axi_wstrb (clk, mem_axi_wstrb , io_mem_axi_wstrb ); + delay4 #( 1) delay_mem_axi_bvalid (clk, io_mem_axi_bvalid , mem_axi_bvalid ); + delay4 #( 1) delay_mem_axi_bready (clk, mem_axi_bready , io_mem_axi_bready ); + delay4 #( 1) delay_mem_axi_arvalid (clk, mem_axi_arvalid, io_mem_axi_arvalid); + delay4 #( 1) delay_mem_axi_arready (clk, io_mem_axi_arready, mem_axi_arready); + delay4 #(32) delay_mem_axi_araddr (clk, mem_axi_araddr , io_mem_axi_araddr ); + delay4 #( 3) delay_mem_axi_arprot (clk, mem_axi_arprot , io_mem_axi_arprot ); + delay4 #( 1) delay_mem_axi_rvalid (clk, io_mem_axi_rvalid , mem_axi_rvalid ); + delay4 #( 1) delay_mem_axi_rready (clk, mem_axi_rready , io_mem_axi_rready ); + delay4 #(32) delay_mem_axi_rdata (clk, io_mem_axi_rdata , mem_axi_rdata ); + delay4 #(32) delay_irq (clk, io_irq , irq ); + delay4 #(32) delay_eoi (clk, eoi , io_eoi ); + + picorv32_axi core ( + .clk (clk ), + .resetn (resetn ), + .trap (trap ), + .mem_axi_awvalid(mem_axi_awvalid), + .mem_axi_awready(mem_axi_awready), + .mem_axi_awaddr (mem_axi_awaddr ), + .mem_axi_awprot (mem_axi_awprot ), + .mem_axi_wvalid (mem_axi_wvalid ), + .mem_axi_wready (mem_axi_wready ), + .mem_axi_wdata (mem_axi_wdata ), + .mem_axi_wstrb (mem_axi_wstrb ), + .mem_axi_bvalid (mem_axi_bvalid ), + .mem_axi_bready (mem_axi_bready ), + .mem_axi_arvalid(mem_axi_arvalid), + .mem_axi_arready(mem_axi_arready), + .mem_axi_araddr (mem_axi_araddr ), + .mem_axi_arprot (mem_axi_arprot ), + .mem_axi_rvalid (mem_axi_rvalid ), + .mem_axi_rready (mem_axi_rready ), + .mem_axi_rdata (mem_axi_rdata ), + .irq (irq ), + .eoi (eoi ) + ); +endmodule + +module delay4 #( + parameter WIDTH = 1 +) ( + input clk, + input [WIDTH-1:0] in, + output reg [WIDTH-1:0] out +); + reg [WIDTH-1:0] q1, q2, q3; + always @(posedge clk) begin + q1 <= in; + q2 <= q1; + q3 <= q2; + out <= q3; + end +endmodule +