xilinx synthesis debugging foxes

This commit is contained in:
Blaise Tine 2024-09-17 06:22:07 -07:00
parent bbe9c0372f
commit 50458bbae0
21 changed files with 710 additions and 413 deletions

2
configure vendored
View file

@ -65,7 +65,7 @@ copy_files() {
filename_no_ext="${filename%.in}" filename_no_ext="${filename%.in}"
dest_file="$dest_dir/$filename_no_ext" dest_file="$dest_dir/$filename_no_ext"
mkdir -p "$dest_dir" mkdir -p "$dest_dir"
sed "s|@VORTEX_HOME@|$SCRIPT_DIR|g; s|@XLEN@|$XLEN|g; s|@TOOLDIR@|$TOOLDIR|g; s|@OSVERSION@|$OSVERSION|g; s|@INSTALLDIR@|$PREFIX|g" "$file" > "$dest_file" sed "s|@VORTEX_HOME@|$SCRIPT_DIR|g; s|@XLEN@|$XLEN|g; s|@TOOLDIR@|$TOOLDIR|g; s|@OSVERSION@|$OSVERSION|g; s|@INSTALLDIR@|$PREFIX|g; s|@CURRENTDIR@|$CURRENT_DIR|g" "$file" > "$dest_file"
# apply permissions to bash scripts # apply permissions to bash scripts
read -r firstline < "$dest_file" read -r firstline < "$dest_file"
if [[ "$firstline" =~ ^#!.*bash ]]; then if [[ "$firstline" =~ ^#!.*bash ]]; then

View file

@ -56,8 +56,25 @@
`define UNUSED_PIN(x) . x () `define UNUSED_PIN(x) . x ()
`define UNUSED_ARG(x) x `define UNUSED_ARG(x) x
`define __SCOPE (* mark_debug="true" *)
`define __SCOPE_X
`define __SCOPE_ON \
`undef __SCOPE_X \
`define __SCOPE_X `__SCOPE
`define __SCOPE_OFF \
`undef __SCOPE_X \
`define __SCOPE_X
`else // not SYNTHESIS `else // not SYNTHESIS
`define __SCOPE
`define __SCOPE_X
`define __SCOPE_ON
`define __SCOPE_OFF
`ifdef VERILATOR `ifdef VERILATOR
`ifndef TRACING_ALL `ifndef TRACING_ALL

View file

@ -21,8 +21,8 @@ module VX_afu_wrap #(
parameter C_M_AXI_MEM_DATA_WIDTH = `VX_MEM_DATA_WIDTH parameter C_M_AXI_MEM_DATA_WIDTH = `VX_MEM_DATA_WIDTH
) ( ) (
// System signals // System signals
input wire ap_clk, input wire clk,
input wire ap_rst_n, input wire reset,
// AXI4 master interface // AXI4 master interface
`REPEAT (`M_AXI_MEM_NUM_BANKS, GEN_AXI_MEM, REPEAT_COMMA), `REPEAT (`M_AXI_MEM_NUM_BANKS, GEN_AXI_MEM, REPEAT_COMMA),
@ -82,8 +82,6 @@ module VX_afu_wrap #(
// convert memory interface to array // convert memory interface to array
`REPEAT (`M_AXI_MEM_NUM_BANKS, AXI_MEM_TO_ARRAY, REPEAT_SEMICOLON); `REPEAT (`M_AXI_MEM_NUM_BANKS, AXI_MEM_TO_ARRAY, REPEAT_SEMICOLON);
wire reset = ~ap_rst_n;
reg [`CLOG2(`RESET_DELAY+1)-1:0] vx_reset_ctr; reg [`CLOG2(`RESET_DELAY+1)-1:0] vx_reset_ctr;
reg [15:0] vx_pending_writes; reg [15:0] vx_pending_writes;
reg vx_busy_wait; reg vx_busy_wait;
@ -122,7 +120,7 @@ module VX_afu_wrap #(
end end
end end
always @(posedge ap_clk) begin always @(posedge clk) begin
if (reset || ap_reset) begin if (reset || ap_reset) begin
state <= STATE_IDLE; state <= STATE_IDLE;
vx_pending_writes <= '0; vx_pending_writes <= '0;
@ -187,7 +185,7 @@ module VX_afu_wrap #(
.AXI_DATA_WIDTH (C_S_AXI_CTRL_DATA_WIDTH), .AXI_DATA_WIDTH (C_S_AXI_CTRL_DATA_WIDTH),
.AXI_NUM_BANKS (C_M_AXI_MEM_NUM_BANKS) .AXI_NUM_BANKS (C_M_AXI_MEM_NUM_BANKS)
) afu_ctrl ( ) afu_ctrl (
.clk (ap_clk), .clk (clk),
.reset (reset), .reset (reset),
.s_axi_awvalid (s_axi_ctrl_awvalid), .s_axi_awvalid (s_axi_ctrl_awvalid),
@ -245,7 +243,7 @@ module VX_afu_wrap #(
) vortex_axi ( ) vortex_axi (
`SCOPE_IO_BIND (1) `SCOPE_IO_BIND (1)
.clk (ap_clk), .clk (clk),
.reset (vx_reset), .reset (vx_reset),
.m_axi_awvalid (m_axi_mem_awvalid_a), .m_axi_awvalid (m_axi_mem_awvalid_a),
@ -301,9 +299,32 @@ module VX_afu_wrap #(
// SCOPE ////////////////////////////////////////////////////////////////////// // SCOPE //////////////////////////////////////////////////////////////////////
`ifdef CHIPSCOPE
ila_afu ila_afu_inst (
.clk (clk),
.probe0 ({
ap_reset,
ap_start,
ap_done,
ap_idle,
interrupt
}),
.probe1 ({
vx_pending_writes,
vx_busy_wait,
vx_busy,
vx_reset,
dcr_wr_valid,
dcr_wr_addr,
dcr_wr_data
})
);
`endif
`ifdef DBG_SCOPE_AFU `ifdef DBG_SCOPE_AFU
`define TRIGGERS { \ `define TRIGGERS { \
reset, \ reset, \
ap_reset, \
ap_start, \ ap_start, \
ap_done, \ ap_done, \
ap_idle, \ ap_idle, \
@ -343,7 +364,7 @@ module VX_afu_wrap #(
initial begin initial begin
$assertoff(0, vortex_axi); $assertoff(0, vortex_axi);
end end
always @(posedge ap_clk) begin always @(posedge clk) begin
if (reset) begin if (reset) begin
assert_delay_ctr <= '0; assert_delay_ctr <= '0;
assert_enabled <= 0; assert_enabled <= 0;
@ -362,7 +383,7 @@ module VX_afu_wrap #(
`endif `endif
`ifdef DBG_TRACE_AFU `ifdef DBG_TRACE_AFU
always @(posedge ap_clk) begin always @(posedge clk) begin
for (integer i = 0; i < C_M_AXI_MEM_NUM_BANKS; ++i) begin for (integer i = 0; i < C_M_AXI_MEM_NUM_BANKS; ++i) begin
if (m_axi_mem_awvalid_a[i] && m_axi_mem_awready_a[i]) begin if (m_axi_mem_awvalid_a[i] && m_axi_mem_awready_a[i]) begin
`TRACE(2, ("%t: AFU Wr Req [%0d]: addr=0x%0h, tag=0x%0h\n", $time, i, m_axi_mem_awaddr_a[i], m_axi_mem_awid_a[i])) `TRACE(2, ("%t: AFU Wr Req [%0d]: addr=0x%0h, tag=0x%0h\n", $time, i, m_axi_mem_awaddr_a[i], m_axi_mem_awid_a[i]))

View file

@ -56,8 +56,8 @@ module vortex_afu #(
.C_M_AXI_MEM_ADDR_WIDTH (C_M_AXI_MEM_ADDR_WIDTH), .C_M_AXI_MEM_ADDR_WIDTH (C_M_AXI_MEM_ADDR_WIDTH),
.C_M_AXI_MEM_DATA_WIDTH (C_M_AXI_MEM_DATA_WIDTH) .C_M_AXI_MEM_DATA_WIDTH (C_M_AXI_MEM_DATA_WIDTH)
) afu_wrap ( ) afu_wrap (
.ap_clk (ap_clk), .clk (ap_clk),
.ap_rst_n (ap_rst_n), .reset (~ap_rst_n),
`REPEAT (`M_AXI_MEM_NUM_BANKS, AXI_MEM_ARGS, REPEAT_COMMA), `REPEAT (`M_AXI_MEM_NUM_BANKS, AXI_MEM_ARGS, REPEAT_COMMA),

