summaryrefslogtreecommitdiffstats
path: root/scripts/vivado
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/vivado')
-rw-r--r--scripts/vivado/.gitignore18
-rw-r--r--scripts/vivado/Makefile69
-rw-r--r--scripts/vivado/firmware.S12
-rw-r--r--scripts/vivado/firmware.c43
-rw-r--r--scripts/vivado/firmware.lds11
-rw-r--r--scripts/vivado/synth_area.tcl8
-rw-r--r--scripts/vivado/synth_area.xdc1
-rw-r--r--scripts/vivado/synth_area_large.tcl10
-rw-r--r--scripts/vivado/synth_area_regular.tcl10
-rw-r--r--scripts/vivado/synth_area_small.tcl10
-rw-r--r--scripts/vivado/synth_area_top.v140
-rw-r--r--scripts/vivado/synth_speed.tcl13
-rw-r--r--scripts/vivado/synth_speed.xdc1
-rw-r--r--scripts/vivado/synth_system.tcl17
-rw-r--r--scripts/vivado/synth_system.xdc34
-rw-r--r--scripts/vivado/system.v101
-rw-r--r--scripts/vivado/system_tb.v38
-rw-r--r--scripts/vivado/table.sh21
-rw-r--r--scripts/vivado/tabtest.sh103
-rw-r--r--scripts/vivado/tabtest.v118
20 files changed, 778 insertions, 0 deletions
diff --git a/scripts/vivado/.gitignore b/scripts/vivado/.gitignore
new file mode 100644
index 0000000..2374269
--- /dev/null
+++ b/scripts/vivado/.gitignore
@@ -0,0 +1,18 @@
+.Xil/
+firmware.bin
+firmware.elf
+firmware.hex
+firmware.map
+synth_*.log
+synth_*.mmi
+synth_*.bit
+synth_system.v
+table.txt
+tab_*/
+webtalk.jou
+webtalk.log
+webtalk_*.jou
+webtalk_*.log
+xelab.*
+xsim.*
+xvlog.*
diff --git a/scripts/vivado/Makefile b/scripts/vivado/Makefile
new file mode 100644
index 0000000..3c92901
--- /dev/null
+++ b/scripts/vivado/Makefile
@@ -0,0 +1,69 @@
+
+VIVADO_BASE = /opt/Xilinx/Vivado/2018.2
+VIVADO = $(VIVADO_BASE)/bin/vivado
+XVLOG = $(VIVADO_BASE)/bin/xvlog
+XELAB = $(VIVADO_BASE)/bin/xelab
+GLBL = $(VIVADO_BASE)/data/verilog/src/glbl.v
+TOOLCHAIN_PREFIX = riscv32-unknown-elf-
+
+export VIVADO
+
+# work-around for http://svn.clifford.at/handicraft/2016/vivadosig11
+export RDI_VERBOSE = False
+
+help:
+ @echo ""
+ @echo "Simple synthesis tests:"
+ @echo " make synth_area_{small|regular|large}"
+ @echo " make synth_speed"
+ @echo ""
+ @echo "Example system:"
+ @echo " make synth_system"
+ @echo " make sim_system"
+ @echo ""
+ @echo "Timing and Utilization Evaluation:"
+ @echo " make table.txt"
+ @echo " make area"
+ @echo ""
+
+synth_%:
+ rm -f $@.log
+ $(VIVADO) -nojournal -log $@.log -mode batch -source $@.tcl
+ rm -rf .Xil fsm_encoding.os synth_*.backup.log usage_statistics_webtalk.*
+ -grep -B4 -A10 'Slice LUTs' $@.log
+ -grep -B1 -A9 ^Slack $@.log && echo
+
+synth_system: firmware.hex
+
+sim_system:
+ $(XVLOG) system_tb.v synth_system.v
+ $(XVLOG) $(GLBL)
+ $(XELAB) -L unifast_ver -L unisims_ver -R system_tb glbl
+
+firmware.hex: firmware.S firmware.c firmware.lds
+ $(TOOLCHAIN_PREFIX)gcc -Os -ffreestanding -nostdlib -o firmware.elf firmware.S firmware.c \
+ --std=gnu99 -Wl,-Bstatic,-T,firmware.lds,-Map,firmware.map,--strip-debug -lgcc
+ $(TOOLCHAIN_PREFIX)objcopy -O binary firmware.elf firmware.bin
+ python3 ../../firmware/makehex.py firmware.bin 4096 > firmware.hex
+
+tab_%/results.txt:
+ bash tabtest.sh $@
+
+area: synth_area_small synth_area_regular synth_area_large
+ -grep -B4 -A10 'Slice LUTs' synth_area_small.log synth_area_regular.log synth_area_large.log
+
+table.txt: tab_small_xc7k_2/results.txt tab_small_xc7k_3/results.txt
+table.txt: tab_small_xc7v_2/results.txt tab_small_xc7v_3/results.txt
+table.txt: tab_small_xcku_2/results.txt tab_small_xcku_3/results.txt
+table.txt: tab_small_xcvu_2/results.txt tab_small_xcvu_3/results.txt
+table.txt: tab_small_xckup_2/results.txt tab_small_xckup_3/results.txt
+table.txt: tab_small_xcvup_2/results.txt tab_small_xcvup_3/results.txt
+
+table.txt:
+ bash table.sh > table.txt
+
+clean:
+ rm -rf .Xil/ firmware.bin firmware.elf firmware.hex firmware.map synth_*.log
+ rm -rf synth_*.mmi synth_*.bit synth_system.v table.txt tab_*/ webtalk.jou
+ rm -rf webtalk.log webtalk_*.jou webtalk_*.log xelab.* xsim[._]* xvlog.*
+
diff --git a/scripts/vivado/firmware.S b/scripts/vivado/firmware.S
new file mode 100644
index 0000000..c55a3ba
--- /dev/null
+++ b/scripts/vivado/firmware.S
@@ -0,0 +1,12 @@
+.section .init
+.global main
+
+/* set stack pointer */
+lui sp, %hi(16*1024)
+addi sp, sp, %lo(16*1024)
+
+/* call main */
+jal ra, main
+
+/* break */
+ebreak
diff --git a/scripts/vivado/firmware.c b/scripts/vivado/firmware.c
new file mode 100644
index 0000000..6c62169
--- /dev/null
+++ b/scripts/vivado/firmware.c
@@ -0,0 +1,43 @@
+void putc(char c)
+{
+ *(volatile char*)0x10000000 = c;
+}
+
+void puts(const char *s)
+{
+ while (*s) putc(*s++);
+}
+
+void *memcpy(void *dest, const void *src, int n)
+{
+ while (n) {
+ n--;
+ ((char*)dest)[n] = ((char*)src)[n];
+ }
+ return dest;
+}
+
+void main()
+{
+ char message[] = "$Uryyb+Jbeyq!+Vs+lbh+pna+ernq+guvf+zrffntr+gura$gur+CvpbEI32+PCH"
+ "+frrzf+gb+or+jbexvat+whfg+svar.$$++++++++++++++++GRFG+CNFFRQ!$$";
+ for (int i = 0; message[i]; i++)
+ switch (message[i])
+ {
+ case 'a' ... 'm':
+ case 'A' ... 'M':
+ message[i] += 13;
+ break;
+ case 'n' ... 'z':
+ case 'N' ... 'Z':
+ message[i] -= 13;
+ break;
+ case '$':
+ message[i] = '\n';
+ break;
+ case '+':
+ message[i] = ' ';
+ break;
+ }
+ puts(message);
+}
diff --git a/scripts/vivado/firmware.lds b/scripts/vivado/firmware.lds
new file mode 100644
index 0000000..970000a
--- /dev/null
+++ b/scripts/vivado/firmware.lds
@@ -0,0 +1,11 @@
+SECTIONS {
+ .memory : {
+ . = 0x000000;
+ *(.init);
+ *(.text);
+ *(*);
+ . = ALIGN(4);
+ end = .;
+ }
+}
+
diff --git a/scripts/vivado/synth_area.tcl b/scripts/vivado/synth_area.tcl
new file mode 100644
index 0000000..c222a00
--- /dev/null
+++ b/scripts/vivado/synth_area.tcl
@@ -0,0 +1,8 @@
+read_verilog ../../picorv32.v
+read_xdc synth_area.xdc
+
+synth_design -part xc7k70t-fbg676 -top picorv32_axi
+opt_design -resynth_seq_area
+
+report_utilization
+report_timing
diff --git a/scripts/vivado/synth_area.xdc b/scripts/vivado/synth_area.xdc
new file mode 100644
index 0000000..3c3d5a1
--- /dev/null
+++ b/scripts/vivado/synth_area.xdc
@@ -0,0 +1 @@
+create_clock -period 20.00 [get_ports clk]
diff --git a/scripts/vivado/synth_area_large.tcl b/scripts/vivado/synth_area_large.tcl
new file mode 100644
index 0000000..af611b5
--- /dev/null
+++ b/scripts/vivado/synth_area_large.tcl
@@ -0,0 +1,10 @@
+read_verilog ../../picorv32.v
+read_verilog synth_area_top.v
+read_xdc synth_area.xdc
+
+synth_design -part xc7k70t-fbg676 -top top_large
+opt_design -sweep -propconst -resynth_seq_area
+opt_design -directive ExploreSequentialArea
+
+report_utilization
+report_timing
diff --git a/scripts/vivado/synth_area_regular.tcl b/scripts/vivado/synth_area_regular.tcl
new file mode 100644
index 0000000..2bf6b4c
--- /dev/null
+++ b/scripts/vivado/synth_area_regular.tcl
@@ -0,0 +1,10 @@
+read_verilog ../../picorv32.v
+read_verilog synth_area_top.v
+read_xdc synth_area.xdc
+
+synth_design -part xc7k70t-fbg676 -top top_regular
+opt_design -sweep -propconst -resynth_seq_area
+opt_design -directive ExploreSequentialArea
+
+report_utilization
+report_timing
diff --git a/scripts/vivado/synth_area_small.tcl b/scripts/vivado/synth_area_small.tcl
new file mode 100644
index 0000000..11d2104
--- /dev/null
+++ b/scripts/vivado/synth_area_small.tcl
@@ -0,0 +1,10 @@
+read_verilog ../../picorv32.v
+read_verilog synth_area_top.v
+read_xdc synth_area.xdc
+
+synth_design -part xc7k70t-fbg676 -top top_small
+opt_design -sweep -propconst -resynth_seq_area
+opt_design -directive ExploreSequentialArea
+
+report_utilization
+report_timing
diff --git a/scripts/vivado/synth_area_top.v b/scripts/vivado/synth_area_top.v
new file mode 100644
index 0000000..6298a86
--- /dev/null
+++ b/scripts/vivado/synth_area_top.v
@@ -0,0 +1,140 @@
+
+module top_small (
+ input clk, resetn,
+
+ output mem_valid,
+ output mem_instr,
+ input mem_ready,
+
+ output [31:0] mem_addr,
+ output [31:0] mem_wdata,
+ output [ 3:0] mem_wstrb,
+ input [31:0] mem_rdata
+);
+ picorv32 #(
+ .ENABLE_COUNTERS(0),
+ .LATCHED_MEM_RDATA(1),
+ .TWO_STAGE_SHIFT(0),
+ .CATCH_MISALIGN(0),
+ .CATCH_ILLINSN(0)
+ ) picorv32 (
+ .clk (clk ),
+ .resetn (resetn ),
+ .mem_valid(mem_valid),
+ .mem_instr(mem_instr),
+ .mem_ready(mem_ready),
+ .mem_addr (mem_addr ),
+ .mem_wdata(mem_wdata),
+ .mem_wstrb(mem_wstrb),
+ .mem_rdata(mem_rdata)
+ );
+endmodule
+
+module top_regular (
+ input clk, resetn,
+ output trap,
+
+ output mem_valid,
+ output mem_instr,
+ input mem_ready,
+
+ output [31:0] mem_addr,
+ output [31:0] mem_wdata,
+ output [ 3:0] mem_wstrb,
+ input [31:0] mem_rdata,
+
+ // Look-Ahead Interface
+ output mem_la_read,
+ output mem_la_write,
+ output [31:0] mem_la_addr,
+ output [31:0] mem_la_wdata,
+ output [ 3:0] mem_la_wstrb
+);
+ picorv32 picorv32 (
+ .clk (clk ),
+ .resetn (resetn ),
+ .trap (trap ),
+ .mem_valid (mem_valid ),
+ .mem_instr (mem_instr ),
+ .mem_ready (mem_ready ),
+ .mem_addr (mem_addr ),
+ .mem_wdata (mem_wdata ),
+ .mem_wstrb (mem_wstrb ),
+ .mem_rdata (mem_rdata ),
+ .mem_la_read (mem_la_read ),
+ .mem_la_write(mem_la_write),
+ .mem_la_addr (mem_la_addr ),
+ .mem_la_wdata(mem_la_wdata),
+ .mem_la_wstrb(mem_la_wstrb)
+ );
+endmodule
+
+module top_large (
+ input clk, resetn,
+ output trap,
+
+ output mem_valid,
+ output mem_instr,
+ input mem_ready,
+
+ output [31:0] mem_addr,
+ output [31:0] mem_wdata,
+ output [ 3:0] mem_wstrb,
+ input [31:0] mem_rdata,
+
+ // Look-Ahead Interface
+ output mem_la_read,
+ output mem_la_write,
+ output [31:0] mem_la_addr,
+ output [31:0] mem_la_wdata,
+ output [ 3:0] mem_la_wstrb,
+
+ // Pico Co-Processor Interface (PCPI)
+ output pcpi_valid,
+ output [31:0] pcpi_insn,
+ output [31:0] pcpi_rs1,
+ output [31:0] pcpi_rs2,
+ input pcpi_wr,
+ input [31:0] pcpi_rd,
+ input pcpi_wait,
+ input pcpi_ready,
+
+ // IRQ Interface
+ input [31:0] irq,
+ output [31:0] eoi
+);
+ picorv32 #(
+ .COMPRESSED_ISA(1),
+ .BARREL_SHIFTER(1),
+ .ENABLE_PCPI(1),
+ .ENABLE_MUL(1),
+ .ENABLE_IRQ(1)
+ ) picorv32 (
+ .clk (clk ),
+ .resetn (resetn ),
+ .trap (trap ),
+ .mem_valid (mem_valid ),
+ .mem_instr (mem_instr ),
+ .mem_ready (mem_ready ),
+ .mem_addr (mem_addr ),
+ .mem_wdata (mem_wdata ),
+ .mem_wstrb (mem_wstrb ),
+ .mem_rdata (mem_rdata ),
+ .mem_la_read (mem_la_read ),
+ .mem_la_write (mem_la_write ),
+ .mem_la_addr (mem_la_addr ),
+ .mem_la_wdata (mem_la_wdata ),
+ .mem_la_wstrb (mem_la_wstrb ),
+ .pcpi_valid (pcpi_valid ),
+ .pcpi_insn (pcpi_insn ),
+ .pcpi_rs1 (pcpi_rs1 ),
+ .pcpi_rs2 (pcpi_rs2 ),
+ .pcpi_wr (pcpi_wr ),
+ .pcpi_rd (pcpi_rd ),
+ .pcpi_wait (pcpi_wait ),
+ .pcpi_ready (pcpi_ready ),
+ .irq (irq ),
+ .eoi (eoi )
+ );
+endmodule
+
diff --git a/scripts/vivado/synth_speed.tcl b/scripts/vivado/synth_speed.tcl
new file mode 100644
index 0000000..f3874e4
--- /dev/null
+++ b/scripts/vivado/synth_speed.tcl
@@ -0,0 +1,13 @@
+
+read_verilog ../../picorv32.v
+read_xdc synth_speed.xdc
+
+synth_design -part xc7k70t-fbg676 -top picorv32_axi
+opt_design
+place_design
+phys_opt_design
+route_design
+
+report_utilization
+report_timing
+
diff --git a/scripts/vivado/synth_speed.xdc b/scripts/vivado/synth_speed.xdc
new file mode 100644
index 0000000..877ec8d
--- /dev/null
+++ b/scripts/vivado/synth_speed.xdc
@@ -0,0 +1 @@
+create_clock -period 2.50 [get_ports clk]
diff --git a/scripts/vivado/synth_system.tcl b/scripts/vivado/synth_system.tcl
new file mode 100644
index 0000000..26ea01c
--- /dev/null
+++ b/scripts/vivado/synth_system.tcl
@@ -0,0 +1,17 @@
+
+read_verilog system.v
+read_verilog ../../picorv32.v
+read_xdc synth_system.xdc
+
+synth_design -part xc7a35t-cpg236-1 -top system
+opt_design
+place_design
+route_design
+
+report_utilization
+report_timing
+
+write_verilog -force synth_system.v
+write_bitstream -force synth_system.bit
+# write_mem_info -force synth_system.mmi
+
diff --git a/scripts/vivado/synth_system.xdc b/scripts/vivado/synth_system.xdc
new file mode 100644
index 0000000..5748466
--- /dev/null
+++ b/scripts/vivado/synth_system.xdc
@@ -0,0 +1,34 @@
+
+# XDC File for Basys3 Board
+###########################
+
+set_property PACKAGE_PIN W5 [get_ports clk]
+set_property IOSTANDARD LVCMOS33 [get_ports clk]
+create_clock -period 10.00 [get_ports clk]
+
+# Pmod Header JA (JA0..JA7)
+set_property PACKAGE_PIN J1 [get_ports {out_byte[0]}]
+set_property IOSTANDARD LVCMOS33 [get_ports {out_byte[0]}]
+set_property PACKAGE_PIN L2 [get_ports {out_byte[1]}]
+set_property IOSTANDARD LVCMOS33 [get_ports {out_byte[1]}]
+set_property PACKAGE_PIN J2 [get_ports {out_byte[2]}]
+set_property IOSTANDARD LVCMOS33 [get_ports {out_byte[2]}]
+set_property PACKAGE_PIN G2 [get_ports {out_byte[3]}]
+set_property IOSTANDARD LVCMOS33 [get_ports {out_byte[3]}]
+set_property PACKAGE_PIN H1 [get_ports {out_byte[4]}]
+set_property IOSTANDARD LVCMOS33 [get_ports {out_byte[4]}]
+set_property PACKAGE_PIN K2 [get_ports {out_byte[5]}]
+set_property IOSTANDARD LVCMOS33 [get_ports {out_byte[5]}]
+set_property PACKAGE_PIN H2 [get_ports {out_byte[6]}]
+set_property IOSTANDARD LVCMOS33 [get_ports {out_byte[6]}]
+set_property PACKAGE_PIN G3 [get_ports {out_byte[7]}]
+set_property IOSTANDARD LVCMOS33 [get_ports {out_byte[7]}]
+
+# Pmod Header JB (JB0..JB2)
+set_property PACKAGE_PIN A14 [get_ports {resetn}]
+set_property IOSTANDARD LVCMOS33 [get_ports {resetn}]
+set_property PACKAGE_PIN A16 [get_ports {trap}]
+set_property IOSTANDARD LVCMOS33 [get_ports {trap}]
+set_property PACKAGE_PIN B15 [get_ports {out_byte_en}]
+set_property IOSTANDARD LVCMOS33 [get_ports {out_byte_en}]
+
diff --git a/scripts/vivado/system.v b/scripts/vivado/system.v
new file mode 100644
index 0000000..c4882a1
--- /dev/null
+++ b/scripts/vivado/system.v
@@ -0,0 +1,101 @@
+`timescale 1 ns / 1 ps
+
+module system (
+ input clk,
+ input resetn,
+ output trap,
+ output reg [7:0] out_byte,
+ output reg out_byte_en
+);
+ // set this to 0 for better timing but less performance/MHz
+ parameter FAST_MEMORY = 1;
+
+ // 4096 32bit words = 16kB memory
+ parameter MEM_SIZE = 4096;
+
+ wire mem_valid;
+ wire mem_instr;
+ reg mem_ready;
+ wire [31:0] mem_addr;
+ wire [31:0] mem_wdata;
+ wire [3:0] mem_wstrb;
+ reg [31:0] mem_rdata;
+
+ wire mem_la_read;
+ wire mem_la_write;
+ wire [31:0] mem_la_addr;
+ wire [31:0] mem_la_wdata;
+ wire [3:0] mem_la_wstrb;
+
+ picorv32 picorv32_core (
+ .clk (clk ),
+ .resetn (resetn ),
+ .trap (trap ),
+ .mem_valid (mem_valid ),
+ .mem_instr (mem_instr ),
+ .mem_ready (mem_ready ),
+ .mem_addr (mem_addr ),
+ .mem_wdata (mem_wdata ),
+ .mem_wstrb (mem_wstrb ),
+ .mem_rdata (mem_rdata ),
+ .mem_la_read (mem_la_read ),
+ .mem_la_write(mem_la_write),
+ .mem_la_addr (mem_la_addr ),
+ .mem_la_wdata(mem_la_wdata),
+ .mem_la_wstrb(mem_la_wstrb)
+ );
+
+ reg [31:0] memory [0:MEM_SIZE-1];
+ initial $readmemh("firmware.hex", memory);
+
+ reg [31:0] m_read_data;
+ reg m_read_en;
+
+ generate if (FAST_MEMORY) begin
+ always @(posedge clk) begin
+ mem_ready <= 1;
+ out_byte_en <= 0;
+ mem_rdata <= memory[mem_la_addr >> 2];
+ if (mem_la_write && (mem_la_addr >> 2) < MEM_SIZE) begin
+ if (mem_la_wstrb[0]) memory[mem_la_addr >> 2][ 7: 0] <= mem_la_wdata[ 7: 0];
+ if (mem_la_wstrb[1]) memory[mem_la_addr >> 2][15: 8] <= mem_la_wdata[15: 8];
+ if (mem_la_wstrb[2]) memory[mem_la_addr >> 2][23:16] <= mem_la_wdata[23:16];
+ if (mem_la_wstrb[3]) memory[mem_la_addr >> 2][31:24] <= mem_la_wdata[31:24];
+ end
+ else
+ if (mem_la_write && mem_la_addr == 32'h1000_0000) begin
+ out_byte_en <= 1;
+ out_byte <= mem_la_wdata;
+ end
+ end
+ end else begin
+ always @(posedge clk) begin
+ m_read_en <= 0;
+ mem_ready <= mem_valid && !mem_ready && m_read_en;
+
+ m_read_data <= memory[mem_addr >> 2];
+ mem_rdata <= m_read_data;
+
+ out_byte_en <= 0;
+
+ (* parallel_case *)
+ case (1)
+ mem_valid && !mem_ready && !mem_wstrb && (mem_addr >> 2) < MEM_SIZE: begin
+ m_read_en <= 1;
+ end
+ mem_valid && !mem_ready && |mem_wstrb && (mem_addr >> 2) < MEM_SIZE: begin
+ if (mem_wstrb[0]) memory[mem_addr >> 2][ 7: 0] <= mem_wdata[ 7: 0];
+ if (mem_wstrb[1]) memory[mem_addr >> 2][15: 8] <= mem_wdata[15: 8];
+ if (mem_wstrb[2]) memory[mem_addr >> 2][23:16] <= mem_wdata[23:16];
+ if (mem_wstrb[3]) memory[mem_addr >> 2][31:24] <= mem_wdata[31:24];
+ mem_ready <= 1;
+ end
+ mem_valid && !mem_ready && |mem_wstrb && mem_addr == 32'h1000_0000: begin
+ out_byte_en <= 1;
+ out_byte <= mem_wdata;
+ mem_ready <= 1;
+ end
+ endcase
+ end
+ end endgenerate
+endmodule
diff --git a/scripts/vivado/system_tb.v b/scripts/vivado/system_tb.v
new file mode 100644
index 0000000..a66d612
--- /dev/null
+++ b/scripts/vivado/system_tb.v
@@ -0,0 +1,38 @@
+`timescale 1 ns / 1 ps
+
+module system_tb;
+ reg clk = 1;
+ always #5 clk = ~clk;
+
+ reg resetn = 0;
+ initial begin
+ if ($test$plusargs("vcd")) begin
+ $dumpfile("system.vcd");
+ $dumpvars(0, system_tb);
+ end
+ repeat (100) @(posedge clk);
+ resetn <= 1;
+ end
+
+ wire trap;
+ wire [7:0] out_byte;
+ wire out_byte_en;
+
+ system uut (
+ .clk (clk ),
+ .resetn (resetn ),
+ .trap (trap ),
+ .out_byte (out_byte ),
+ .out_byte_en(out_byte_en)
+ );
+
+ always @(posedge clk) begin
+ if (resetn && out_byte_en) begin
+ $write("%c", out_byte);
+ $fflush;
+ end
+ if (resetn && trap) begin
+ $finish;
+ end
+ end
+endmodule
diff --git a/scripts/vivado/table.sh b/scripts/vivado/table.sh
new file mode 100644
index 0000000..81e2cf4
--- /dev/null
+++ b/scripts/vivado/table.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+
+dashes="----------------------------------------------------------------"
+printf '| %-25s | %-10s | %-20s |\n' "Device" "Speedgrade" "Clock Period (Freq.)"
+printf '|:%.25s |:%.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" ;;
+ xcku) d="Xilinx Kintex UltraScale" ;;
+ xcvu) d="Xilinx Virtex UltraScale" ;;
+ xckup) d="Xilinx Kintex UltraScale+" ;;
+ xcvup) d="Xilinx Virtex UltraScale+" ;;
+ esac
+ speedtxt=$( printf '%s.%s ns (%d MHz)' ${speed%?} ${speed#?} $((10000 / speed)) )
+ printf '| %-25s | %-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..bc3d840
--- /dev/null
+++ b/scripts/vivado/tabtest.sh
@@ -0,0 +1,103 @@
+#!/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=20
+step=16
+
+synth_case() {
+ if [ -f test_${1}.txt ]; then
+ echo "Reusing cached tab_${ip}_${dev}_${grade}/test_${1}."
+ return
+ fi
+
+ case "${dev}" in
+ xc7k) xl_device="xc7k70t-fbg676-${grade}" ;;
+ xc7v) xl_device="xc7v585t-ffg1761-${grade}" ;;
+ xcku) xl_device="xcku035-fbva676-${grade}-e" ;;
+ xcvu) xl_device="xcvu065-ffvc1517-${grade}-e" ;;
+ xckup) xl_device="xcku3p-ffva676-${grade}-e" ;;
+ xcvup) xl_device="xcvu3p-ffvc1517-${grade}-e" ;;
+ 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 -propconst
+ opt_design -directive Explore
+ 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
+}
+
+got_violated=false
+got_met=false
+
+countdown=2
+while [ $countdown -gt 0 ]; do
+ synth_case $speed
+
+ if grep -q '^Slack.*(VIOLATED)' test_${speed}.txt; then
+ echo " tab_${ip}_${dev}_${grade}/test_${speed} VIOLATED"
+ step=$((step / 2))
+ speed=$((speed + step))
+ got_violated=true
+ elif grep -q '^Slack.*(MET)' test_${speed}.txt; then
+ echo " tab_${ip}_${dev}_${grade}/test_${speed} MET"
+ [ $speed -lt $best_speed ] && best_speed=$speed
+ step=$((step / 2))
+ speed=$((speed - step))
+ got_met=true
+ else
+ echo "ERROR: No slack line found in $PWD/test_${speed}.txt!"
+ exit 1
+ fi
+
+ if [ $step -eq 0 ]; then
+ countdown=$((countdown - 1))
+ speed=$((best_speed - 2))
+ step=1
+ fi
+done
+
+if ! $got_violated; then
+ echo "ERROR: No timing violated in $PWD!"
+ exit 1
+fi
+
+if ! $got_met; then
+ echo "ERROR: No timing met in $PWD!"
+ exit 1
+fi
+
+
+echo "-----------------------"
+echo "Best speed for tab_${ip}_${dev}_${grade}: $best_speed"
+echo "-----------------------"
+echo $best_speed > results.txt
+
diff --git a/scripts/vivado/tabtest.v b/scripts/vivado/tabtest.v
new file mode 100644
index 0000000..cdf2057
--- /dev/null
+++ b/scripts/vivado/tabtest.v
@@ -0,0 +1,118 @@
+
+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 #(
+ .TWO_CYCLE_ALU(1)
+ ) cpu (
+ .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
+