231
hw/scripts/ila_insert.tcl Normal file
View file

@ -0,0 +1,231 @@
######################################################################
# Automatically inserts ILA instances in a batch flow, and calls "implement_debug_core". Can also be used in a GUI flow
# This should ONLY be invoked after synthesis, and before opt_design. If opt_design is called first, marked nets may be missing and not found
# Warning: Currently will skip a net if it has no obvious clock domain on the driver. Nets connected to input buffers will be dropped unless "mark_debug_clock" is attached to the net.
# Nets attached to VIO cores have the "mark_debug" attribute, and will be filtered out unless the "mark_debug_valid" attribute is attached.
# Supports the following additional attributes beyond "mark_debug"
# attribute mark_debug_valid of X : signal is "true"; -- Marks a net for ILA capture, even if net is also attached to a VIO core
# attribute mark_debug_clock of X : signal is "inst1_bufg/clock"; -- Specifies clock net to use for capturing this net. May create a new ILA core for that clock domain
# attribute mark_debug_depth of X : signal is "4096"; -- overrides default depth for this ILA core. valid values: 1024, 2048, ... 132072. Last attribute that is scanned will win.
# attribute mark_debug_adv_trigger of X : signal is "true"; -- specifies that advanced trigger capability will be added to ILA core
# Engineer: J. McCluskey
proc insert_ila { depth } {
# sequence through debug nets and organize them by clock in the
# clock_list array. Also create max and min array for bus indices
set dbgs [get_nets -hierarchical -filter {MARK_DEBUG}]
if {[llength $dbgs] == 0} {
puts "No debug net found. No ILA cores created"
return
}
# process list of nets to find and reject nets that are attached to VIO cores.
# This has a side effect that VIO nets can't be monitored with an ILA
# This can be overridden by using the attribute "mark_debug_valid" = "true" on a net like this.
set net_list {}
foreach net $dbgs {
if { [get_property -quiet MARK_DEBUG_VALID $net] != "true" } {
set pin_list [get_pins -of_objects [get_nets -segments $net]]
set not_vio_net 1
foreach pin $pin_list {
if { [get_property IS_DEBUG_CORE [get_cells -of_object $pin]] == 1 } {
# It seems this net is attached to a debug core (i.e. VIO core) already, so we should skip adding it to the netlist
set not_vio_net 0
break
}
}
if { $not_vio_net == 1 } { lappend net_list $net; }
} else {
lappend net_list $net
}
}
# check again to see if we have any nets left now
if {[llength $net_list] == 0} {
puts "All nets with MARK_DEBUG are already connected to VIO cores. No ILA cores created"
return
}
# Now that the netlist has been filtered, determine bus names and clock domains
foreach d $net_list {
# name is root name of a bus, index is the bit index in the bus
set name [regsub {\[[[:digit:]]+\]$} $d {}]
set index [regsub {^.*\[([[:digit:]]+)\]$} $d {\1}]
if {[string is integer -strict $index]} {
if {![info exists max($name)]} {
set max($name) $index
set min($name) $index
} elseif {$index > $max($name)} {
set max($name) $index
} elseif {$index < $min($name)} {
set min($name) $index
}
} else {
set max($name) -1
}
# Now we search for the local clock net associated with the target net.
# There may be ambiguities or no answer in some cases
if {![info exists clocks($name)]} {
# does MARK_DEBUG_CLOCK decorate this net? If not, then search backwards to the driver cell
set clk_name [get_property -quiet MARK_DEBUG_CLOCK $d]
if { [llength $clk_name] == 0 } {
# trace to the clock net, tracing backwards via the driver pin.
set driver_pin [get_pins -filter {DIRECTION == "OUT" && IS_LEAF == TRUE } -of_objects [ get_nets -segments $d ]]
set driver_cell [get_cells -of_objects $driver_pin]
if { [get_property IS_SEQUENTIAL $driver_cell] == 1 } {
set timing_arc [get_timing_arcs -to $driver_pin]
set cell_clock_pin [get_pins -filter {IS_CLOCK} [get_property FROM_PIN $timing_arc]]
if { [llength $cell_clock_pin] > 1 } {
puts "Error: in insert_ila. Found more than 1 clock pin in driver cell $driver_cell with timing arc $timing_arc for net $d"
continue
}
} else {
# our driver cell is a LUT or LUTMEM in combinatorial mode, we need to trace further.
set paths [get_timing_paths -quiet -through $driver_pin ]
if { [llength $paths] > 0 } {
# note that here we arbitrarily select the start point of the FIRST timing path... there might be multiple clocks with timing paths for this net.
# use MARK_DEBUG_CLOCK to specify another clock in this case.
set cell_clock_pin [get_pins [get_property STARTPOINT_PIN [lindex $paths 0]]]
} else {
# Can't find any timing path, so skip the net, and warn the user.
puts "Critical Warning: from insert_ila.tcl Can't trace any clock domain on driver of net $d"
puts "Please attach the attribute MARK_DEBUG_CLOCK with a string containing the net name of the desired sampling clock, .i.e."
puts "attribute mark_debug_clock of $d : signal is \"inst_bufg/clk\";"
continue
}
}
# clk_net will usually be a list of net segments, which needs filtering to determine the net connected to the driver pin
set clk_net [get_nets -segments -of_objects $cell_clock_pin]
} else {
set clk_net [get_nets -segments $clk_name]
if { [llength $clk_net] == 0 } { puts "MARK_DEBUG_CLOCK attribute on net $d does not match any known net. Please fix."; continue; }
}
# trace forward to net actually connected to clock buffer output, not any of the lower level segment names
set clocks($name) [get_nets -of_objects [get_pins -filter {DIRECTION == "OUT" && IS_LEAF == TRUE } -of_objects $clk_net]]
if { [llength $clocks($name)] == 0 } {
puts "Critical Warning: from insert_ila.tcl Can't trace any clock domain on driver of net $d"
puts "Please attach the attribute MARK_DEBUG_CLOCK with a string containing the net name of the desired sampling clock, .i.e."
puts "attribute mark_debug_clock of $d : signal is \"inst_bufg/clk\";"
continue
}
if {![info exists clock_list($clocks($name))]} {
# found a new clock
puts "New clock found is $clocks($name)"
set clock_list($clocks($name)) [list $name]
set ila_depth($clocks($name)) $depth
set ila_adv_trigger($clocks($name)) false
} else {
lappend clock_list($clocks($name)) $name
}
# Does this net have a "MARK_DEBUG_DEPTH" attribute attached?
set clk_depth [get_property -quiet MARK_DEBUG_DEPTH $d]
if { [llength $clk_depth] != 0 } {
set ila_depth($clocks($name)) $clk_depth
}
# Does this net have a "MARK_DEBUG_ADV_TRIGGER" attribute attached?
set trigger [get_property -quiet MARK_DEBUG_ADV_TRIGGER $d]
if { $trigger == "true" } {
set ila_adv_trigger($clocks($name)) true
}
}
}
set ila_count 0
set trig_out ""
set trig_out_ack ""
if { [llength [array names clock_list]] > 1 } {
set enable_trigger true
} else {
set enable_trigger false
}
foreach c [array names clock_list] {
# Now build and connect an ILA core for each clock domain
[incr ila_count ]
set ila_inst "ila_$ila_count"
# first verify if depth is a member of the set, 1024, 2048, 4096, 8192, ... 131072
if { $ila_depth($c) < 1024 || [expr $ila_depth($c) & ($ila_depth($c) - 1)] || $ila_depth($c) > 131072 } {
# Depth is not right... lets fix it, and continue
if { $ila_depth($c) < 1024 } {
set new_depth 1024
} elseif { $ila_depth($c) > 131072 } {
set new_depth 131072
} else {
# round value to next highest power of 2, (in log space)
set new_depth [expr 1 << int( log($ila_depth($c))/log(2) + .9999 )]
}
puts "Can't create ILA core $ila_inst with depth of $ila_depth($c)! Changed capture depth to $new_depth"
set ila_depth($c) $new_depth
}
# create ILA and connect its clock
puts "Creating ILA $ila_inst with clock $c, capture depth $ila_depth($c) and advanced trigger = $ila_adv_trigger($c)"
create_debug_core $ila_inst ila
if { $ila_adv_trigger($c) } { set mu_cnt 4; } else { set mu_cnt 2; }
set_property C_DATA_DEPTH $ila_depth($c) [get_debug_cores $ila_inst]
set_property C_TRIGIN_EN $enable_trigger [get_debug_cores $ila_inst]
set_property C_TRIGOUT_EN $enable_trigger [get_debug_cores $ila_inst]
set_property C_ADV_TRIGGER $ila_adv_trigger($c) [get_debug_cores $ila_inst]
set_property C_INPUT_PIPE_STAGES 1 [get_debug_cores $ila_inst]
set_property C_EN_STRG_QUAL true [get_debug_cores $ila_inst]
set_property ALL_PROBE_SAME_MU true [get_debug_cores $ila_inst]
set_property ALL_PROBE_SAME_MU_CNT $mu_cnt [get_debug_cores $ila_inst]
set_property port_width 1 [get_debug_ports $ila_inst/clk]
connect_debug_port $ila_inst/clk $c
# hookup trigger ports in a circle if more than one ILA is created
if { $enable_trigger == true } {
create_debug_port $ila_inst trig_in
create_debug_port $ila_inst trig_in_ack
create_debug_port $ila_inst trig_out
create_debug_port $ila_inst trig_out_ack
if { $trig_out != "" } {
connect_debug_port $ila_inst/trig_in [get_nets $trig_out]
}
if { $trig_out_ack != "" } {
connect_debug_port $ila_inst/trig_in_ack [get_nets $trig_out_ack]
}
set trig_out ${ila_inst}_trig_out_$ila_count
create_net $trig_out
connect_debug_port $ila_inst/trig_out [get_nets $trig_out]
set trig_out_ack ${ila_inst}_trig_out_ack_$ila_count
create_net $trig_out_ack
connect_debug_port $ila_inst/trig_out_ack [get_nets $trig_out_ack]
}
# add probes
set nprobes 0
foreach n [lsort $clock_list($c)] {
set nets {}
if {$max($n) < 0} {
lappend nets [get_nets $n]
} else {
# n is a bus name
for {set i $min($n)} {$i <= $max($n)} {incr i} {
lappend nets [get_nets $n[$i]]
}
}
set prb probe$nprobes
if {$nprobes > 0} {
create_debug_port $ila_inst probe
}
set_property port_width [llength $nets] [get_debug_ports $ila_inst/$prb]
connect_debug_port $ila_inst/$prb $nets
incr nprobes
}
}
# at this point, we need to complete the circular connection of trigger outputs and acks
if { $enable_trigger == true } {
connect_debug_port ila_1/trig_in [get_nets $trig_out]
connect_debug_port ila_1/trig_in_ack [get_nets $trig_out_ack]
}
set project_found [get_projects -quiet]
if { $project_found != "New Project" } {
puts "Saving constraints now in project [current_project -quiet]"
save_constraints_as debug_constraints.xdc
}
# run ILA cores implementation
implement_debug_core
# write out probe info file
write_debug_probes -force debug_nets.ltx
}

View file

@ -13,7 +13,7 @@ IP_CACHE_DIR := $(ROOT_DIR)/hw/syn/altera/ip_cache/$(DEVICE_FAMILY)
ip-gen: $(IP_CACHE_DIR)/ip_gen.log ip-gen: $(IP_CACHE_DIR)/ip_gen.log
$(IP_CACHE_DIR)/ip_gen.log: $(IP_CACHE_DIR)/ip_gen.log:
$(SCRIPT_DIR)/ip_gen.sh $(IP_CACHE_DIR) $(SCRIPT_DIR)/altera_ip_gen.sh $(IP_CACHE_DIR)
unittest: unittest:
mkdir -p unittest/$(BUILD_DIR) mkdir -p unittest/$(BUILD_DIR)

View file

@ -102,7 +102,7 @@ all: swconfig ip-gen setup build
ip-gen: $(IP_CACHE_DIR)/ip-gen.log ip-gen: $(IP_CACHE_DIR)/ip-gen.log
$(IP_CACHE_DIR)/ip-gen.log: $(IP_CACHE_DIR)/ip-gen.log:
$(SCRIPT_DIR)/ip_gen.sh $(IP_CACHE_DIR) $(SCRIPT_DIR)/altera_ip_gen.sh $(IP_CACHE_DIR)
swconfig: vortex_afu.h swconfig: vortex_afu.h
vortex_afu.h: $(SRC_DIR)/vortex_afu.json vortex_afu.h: $(SRC_DIR)/vortex_afu.json

View file

@ -5,7 +5,7 @@ platforminfo -l
xbutil validate --device 0000:09:00.1 --verbose xbutil validate --device 0000:09:00.1 --verbose
# generate FPU IPs # generate FPU IPs
vivado -mode batch -source scripts/gen_ip.tcl -tclargs ip/xilinx_u50_gen3x16_xdma_5_202210_1 vivado -mode batch -source xilinx_ip_gen.tcl -tclargs ip/xilinx_u50_gen3x16_xdma_5_202210_1
# build FPGA # build FPGA
PREFIX=build_base_1c NUM_CORES=1 TARGET=hw_emu PLATFORM=xilinx_u50_gen3x16_xdma_5_202210_1 make > build_u50_hw_emu_base_1c.log 2>&1 & PREFIX=build_base_1c NUM_CORES=1 TARGET=hw_emu PLATFORM=xilinx_u50_gen3x16_xdma_5_202210_1 make > build_u50_hw_emu_base_1c.log 2>&1 &

View file

@ -31,9 +31,9 @@ project_1/sources.txt:
build: $(PROJECT).xpr build: $(PROJECT).xpr
$(PROJECT).xpr: project_1/sources.txt $(PROJECT).xpr: project_1/sources.txt
ifdef FPU_IP ifdef FPU_IP
MAX_JOBS=$(JOBS) FPU_IP=project_1/ip $(VIVADO) -mode batch -source $(SRC_DIR)/project.tcl -tclargs $(TOP_LEVEL_ENTITY) $(DEVICE) project_1/sources.txt $(SRC_DIR)/project.xdc $(SCRIPT_DIR) $(SRC_DIR)/../scripts MAX_JOBS=$(JOBS) FPU_IP=project_1/ip $(VIVADO) -mode batch -source $(SRC_DIR)/project.tcl -tclargs $(TOP_LEVEL_ENTITY) $(DEVICE) project_1/sources.txt $(SRC_DIR)/project.xdc $(SCRIPT_DIR)
else else
MAX_JOBS=$(JOBS) $(VIVADO) -mode batch -source $(SRC_DIR)/project.tcl -tclargs $(TOP_LEVEL_ENTITY) $(DEVICE) project_1/sources.txt $(SRC_DIR)/project.xdc $(SCRIPT_DIR) $(SRC_DIR)/../scripts MAX_JOBS=$(JOBS) $(VIVADO) -mode batch -source $(SRC_DIR)/project.tcl -tclargs $(TOP_LEVEL_ENTITY) $(DEVICE) project_1/sources.txt $(SRC_DIR)/project.xdc $(SCRIPT_DIR)
endif endif
clean: clean:

View file

@ -14,9 +14,9 @@
# Start time # Start time
set start_time [clock seconds] set start_time [clock seconds]
if { $::argc != 6 } { if { $::argc != 5 } {
puts "ERROR: Program \"$::argv0\" requires 5 arguments!\n" puts "ERROR: Program \"$::argv0\" requires 5 arguments!\n"
puts "Usage: $::argv0 <top_module> <device_part> <vcs_file> <xdc_file> <tool_dir> <script_dir>\n" puts "Usage: $::argv0 <top_module> <device_part> <vcs_file> <xdc_file> <tool_dir>\n"
exit exit
} }
@ -28,14 +28,12 @@ set device_part [lindex $::argv 1]
set vcs_file [lindex $::argv 2] set vcs_file [lindex $::argv 2]
set xdc_file [lindex $::argv 3] set xdc_file [lindex $::argv 3]
set tool_dir [lindex $::argv 4] set tool_dir [lindex $::argv 4]
set script_dir [lindex $::argv 5]
puts "Using top_module=$top_module" puts "Using top_module=$top_module"
puts "Using device_part=$device_part" puts "Using device_part=$device_part"
puts "Using vcs_file=$vcs_file" puts "Using vcs_file=$vcs_file"
puts "Using xdc_file=$xdc_file" puts "Using xdc_file=$xdc_file"
puts "Using tool_dir=$tool_dir" puts "Using tool_dir=$tool_dir"
puts "Using script_dir=$script_dir"
# Set the number of jobs based on MAX_JOBS environment variable # Set the number of jobs based on MAX_JOBS environment variable
if {[info exists ::env(MAX_JOBS)]} { if {[info exists ::env(MAX_JOBS)]} {
@ -50,7 +48,7 @@ if {[info exists ::env(FPU_IP)]} {
set ip_dir $::env(FPU_IP) set ip_dir $::env(FPU_IP)
set argv [list $ip_dir $device_part] set argv [list $ip_dir $device_part]
set argc 2 set argc 2
source ${script_dir}/gen_ip.tcl source ${tool_dir}/xilinx_ip_gen.tcl
} }
source "${tool_dir}/parse_vcs_list.tcl" source "${tool_dir}/parse_vcs_list.tcl"

View file

@ -12,7 +12,7 @@
# limitations under the License. # limitations under the License.
if { $::argc != 5 } { if { $::argc != 5 } {
puts "ERROR: Program \"$::argv0\" requires 4 arguments!\n" puts "ERROR: Program \"$::argv0\" requires 5 arguments!\n"
puts "Usage: $::argv0 <xoname> <krnl_name> <vcs_file> <tool_dir> <build_dir>\n" puts "Usage: $::argv0 <xoname> <krnl_name> <vcs_file> <tool_dir> <build_dir>\n"
exit exit
} }

View file

@ -71,65 +71,60 @@ set_property -verbose -name "top" -value ${krnl_name} -objects $obj
if { $chipscope == 1 } { if { $chipscope == 1 } {
# hw debugging # hw debugging
create_ip -name axis_ila -vendor xilinx.com -library ip -version 1.1 -module_name ila_afu create_ip -name ila -vendor xilinx.com -library ip -version 6.2 -module_name ila_afu
set_property -dict [list CONFIG.C_ADV_TRIGGER {true} \ set_property -dict [list CONFIG.C_ADV_TRIGGER {true} \
CONFIG.C_EN_STRG_QUAL {1} \ CONFIG.C_EN_STRG_QUAL {1} \
CONFIG.C_DATA_DEPTH {4096} \ CONFIG.C_DATA_DEPTH {8192} \
CONFIG.C_NUM_OF_PROBES {2} \ CONFIG.C_NUM_OF_PROBES {2} \
CONFIG.C_PROBE0_WIDTH {8} \ CONFIG.C_PROBE0_WIDTH {8} \
CONFIG.C_PROBE1_WIDTH {24} \ CONFIG.C_PROBE1_WIDTH {64} \
CONFIG.ALL_PROBE_SAME_MU {false} \
CONFIG.ALL_PROBE_SAME_MU_CNT {2} \
] [get_ips ila_afu] ] [get_ips ila_afu]
generate_target {instantiation_template} [get_files ila_afu.xci] generate_target {instantiation_template} [get_files ila_afu.xci]
set_property generate_synth_checkpoint false [get_files ila_afu.xci] set_property generate_synth_checkpoint false [get_files ila_afu.xci]
create_ip -name axis_ila -vendor xilinx.com -library ip -version 1.1 -module_name ila_fetch create_ip -name ila -vendor xilinx.com -library ip -version 6.2 -module_name ila_fetch
set_property -dict [list CONFIG.C_ADV_TRIGGER {true} \ set_property -dict [list CONFIG.C_ADV_TRIGGER {true} \
CONFIG.C_EN_STRG_QUAL {1} \ CONFIG.C_EN_STRG_QUAL {1} \
CONFIG.C_DATA_DEPTH {4096} \ CONFIG.C_DATA_DEPTH {8192} \
CONFIG.C_NUM_OF_PROBES {3} \ CONFIG.C_NUM_OF_PROBES {3} \
CONFIG.C_PROBE0_WIDTH {128} \ CONFIG.C_PROBE0_WIDTH {128} \
CONFIG.C_PROBE1_WIDTH {128} \ CONFIG.C_PROBE1_WIDTH {128} \
CONFIG.C_PROBE2_WIDTH {128} \ CONFIG.C_PROBE2_WIDTH {128} \
CONFIG.ALL_PROBE_SAME_MU {false} \
CONFIG.ALL_PROBE_SAME_MU_CNT {2} \
] [get_ips ila_fetch] ] [get_ips ila_fetch]
generate_target {instantiation_template} [get_files ila_fetch.xci] generate_target {instantiation_template} [get_files ila_fetch.xci]
set_property generate_synth_checkpoint false [get_files ila_fetch.xci] set_property generate_synth_checkpoint false [get_files ila_fetch.xci]
create_ip -name axis_ila -vendor xilinx.com -library ip -version 1.1 -module_name ila_issue create_ip -name ila -vendor xilinx.com -library ip -version 6.2 -module_name ila_issue
set_property -dict [list CONFIG.C_ADV_TRIGGER {true} \ set_property -dict [list CONFIG.C_ADV_TRIGGER {true} \
CONFIG.C_EN_STRG_QUAL {1} \ CONFIG.C_EN_STRG_QUAL {1} \
CONFIG.C_DATA_DEPTH {4096} \ CONFIG.C_DATA_DEPTH {8192} \
CONFIG.C_NUM_OF_PROBES {2} \ CONFIG.C_NUM_OF_PROBES {2} \
CONFIG.C_PROBE0_WIDTH {256} \ CONFIG.C_PROBE0_WIDTH {256} \
CONFIG.C_PROBE1_WIDTH {128} \ CONFIG.C_PROBE1_WIDTH {128} \
CONFIG.ALL_PROBE_SAME_MU {false} \
CONFIG.ALL_PROBE_SAME_MU_CNT {2} \
] [get_ips ila_issue] ] [get_ips ila_issue]
generate_target {instantiation_template} [get_files ila_issue.xci] generate_target {instantiation_template} [get_files ila_issue.xci]
set_property generate_synth_checkpoint false [get_files ila_issue.xci] set_property generate_synth_checkpoint false [get_files ila_issue.xci]
create_ip -name axis_ila -vendor xilinx.com -library ip -version 1.1 -module_name ila_lsu create_ip -name ila -vendor xilinx.com -library ip -version 6.2 -module_name ila_lsu
set_property -dict [list CONFIG.C_ADV_TRIGGER {true} \ set_property -dict [list CONFIG.C_ADV_TRIGGER {true} \
CONFIG.C_EN_STRG_QUAL {1} \ CONFIG.C_EN_STRG_QUAL {1} \
CONFIG.C_DATA_DEPTH {4096} \ CONFIG.C_DATA_DEPTH {8192} \
CONFIG.C_NUM_OF_PROBES {4} \ CONFIG.C_NUM_OF_PROBES {4} \
CONFIG.C_PROBE0_WIDTH {256} \ CONFIG.C_PROBE0_WIDTH {256} \
CONFIG.C_PROBE1_WIDTH {128} \ CONFIG.C_PROBE1_WIDTH {128} \
CONFIG.C_PROBE2_WIDTH {288} \ CONFIG.C_PROBE2_WIDTH {288} \
CONFIG.C_PROBE3_WIDTH {256} \ CONFIG.C_PROBE3_WIDTH {256} \
CONFIG.ALL_PROBE_SAME_MU {false} \
CONFIG.ALL_PROBE_SAME_MU_CNT {2} \
] [get_ips ila_lsu] ] [get_ips ila_lsu]
generate_target {instantiation_template} [get_files ila_lsu.xci] generate_target {instantiation_template} [get_files ila_lsu.xci]
set_property generate_synth_checkpoint false [get_files ila_lsu.xci] set_property generate_synth_checkpoint false [get_files ila_lsu.xci]
create_ip -name axis_ila -vendor xilinx.com -library ip -version 1.1 -module_name ila_msched
set_property -dict [list CONFIG.C_ADV_TRIGGER {true} \
CONFIG.C_EN_STRG_QUAL {1} \
CONFIG.C_DATA_DEPTH {4096} \
CONFIG.C_NUM_OF_PROBES {4} \
CONFIG.C_PROBE0_WIDTH {128} \
CONFIG.C_PROBE1_WIDTH {128} \
CONFIG.C_PROBE2_WIDTH {128} \
CONFIG.C_PROBE3_WIDTH {128} \
] [get_ips ila_msched]
generate_target {instantiation_template} [get_files ila_msched.xci]
set_property generate_synth_checkpoint false [get_files ila_msched.xci]
} }
update_compile_order -fileset sources_1 update_compile_order -fileset sources_1

View file

@ -19,16 +19,16 @@ KERNEL ?= fibonacci
NCPUS := $(shell lscpu | grep "^Core(s) per socket:" | awk '{print $$4}') NCPUS := $(shell lscpu | grep "^Core(s) per socket:" | awk '{print $$4}')
JOBS ?= $(shell echo $$(( $(NCPUS) > $(MAX_JOBS) ? $(MAX_JOBS) : $(NCPUS) ))) JOBS ?= $(shell echo $$(( $(NCPUS) > $(MAX_JOBS) ? $(MAX_JOBS) : $(NCPUS) )))
COE_FILE := $(shell realpath kernel.bin.coe)
ESCAPED_COE_FILE := $(shell echo "$(COE_FILE)" | sed -e 's/[\/&]/\\&/g')
# include paths # include paths
FPU_INCLUDE = -I$(RTL_DIR)/fpu FPU_INCLUDE = -I$(RTL_DIR)/fpu
ifneq (,$(findstring FPU_FPNEW,$(CONFIGS))) ifneq (,$(findstring FPU_FPNEW,$(CONFIGS)))
FPU_INCLUDE += -J$(THIRD_PARTY_DIR)/cvfpu/src/common_cells/include -J$(THIRD_PARTY_DIR)/cvfpu/src/common_cells/src -J$(THIRD_PARTY_DIR)/cvfpu/src/fpu_div_sqrt_mvp/hdl -J$(THIRD_PARTY_DIR)/cvfpu/src FPU_INCLUDE += -J$(THIRD_PARTY_DIR)/cvfpu/src/common_cells/include -J$(THIRD_PARTY_DIR)/cvfpu/src/common_cells/src -J$(THIRD_PARTY_DIR)/cvfpu/src/fpu_div_sqrt_mvp/hdl -J$(THIRD_PARTY_DIR)/cvfpu/src
endif endif
TEX_INCLUDE = -I$(RTL_DIR)/tex
RASTER_INCLUDE = -I$(RTL_DIR)/raster
OM_INCLUDE = -I$(RTL_DIR)/om
RTL_INCLUDE = -I$(RTL_DIR) -I$(RTL_DIR)/libs -I$(RTL_DIR)/interfaces -I$(RTL_DIR)/core -I$(RTL_DIR)/mem -I$(RTL_DIR)/cache RTL_INCLUDE = -I$(RTL_DIR) -I$(RTL_DIR)/libs -I$(RTL_DIR)/interfaces -I$(RTL_DIR)/core -I$(RTL_DIR)/mem -I$(RTL_DIR)/cache
RTL_INCLUDE += $(FPU_INCLUDE) RTL_INCLUDE += $(FPU_INCLUDE) $(TEX_INCLUDE) $(RASTER_INCLUDE) $(OM_INCLUDE)
RTL_INCLUDE += -I$(SRC_DIR) RTL_INCLUDE += -I$(SRC_DIR)
# compilation flags # compilation flags
@ -43,9 +43,6 @@ CFLAGS += -DSTACK_BASE_ADDR=32\'hFF000
all: build all: build
project2.tcl: project.tcl
@sed -e "s/@COE_FILE@/$(ESCAPED_COE_FILE)/g" $< > $@
$(KERNEL).bin: $(KERNEL).bin:
$(MAKE) -C $(ROOT_DIR)/kernel clean $(MAKE) -C $(ROOT_DIR)/kernel clean
STACK_BASE_ADDR=0xFF000 $(MAKE) -C $(ROOT_DIR)/kernel STACK_BASE_ADDR=0xFF000 $(MAKE) -C $(ROOT_DIR)/kernel
@ -61,13 +58,14 @@ project_1/sources.txt:
mkdir -p project_1 mkdir -p project_1
$(SCRIPT_DIR)/gen_sources.sh $(CFLAGS) -P -Cproject_1/src -Oproject_1/sources.txt $(SCRIPT_DIR)/gen_sources.sh $(CFLAGS) -P -Cproject_1/src -Oproject_1/sources.txt
build: project_1/project_1.xpr build: done.dcp
project_1/project_1.xpr: project_1/sources.txt kernel.bin.coe project2.tcl done.dcp: project_1/sources.txt kernel.bin.coe project.tcl
MAX_JOBS=$(JOBS) $(VIVADO) -mode batch -source project2.tcl -tclargs $(DEVICE) project_1/sources.txt $(SCRIPT_DIR) MAX_JOBS=$(JOBS) $(VIVADO) -mode batch -source project.tcl -tclargs $(DEVICE) project_1/sources.txt $(SCRIPT_DIR)
echo done > done.dcp
run: project_1/project_1.xpr run: project_1/project_1.xpr
$(VIVADO) project_1/project_1.xpr & $(VIVADO) project_1/project_1.xpr &
clean: clean:
rm -rf project_1 project2.tcl $(KERNEL).bin kernel.bin.coe rm -rf project_1 project1.tcl $(KERNEL).bin kernel.bin.coe
rm -rf .Xil *.log *.jou rm -rf .Xil *.log *.jou *.dcp *.rpt

View file

@ -11,9 +11,6 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
# Start time
set start_time [clock seconds]
if { $::argc != 3 } { if { $::argc != 3 } {
puts "ERROR: Program \"$::argv0\" requires 3 arguments!\n" puts "ERROR: Program \"$::argv0\" requires 3 arguments!\n"
puts "Usage: $::argv0 <device_part> <vcs_file> <tool_dir>\n" puts "Usage: $::argv0 <device_part> <vcs_file> <tool_dir>\n"
@ -24,7 +21,7 @@ set device_part [lindex $::argv 0]
set vcs_file [lindex $::argv 1] set vcs_file [lindex $::argv 1]
set tool_dir [lindex $::argv 2] set tool_dir [lindex $::argv 2]
uuts "Using device_part=$device_part" puts "Using device_part=$device_part"
puts "Using vcs_file=$vcs_file" puts "Using vcs_file=$vcs_file"
puts "Using tool_dir=$tool_dir" puts "Using tool_dir=$tool_dir"
@ -37,12 +34,8 @@ if {[info exists ::env(MAX_JOBS)]} {
set num_jobs 0 set num_jobs 0
} }
set origin_dir [file normalize "."] proc run_setup {} {
global device_part vcs_file tool_dir
# Use origin directory path location variable, if specified in the tcl shell
if { [info exists ::origin_dir_loc] } {
set origin_dir $::origin_dir_loc
}
# Set the project name # Set the project name
set project_name "project_1" set project_name "project_1"
@ -110,12 +103,18 @@ if {[string equal [get_filesets -quiet sim_1] ""]} {
create_fileset -simset sim_1 create_fileset -simset sim_1
} }
set testbench_file ""
foreach file ${vsources_list} {
if {[string match "*testbench.v" $file]} {
set testbench_file [file normalize $file]
break
}
}
# Set 'sim_1' fileset object # Set 'sim_1' fileset object
set obj [get_filesets sim_1] set obj [get_filesets sim_1]
# Import local files from the original project # Import local files from the original project
set files [list \ set files [list $testbench_file]
[file normalize "testbench.v" ]\
]
set imported_files [import_files -fileset sim_1 $files] set imported_files [import_files -fileset sim_1 $files]
# Set 'sim_1' fileset file properties for remote files # Set 'sim_1' fileset file properties for remote files
@ -301,7 +300,7 @@ set_property -dict [ list \
CONFIG.Assume_Synchronous_Clk {true} \ CONFIG.Assume_Synchronous_Clk {true} \
CONFIG.Byte_Size {8} \ CONFIG.Byte_Size {8} \
CONFIG.Load_Init_File {true} \ CONFIG.Load_Init_File {true} \
CONFIG.Coe_File {@COE_FILE@} \ CONFIG.Coe_File {@CURRENTDIR@/hw/syn/xilinx/sandbox/kernel.bin.coe} \
CONFIG.EN_SAFETY_CKT {true} \ CONFIG.EN_SAFETY_CKT {true} \
CONFIG.Enable_32bit_Address {true} \ CONFIG.Enable_32bit_Address {true} \
CONFIG.Fill_Remaining_Memory_Locations {false} \ CONFIG.Fill_Remaining_Memory_Locations {false} \
@ -401,7 +400,10 @@ set wrapper_path [make_wrapper -fileset sources_1 -files [ get_files -norecurse
add_files -norecurse -fileset sources_1 $wrapper_path add_files -norecurse -fileset sources_1 $wrapper_path
update_compile_order -fileset sources_1 update_compile_order -fileset sources_1
}
proc run_synthesis {} {
global num_jobs
# Synthesis # Synthesis
if {$num_jobs != 0} { if {$num_jobs != 0} {
launch_runs synth_1 -jobs $num_jobs launch_runs synth_1 -jobs $num_jobs
@ -410,9 +412,16 @@ if {$num_jobs != 0} {
} }
wait_on_run synth_1 wait_on_run synth_1
open_run synth_1 open_run synth_1
write_checkpoint -force post_synth.dcp
report_utilization -file utilization.rpt -hierarchical -hierarchical_percentages report_utilization -file utilization.rpt -hierarchical -hierarchical_percentages
write_checkpoint -force post_synth.dcp
}
proc run_implementation {} {
global tool_dir num_jobs
source "${tool_dir}/ila_insert.tcl"
insert_ila 8192
# Implementation # Implementation
if {$num_jobs != 0} { if {$num_jobs != 0} {
launch_runs impl_1 -jobs $num_jobs launch_runs impl_1 -jobs $num_jobs
@ -421,14 +430,40 @@ if {$num_jobs != 0} {
} }
wait_on_run impl_1 wait_on_run impl_1
open_run impl_1 open_run impl_1
write_checkpoint -force post_impl.dcp
# Generate reports
report_place_status -file place.rpt report_place_status -file place.rpt
report_route_status -file route.rpt report_route_status -file route.rpt
write_checkpoint -force post_impl.dcp
}
proc run_report {} {
# Generate reports
report_timing_summary -file timing.rpt report_timing_summary -file timing.rpt
report_power -file power.rpt report_power -file power.rpt
report_drc -file drc.rpt report_drc -file drc.rpt
}
###############################################################################
# Start time
set start_time [clock seconds]
# Check if the post-implementation checkpoint exists
if { [file exists post_impl.dcp] } {
puts "Resuming from post-implementation checkpoint: post_impl.dcp"
open_checkpoint post_impl.dcp
run_report
} elseif { [file exists post_synth.dcp] } {
puts "Resuming from post-synthesis checkpoint: post_synth.dcp"
open_checkpoint post_synth.dcp
run_implementation
run_report
} else {
# execute full pipeline
run_setup
run_synthesis
run_implementation
run_report
}
# End time and calculation # End time and calculation
set elapsed_time [expr {[clock seconds] - $start_time}] set elapsed_time [expr {[clock seconds] - $start_time}]

View file

@ -122,7 +122,8 @@ ifdef DEBUG
VPP_FLAGS += --vivado.prop fileset.sim_1.xsim.elaborate.debug_level=all VPP_FLAGS += --vivado.prop fileset.sim_1.xsim.elaborate.debug_level=all
CFLAGS += -DDEBUG_LEVEL=$(DEBUG) $(DBG_TRACE_FLAGS) CFLAGS += -DDEBUG_LEVEL=$(DEBUG) $(DBG_TRACE_FLAGS)
else else
CFLAGS += -DNDEBUG VPP_FLAGS += --debug.chipscope vortex_afu_1
CFLAGS += -DNDEBUG -DCHIPSCOPE $(DBG_SCOPE_FLAGS)
endif endif
else else
VPP_FLAGS += --optimize 3 VPP_FLAGS += --optimize 3
@ -167,7 +168,7 @@ $(BUILD_DIR)/scope.json: $(BUILD_DIR)/vortex.xml
gen-xo: $(XO_CONTAINER) gen-xo: $(XO_CONTAINER)
$(XO_CONTAINER): $(BUILD_DIR)/sources.txt $(XO_CONTAINER): $(BUILD_DIR)/sources.txt
mkdir -p $(BUILD_DIR); cd $(BUILD_DIR); $(VIVADO) -mode batch -source $(SRC_DIR)/../scripts/gen_xo.tcl -tclargs ../$(XO_CONTAINER) vortex_afu sources.txt $(SCRIPT_DIR) ../$(BUILD_DIR) mkdir -p $(BUILD_DIR); cd $(BUILD_DIR); $(VIVADO) -mode batch -source $(SRC_DIR)/gen_xo.tcl -tclargs ../$(XO_CONTAINER) vortex_afu sources.txt $(SCRIPT_DIR) ../$(BUILD_DIR)
gen-bin: $(XCLBIN_CONTAINER) gen-bin: $(XCLBIN_CONTAINER)
$(XCLBIN_CONTAINER): $(XO_CONTAINER) $(SCOPE_JSON) $(XCLBIN_CONTAINER): $(XO_CONTAINER) $(SCOPE_JSON)

View file

@ -514,6 +514,7 @@ public:
bank_req.type = bank_req_t::Core; bank_req.type = bank_req_t::Core;
bank_req.write = core_req.write; bank_req.write = core_req.write;
pipeline_req = bank_req; pipeline_req = bank_req;
DT(3, simobject_->name() << " core-req: " << core_req);
} }
if (core_req.write) if (core_req.write)