minor udpate

This commit is contained in:
Blaise Tine 2023-03-24 06:41:23 -04:00
parent 874e3e138e
commit b347fbe6c4
39 changed files with 20 additions and 4507 deletions

View file

@ -13,6 +13,26 @@
///////////////////////////////////////////////////////////////////////////////
`ifdef SYNTHESIS
`define TRACING_ON
`define TRACING_OFF
`ifndef NDEBUG
`define DEBUG_BLOCK(x) x
`else
`define DEBUG_BLOCK(x)
`endif
`define IGNORE_UNOPTFLAT_BEGIN
`define IGNORE_UNOPTFLAT_END
`define IGNORE_UNUSED_BEGIN
`define IGNORE_UNUSED_END
`define IGNORE_WARNINGS_BEGIN
`define IGNORE_WARNINGS_END
`define UNUSED_PARAM(x)
`define UNUSED_SPARAM(x)
`define UNUSED_VAR(x)
`define UNUSED_PIN(x) . x ()
`define TRACE(level, args) $write args
`else
`ifdef VERILATOR
`define TRACING_ON /* verilator tracing_on */
`define TRACING_OFF /* verilator tracing_off */
@ -66,25 +86,7 @@
. x () \
/* verilator lint_on PINCONNECTEMPTY */
`define TRACE(level, args) dpi_trace(level, $sformatf args)
`else
`define TRACING_ON
`define TRACING_OFF
`ifndef NDEBUG
`define DEBUG_BLOCK(x) x
`else
`define DEBUG_BLOCK(x)
`endif
`define IGNORE_UNOPTFLAT_BEGIN
`define IGNORE_UNOPTFLAT_END
`define IGNORE_UNUSED_BEGIN
`define IGNORE_UNUSED_END
`define IGNORE_WARNINGS_BEGIN
`define IGNORE_WARNINGS_END
`define UNUSED_PARAM(x)
`define UNUSED_SPARAM(x)
`define UNUSED_VAR(x)
`define UNUSED_PIN(x) . x ()
`define TRACE(level, args) $write args
`endif
`define STATIC_ASSERT(cond, msg) \

View file

@ -1,3 +0,0 @@
/build*/*
/.run/*
/.Xil/*

View file

@ -1,128 +0,0 @@
ifneq ($(findstring Makefile, $(MAKEFILE_LIST)), Makefile)
help:
$(ECHO) "Makefile Usage:"
$(ECHO) " make all TARGET=<sw_emu/hw_emu/hw> PLATFORM=<FPGA platform>"
$(ECHO) " Command to generate the design for specified Target and Device."
$(ECHO) ""
$(ECHO) " make clean"
$(ECHO) " Command to remove the generated non-hardware files."
$(ECHO) ""
endif
TARGET ?= hw
PLATFORM ?=
PREFIX ?= build
RTL_DIR = ../hdl
BUILD_DIR = $(PREFIX)_$(PLATFORM)_$(TARGET)
BIN_DIR = $(BUILD_DIR)/bin
RTL_INCLUDE += -I$(RTL_DIR)
CONFIGS += -DSYNTHESIS -DVIVADO
VIVADO = $(XILINX_VIVADO)/bin/vivado
VPP = $(XILINX_VITIS)/bin/v++
CP = cp -rf
RMDIR = rm -rf
ECHO = @echo
XO_CONTAINER = $(BIN_DIR)/krnl_vadd_rtl.xo
XCLBIN_CONTAINER = $(BIN_DIR)/krnl_vadd_rtl.xclbin
EMCONFIG = $(BIN_DIR)/emconfig.json
NCPUS := $(shell grep -c ^processor /proc/cpuinfo)
JOBS := $(shell expr $(NCPUS) - 1)
# Kernel compiler global settings
VPP_FLAGS += --link --target $(TARGET) --platform $(PLATFORM) --save-temps --no_ip_cache
VPP_FLAGS += --vivado.synth.jobs $(JOBS) --vivado.impl.jobs $(JOBS)
VPP_FLAGS += --connectivity.sp krnl_vadd_rtl_1.m_axi_mem:HBM[0:15]
VPP_FLAGS += --report estimate
VPP_FLAGS += --config ../vitis.ini
# Enable perf counters
ifdef PERF
CONFIGS += -DPERF_ENABLE
endif
# Generates profile summary report
ifdef PROFILE
VPP_FLAGS += --profile_kernel data:all:all:all
VPP_FLAGS += --profile_kernel stall:all:all:all
endif
# Debugigng
ifdef DEBUG
VPP_FLAGS += -g --optimize 0 --debug.protocol all
ifeq ($(TARGET), hw)
VPP_FLAGS += --debug.chipscope krnl_vadd_rtl_1
CONFIGS += -DCHIPSCOPE
else
CONFIGS += -DSIMULATION $(DBG_FLAGS)
VPP_FLAGS += --vivado.prop fileset.sim_1.xsim.elaborate.debug_level=all
endif
else
CONFIGS += -DNDEBUG
VPP_FLAGS += --optimize 3
endif
# Host
EXECUTABLE = ./test
CMD_ARGS = -x $(XCLBIN_CONTAINER)
CXXFLAGS += -std=c++14 -g -O0 -fmessage-length=0 -I$(XILINX_XRT)/include -I$(XILINX_VIVADO)/include -Wall -I../src
LDFLAGS += -L$(XILINX_XRT)/lib -pthread -luuid -lxrt_coreutil
HOST_SRCS += ./src/host.cpp ./src/cmdlineparser.cpp ./src/logger.cpp
# RTL Kernel only supports Hardware and Hardware Emulation.
ifneq ($(TARGET),$(findstring $(TARGET), hw hw_emu))
$(warning WARNING:Application supports only hw hw_emu TARGET. Please use the target for running the application)
endif
.PHONY: all run host clean gen-sources emconfig check-devices
all: check-devices $(XCLBIN_CONTAINER) emconfig host
gen-sources: $(BUILD_DIR)/sources.txt
$(BUILD_DIR)/sources.txt:
mkdir -p $(BUILD_DIR); cd $(BUILD_DIR); ../scripts/gen_sources.sh $(RTL_INCLUDE) $(CONFIGS) > sources.txt
$(XO_CONTAINER): $(BUILD_DIR)/sources.txt ./kernel.xml
mkdir -p $(BUILD_DIR); cd $(BUILD_DIR); $(VIVADO) -mode batch -source ../scripts/gen_xo.tcl -tclargs ../$(XO_CONTAINER) krnl_vadd_rtl sources.txt ../kernel.xml ../$(BUILD_DIR)
$(XCLBIN_CONTAINER): $(XO_CONTAINER)
mkdir -p $(BIN_DIR); cd $(BUILD_DIR); $(VPP) $(VPP_FLAGS) -o ../$(XCLBIN_CONTAINER) ../$(XO_CONTAINER)
emconfig: $(EMCONFIG)
$(EMCONFIG):
mkdir -p $(BIN_DIR); cd $(BUILD_DIR); emconfigutil --platform $(PLATFORM) --od ../$(BIN_DIR)
host: $(EXECUTABLE)
$(EXECUTABLE): $(HOST_SRCS)
g++ $^ $(CXXFLAGS) $(LDFLAGS) -o $@
run: $(EXECUTABLE) $(EMCONFIG)
ifeq ($(TARGET),$(filter $(TARGET),sw_emu hw_emu))
EMCONFIG_PATH=$(BIN_DIR) XCL_EMULATION_MODE=$(TARGET) $(EXECUTABLE) $(CMD_ARGS)
else
EMCONFIG_PATH=$(BIN_DIR) $(EXECUTABLE) $(CMD_ARGS)
endif
clean:
$(RMDIR) $(BUILD_DIR) $(EXECUTABLE)
# Check the devices avaiable
check-devices:
ifndef PLATFORM
$(error PLATFORM not set. Please set the PLATFORM properly and rerun. Run "make help" for more details.)
endif
ifndef XILINX_VITIS
$(error XILINX_VITIS variable is not set, please set correctly and rerun)
endif

View file

@ -1,178 +0,0 @@
/**
* Copyright (C) 2019-2021 Xilinx, Inc
*
* Licensed under the Apache License, Version 2.0 (the "License"). You may
* not use this file except in compliance with the License. A copy of the
* License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
///////////////////////////////////////////////////////////////////////////////
// Description: This is a wrapper of module "krnl_vadd_rtl_int"
///////////////////////////////////////////////////////////////////////////////
// default_nettype of none prevents implicit wire declaration.
`default_nettype none
`timescale 1 ns / 1 ps
`ifndef NOGLOBALS
`include "globals.vh"
`endif
module krnl_vadd_rtl #(
parameter integer C_S_AXI_CTRL_DATA_WIDTH = 32,
parameter integer C_S_AXI_CTRL_ADDR_WIDTH = 6,
parameter integer C_M_AXI_MEM_ID_WIDTH = 1,
parameter integer C_M_AXI_MEM_ADDR_WIDTH = 32,
parameter integer C_M_AXI_MEM_DATA_WIDTH = 32
)
(
// System signals
input wire ap_clk,
input wire ap_rst_n,
// AXI4 master interface
output wire m_axi_mem_awvalid,
input wire m_axi_mem_awready,
output wire [C_M_AXI_MEM_ADDR_WIDTH-1:0] m_axi_mem_awaddr,
output wire [C_M_AXI_MEM_ID_WIDTH - 1:0] m_axi_mem_awid,
output wire [7:0] m_axi_mem_awlen,
output wire [2:0] m_axi_mem_awsize,
output wire [1:0] m_axi_mem_awburst,
output wire [1:0] m_axi_mem_awlock,
output wire [3:0] m_axi_mem_awcache,
output wire [2:0] m_axi_mem_awprot,
output wire [3:0] m_axi_mem_awqos,
output wire [3:0] m_axi_mem_awregion,
output wire m_axi_mem_wvalid,
input wire m_axi_mem_wready,
output wire [C_M_AXI_MEM_DATA_WIDTH-1:0] m_axi_mem_wdata,
output wire [C_M_AXI_MEM_DATA_WIDTH/8-1:0] m_axi_mem_wstrb,
output wire m_axi_mem_wlast,
input wire m_axi_mem_bvalid,
output wire m_axi_mem_bready,
input wire [C_M_AXI_MEM_ID_WIDTH - 1:0] m_axi_mem_bid,
input wire [1:0] m_axi_mem_bresp,
output wire m_axi_mem_arvalid,
input wire m_axi_mem_arready,
output wire [C_M_AXI_MEM_ADDR_WIDTH-1:0] m_axi_mem_araddr,
output wire [C_M_AXI_MEM_ID_WIDTH-1:0] m_axi_mem_arid,
output wire [7:0] m_axi_mem_arlen,
output wire [2:0] m_axi_mem_arsize,
output wire [1:0] m_axi_mem_arburst,
output wire [1:0] m_axi_mem_arlock,
output wire [3:0] m_axi_mem_arcache,
output wire [2:0] m_axi_mem_arprot,
output wire [3:0] m_axi_mem_arqos,
output wire [3:0] m_axi_mem_arregion,
input wire m_axi_mem_rvalid,
output wire m_axi_mem_rready,
input wire [C_M_AXI_MEM_DATA_WIDTH - 1:0] m_axi_mem_rdata,
input wire m_axi_mem_rlast,
input wire [C_M_AXI_MEM_ID_WIDTH - 1:0] m_axi_mem_rid,
input wire [1:0] m_axi_mem_rresp,
// AXI4-Lite slave interface
input wire s_axi_ctrl_awvalid,
output wire s_axi_ctrl_awready,
input wire [C_S_AXI_CTRL_ADDR_WIDTH-1:0] s_axi_ctrl_awaddr,
input wire s_axi_ctrl_wvalid,
output wire s_axi_ctrl_wready,
input wire [C_S_AXI_CTRL_DATA_WIDTH-1:0] s_axi_ctrl_wdata,
input wire [C_S_AXI_CTRL_DATA_WIDTH/8-1:0] s_axi_ctrl_wstrb,
input wire s_axi_ctrl_arvalid,
output wire s_axi_ctrl_arready,
input wire [C_S_AXI_CTRL_ADDR_WIDTH-1:0] s_axi_ctrl_araddr,
output wire s_axi_ctrl_rvalid,
input wire s_axi_ctrl_rready,
output wire [C_S_AXI_CTRL_DATA_WIDTH-1:0] s_axi_ctrl_rdata,
output wire [1:0] s_axi_ctrl_rresp,
output wire s_axi_ctrl_bvalid,
input wire s_axi_ctrl_bready,
output wire [1:0] s_axi_ctrl_bresp,
output wire interrupt
);
krnl_vadd_rtl_int #(
.C_S_AXI_CTRL_DATA_WIDTH ( C_S_AXI_CTRL_DATA_WIDTH ),
.C_S_AXI_CTRL_ADDR_WIDTH ( C_S_AXI_CTRL_ADDR_WIDTH ),
.C_M_AXI_MEM_ID_WIDTH ( C_M_AXI_MEM_ID_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 )
)
inst_krnl_vadd_rtl_int (
.ap_clk ( ap_clk ),
.ap_rst_n ( ap_rst_n ),
.m_axi_mem_awvalid ( m_axi_mem_awvalid ),
.m_axi_mem_awready ( m_axi_mem_awready ),
.m_axi_mem_awaddr ( m_axi_mem_awaddr ),
.m_axi_mem_awid ( m_axi_mem_awid ),
.m_axi_mem_awlen ( m_axi_mem_awlen ),
.m_axi_mem_awsize ( m_axi_mem_awsize ),
.m_axi_mem_awburst ( m_axi_mem_awburst ),
.m_axi_mem_awlock ( m_axi_mem_awlock ),
.m_axi_mem_awcache ( m_axi_mem_awcache ),
.m_axi_mem_awprot ( m_axi_mem_awprot ),
.m_axi_mem_awqos ( m_axi_mem_awqos ),
.m_axi_mem_awregion ( m_axi_mem_awregion ),
.m_axi_mem_wvalid ( m_axi_mem_wvalid ),
.m_axi_mem_wready ( m_axi_mem_wready ),
.m_axi_mem_wdata ( m_axi_mem_wdata ),
.m_axi_mem_wstrb ( m_axi_mem_wstrb ),
.m_axi_mem_wlast ( m_axi_mem_wlast ),
.m_axi_mem_arvalid ( m_axi_mem_arvalid ),
.m_axi_mem_arready ( m_axi_mem_arready ),
.m_axi_mem_araddr ( m_axi_mem_araddr ),
.m_axi_mem_arid ( m_axi_mem_arid ),
.m_axi_mem_arlen ( m_axi_mem_arlen ),
.m_axi_mem_arsize ( m_axi_mem_arsize ),
.m_axi_mem_arburst ( m_axi_mem_arburst ),
.m_axi_mem_arlock ( m_axi_mem_arlock ),
.m_axi_mem_arcache ( m_axi_mem_arcache ),
.m_axi_mem_arprot ( m_axi_mem_arprot ),
.m_axi_mem_arqos ( m_axi_mem_arqos ),
.m_axi_mem_arregion ( m_axi_mem_arregion ),
.m_axi_mem_rvalid ( m_axi_mem_rvalid ),
.m_axi_mem_rready ( m_axi_mem_rready ),
.m_axi_mem_rdata ( m_axi_mem_rdata ),
.m_axi_mem_rlast ( m_axi_mem_rlast ),
.m_axi_mem_rid ( m_axi_mem_rid ),
.m_axi_mem_rresp ( m_axi_mem_rresp ),
.m_axi_mem_bvalid ( m_axi_mem_bvalid ),
.m_axi_mem_bready ( m_axi_mem_bready ),
.m_axi_mem_bresp ( m_axi_mem_bresp ),
.m_axi_mem_bid ( m_axi_mem_bid ),
.s_axi_ctrl_awvalid ( s_axi_ctrl_awvalid ),
.s_axi_ctrl_awready ( s_axi_ctrl_awready ),
.s_axi_ctrl_awaddr ( s_axi_ctrl_awaddr ),
.s_axi_ctrl_wvalid ( s_axi_ctrl_wvalid ),
.s_axi_ctrl_wready ( s_axi_ctrl_wready ),
.s_axi_ctrl_wdata ( s_axi_ctrl_wdata ),
.s_axi_ctrl_wstrb ( s_axi_ctrl_wstrb ),
.s_axi_ctrl_arvalid ( s_axi_ctrl_arvalid ),
.s_axi_ctrl_arready ( s_axi_ctrl_arready ),
.s_axi_ctrl_araddr ( s_axi_ctrl_araddr ),
.s_axi_ctrl_rvalid ( s_axi_ctrl_rvalid ),
.s_axi_ctrl_rready ( s_axi_ctrl_rready ),
.s_axi_ctrl_rdata ( s_axi_ctrl_rdata ),
.s_axi_ctrl_rresp ( s_axi_ctrl_rresp ),
.s_axi_ctrl_bvalid ( s_axi_ctrl_bvalid ),
.s_axi_ctrl_bready ( s_axi_ctrl_bready ),
.s_axi_ctrl_bresp ( s_axi_ctrl_bresp ),
.interrupt ( interrupt )
);
endmodule : krnl_vadd_rtl
`default_nettype wire

View file

@ -1,68 +0,0 @@
/**
* Copyright (C) 2019-2021 Xilinx, Inc
*
* Licensed under the Apache License, Version 2.0 (the "License"). You may
* not use this file except in compliance with the License. A copy of the
* License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
////////////////////////////////////////////////////////////////////////////////
// Description: Basic Adder, no overflow. Unsigned. Combinatorial.
////////////////////////////////////////////////////////////////////////////////
`default_nettype none
module krnl_vadd_rtl_adder #(
parameter integer C_DATA_WIDTH = 32, // Data width of both input and output data
parameter integer C_NUM_CHANNELS = 2 // Number of input channels. Only a value of 2 implemented.
)
(
input wire aclk,
input wire areset,
input wire [C_NUM_CHANNELS-1:0] s_tvalid,
input wire [C_NUM_CHANNELS-1:0][C_DATA_WIDTH-1:0] s_tdata,
output wire [C_NUM_CHANNELS-1:0] s_tready,
output wire m_tvalid,
output wire [C_DATA_WIDTH-1:0] m_tdata,
input wire m_tready
);
timeunit 1ps;
timeprecision 1ps;
/////////////////////////////////////////////////////////////////////////////
// Variables
/////////////////////////////////////////////////////////////////////////////
logic [C_DATA_WIDTH-1:0] acc;
/////////////////////////////////////////////////////////////////////////////
// Logic
/////////////////////////////////////////////////////////////////////////////
always_comb begin
acc = s_tdata[0];
for (int i = 1; i < C_NUM_CHANNELS; i++) begin
acc = acc + s_tdata[i];
end
end
assign m_tvalid = &s_tvalid;
assign m_tdata = acc;
// Only assert s_tready when transfer has been accepted. tready asserted on all channels simultaneously
assign s_tready = m_tready & m_tvalid ? {C_NUM_CHANNELS{1'b1}} : {C_NUM_CHANNELS{1'b0}};
endmodule : krnl_vadd_rtl_adder
`default_nettype wire

View file

@ -1,274 +0,0 @@
/**
* Copyright (C) 2019-2021 Xilinx, Inc
*
* Licensed under the Apache License, Version 2.0 (the "License"). You may
* not use this file except in compliance with the License. A copy of the
* License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
///////////////////////////////////////////////////////////////////////////////
// Description: This is a multi-threaded AXI4 read master. Each channel will
// issue commands on a different IDs. As a result data may arrive out of
// order. The amount of data requested is equal to the ctrl_length variable.
// Prog full is set and sampled such that the FIFO will never overflow. Thus
// rready can be always asserted for better timing.
///////////////////////////////////////////////////////////////////////////////
`default_nettype none
module krnl_vadd_rtl_axi_read_master #(
parameter integer C_ID_WIDTH = 1, // Must be >= $clog2(C_NUM_CHANNELS)
parameter integer C_ADDR_WIDTH = 64,
parameter integer C_DATA_WIDTH = 32,
parameter integer C_NUM_CHANNELS = 2, // Only 2 tested.
parameter integer C_LENGTH_WIDTH = 32,
parameter integer C_BURST_LEN = 256, // Max AXI burst length for read commands
parameter integer C_LOG_BURST_LEN = 8,
parameter integer C_MAX_OUTSTANDING = 3
)
(
// System signals
input wire aclk,
input wire areset,
// Control signals
input wire ctrl_start,
output wire ctrl_done,
input wire [C_NUM_CHANNELS-1:0][C_ADDR_WIDTH-1:0] ctrl_offset,
input wire [C_LENGTH_WIDTH-1:0] ctrl_length,
input wire [C_NUM_CHANNELS-1:0] ctrl_prog_full,
// AXI4 master interface
output wire arvalid,
input wire arready,
output wire [C_ADDR_WIDTH-1:0] araddr,
output wire [C_ID_WIDTH-1:0] arid,
output wire [7:0] arlen,
output wire [2:0] arsize,
input wire rvalid,
output wire rready,
input wire [C_DATA_WIDTH - 1:0] rdata,
input wire rlast,
input wire [C_ID_WIDTH - 1:0] rid,
input wire [1:0] rresp,
// AXI4-Stream master interface, 1 interface per channel.
output wire [C_NUM_CHANNELS-1:0] m_tvalid,
input wire [C_NUM_CHANNELS-1:0] m_tready,
output wire [C_NUM_CHANNELS-1:0][C_DATA_WIDTH-1:0] m_tdata
);
timeunit 1ps;
timeprecision 1ps;
///////////////////////////////////////////////////////////////////////////////
// Local Parameters
///////////////////////////////////////////////////////////////////////////////
localparam integer LP_MAX_OUTSTANDING_CNTR_WIDTH = $clog2(C_MAX_OUTSTANDING+1);
localparam integer LP_TRANSACTION_CNTR_WIDTH = C_LENGTH_WIDTH-C_LOG_BURST_LEN;
///////////////////////////////////////////////////////////////////////////////
// Variables
///////////////////////////////////////////////////////////////////////////////
// Control logic
logic [C_NUM_CHANNELS-1:0] done = '0;
logic [LP_TRANSACTION_CNTR_WIDTH-1:0] num_full_bursts;
logic num_partial_bursts;
logic start = 1'b0;
logic [LP_TRANSACTION_CNTR_WIDTH-1:0] num_transactions;
logic has_partial_burst;
logic [C_LOG_BURST_LEN-1:0] final_burst_len;
logic single_transaction;
logic ar_idle = 1'b1;
logic ar_done;
// AXI Read Address Channel
logic fifo_stall;
logic arxfer;
logic arvalid_r = 1'b0;
logic [C_NUM_CHANNELS-1:0][C_ADDR_WIDTH-1:0] addr;
logic [C_ID_WIDTH-1:0] id = {C_ID_WIDTH{1'b1}};
logic [LP_TRANSACTION_CNTR_WIDTH-1:0] ar_transactions_to_go;
logic ar_final_transaction;
logic [C_NUM_CHANNELS-1:0] incr_ar_to_r_cnt;
logic [C_NUM_CHANNELS-1:0] decr_ar_to_r_cnt;
logic [C_NUM_CHANNELS-1:0] stall_ar;
logic [C_NUM_CHANNELS-1:0][LP_MAX_OUTSTANDING_CNTR_WIDTH-1:0] outstanding_vacancy_count;
// AXI Data Channel
logic [C_NUM_CHANNELS-1:0] tvalid;
logic [C_NUM_CHANNELS-1:0][C_DATA_WIDTH-1:0] tdata;
logic rxfer;
logic [C_NUM_CHANNELS-1:0] decr_r_transaction_cntr;
logic [C_NUM_CHANNELS-1:0][LP_TRANSACTION_CNTR_WIDTH-1:0] r_transactions_to_go;
logic [C_NUM_CHANNELS-1:0] r_final_transaction;
///////////////////////////////////////////////////////////////////////////////
// Control Logic
///////////////////////////////////////////////////////////////////////////////
always @(posedge aclk) begin
for (int i = 0; i < C_NUM_CHANNELS; i++) begin
done[i] <= rxfer & rlast & (rid == i) & r_final_transaction[i] ? 1'b1 :
ctrl_done ? 1'b0 : done[i];
end
end
assign ctrl_done = &done;
// Determine how many full burst to issue and if there are any partial bursts.
assign num_full_bursts = ctrl_length[C_LOG_BURST_LEN+:C_LENGTH_WIDTH-C_LOG_BURST_LEN];
assign num_partial_bursts = ctrl_length[0+:C_LOG_BURST_LEN] ? 1'b1 : 1'b0;
always @(posedge aclk) begin
start <= ctrl_start;
num_transactions <= (num_partial_bursts == 1'b0) ? num_full_bursts - 1'b1 : num_full_bursts;
has_partial_burst <= num_partial_bursts;
final_burst_len <= ctrl_length[0+:C_LOG_BURST_LEN] - 1'b1;
end
// Special case if there is only 1 AXI transaction.
assign single_transaction = (num_transactions == {LP_TRANSACTION_CNTR_WIDTH{1'b0}}) ? 1'b1 : 1'b0;
///////////////////////////////////////////////////////////////////////////////
// AXI Read Address Channel
///////////////////////////////////////////////////////////////////////////////
assign arvalid = arvalid_r;
assign araddr = addr[id];
assign arlen = ar_final_transaction || (start & single_transaction) ? final_burst_len : C_BURST_LEN - 1;
assign arsize = $clog2((C_DATA_WIDTH/8));
assign arid = id;
assign arxfer = arvalid & arready;
assign fifo_stall = ctrl_prog_full[id];
always @(posedge aclk) begin
if (areset) begin
arvalid_r <= 1'b0;
end
else begin
arvalid_r <= ~ar_idle & ~stall_ar[id] & ~arvalid_r & ~fifo_stall ? 1'b1 :
arready ? 1'b0 : arvalid_r;
end
end
// When ar_idle, there are no transactions to issue.
always @(posedge aclk) begin
if (areset) begin
ar_idle <= 1'b1;
end
else begin
ar_idle <= start ? 1'b0 :
ar_done ? 1'b1 :
ar_idle;
end
end
// each channel is assigned a different id. The transactions are interleaved.
always @(posedge aclk) begin
if (start) begin
id <= {C_ID_WIDTH{1'b1}};
end
else begin
id <= arxfer ? id - 1'b1 : id;
end
end
// Increment to next address after each transaction is issued.
always @(posedge aclk) begin
for (int i = 0; i < C_NUM_CHANNELS; i++) begin
addr[i] <= ctrl_start ? ctrl_offset[i] :
arxfer && (id == i) ? addr[i] + C_BURST_LEN*C_DATA_WIDTH/8 :
addr[i];
end
end
// Counts down the number of transactions to send.
krnl_vadd_rtl_counter #(
.C_WIDTH ( LP_TRANSACTION_CNTR_WIDTH ) ,
.C_INIT ( {LP_TRANSACTION_CNTR_WIDTH{1'b0}} )
)
inst_ar_transaction_cntr (
.clk ( aclk ) ,
.clken ( 1'b1 ) ,
.rst ( areset ) ,
.load ( start ) ,
.incr ( 1'b0 ) ,
.decr ( arxfer && id == '0 ) ,
.load_value ( num_transactions ) ,
.count ( ar_transactions_to_go ) ,
.is_zero ( ar_final_transaction )
);
assign ar_done = ar_final_transaction && arxfer && id == 1'b0;
always_comb begin
for (int i = 0; i < C_NUM_CHANNELS; i++) begin
incr_ar_to_r_cnt[i] = rxfer & rlast & (rid == i);
decr_ar_to_r_cnt[i] = arxfer & (arid == i);
end
end
// Keeps track of the number of outstanding transactions. Stalls
// when the value is reached so that the FIFO won't overflow.
krnl_vadd_rtl_counter #(
.C_WIDTH ( LP_MAX_OUTSTANDING_CNTR_WIDTH ) ,
.C_INIT ( C_MAX_OUTSTANDING[0+:LP_MAX_OUTSTANDING_CNTR_WIDTH] )
)
inst_ar_to_r_transaction_cntr[C_NUM_CHANNELS-1:0] (
.clk ( aclk ) ,
.clken ( 1'b1 ) ,
.rst ( areset ) ,
.load ( 1'b0 ) ,
.incr ( incr_ar_to_r_cnt ) ,
.decr ( decr_ar_to_r_cnt ) ,
.load_value ( {LP_MAX_OUTSTANDING_CNTR_WIDTH{1'b0}} ) ,
.count ( outstanding_vacancy_count ) ,
.is_zero ( stall_ar )
);
///////////////////////////////////////////////////////////////////////////////
// AXI Read Channel
///////////////////////////////////////////////////////////////////////////////
assign m_tvalid = tvalid;
assign m_tdata = tdata;
always_comb begin
for (int i = 0; i < C_NUM_CHANNELS; i++) begin
tvalid[i] = rvalid && (rid == i);
tdata[i] = rdata;
end
end
// rready can remain high for optimal timing because ar transactions are not issued
// unless there is enough space in the FIFO.
assign rready = 1'b1;
assign rxfer = rready & rvalid;
always_comb begin
for (int i = 0; i < C_NUM_CHANNELS; i++) begin
decr_r_transaction_cntr[i] = rxfer & rlast & (rid == i);
end
end
krnl_vadd_rtl_counter #(
.C_WIDTH ( LP_TRANSACTION_CNTR_WIDTH ) ,
.C_INIT ( {LP_TRANSACTION_CNTR_WIDTH{1'b0}} )
)
inst_r_transaction_cntr[C_NUM_CHANNELS-1:0] (
.clk ( aclk ) ,
.clken ( 1'b1 ) ,
.rst ( areset ) ,
.load ( start ) ,
.incr ( 1'b0 ) ,
.decr ( decr_r_transaction_cntr ) ,
.load_value ( num_transactions ) ,
.count ( r_transactions_to_go ) ,
.is_zero ( r_final_transaction )
);
endmodule : krnl_vadd_rtl_axi_read_master
`default_nettype wire

View file

@ -1,276 +0,0 @@
/**
* Copyright (C) 2019-2021 Xilinx, Inc
*
* Licensed under the Apache License, Version 2.0 (the "License"). You may
* not use this file except in compliance with the License. A copy of the
* License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
////////////////////////////////////////////////////////////
// Description: AXI4 Write Master. Takes a stream of data in,
// appends address information and sends it out.
`default_nettype none
module krnl_vadd_rtl_axi_write_master #(
parameter integer C_ADDR_WIDTH = 64,
parameter integer C_DATA_WIDTH = 32,
parameter integer C_MAX_LENGTH_WIDTH = 32,
parameter integer C_BURST_LEN = 256,
parameter integer C_LOG_BURST_LEN = 8
)
(
// Control interface
input wire ctrl_start,
input wire [C_ADDR_WIDTH-1:0] ctrl_offset,
input wire [C_MAX_LENGTH_WIDTH-1:0] ctrl_length,
output wire ctrl_done,
// AXI4-Stream interface
input wire s_tvalid,
input wire [C_DATA_WIDTH-1:0] s_tdata,
output wire s_tready,
// AXI Interface
input wire aclk,
input wire areset,
output wire [C_ADDR_WIDTH-1:0] awaddr,
output wire [7:0] awlen,
output wire [2:0] awsize,
output wire awvalid,
input wire awready,
output wire [C_DATA_WIDTH-1:0] wdata,
output wire [C_DATA_WIDTH/8-1:0] wstrb,
output wire wlast,
output wire wvalid,
input wire wready,
input wire [1:0] bresp,
input wire bvalid,
output wire bready
);
timeunit 1ps;
timeprecision 1ps;
/////////////////////////////////////////////////////////////////////////////
// Local Parameters
/////////////////////////////////////////////////////////////////////////////
localparam integer LP_LOG_MAX_W_TO_AW = 8; // Allow up to 256 outstanding w to aw transactions
localparam integer LP_TRANSACTION_CNTR_WIDTH = C_MAX_LENGTH_WIDTH-C_LOG_BURST_LEN;
/////////////////////////////////////////////////////////////////////////////
// Variables
/////////////////////////////////////////////////////////////////////////////
logic [LP_TRANSACTION_CNTR_WIDTH-1:0] num_full_bursts;
logic num_partial_bursts;
logic start = 1'b0;
logic [LP_TRANSACTION_CNTR_WIDTH-1:0] num_transactions;
logic has_partial_burst;
logic [C_LOG_BURST_LEN-1:0] final_burst_len;
logic single_transaction;
logic wxfer; // Unregistered write data transfer
logic wfirst = 1'b1;
logic load_burst_cntr;
logic [C_LOG_BURST_LEN-1:0] wxfers_to_go; // Used for simulation debug
logic [LP_TRANSACTION_CNTR_WIDTH-1:0] w_transactions_to_go;
logic w_final_transaction;
logic w_almost_final_transaction = 1'b0;
logic awxfer;
logic awvalid_r = 1'b0;
logic [C_ADDR_WIDTH-1:0] addr;
logic wfirst_d1 = 1'b0;
logic wfirst_pulse = 1'b0;
logic [LP_LOG_MAX_W_TO_AW-1:0] dbg_w_to_aw_outstanding;
logic idle_aw;
logic [LP_TRANSACTION_CNTR_WIDTH-1:0] aw_transactions_to_go;
logic aw_final_transaction;
wire bxfer;
logic [LP_TRANSACTION_CNTR_WIDTH-1:0] b_transactions_to_go;
logic b_final_transaction;
/////////////////////////////////////////////////////////////////////////////
// Control logic
/////////////////////////////////////////////////////////////////////////////
// Count the number of transfers and assert done when the last bvalid is received.
assign num_full_bursts = ctrl_length[C_LOG_BURST_LEN+:C_MAX_LENGTH_WIDTH-C_LOG_BURST_LEN];
assign num_partial_bursts = ctrl_length[0+:C_LOG_BURST_LEN] ? 1'b1 : 1'b0;
always @(posedge aclk) begin
start <= ctrl_start;
num_transactions <= (num_partial_bursts == 1'b0) ? num_full_bursts - 1'b1 : num_full_bursts;
has_partial_burst <= num_partial_bursts;
final_burst_len <= ctrl_length[0+:C_LOG_BURST_LEN] - 1'b1;
end
assign ctrl_done = bxfer & b_final_transaction;
assign single_transaction = (num_transactions == {LP_TRANSACTION_CNTR_WIDTH{1'b0}}) ? 1'b1 : 1'b0;
/////////////////////////////////////////////////////////////////////////////
// AXI Write Data Channel
/////////////////////////////////////////////////////////////////////////////
assign wvalid = s_tvalid;
assign wdata = s_tdata;
assign wstrb = {(C_DATA_WIDTH/8){1'b1}};
assign s_tready = wready;
assign wxfer = wvalid & wready;
always @(posedge aclk) begin
if (areset) begin
wfirst <= 1'b1;
end
else begin
wfirst <= wxfer ? wlast : wfirst;
end
end
// Load burst counter with partial burst if on final transaction or if there is only 1 transaction
assign load_burst_cntr = (wxfer & wlast & w_almost_final_transaction) || (start & single_transaction);
krnl_vadd_rtl_counter #(
.C_WIDTH ( C_LOG_BURST_LEN ) ,
.C_INIT ( {C_LOG_BURST_LEN{1'b1}} )
)
inst_burst_cntr (
.clk ( aclk ) ,
.clken ( 1'b1 ) ,
.rst ( areset ) ,
.load ( load_burst_cntr ) ,
.incr ( 1'b0 ) ,
.decr ( wxfer ) ,
.load_value ( final_burst_len ) ,
.count ( wxfers_to_go ) ,
.is_zero ( wlast )
);
krnl_vadd_rtl_counter #(
.C_WIDTH ( LP_TRANSACTION_CNTR_WIDTH ) ,
.C_INIT ( {LP_TRANSACTION_CNTR_WIDTH{1'b0}} )
)
inst_w_transaction_cntr (
.clk ( aclk ) ,
.clken ( 1'b1 ) ,
.rst ( areset ) ,
.load ( start ) ,
.incr ( 1'b0 ) ,
.decr ( wxfer & wlast ) ,
.load_value ( num_transactions ) ,
.count ( w_transactions_to_go ) ,
.is_zero ( w_final_transaction )
);
always @(posedge aclk) begin
w_almost_final_transaction <= (w_transactions_to_go == 1) ? 1'b1 : 1'b0;
end
/////////////////////////////////////////////////////////////////////////////
// AXI Write Address Channel
/////////////////////////////////////////////////////////////////////////////
// The address channel samples the data channel and send out transactions when
// first beat of wdata is asserted. This ensures that address requests are not
// sent without data on the way.
assign awvalid = awvalid_r;
assign awxfer = awvalid & awready;
always @(posedge aclk) begin
if (areset) begin
awvalid_r <= 1'b0;
end
else begin
awvalid_r <= ~idle_aw & ~awvalid_r ? 1'b1 :
awready ? 1'b0 :
awvalid_r;
end
end
assign awaddr = addr;
always @(posedge aclk) begin
addr <= ctrl_start ? ctrl_offset :
awxfer ? addr + C_BURST_LEN*C_DATA_WIDTH/8 :
addr;
end
assign awlen = aw_final_transaction || (start & single_transaction) ? final_burst_len : C_BURST_LEN - 1;
assign awsize = $clog2((C_DATA_WIDTH/8));
krnl_vadd_rtl_counter #(
.C_WIDTH (LP_LOG_MAX_W_TO_AW),
.C_INIT ({LP_LOG_MAX_W_TO_AW{1'b0}})
)
inst_w_to_aw_cntr (
.clk ( aclk ) ,
.clken ( 1'b1 ) ,
.rst ( areset ) ,
.load ( 1'b0 ) ,
.incr ( wfirst_pulse ) ,
.decr ( awxfer ) ,
.load_value ( ) ,
.count ( dbg_w_to_aw_outstanding ) ,
.is_zero ( idle_aw )
);
always @(posedge aclk) begin
wfirst_d1 <= wvalid & wfirst;
end
always @(posedge aclk) begin
wfirst_pulse <= wvalid & wfirst & ~wfirst_d1;
end
krnl_vadd_rtl_counter #(
.C_WIDTH ( LP_TRANSACTION_CNTR_WIDTH ) ,
.C_INIT ( {LP_TRANSACTION_CNTR_WIDTH{1'b0}} )
)
inst_aw_transaction_cntr (
.clk ( aclk ) ,
.clken ( 1'b1 ) ,
.rst ( areset ) ,
.load ( start ) ,
.incr ( 1'b0 ) ,
.decr ( awxfer ) ,
.load_value ( num_transactions ) ,
.count ( aw_transactions_to_go ) ,
.is_zero ( aw_final_transaction )
);
/////////////////////////////////////////////////////////////////////////////
// AXI Write Response Channel
/////////////////////////////////////////////////////////////////////////////
assign bready = 1'b1;
assign bxfer = bready & bvalid;
krnl_vadd_rtl_counter #(
.C_WIDTH ( LP_TRANSACTION_CNTR_WIDTH ) ,
.C_INIT ( {LP_TRANSACTION_CNTR_WIDTH{1'b0}} )
)
inst_b_transaction_cntr (
.clk ( aclk ) ,
.clken ( 1'b1 ) ,
.rst ( areset ) ,
.load ( start ) ,
.incr ( 1'b0 ) ,
.decr ( bxfer ) ,
.load_value ( num_transactions ) ,
.count ( b_transactions_to_go ) ,
.is_zero ( b_final_transaction )
);
endmodule : krnl_vadd_rtl_axi_write_master
`default_nettype wire

View file

@ -1,437 +0,0 @@
/**
* Copyright (C) 2019-2021 Xilinx, Inc
*
* Licensed under the Apache License, Version 2.0 (the "License"). You may
* not use this file except in compliance with the License. A copy of the
* License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
`timescale 1ns/1ps
module krnl_vadd_rtl_control_s_axi
#(parameter
C_S_AXI_ADDR_WIDTH = 6,
C_S_AXI_DATA_WIDTH = 32
)(
// axi4 lite slave signals
input wire ACLK,
input wire ARESET,
input wire ACLK_EN,
input wire [C_S_AXI_ADDR_WIDTH-1:0] AWADDR,
input wire AWVALID,
output wire AWREADY,
input wire [C_S_AXI_DATA_WIDTH-1:0] WDATA,
input wire [C_S_AXI_DATA_WIDTH/8-1:0] WSTRB,
input wire WVALID,
output wire WREADY,
output wire [1:0] BRESP,
output wire BVALID,
input wire BREADY,
input wire [C_S_AXI_ADDR_WIDTH-1:0] ARADDR,
input wire ARVALID,
output wire ARREADY,
output wire [C_S_AXI_DATA_WIDTH-1:0] RDATA,
output wire [1:0] RRESP,
output wire RVALID,
input wire RREADY,
output wire interrupt,
// user signals
output wire ap_start,
input wire ap_done,
input wire ap_ready,
input wire ap_idle,
output wire [63:0] a,
output wire [63:0] b,
output wire [63:0] c,
output wire [31:0] length_r
);
//------------------------Address Info-------------------
// 0x00 : Control signals
// bit 0 - ap_start (Read/Write/COH)
// bit 1 - ap_done (Read/COR)
// bit 2 - ap_idle (Read)
// bit 3 - ap_ready (Read)
// bit 7 - auto_restart (Read/Write)
// others - reserved
// 0x04 : Global Interrupt Enable Register
// bit 0 - Global Interrupt Enable (Read/Write)
// others - reserved
// 0x08 : IP Interrupt Enable Register (Read/Write)
// bit 0 - Channel 0 (ap_done)
// bit 1 - Channel 1 (ap_ready)
// others - reserved
// 0x0c : IP Interrupt Status Register (Read/TOW)
// bit 0 - Channel 0 (ap_done)
// bit 1 - Channel 1 (ap_ready)
// others - reserved
// 0x10 : Data signal of a
// bit 31~0 - a[31:0] (Read/Write)
// 0x14 : Data signal of a
// bit 31~0 - a[63:32] (Read/Write)
// 0x18 : reserved
// 0x1c : Data signal of b
// bit 31~0 - b[31:0] (Read/Write)
// 0x20 : Data signal of b
// bit 31~0 - b[63:32] (Read/Write)
// 0x24 : reserved
// 0x28 : Data signal of c
// bit 31~0 - c[31:0] (Read/Write)
// 0x2c : Data signal of c
// bit 31~0 - c[63:32] (Read/Write)
// 0x30 : reserved
// 0x34 : Data signal of length_r
// bit 31~0 - length_r[31:0] (Read/Write)
// 0x38 : reserved
// (SC = Self Clear, COR = Clear on Read, TOW = Toggle on Write, COH = Clear on Handshake)
//------------------------Parameter----------------------
localparam
ADDR_AP_CTRL = 6'h00,
ADDR_GIE = 6'h04,
ADDR_IER = 6'h08,
ADDR_ISR = 6'h0c,
ADDR_A_DATA_0 = 6'h10,
ADDR_A_DATA_1 = 6'h14,
ADDR_A_CTRL = 6'h18,
ADDR_B_DATA_0 = 6'h1c,
ADDR_B_DATA_1 = 6'h20,
ADDR_B_CTRL = 6'h24,
ADDR_C_DATA_0 = 6'h28,
ADDR_C_DATA_1 = 6'h2c,
ADDR_C_CTRL = 6'h30,
ADDR_LENGTH_R_DATA_0 = 6'h34,
ADDR_LENGTH_R_CTRL = 6'h38,
WRIDLE = 2'd0,
WRDATA = 2'd1,
WRRESP = 2'd2,
RDIDLE = 2'd0,
RDDATA = 2'd1,
ADDR_BITS = 6;
//------------------------Local signal-------------------
reg [1:0] wstate = WRIDLE;
reg [1:0] wnext;
reg [ADDR_BITS-1:0] waddr;
wire [31:0] wmask;
wire aw_hs;
wire w_hs;
reg [1:0] rstate = RDIDLE;
reg [1:0] rnext;
reg [31:0] rdata;
wire ar_hs;
wire [ADDR_BITS-1:0] raddr;
// internal registers
wire int_ap_idle;
wire int_ap_ready;
reg int_ap_done = 1'b0;
reg int_ap_start = 1'b0;
reg int_auto_restart = 1'b0;
reg int_gie = 2'b0;
reg [1:0] int_ier = 2'b0;
reg [1:0] int_isr = 2'b0;
reg [63:0] int_a = 64'b0;
reg [63:0] int_b = 64'b0;
reg [63:0] int_c = 64'b0;
reg [31:0] int_length_r = 32'b0;
//------------------------Instantiation------------------
//------------------------AXI write fsm------------------
assign AWREADY = (~ARESET) & (wstate == WRIDLE);
assign WREADY = (wstate == WRDATA);
assign BRESP = 2'b00; // OKAY
assign BVALID = (wstate == WRRESP);
assign wmask = { {8{WSTRB[3]}}, {8{WSTRB[2]}}, {8{WSTRB[1]}}, {8{WSTRB[0]}} };
assign aw_hs = AWVALID & AWREADY;
assign w_hs = WVALID & WREADY;
// wstate
always @(posedge ACLK) begin
if (ARESET)
wstate <= WRIDLE;
else if (ACLK_EN)
wstate <= wnext;
end
// wnext
always @(*) begin
case (wstate)
WRIDLE:
if (AWVALID)
wnext = WRDATA;
else
wnext = WRIDLE;
WRDATA:
if (WVALID)
wnext = WRRESP;
else
wnext = WRDATA;
WRRESP:
if (BREADY)
wnext = WRIDLE;
else
wnext = WRRESP;
default:
wnext = WRIDLE;
endcase
end
// waddr
always @(posedge ACLK) begin
if (ACLK_EN) begin
if (aw_hs)
waddr <= AWADDR[ADDR_BITS-1:0];
end
end
//------------------------AXI read fsm-------------------
assign ARREADY = (~ARESET) && (rstate == RDIDLE);
assign RDATA = rdata;
assign RRESP = 2'b00; // OKAY
assign RVALID = (rstate == RDDATA);
assign ar_hs = ARVALID & ARREADY;
assign raddr = ARADDR[ADDR_BITS-1:0];
// rstate
always @(posedge ACLK) begin
if (ARESET)
rstate <= RDIDLE;
else if (ACLK_EN)
rstate <= rnext;
end
// rnext
always @(*) begin
case (rstate)
RDIDLE:
if (ARVALID)
rnext = RDDATA;
else
rnext = RDIDLE;
RDDATA:
if (RREADY & RVALID)
rnext = RDIDLE;
else
rnext = RDDATA;
default:
rnext = RDIDLE;
endcase
end
// rdata
always @(posedge ACLK) begin
if (ACLK_EN) begin
if (ar_hs) begin
rdata <= 1'b0;
case (raddr)
ADDR_AP_CTRL: begin
rdata[0] <= int_ap_start;
rdata[1] <= int_ap_done;
rdata[2] <= int_ap_idle;
rdata[3] <= int_ap_ready;
rdata[7] <= int_auto_restart;
end
ADDR_GIE: begin
rdata <= int_gie;
end
ADDR_IER: begin
rdata <= int_ier;
end
ADDR_ISR: begin
rdata <= int_isr;
end
ADDR_A_DATA_0: begin
rdata <= int_a[31:0];
end
ADDR_A_DATA_1: begin
rdata <= int_a[63:32];
end
ADDR_B_DATA_0: begin
rdata <= int_b[31:0];
end
ADDR_B_DATA_1: begin
rdata <= int_b[63:32];
end
ADDR_C_DATA_0: begin
rdata <= int_c[31:0];
end
ADDR_C_DATA_1: begin
rdata <= int_c[63:32];
end
ADDR_LENGTH_R_DATA_0: begin
rdata <= int_length_r[31:0];
end
endcase
end
end
end
//------------------------Register logic-----------------
assign interrupt = int_gie & (|int_isr);
assign ap_start = int_ap_start;
assign int_ap_idle = ap_idle;
assign int_ap_ready = ap_ready;
assign a = int_a;
assign b = int_b;
assign c = int_c;
assign length_r = int_length_r;
// int_ap_start
always @(posedge ACLK) begin
if (ARESET)
int_ap_start <= 1'b0;
else if (ACLK_EN) begin
if (w_hs && waddr == ADDR_AP_CTRL && WSTRB[0] && WDATA[0])
int_ap_start <= 1'b1;
else if (int_ap_ready)
int_ap_start <= int_auto_restart; // clear on handshake/auto restart
end
end
// int_ap_done
always @(posedge ACLK) begin
if (ARESET)
int_ap_done <= 1'b0;
else if (ACLK_EN) begin
if (ap_done)
int_ap_done <= 1'b1;
else if (ar_hs && raddr == ADDR_AP_CTRL)
int_ap_done <= 1'b0; // clear on read
end
end
// int_auto_restart
always @(posedge ACLK) begin
if (ARESET)
int_auto_restart <= 1'b0;
else if (ACLK_EN) begin
if (w_hs && waddr == ADDR_AP_CTRL && WSTRB[0])
int_auto_restart <= WDATA[7];
end
end
// int_gie
always @(posedge ACLK) begin
if (ARESET)
int_gie <= 1'b0;
else if (ACLK_EN) begin
if (w_hs && waddr == ADDR_GIE && WSTRB[0])
int_gie <= WDATA[0];
end
end
// int_ier
always @(posedge ACLK) begin
if (ARESET)
int_ier <= 1'b0;
else if (ACLK_EN) begin
if (w_hs && waddr == ADDR_IER && WSTRB[0])
int_ier <= WDATA[1:0];
end
end
// int_isr[0]
always @(posedge ACLK) begin
if (ARESET)
int_isr[0] <= 1'b0;
else if (ACLK_EN) begin
if (int_ier[0] & ap_done)
int_isr[0] <= 1'b1;
else if (w_hs && waddr == ADDR_ISR && WSTRB[0])
int_isr[0] <= int_isr[0] ^ WDATA[0]; // toggle on write
end
end
// int_isr[1]
always @(posedge ACLK) begin
if (ARESET)
int_isr[1] <= 1'b0;
else if (ACLK_EN) begin
if (int_ier[1] & ap_ready)
int_isr[1] <= 1'b1;
else if (w_hs && waddr == ADDR_ISR && WSTRB[0])
int_isr[1] <= int_isr[1] ^ WDATA[1]; // toggle on write
end
end
// int_a[31:0]
always @(posedge ACLK) begin
if (ARESET)
int_a[31:0] <= 0;
else if (ACLK_EN) begin
if (w_hs && waddr == ADDR_A_DATA_0)
int_a[31:0] <= (WDATA[31:0] & wmask) | (int_a[31:0] & ~wmask);
end
end
// int_a[63:32]
always @(posedge ACLK) begin
if (ARESET)
int_a[63:32] <= 0;
else if (ACLK_EN) begin
if (w_hs && waddr == ADDR_A_DATA_1)
int_a[63:32] <= (WDATA[31:0] & wmask) | (int_a[63:32] & ~wmask);
end
end
// int_b[31:0]
always @(posedge ACLK) begin
if (ARESET)
int_b[31:0] <= 0;
else if (ACLK_EN) begin
if (w_hs && waddr == ADDR_B_DATA_0)
int_b[31:0] <= (WDATA[31:0] & wmask) | (int_b[31:0] & ~wmask);
end
end
// int_b[63:32]
always @(posedge ACLK) begin
if (ARESET)
int_b[63:32] <= 0;
else if (ACLK_EN) begin
if (w_hs && waddr == ADDR_B_DATA_1)
int_b[63:32] <= (WDATA[31:0] & wmask) | (int_b[63:32] & ~wmask);
end
end
// int_c[31:0]
always @(posedge ACLK) begin
if (ARESET)
int_c[31:0] <= 0;
else if (ACLK_EN) begin
if (w_hs && waddr == ADDR_C_DATA_0)
int_c[31:0] <= (WDATA[31:0] & wmask) | (int_c[31:0] & ~wmask);
end
end
// int_c[63:32]
always @(posedge ACLK) begin
if (ARESET)
int_c[63:32] <= 0;
else if (ACLK_EN) begin
if (w_hs && waddr == ADDR_C_DATA_1)
int_c[63:32] <= (WDATA[31:0] & wmask) | (int_c[63:32] & ~wmask);
end
end
// int_length_r[31:0]
always @(posedge ACLK) begin
if (ARESET)
int_length_r[31:0] <= 0;
else if (ACLK_EN) begin
if (w_hs && waddr == ADDR_LENGTH_R_DATA_0)
int_length_r[31:0] <= (WDATA[31:0] & wmask) | (int_length_r[31:0] & ~wmask);
end
end
//------------------------Memory logic-------------------
endmodule

View file

@ -1,87 +0,0 @@
/**
* Copyright (C) 2019-2021 Xilinx, Inc
*
* Licensed under the Apache License, Version 2.0 (the "License"). You may
* not use this file except in compliance with the License. A copy of the
* License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
//-----------------------------------------------------------------------------
// Simple up/down counter with reset.
//-----------------------------------------------------------------------------
`default_nettype none
`timescale 1ps/1ps
module krnl_vadd_rtl_counter #(
parameter integer C_WIDTH = 4,
parameter [C_WIDTH-1:0] C_INIT = {C_WIDTH{1'b0}}
)
(
input wire clk,
input wire clken,
input wire rst,
input wire load,
input wire incr,
input wire decr,
input wire [C_WIDTH-1:0] load_value,
output wire [C_WIDTH-1:0] count,
output wire is_zero
);
localparam [C_WIDTH-1:0] LP_ZERO = {C_WIDTH{1'b0}};
localparam [C_WIDTH-1:0] LP_ONE = {{C_WIDTH-1{1'b0}},1'b1};
localparam [C_WIDTH-1:0] LP_MAX = {C_WIDTH{1'b1}};
reg [C_WIDTH-1:0] count_r = C_INIT;
reg is_zero_r = (C_INIT == LP_ZERO);
assign count = count_r;
always @(posedge clk) begin
if (rst) begin
count_r <= C_INIT;
end
else if (clken) begin
if (load) begin
count_r <= load_value;
end
else if (incr & ~decr) begin
count_r <= count_r + 1'b1;
end
else if (~incr & decr) begin
count_r <= count_r - 1'b1;
end
else
count_r <= count_r;
end
end
assign is_zero = is_zero_r;
always @(posedge clk) begin
if (rst) begin
is_zero_r <= (C_INIT == LP_ZERO);
end
else if (clken) begin
if (load) begin
is_zero_r <= (load_value == LP_ZERO);
end
else begin
is_zero_r <= incr ^ decr ? (decr && (count_r == LP_ONE)) || (incr && (count_r == LP_MAX)) : is_zero_r;
end
end
else begin
is_zero_r <= is_zero_r;
end
end
endmodule : krnl_vadd_rtl_counter
`default_nettype wire

View file

@ -1,418 +0,0 @@
/**
* Copyright (C) 2019-2021 Xilinx, Inc
*
* Licensed under the Apache License, Version 2.0 (the "License"). You may
* not use this file except in compliance with the License. A copy of the
* License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
///////////////////////////////////////////////////////////////////////////////
// Description: This is a example of how to create an RTL Kernel. The function
// of this module is to add two 32-bit values and produce a result. The values
// are read from one AXI4 memory mapped master, processed and then written out.
//
// Data flow: axi_read_master->fifo[2]->adder->fifo->axi_write_master
///////////////////////////////////////////////////////////////////////////////
// default_nettype of none prevents implicit wire declaration.
`default_nettype none
`timescale 1 ns / 1 ps
module krnl_vadd_rtl_int #(
parameter integer C_S_AXI_CTRL_DATA_WIDTH = 32,
parameter integer C_S_AXI_CTRL_ADDR_WIDTH = 6,
parameter integer C_M_AXI_MEM_ID_WIDTH = 1,
parameter integer C_M_AXI_MEM_ADDR_WIDTH = 32,
parameter integer C_M_AXI_MEM_DATA_WIDTH = 32
)
(
// System signals
input wire ap_clk,
input wire ap_rst_n,
// AXI4 master interface
output wire m_axi_mem_awvalid,
input wire m_axi_mem_awready,
output wire [C_M_AXI_MEM_ADDR_WIDTH-1:0] m_axi_mem_awaddr,
output wire [C_M_AXI_MEM_ID_WIDTH - 1:0] m_axi_mem_awid,
output wire [7:0] m_axi_mem_awlen,
output wire [2:0] m_axi_mem_awsize,
output wire [1:0] m_axi_mem_awburst,
output wire [1:0] m_axi_mem_awlock,
output wire [3:0] m_axi_mem_awcache,
output wire [2:0] m_axi_mem_awprot,
output wire [3:0] m_axi_mem_awqos,
output wire [3:0] m_axi_mem_awregion,
output wire m_axi_mem_wvalid,
input wire m_axi_mem_wready,
output wire [C_M_AXI_MEM_DATA_WIDTH-1:0] m_axi_mem_wdata,
output wire [C_M_AXI_MEM_DATA_WIDTH/8-1:0] m_axi_mem_wstrb,
output wire m_axi_mem_wlast,
input wire m_axi_mem_bvalid,
output wire m_axi_mem_bready,
input wire [1:0] m_axi_mem_bresp,
input wire [C_M_AXI_MEM_ID_WIDTH - 1:0] m_axi_mem_bid,
output wire m_axi_mem_arvalid,
input wire m_axi_mem_arready,
output wire [C_M_AXI_MEM_ADDR_WIDTH-1:0] m_axi_mem_araddr,
output wire [C_M_AXI_MEM_ID_WIDTH-1:0] m_axi_mem_arid,
output wire [7:0] m_axi_mem_arlen,
output wire [2:0] m_axi_mem_arsize,
output wire [1:0] m_axi_mem_arburst,
output wire [1:0] m_axi_mem_arlock,
output wire [3:0] m_axi_mem_arcache,
output wire [2:0] m_axi_mem_arprot,
output wire [3:0] m_axi_mem_arqos,
output wire [3:0] m_axi_mem_arregion,
input wire m_axi_mem_rvalid,
output wire m_axi_mem_rready,
input wire [C_M_AXI_MEM_DATA_WIDTH - 1:0] m_axi_mem_rdata,
input wire m_axi_mem_rlast,
input wire [C_M_AXI_MEM_ID_WIDTH - 1:0] m_axi_mem_rid,
input wire [1:0] m_axi_mem_rresp,
// AXI4-Lite slave interface
input wire s_axi_ctrl_awvalid,
output wire s_axi_ctrl_awready,
input wire [C_S_AXI_CTRL_ADDR_WIDTH-1:0] s_axi_ctrl_awaddr,
input wire s_axi_ctrl_wvalid,
output wire s_axi_ctrl_wready,
input wire [C_S_AXI_CTRL_DATA_WIDTH-1:0] s_axi_ctrl_wdata,
input wire [C_S_AXI_CTRL_DATA_WIDTH/8-1:0] s_axi_ctrl_wstrb,
input wire s_axi_ctrl_arvalid,
output wire s_axi_ctrl_arready,
input wire [C_S_AXI_CTRL_ADDR_WIDTH-1:0] s_axi_ctrl_araddr,
output wire s_axi_ctrl_rvalid,
input wire s_axi_ctrl_rready,
output wire [C_S_AXI_CTRL_DATA_WIDTH-1:0] s_axi_ctrl_rdata,
output wire [1:0] s_axi_ctrl_rresp,
output wire s_axi_ctrl_bvalid,
input wire s_axi_ctrl_bready,
output wire [1:0] s_axi_ctrl_bresp,
output wire interrupt
);
///////////////////////////////////////////////////////////////////////////////
// Local Parameters (constants)
///////////////////////////////////////////////////////////////////////////////
localparam integer LP_NUM_READ_CHANNELS = 2;
localparam integer LP_LENGTH_WIDTH = 32;
localparam integer LP_DW_BYTES = C_M_AXI_MEM_DATA_WIDTH/8;
localparam integer LP_AXI_BURST_LEN = 4096/LP_DW_BYTES < 256 ? 4096/LP_DW_BYTES : 256;
localparam integer LP_LOG_BURST_LEN = $clog2(LP_AXI_BURST_LEN);
localparam integer LP_RD_MAX_OUTSTANDING = 3;
localparam integer LP_RD_FIFO_DEPTH = LP_AXI_BURST_LEN*(LP_RD_MAX_OUTSTANDING + 1);
localparam integer LP_WR_FIFO_DEPTH = LP_AXI_BURST_LEN;
///////////////////////////////////////////////////////////////////////////////
// Variables
///////////////////////////////////////////////////////////////////////////////
logic areset = 1'b0;
logic ap_start;
logic ap_start_pulse;
logic ap_start_r;
logic ap_ready;
logic ap_done;
logic ap_idle = 1'b1;
logic [C_M_AXI_MEM_ADDR_WIDTH-1:0] a;
logic [C_M_AXI_MEM_ADDR_WIDTH-1:0] b;
logic [C_M_AXI_MEM_ADDR_WIDTH-1:0] c;
logic [LP_LENGTH_WIDTH-1:0] length_r;
logic read_done;
logic [LP_NUM_READ_CHANNELS-1:0] rd_tvalid;
logic [LP_NUM_READ_CHANNELS-1:0] rd_tready_n;
logic [LP_NUM_READ_CHANNELS-1:0] [C_M_AXI_MEM_DATA_WIDTH-1:0] rd_tdata;
logic [LP_NUM_READ_CHANNELS-1:0] ctrl_rd_fifo_prog_full;
logic [LP_NUM_READ_CHANNELS-1:0] rd_fifo_tvalid_n;
logic [LP_NUM_READ_CHANNELS-1:0] rd_fifo_tready;
logic [LP_NUM_READ_CHANNELS-1:0] [C_M_AXI_MEM_DATA_WIDTH-1:0] rd_fifo_tdata;
logic adder_tvalid;
logic adder_tready_n;
logic [C_M_AXI_MEM_DATA_WIDTH-1:0] adder_tdata;
logic wr_fifo_tvalid_n;
logic wr_fifo_tready;
logic [C_M_AXI_MEM_DATA_WIDTH-1:0] wr_fifo_tdata;
///////////////////////////////////////////////////////////////////////////////
// RTL Logic
///////////////////////////////////////////////////////////////////////////////
// Tie-off unused AXI protocol features
assign m_axi_mem_awid = {C_M_AXI_MEM_ID_WIDTH{1'b0}};
assign m_axi_mem_awburst = 2'b01;
assign m_axi_mem_awlock = 2'b00;
assign m_axi_mem_awcache = 4'b0000;
assign m_axi_mem_awprot = 3'b000;
assign m_axi_mem_awqos = 4'b0000;
assign m_axi_mem_awregion = 4'b0000;
assign m_axi_mem_arburst = 2'b01;
assign m_axi_mem_arlock = 2'b00;
assign m_axi_mem_arcache = 4'b0000;
assign m_axi_mem_arprot = 3'b000;
assign m_axi_mem_arqos = 4'b0000;
assign m_axi_mem_arregion = 4'b0000;
// Register and invert reset signal for better timing.
always @(posedge ap_clk) begin
areset <= ~ap_rst_n;
end
// create pulse when ap_start transitions to 1
always @(posedge ap_clk) begin
begin
ap_start_r <= ap_start;
end
end
assign ap_start_pulse = ap_start & ~ap_start_r;
// ap_idle is asserted when done is asserted, it is de-asserted when ap_start_pulse
// is asserted
always @(posedge ap_clk) begin
if (areset) begin
ap_idle <= 1'b1;
end
else begin
ap_idle <= ap_done ? 1'b1 :
ap_start_pulse ? 1'b0 :
ap_idle;
end
end
assign ap_ready = ap_done;
// AXI4-Lite slave
krnl_vadd_rtl_control_s_axi #(
.C_S_AXI_ADDR_WIDTH( C_S_AXI_CTRL_ADDR_WIDTH ),
.C_S_AXI_DATA_WIDTH( C_S_AXI_CTRL_DATA_WIDTH )
)
inst_krnl_vadd_control_s_axi (
.AWVALID ( s_axi_ctrl_awvalid ) ,
.AWREADY ( s_axi_ctrl_awready ) ,
.AWADDR ( s_axi_ctrl_awaddr ) ,
.WVALID ( s_axi_ctrl_wvalid ) ,
.WREADY ( s_axi_ctrl_wready ) ,
.WDATA ( s_axi_ctrl_wdata ) ,
.WSTRB ( s_axi_ctrl_wstrb ) ,
.ARVALID ( s_axi_ctrl_arvalid ) ,
.ARREADY ( s_axi_ctrl_arready ) ,
.ARADDR ( s_axi_ctrl_araddr ) ,
.RVALID ( s_axi_ctrl_rvalid ) ,
.RREADY ( s_axi_ctrl_rready ) ,
.RDATA ( s_axi_ctrl_rdata ) ,
.RRESP ( s_axi_ctrl_rresp ) ,
.BVALID ( s_axi_ctrl_bvalid ) ,
.BREADY ( s_axi_ctrl_bready ) ,
.BRESP ( s_axi_ctrl_bresp ) ,
.ACLK ( ap_clk ) ,
.ARESET ( areset ) ,
.ACLK_EN ( 1'b1 ) ,
.ap_start ( ap_start ) ,
.interrupt ( interrupt ) ,
.ap_ready ( ap_ready ) ,
.ap_done ( ap_done ) ,
.ap_idle ( ap_idle ) ,
.a ( a[0+:C_M_AXI_MEM_ADDR_WIDTH] ) ,
.b ( b[0+:C_M_AXI_MEM_ADDR_WIDTH] ) ,
.c ( c[0+:C_M_AXI_MEM_ADDR_WIDTH] ) ,
.length_r ( length_r[0+:LP_LENGTH_WIDTH] )
);
// AXI4 Read Master
krnl_vadd_rtl_axi_read_master #(
.C_ADDR_WIDTH ( C_M_AXI_MEM_ADDR_WIDTH ) ,
.C_DATA_WIDTH ( C_M_AXI_MEM_DATA_WIDTH ) ,
.C_ID_WIDTH ( C_M_AXI_MEM_ID_WIDTH ) ,
.C_NUM_CHANNELS ( LP_NUM_READ_CHANNELS ) ,
.C_LENGTH_WIDTH ( LP_LENGTH_WIDTH ) ,
.C_BURST_LEN ( LP_AXI_BURST_LEN ) ,
.C_LOG_BURST_LEN ( LP_LOG_BURST_LEN ) ,
.C_MAX_OUTSTANDING ( LP_RD_MAX_OUTSTANDING )
)
inst_axi_read_master (
.aclk ( ap_clk ) ,
.areset ( areset ) ,
.ctrl_start ( ap_start_pulse ) ,
.ctrl_done ( read_done ) ,
.ctrl_offset ( {b,a} ) ,
.ctrl_length ( length_r ) ,
.ctrl_prog_full ( ctrl_rd_fifo_prog_full ) ,
.arvalid ( m_axi_mem_arvalid ) ,
.arready ( m_axi_mem_arready ) ,
.araddr ( m_axi_mem_araddr ) ,
.arid ( m_axi_mem_arid ) ,
.arlen ( m_axi_mem_arlen ) ,
.arsize ( m_axi_mem_arsize ) ,
.rvalid ( m_axi_mem_rvalid ) ,
.rready ( m_axi_mem_rready ) ,
.rdata ( m_axi_mem_rdata ) ,
.rlast ( m_axi_mem_rlast ) ,
.rid ( m_axi_mem_rid ) ,
.rresp ( m_axi_mem_rresp ) ,
.m_tvalid ( rd_tvalid ) ,
.m_tready ( ~rd_tready_n ) ,
.m_tdata ( rd_tdata )
);
// xpm_fifo_sync: Synchronous FIFO
// Xilinx Parameterized Macro, Version 2016.4
xpm_fifo_sync # (
.FIFO_MEMORY_TYPE ("auto"), //string; "auto", "block", "distributed", or "ultra";
.ECC_MODE ("no_ecc"), //string; "no_ecc" or "en_ecc";
.FIFO_WRITE_DEPTH (LP_RD_FIFO_DEPTH), //positive integer
.WRITE_DATA_WIDTH (C_M_AXI_MEM_DATA_WIDTH), //positive integer
.WR_DATA_COUNT_WIDTH ($clog2(LP_RD_FIFO_DEPTH)+1), //positive integer, Not used
.PROG_FULL_THRESH (LP_AXI_BURST_LEN-2), //positive integer
.FULL_RESET_VALUE (1), //positive integer; 0 or 1
.READ_MODE ("fwft"), //string; "std" or "fwft";
.FIFO_READ_LATENCY (1), //positive integer;
.READ_DATA_WIDTH (C_M_AXI_MEM_DATA_WIDTH), //positive integer
.RD_DATA_COUNT_WIDTH ($clog2(LP_RD_FIFO_DEPTH)+1), //positive integer, not used
.PROG_EMPTY_THRESH (10), //positive integer, not used
.DOUT_RESET_VALUE ("0"), //string, don't care
.WAKEUP_TIME (0) //positive integer; 0 or 2;
) inst_rd_xpm_fifo_sync[LP_NUM_READ_CHANNELS-1:0] (
.sleep ( 1'b0 ) ,
.rst ( areset ) ,
.wr_clk ( ap_clk ) ,
.wr_en ( rd_tvalid ) ,
.din ( rd_tdata ) ,
.full ( rd_tready_n ) ,
.prog_full ( ctrl_rd_fifo_prog_full) ,
.wr_data_count ( ) ,
.overflow ( ) ,
.wr_rst_busy ( ) ,
.rd_en ( rd_fifo_tready ) ,
.dout ( rd_fifo_tdata ) ,
.empty ( rd_fifo_tvalid_n ) ,
.prog_empty ( ) ,
.rd_data_count ( ) ,
.underflow ( ) ,
.rd_rst_busy ( ) ,
.injectsbiterr ( 1'b0 ) ,
.injectdbiterr ( 1'b0 ) ,
.sbiterr ( ) ,
.dbiterr ( )
);
// Combinatorial Adder
krnl_vadd_rtl_adder #(
.C_DATA_WIDTH ( C_M_AXI_MEM_DATA_WIDTH ) ,
.C_NUM_CHANNELS ( LP_NUM_READ_CHANNELS )
)
inst_adder (
.aclk ( ap_clk ) ,
.areset ( areset ) ,
.s_tvalid ( ~rd_fifo_tvalid_n ) ,
.s_tready ( rd_fifo_tready ) ,
.s_tdata ( rd_fifo_tdata ) ,
.m_tvalid ( adder_tvalid ) ,
.m_tready ( ~adder_tready_n ) ,
.m_tdata ( adder_tdata )
);
// xpm_fifo_sync: Synchronous FIFO
// Xilinx Parameterized Macro, Version 2016.4
xpm_fifo_sync # (
.FIFO_MEMORY_TYPE ("auto"), //string; "auto", "block", "distributed", or "ultra";
.ECC_MODE ("no_ecc"), //string; "no_ecc" or "en_ecc";
.FIFO_WRITE_DEPTH (LP_WR_FIFO_DEPTH), //positive integer
.WRITE_DATA_WIDTH (C_M_AXI_MEM_DATA_WIDTH), //positive integer
.WR_DATA_COUNT_WIDTH ($clog2(LP_WR_FIFO_DEPTH)), //positive integer, Not used
.PROG_FULL_THRESH (10), //positive integer, Not used
.FULL_RESET_VALUE (1), //positive integer; 0 or 1
.READ_MODE ("fwft"), //string; "std" or "fwft";
.FIFO_READ_LATENCY (1), //positive integer;
.READ_DATA_WIDTH (C_M_AXI_MEM_DATA_WIDTH), //positive integer
.RD_DATA_COUNT_WIDTH ($clog2(LP_WR_FIFO_DEPTH)), //positive integer, not used
.PROG_EMPTY_THRESH (10), //positive integer, not used
.DOUT_RESET_VALUE ("0"), //string, don't care
.WAKEUP_TIME (0) //positive integer; 0 or 2;
) inst_wr_xpm_fifo_sync (
.sleep ( 1'b0 ) ,
.rst ( areset ) ,
.wr_clk ( ap_clk ) ,
.wr_en ( adder_tvalid ) ,
.din ( adder_tdata ) ,
.full ( adder_tready_n ) ,
.prog_full ( ) ,
.wr_data_count ( ) ,
.overflow ( ) ,
.wr_rst_busy ( ) ,
.rd_en ( wr_fifo_tready ) ,
.dout ( wr_fifo_tdata ) ,
.empty ( wr_fifo_tvalid_n ) ,
.prog_empty ( ) ,
.rd_data_count ( ) ,
.underflow ( ) ,
.rd_rst_busy ( ) ,
.injectsbiterr ( 1'b0 ) ,
.injectdbiterr ( 1'b0 ) ,
.sbiterr ( ) ,
.dbiterr ( )
);
// AXI4 Write Master
krnl_vadd_rtl_axi_write_master #(
.C_ADDR_WIDTH ( C_M_AXI_MEM_ADDR_WIDTH ) ,
.C_DATA_WIDTH ( C_M_AXI_MEM_DATA_WIDTH ) ,
.C_MAX_LENGTH_WIDTH ( LP_LENGTH_WIDTH ) ,
.C_BURST_LEN ( LP_AXI_BURST_LEN ) ,
.C_LOG_BURST_LEN ( LP_LOG_BURST_LEN )
)
inst_axi_write_master (
.aclk ( ap_clk ) ,
.areset ( areset ) ,
.ctrl_start ( ap_start_pulse ) ,
.ctrl_offset ( c ) ,
.ctrl_length ( length_r ) ,
.ctrl_done ( ap_done ) ,
.awvalid ( m_axi_mem_awvalid ) ,
.awready ( m_axi_mem_awready ) ,
.awaddr ( m_axi_mem_awaddr ) ,
.awlen ( m_axi_mem_awlen ) ,
.awsize ( m_axi_mem_awsize ) ,
.s_tvalid ( ~wr_fifo_tvalid_n ) ,
.s_tready ( wr_fifo_tready ) ,
.s_tdata ( wr_fifo_tdata ) ,
.wvalid ( m_axi_mem_wvalid ) ,
.wready ( m_axi_mem_wready ) ,
.wdata ( m_axi_mem_wdata ) ,
.wstrb ( m_axi_mem_wstrb ) ,
.wlast ( m_axi_mem_wlast ) ,
.bvalid ( m_axi_mem_bvalid ) ,
.bready ( m_axi_mem_bready ) ,
.bresp ( m_axi_mem_bresp )
);
endmodule : krnl_vadd_rtl_int
`default_nettype wire

View file

@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<root versionMajor="1" versionMinor="6">
<kernel name="krnl_vadd_rtl" language="ip_c" vlnv="xilinx.com:RTLKernel:krnl_vadd_rtl:1.0" attributes="" preferredWorkGroupSizeMultiple="0" workGroupSize="1" interrupt="true" hwControlProtocol="user_managed">
<ports>
<port name="s_axi_ctrl" mode="slave" range="0x1000" dataWidth="32" portType="addressable" base="0x0"/>
<port name="m_axi_mem" mode="master" range="0xFFFFFFFF" dataWidth="32" portType="addressable" base="0x0"/>
</ports>
<args>
<arg id="0" name="a" addressQualifier="1" port="m_axi_mem" size="0x8" offset="0x010" type="void*" hostOffset="0x0" hostSize="0x8"/>
<arg id="1" name="b" addressQualifier="1" port="m_axi_mem" size="0x8" offset="0x01C" type="void*" hostOffset="0x0" hostSize="0x8"/>
<arg id="2" name="c" addressQualifier="1" port="m_axi_mem" size="0x8" offset="0x028" type="void*" hostOffset="0x0" hostSize="0x8"/>
<arg id="3" name="l" addressQualifier="0" port="s_axi_ctrl" size="0x4" offset="0x034" type="uint" hostOffset="0x0" hostSize="0x4"/>
</args>
</kernel>
</root>

View file

@ -1,46 +0,0 @@
#!/bin/bash
exclude_list="VX_fpu_fpnew.sv"
macros=()
includes=()
# parse command arguments
while getopts D:I:h flag
do
case "${flag}" in
D) macros+=( ${OPTARG} );;
I) includes+=( ${OPTARG} );;
h) echo "Usage: [-D macro] [-I include] [-h help]"
exit 0
;;
\?)
echo "Invalid option: -$OPTARG" 1>&2
exit 1
;;
esac
done
# dump macros
for value in ${macros[@]}; do
echo "+define+$value"
done
# dump include directories
for dir in ${includes[@]}; do
echo "+incdir+$dir"
done
# dump source files
for dir in ${includes[@]}; do
for file in $(find $dir -maxdepth 1 -name '*.v' -o -name '*.sv' -type f); do
exclude=0
for fe in $exclude_list; do
if [[ $file =~ $fe ]]; then
exclude=1
fi
done
if [[ $exclude == 0 ]]; then
echo $file
fi
done
done

View file

@ -1,23 +0,0 @@
if { $::argc != 5 } {
puts "ERROR: Program \"$::argv0\" requires 5 arguments!\n"
puts "Usage: $::argv0 <xoname> <krnl_name> <vcs_file> <kernel_xml> <build_dir>\n"
exit
}
set xoname [lindex $::argv 0]
set krnl_name [lindex $::argv 1]
set vcs_file [lindex $::argv 2]
set krnl_xml [lindex $::argv 3]
set build_dir [lindex $::argv 4]
set script_path [ file dirname [ file normalize [ info script ] ] ]
if {[file exists "${xoname}"]} {
file delete -force "${xoname}"
}
set argv [list ${krnl_name} ${build_dir}]
set argc 2
source ${script_path}/package_kernel.tcl
package_xo -xo_path ${xoname} -kernel_name ${krnl_name} -ip_directory "${build_dir}/xo/packaged_kernel" -kernel_xml ${krnl_xml}

View file

@ -1,125 +0,0 @@
if { $::argc != 2 } {
puts "ERROR: Program \"$::argv0\" requires 2 arguments!\n"
puts "Usage: $::argv0 <krnl_name> <build_dir>\n"
exit
}
set krnl_name [lindex $::argv 0]
set build_dir [lindex $::argv 1]
set script_path [ file dirname [ file normalize [ info script ] ] ]
set path_to_packaged "${build_dir}/xo/packaged_kernel"
set path_to_tmp_project "${build_dir}/xo/project"
source "${script_path}/parse_vcs_list.tcl"
set vlist [parse_vcs_list "${vcs_file}"]
set vsources_list [lindex $vlist 0]
set vincludes_list [lindex $vlist 1]
set vdefines_list [lindex $vlist 2]
#puts ${vsources_list}
#puts ${vdefines_list}
# dump defines into globals.vh
set chipscope 0
set fh [open "${build_dir}/globals.vh" w]
foreach def $vdefines_list {
set fields [split $def "="]
set len [llength $fields]
set name [lindex $fields 0]
puts -nonewline $fh "`define "
if {$len > 1} {
set value [lindex $fields 1]
puts -nonewline $fh $name
puts -nonewline $fh " "
puts $fh $value
} else {
puts $fh $name
if { $name == "CHIPSCOPE" } {
set chipscope 1
}
}
}
close $fh
create_project -force kernel_pack $path_to_tmp_project
add_files -norecurse ${vsources_list}
set obj [get_filesets sources_1]
set files [list \
[file normalize "${build_dir}/globals.vh"] \
]
add_files -verbose -norecurse -fileset $obj $files
set_property include_dirs ${vincludes_list} [current_fileset]
#set_property verilog_define ${vdefines_list} [current_fileset]
set obj [get_filesets sources_1]
set_property -verbose -name "top" -value ${krnl_name} -objects $obj
if { $chipscope == 1 } {
# hw debugging
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} \
CONFIG.C_NUM_OF_PROBES {3} \
CONFIG.C_DATA_DEPTH {8192} \
CONFIG.C_PROBE0_WIDTH {584} \
CONFIG.C_PROBE1_WIDTH {16} \
CONFIG.C_PROBE2_WIDTH {64} \
] [get_ips ila_afu]
generate_target {instantiation_template} [get_files ila_afu.xci]
set_property generate_synth_checkpoint false [get_files ila_afu.xci]
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} \
CONFIG.C_NUM_OF_PROBES {5} \
CONFIG.C_DATA_DEPTH {8192} \
CONFIG.C_PROBE0_WIDTH {128} \
CONFIG.C_PROBE1_WIDTH {128} \
CONFIG.C_PROBE2_WIDTH {128} \
CONFIG.C_PROBE3_WIDTH {544} \
CONFIG.C_PROBE4_WIDTH {128} \
] [get_ips ila_fetch]
generate_target {instantiation_template} [get_files ila_fetch.xci]
set_property generate_synth_checkpoint false [get_files ila_fetch.xci]
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} \
CONFIG.C_NUM_OF_PROBES {2} \
CONFIG.C_DATA_DEPTH {8192} \
CONFIG.C_PROBE0_WIDTH {128} \
CONFIG.C_PROBE1_WIDTH {128} \
] [get_ips ila_issue]
generate_target {instantiation_template} [get_files ila_issue.xci]
set_property generate_synth_checkpoint false [get_files ila_issue.xci]
}
update_compile_order -fileset sources_1
update_compile_order -fileset sim_1
ipx::package_project -root_dir $path_to_packaged -vendor xilinx.com -library RTLKernel -taxonomy /KernelIP -import_files -set_current false
ipx::unload_core $path_to_packaged/component.xml
ipx::edit_ip_in_project -upgrade true -name tmp_edit_project -directory $path_to_packaged $path_to_packaged/component.xml
set core [ipx::current_core]
set_property core_revision 2 $core
foreach up [ipx::get_user_parameters] {
ipx::remove_user_parameter [get_property NAME $up] $core
}
ipx::associate_bus_interfaces -busif s_axi_ctrl -clock ap_clk $core
ipx::associate_bus_interfaces -busif m_axi_mem -clock ap_clk $core
set_property xpm_libraries {XPM_CDC XPM_MEMORY XPM_FIFO} $core
set_property sdx_kernel true $core
set_property sdx_kernel_type rtl $core
set_property supported_families { } $core
set_property auto_family_support_level level_2 $core
ipx::create_xgui_files $core
ipx::update_checksums $core
ipx::check_integrity -kernel $core
ipx::save_core $core
close_project -delete

View file

@ -1,33 +0,0 @@
proc parse_vcs_list {flist_path} {
set f [split [string trim [read [open $flist_path r]]] "\n"]
set flist [list ]
set dir_list [list ]
set def_list [list ]
foreach x $f {
if {![string match "" $x]} {
# If the item starts with +incdir+, directory files need to be added
if {[string match "#*" $x]} {
# get rid of comment line
} elseif {[string match "+incdir+*" $x]} {
set trimchars "+incdir+"
set temp [string trimleft $x $trimchars]
set expanded [subst $temp]
lappend dir_list $expanded
} elseif {[string match "+define+*" $x]} {
set trimchars "+define+"
set temp [string trimleft $x $trimchars]
set expanded [subst $temp]
lappend def_list $expanded
} else {
set expanded [subst $x]
lappend flist $expanded
}
}
}
#puts $flist
#puts $dir_list
#puts $def_list
return [list $flist $dir_list $def_list]
}

View file

@ -1,19 +0,0 @@
#
# Copyright 2021 Xilinx, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
log_wave -r *
run all
exit

View file

@ -1,348 +0,0 @@
/**
* Copyright (C) 2019-2021 Xilinx, Inc
*
* Licensed under the Apache License, Version 2.0 (the "License"). You may
* not use this file except in compliance with the License. A copy of the
* License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
#include "cmdlineparser.h"
#include "logger.h"
#include <assert.h>
#include <fstream>
#include <iostream>
#include <stdlib.h>
namespace sda {
namespace utils {
bool is_file(const std::string& name) {
ifstream f(name.c_str());
if (f.good()) {
f.close();
return true;
} else {
f.close();
return false;
}
}
bool is_number(const std::string& s) {
std::string::const_iterator it = s.begin();
while (it != s.end() && std::isdigit(*it)) ++it;
return !s.empty() && it == s.end();
}
bool starts_with(const string& src, const string& sub) {
return (src.find(sub) == 0);
}
CmdLineParser::CmdLineParser() {
// TODO Auto-generated constructor stub
m_strDefaultKey = "";
m_appname = "application.exe";
addSwitch("--help", "-h", "prints this help list", "", true);
}
/*
CmdLineParser::CmdLineParser(int argc, char* argv[]) {
// TODO Auto-generated constructor stub
assert(parse(argc, argv) > 0);
}
*/
CmdLineParser::~CmdLineParser() {
// TODO Auto-generated destructor stub
for (size_t i = 0; i < m_vSwitches.size(); i++) {
delete m_vSwitches[i];
m_vSwitches[i] = nullptr;
}
m_vSwitches.resize(0);
}
bool CmdLineParser::addSwitch(const CmdSwitch& s) {
CmdSwitch cmd = s;
if (cmd.desc.length() == 0) {
LogError("No description provided!");
return false;
}
// check input
if (cmd.key.find("--") != 0 || cmd.key.length() < 3) {
LogError(
"The input key is invalid. Please start with -- and keep a "
"length >= 3");
return false;
}
if (m_mapKeySwitch.find(cmd.key) != m_mapKeySwitch.end()) {
LogError("This key %s is taken already!", cmd.key.c_str());
return false;
}
if (cmd.shortcut.length() == 0) {
string temp = "-" + cmd.key[2];
int i = 3;
while (m_mapShortcutKeys.find(temp) != m_mapShortcutKeys.end() && (size_t)i < cmd.key.length()) {
temp = "-" + s.key[i];
i++;
}
cmd.shortcut = temp;
LogInfo("Automatic shortcut assigned %s to %s", temp.c_str(), cmd.key.c_str());
}
if (s.istoggle) {
cmd.default_value = string("false");
cmd.value = cmd.default_value;
cmd.isvalid = true;
} else {
cmd.value = cmd.default_value;
cmd.isvalid = false;
}
// add
CmdSwitch* pcmd = new CmdSwitch(cmd);
m_vSwitches.push_back(pcmd);
m_mapShortcutKeys[s.shortcut] = cmd.key;
m_mapKeySwitch[s.key] = pcmd;
return true;
}
bool CmdLineParser::addSwitch(
const string& name, const string& shortcut, const string& desc, const string& default_value, bool istoggle) {
CmdSwitch s;
s.key = name;
s.shortcut = shortcut;
s.desc = desc;
s.default_value = default_value;
s.istoggle = istoggle;
return addSwitch(s);
}
bool CmdLineParser::setDefaultKey(const char* key) {
string strKey(key);
if (!starts_with(strKey, "--")) strKey = "--" + strKey;
if (m_mapKeySwitch.find(strKey) != m_mapKeySwitch.end()) {
CmdSwitch* pcmd = m_mapKeySwitch[m_strDefaultKey];
if (pcmd != nullptr) {
if (pcmd->istoggle) {
LogError(
"Boolean command line options can not be used as "
"default keys");
return false;
}
}
// set default key
m_strDefaultKey = strKey;
return true;
} else
return false;
}
int CmdLineParser::parse(int argc, char* argv[]) {
int i = 0;
int ctOptions = 0;
while (i < argc) {
string key, val;
bool iskey = false;
string token = string(argv[i]);
bool isNextTokenKey = false;
if (i + 1 < argc) {
string peeknext = string(argv[i + 1]);
if (starts_with(peeknext, "-") || starts_with(peeknext, "--")) {
string fullkey;
isNextTokenKey = token_to_fullkeyname(peeknext, fullkey);
}
}
// full-key
if (starts_with(token, string("--"))) {
if (m_mapKeySwitch.find(token) == m_mapKeySwitch.end()) {
LogError("Unrecognized key passed %s", token.c_str());
printHelp();
return -1;
}
key = token;
iskey = true;
}
// shortcut
else if (starts_with(token, "-")) {
if (m_mapShortcutKeys.find(token) == m_mapShortcutKeys.end()) {
LogError("Unrecognized shortcut key passed %s", token.c_str());
printHelp();
return -1;
}
key = m_mapShortcutKeys[token];
iskey = true;
}
// default key, the value for default key is the last argument
else if (isNextTokenKey == false && m_strDefaultKey.length() > 0 && i == argc - 2) {
if (m_mapKeySwitch.find(m_strDefaultKey) == m_mapKeySwitch.end()) {
LogError("Unrecognized default key %s", m_strDefaultKey.c_str());
printHelp();
return -1;
}
LogInfo("Using default key: %s", m_strDefaultKey.c_str());
key = m_strDefaultKey;
iskey = true;
}
// if iskey and needs param then read it
if (iskey) {
ctOptions++;
if (key == "--help") {
printHelp();
return 1;
}
// fetch value
CmdSwitch* pcmd = m_mapKeySwitch[key];
// read next
if (pcmd->istoggle) {
pcmd->value = string("true");
pcmd->isvalid = true;
} else {
i++;
pcmd->value = string(argv[i]);
pcmd->isvalid = true;
}
}
// next token
i++;
}
// capture real app name
if (argc > 0) {
m_appname = string(argv[0]);
}
return ctOptions;
}
bool CmdLineParser::token_to_fullkeyname(const string& token, string& fullkey) {
fullkey = "";
int ctDashes = 0;
if (starts_with(token, string("--")))
ctDashes = 2;
else if (starts_with(token, string("-")))
ctDashes = 1;
if (ctDashes == 0) return false;
if (ctDashes == 2) {
if (m_mapKeySwitch.find(token) == m_mapKeySwitch.end()) {
LogError("Unrecognized key passed %s", token.c_str());
return false;
}
fullkey = token;
} else if (ctDashes == 1) {
if (m_mapShortcutKeys.find(token) == m_mapShortcutKeys.end()) {
LogError("Unrecognized shortcut key passed %s", token.c_str());
return false;
}
fullkey = m_mapShortcutKeys[token];
}
return (fullkey.length() > 0);
}
string CmdLineParser::value(const char* key) {
string strKey(key);
if (!starts_with(strKey, "--")) strKey = "--" + strKey;
if (m_mapKeySwitch.find(strKey) != m_mapKeySwitch.end())
return m_mapKeySwitch[strKey]->value;
else {
LogWarn("The input key %s is not recognized!", strKey.c_str());
return string("");
}
}
bool CmdLineParser::value_to_bool(const char* key) {
string strVal = value(key);
if (strVal == "true") return true;
return false;
}
int CmdLineParser::value_to_int(const char* key) {
string strVal = value(key);
if (strVal.length() == 0 || !is_number(strVal)) return -1;
return atoi(strVal.c_str());
}
double CmdLineParser::value_to_double(const char* key) {
string strVal = value(key);
if (strVal.length() == 0) return -1;
return atof(strVal.c_str());
}
bool CmdLineParser::isValid(const char* key) {
string strKey(key);
if (!starts_with(strKey, "--")) strKey = "--" + strKey;
if (m_mapKeySwitch.find(strKey) != m_mapKeySwitch.end())
return m_mapKeySwitch[strKey]->isvalid;
else {
LogWarn("The input key %s is not recognized!", strKey.c_str());
return false;
}
}
void CmdLineParser::printHelp() {
printf("===========================================================\n");
string strAllShortcuts = "";
for (size_t i = 0; i < m_vSwitches.size(); i++) {
CmdSwitch* pcmd = m_vSwitches[i];
if (pcmd && pcmd->shortcut.length() > 0) strAllShortcuts = strAllShortcuts + pcmd->shortcut;
}
// example
printf("Usage: %s -[%s]\n\n", m_appname.c_str(), strAllShortcuts.c_str());
// row by row
for (size_t i = 0; i < m_vSwitches.size(); i++) {
CmdSwitch* pcmd = m_vSwitches[i];
if (pcmd->default_value.length() > 0)
printf("\t%s, %s\t\t%s\t Default: [%s]\n", pcmd->key.c_str(), pcmd->shortcut.c_str(), pcmd->desc.c_str(),
pcmd->default_value.c_str());
else
printf("\t%s, %s\t\t%s\n", pcmd->key.c_str(), pcmd->shortcut.c_str(), pcmd->desc.c_str());
}
}
CmdLineParser::CmdSwitch* CmdLineParser::getCmdSwitch(const char* key) {
string strKey(key);
if (!starts_with(strKey, "--")) strKey = "--" + strKey;
if (m_mapKeySwitch.find(strKey) != m_mapKeySwitch.end())
return m_mapKeySwitch[strKey];
else
return nullptr;
}
} // namespace utils
} // namespace sda

View file

@ -1,110 +0,0 @@
/**
* Copyright (C) 2019-2021 Xilinx, Inc
*
* Licensed under the Apache License, Version 2.0 (the "License"). You may
* not use this file except in compliance with the License. A copy of the
* License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
#ifndef CMDLINEPARSER_H_
#define CMDLINEPARSER_H_
#include <map>
#include <string>
#include <vector>
namespace sda {
namespace utils {
bool is_file(const std::string& name);
/*!
* Synopsis:
* 1.Parses the command line passed in from the user and stores all enabled
* system options.
* 2.Prints help for the user if an option is not valid.
* 3.Stores options and provides a mechanism to read those options
*/
class CmdLineParser {
public:
class CmdSwitch {
public:
std::string key;
std::string shortcut;
std::string default_value;
std::string value;
std::string desc;
bool istoggle;
bool isvalid;
};
public:
CmdLineParser();
// CmdLineParser(int argc, char* argv[]);
virtual ~CmdLineParser();
bool addSwitch(const CmdSwitch& s);
bool addSwitch(const std::string& name,
const std::string& shortcut,
const std::string& desc,
const std::string& default_value = "",
bool istoggle = false);
/*!
* sets default key to be able to read a 2 argumented call
*/
bool setDefaultKey(const char* key);
/*!
* parse and store command line
*/
int parse(int argc, char* argv[]);
/*!
* retrieve value using a key
*/
std::string value(const char* key);
bool value_to_bool(const char* key);
int value_to_int(const char* key);
double value_to_double(const char* key);
/*!
* Returns true if a valid value is supplied by user
*/
bool isValid(const char* key);
/*!
* prints the help menu in case the options are not correct.
*/
virtual void printHelp();
protected:
/*!
* Retrieve command switch
*/
CmdSwitch* getCmdSwitch(const char* key);
bool token_to_fullkeyname(const std::string& token, std::string& fullkey);
private:
std::map<std::string, CmdSwitch*> m_mapKeySwitch;
std::map<std::string, std::string> m_mapShortcutKeys;
std::vector<CmdSwitch*> m_vSwitches;
std::string m_strDefaultKey;
std::string m_appname;
};
// bool starts_with(const string& src, const string& sub);
}
}
#endif /* CMDLINEPARSER_H_ */

View file

@ -1,191 +0,0 @@
/**
* Copyright (C) 2019-2021 Xilinx, Inc
*
* Licensed under the Apache License, Version 2.0 (the "License"). You may
* not use this file except in compliance with the License. A copy of the
* License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
#include "cmdlineparser.h"
#include <iostream>
#include <cstring>
#include <unordered_map>
// XRT includes
#include "experimental/xrt_bo.h"
#include "experimental/xrt_ip.h"
#include "experimental/xrt_device.h"
#include "experimental/xrt_kernel.h"
#include "experimental/xrt_xclbin.h"
#define CSR_CTL 0x0
#define CSR_A 0x10
#define CSR_B 0x1C
#define CSR_C 0x28
#define CSR_L 0x34
#define IP_START 0x1
#define IP_IDLE 0x4
#define NUM_ITEMS 1
#define BANK_SIZE 0x10000000
#define NUM_BANKS 16
uint64_t ba_addr = 0x10;
uint64_t bb_addr = 0x20;
uint64_t bc_addr = 0x00;
static int get_bank_info(uint64_t dev_addr, uint32_t* pIdx, uint32_t* pOff) {
uint32_t index = dev_addr / BANK_SIZE;
uint32_t offset = dev_addr % BANK_SIZE;
if (index > NUM_BANKS) {
fprintf(stderr, "[VXDRV] Error: address out of range: 0x%lx\n", dev_addr);
return -1;
}
*pIdx = index;
*pOff = offset;
return 0;
}
class ResourceManager {
public:
xrt::bo get_buffer(xrt::device& device, uint32_t bank_id) {
auto it = xrtBuffers_.find(bank_id);
if (it != xrtBuffers_.end()) {
return it->second;
} else {
xrt::bo xrtBuffer(device, BANK_SIZE, xrt::bo::flags::normal, bank_id);
xrtBuffers_.insert({bank_id, xrtBuffer});
return xrtBuffer;
}
}
private:
struct buf_cnt_t {
xrt::bo xrtBuffer;
uint32_t count;
};
std::unordered_map<uint32_t, xrt::bo> xrtBuffers_;
};
int main(int argc, char** argv) {
// Command Line Parser
sda::utils::CmdLineParser parser;
// Switches
//**************//"<Full Arg>", "<Short Arg>", "<Description>", "<Default>"
parser.addSwitch("--xclbin_file", "-x", "input binary file string", "");
parser.addSwitch("--device_id", "-d", "device index", "0");
parser.parse(argc, argv);
// Read settings
std::string binaryFile = parser.value("xclbin_file");
int device_index = stoi(parser.value("device_id"));
if (argc < 3) {
parser.printHelp();
return EXIT_FAILURE;
}
ResourceManager res_mgr;
std::cout << "Open the device" << device_index << std::endl;
auto device = xrt::device(device_index);
std::cout << "Load the xclbin " << binaryFile << std::endl;
auto uuid = device.load_xclbin(binaryFile);
std::cout << "Load the kernel ip" << std::endl;
auto ip = xrt::ip(device, uuid, "krnl_vadd_rtl");
size_t vector_size_bytes = sizeof(int) * NUM_ITEMS;
uint32_t ba_idx, bb_idx, bc_idx;
uint32_t ba_offset, bb_offset, bc_offset;
get_bank_info(ba_addr, &ba_idx, &ba_offset);
get_bank_info(bb_addr, &bb_idx, &bb_offset);
get_bank_info(bc_addr, &bc_idx, &bc_offset);
auto ba = res_mgr.get_buffer(device, ba_idx);
auto bb = res_mgr.get_buffer(device, bb_idx);
auto bc = res_mgr.get_buffer(device, bc_idx);
// upload source buffers
std::cout << "Writing the input data..." << std::endl;
std::vector<int> src_buf(NUM_ITEMS), dst_buf(NUM_ITEMS), ref_buf(NUM_ITEMS);
for (int i = 0; i < NUM_ITEMS; ++i) {
src_buf[i] = i;
dst_buf[i] = 0xdeadbeef;
ref_buf[i] = i + i;
}
ba.write(src_buf.data(), vector_size_bytes, ba_offset);
ba.sync(XCL_BO_SYNC_BO_TO_DEVICE, vector_size_bytes, ba_offset);
bb.write(src_buf.data(), vector_size_bytes, bb_offset);
bb.sync(XCL_BO_SYNC_BO_TO_DEVICE, vector_size_bytes, bb_offset);
bc.write(dst_buf.data(), vector_size_bytes, bc_offset);
bc.sync(XCL_BO_SYNC_BO_TO_DEVICE, vector_size_bytes, bc_offset);
std::cout << "Setting IP registers..." << std::endl;
ip.write_register(CSR_A, ba_addr);
ip.write_register(CSR_A + 4, ba_addr >> 32);
ip.write_register(CSR_B, bb_addr);
ip.write_register(CSR_B + 4, bb_addr >> 32);
ip.write_register(CSR_C, bc_addr);
ip.write_register(CSR_C + 4, bc_addr >> 32);
ip.write_register(CSR_L, NUM_ITEMS);
// Start execution
std::cout << "IP Start..." << std::endl;
ip.write_register(CSR_CTL, IP_START);
// Wait until the IP is DONE
uint32_t axi_ctrl = 0;
while ((axi_ctrl & IP_IDLE) != IP_IDLE) {
axi_ctrl = ip.read_register(CSR_CTL);
}
std::cout << "IP Done!" << std::endl;
// Get the output
std::cout << "Reading output data..." << std::endl;
bc.sync(XCL_BO_SYNC_BO_FROM_DEVICE, vector_size_bytes, bc_offset);
bc.read(dst_buf.data(), vector_size_bytes, bc_offset);
// Validate our results
std::cout << "Validating results..." << std::endl;
int errors = 0;
for (int i = 0; i < NUM_ITEMS; ++i) {
if (dst_buf[i] != ref_buf[i]) {
std::cout << "*** missmatch: (" << i << ") actual=" << dst_buf[i] << ", expected=" << ref_buf[i] << std::endl;
++errors;
}
}
if (errors != 0) {
std::cout << "TEST FAILED!\n";
return errors;
}
std::cout << "TEST PASSED!\n";
return 0;
}

View file

@ -1,179 +0,0 @@
/**
* Copyright (C) 2019-2021 Xilinx, Inc
*
* Licensed under the Apache License, Version 2.0 (the "License"). You may
* not use this file except in compliance with the License. A copy of the
* License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
#include "logger.h"
#include <algorithm>
#include <fstream>
#include <functional>
#include <stdarg.h>
#include <time.h>
#ifdef WINDOWS
#include <direct.h>
#else
#include <unistd.h>
#endif
using namespace std;
namespace sda {
///////////////////////////////////////////////////////////////////////
string GetApplicationPath() {
#ifdef WINDOWS
#define GetCurrentDir _getcwd
#else
#define GetCurrentDir getcwd
#endif
char strCurrentPath[FILENAME_MAX];
if (!GetCurrentDir(strCurrentPath, sizeof(strCurrentPath))) {
return string("");
}
/* not really required */
strCurrentPath[sizeof(strCurrentPath) - 1] = '\0';
return string(strCurrentPath);
}
string ToLower(const string& s) {
string result = s;
std::transform(result.begin(), result.end(), result.begin(), ::tolower);
return result;
}
string ToUpper(const string& s) {
string result = s;
std::transform(result.begin(), result.end(), result.begin(), ::toupper);
return result;
}
string GetTimeStamp() {
return "";
}
// trim from start
string& ltrim(std::string& s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
return s;
}
// trim from end
string& rtrim(std::string& s) {
s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
return s;
}
// trim from both ends
string& trim(std::string& s) {
return ltrim(rtrim(s));
}
string GetFileExt(const string& s) {
string strext = s.substr(s.find_last_of(".") + 1);
return strext;
}
string GetFileTitleOnly(const string& s) {
string temp = s;
string::size_type d = temp.find_last_of("//");
if (d == string::npos) d = temp.find_last_of("\\");
if (d != string::npos) temp = temp.substr(d + 1);
d = temp.find_last_of(".");
if (d != string::npos) temp = temp.substr(0, d);
return temp;
}
void LogWrapper(int etype, const char* file, int line, const char* desc, ...) {
// crop file name from full path
string strFileLoc(file);
strFileLoc = strFileLoc.substr(strFileLoc.find_last_of("\\/") + 1);
string strHeader = "";
{
char header[512];
// source
switch (etype) {
case (sda::etError): {
snprintf(header, sizeof(header), "ERROR: [%s:%d]", strFileLoc.c_str(), line);
break;
}
case (sda::etInfo): {
snprintf(header, sizeof(header), "INFO: [%s:%d]", strFileLoc.c_str(), line);
break;
}
case (sda::etWarning): {
snprintf(header, sizeof(header), "WARN: [%s:%d]", strFileLoc.c_str(), line);
break;
}
}
strHeader = string(header);
}
// time
string strTime = "";
#ifdef ENABLE_LOG_TIME
{
time_t rawtime;
time(&rawtime);
#ifdef ENABLE_SECURE_API
char buffer[64];
struct tm timeinfo;
localtime_s(&timeinfo, &rawtime);
asctime_s(timeinfo, buffer, sizeof(buffer)) snprintf(buffer, sizeof(buffer), "TIME: [%s]", asctime(timeinfo));
strTime = string(buffer);
#else
char buffer[64];
struct tm* timeinfo = localtime(&rawtime);
string temp = string(asctime(timeinfo));
temp = trim(temp);
// strftime(buffer, sizeof(buffer), "TIME: []")
snprintf(buffer, sizeof(buffer), "TIME: [%s]", temp.c_str());
strTime = string(buffer);
#endif
}
#endif
// format the message itself
string strMsg = "";
{
char msg[512];
va_list args;
va_start(args, desc);
vsnprintf(msg, sizeof(msg), desc, args);
va_end(args);
strMsg = string(msg);
}
// combine
string strOut = strHeader + string(" ") + strTime + string(" ") + strMsg + string("\n");
// display
cout << strOut;
// store
#ifdef ENABLE_LOG_TOFILE
std::ofstream outfile;
outfile.open("benchapp.log", std::ios_base::app);
outfile << strOut;
#endif
return;
}
} // namespace sda

View file

@ -1,70 +0,0 @@
/**
* Copyright (C) 2019-2021 Xilinx, Inc
*
* Licensed under the Apache License, Version 2.0 (the "License"). You may
* not use this file except in compliance with the License. A copy of the
* License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
#ifndef LOGGER_H_
#define LOGGER_H_
#include <iomanip>
#include <iostream>
#include <string>
#include <vector>
#define ENABLE_LOG_TOFILE 1
#define ENABLE_LOG_TIME 1
// global logging
#define LogInfo(desc, ...) sda::LogWrapper(0, __FILE__, __LINE__, desc, ##__VA_ARGS__)
#define LogWarn(desc, ...) sda::LogWrapper(1, __FILE__, __LINE__, desc, ##__VA_ARGS__)
#define LogError(desc, ...) sda::LogWrapper(2, __FILE__, __LINE__, desc, ##__VA_ARGS__)
using namespace std;
namespace sda {
enum LOGTYPE { etInfo, etWarning, etError };
// string
string& ltrim(string& s);
string& rtrim(string& s);
string& trim(string& s);
string GetFileExt(const string& s);
string GetFileTitleOnly(const string& s);
string ToLower(const string& s);
string ToUpper(const string& s);
// time
string GetTimeStamp();
// paths
string GetApplicationPath();
// debug
template <typename T>
void PrintPOD(const vector<T>& pod, size_t display_count = 0, const int precision = 4) {
size_t count = pod.size();
if (display_count > 0) count = std::min<size_t>(pod.size(), display_count);
for (size_t i = 0; i < count; i++) {
cout << std::setprecision(precision) << pod[i] << ", ";
}
cout << endl;
}
// logging
void LogWrapper(int etype, const char* file, int line, const char* desc, ...);
}
#endif /* LOGGER_H_ */

View file

@ -1,9 +0,0 @@
[connectivity]
#nk=krnl_vadd_rtl:1
#sp=krnl_vadd_rtl_1.m_axi_mem:HBM[0:15]
[vivado]
#prop=fileset.sim_1.xsim.elaborate.debug_level=all
[advanced]
#param=compiler.userPostDebugProfileOverlayTcl=../scripts/post_dbg_profile_overlay.tcl

View file

@ -1,11 +0,0 @@
[Runtime]
runtime_log=console
[Emulation]
#debug_mode=gui
#user_pre_sim_script=xsim.tcl
[Debug]
profile=true
timeline_trace=true
data_transfer_trace=fine

View file

@ -1,3 +0,0 @@
/build*/*
/.run/*
/.Xil/*

View file

@ -1,157 +0,0 @@
ifneq ($(findstring Makefile, $(MAKEFILE_LIST)), Makefile)
help:
$(ECHO) "Makefile Usage:"
$(ECHO) " make all TARGET=<sw_emu/hw_emu/hw> PLATFORM=<FPGA platform>"
$(ECHO) " Command to generate the design for specified Target and Device."
$(ECHO) ""
$(ECHO) " make clean"
$(ECHO) " Command to remove the generated non-hardware files."
$(ECHO) ""
endif
TARGET ?= hw
PLATFORM ?=
PREFIX ?= build
RTL_DIR = ../../../../rtl
AFU_DIR = ../../../../afu/xrt
BUILD_DIR = $(PREFIX)_$(PLATFORM)_$(TARGET)
BIN_DIR = $(BUILD_DIR)/bin
# Control RTL debug tracing states
DBG_TRACE_FLAGS += -DDBG_TRACE_CORE_PIPELINE
DBG_TRACE_FLAGS += -DDBG_TRACE_CORE_ICACHE
DBG_TRACE_FLAGS += -DDBG_TRACE_CORE_DCACHE
DBG_TRACE_FLAGS += -DDBG_TRACE_CORE_MEM
DBG_TRACE_FLAGS += -DDBG_TRACE_CACHE_BANK
DBG_TRACE_FLAGS += -DDBG_TRACE_CACHE_MSHR
DBG_TRACE_FLAGS += -DDBG_TRACE_CACHE_TAG
DBG_TRACE_FLAGS += -DDBG_TRACE_CACHE_DATA
DBG_TRACE_FLAGS += -DDBG_TRACE_AFU
DBG_TRACE_FLAGS += -DDBG_TRACE_TEX
DBG_TRACE_FLAGS += -DDBG_TRACE_RASTER
DBG_TRACE_FLAGS += -DDBG_TRACE_ROP
DBG_FLAGS += $(DBG_TRACE_FLAGS)
FPU_INCLUDE = -I$(RTL_DIR)/fpu_unit
TEX_INCLUDE = -I$(RTL_DIR)/tex_unit
RASTER_INCLUDE = -I$(RTL_DIR)/raster_unit
ROP_INCLUDE = -I$(RTL_DIR)/rop_unit
RTL_INCLUDE = -I$(RTL_DIR) -I$(RTL_DIR)/libs -I$(RTL_DIR)/interfaces -I$(RTL_DIR)/core -I$(RTL_DIR)/cache -I$(AFU_DIR)
RTL_INCLUDE += $(FPU_INCLUDE) $(TEX_INCLUDE) $(RASTER_INCLUDE) $(ROP_INCLUDE)
#CONFIGS += -DEXT_GFX_ENABLE
CONFIGS += -DNUM_WARPS=2 -DNUM_THREADS=2 -DEXT_F_DISABLE
CONFIGS += -DSYNTHESIS -DVIVADO
VIVADO = $(XILINX_VIVADO)/bin/vivado
VPP = $(XILINX_VITIS)/bin/v++
CP = cp -rf
RMDIR = rm -rf
ECHO = @echo
XO_CONTAINER = $(BIN_DIR)/vortex_afu.xo
XCLBIN_CONTAINER = $(BIN_DIR)/vortex_afu.xclbin
EMCONFIG = $(BIN_DIR)/emconfig.json
NCPUS := $(shell grep -c ^processor /proc/cpuinfo)
JOBS := $(shell expr $(NCPUS) - 1)
# Kernel compiler global settings
VPP_FLAGS += --link --target $(TARGET) --platform $(PLATFORM) --save-temps --no_ip_cache
VPP_FLAGS += --vivado.synth.jobs $(JOBS) --vivado.impl.jobs $(JOBS)
VPP_FLAGS += --connectivity.sp vortex_afu_1.m_axi_mem:HBM[0:15]
VPP_FLAGS += --report 2
VPP_FLAGS += --config ../vitis.ini
# Enable perf counters
ifdef PERF
CONFIGS += -DPERF_ENABLE
endif
# Generates profile summary report
ifdef PROFILE
VPP_FLAGS += --profile_kernel data:all:all:all
VPP_FLAGS += --profile_kernel stall:all:all:all
endif
# Debugigng
ifdef DEBUG
VPP_FLAGS += -g --optimize 0 --debug.protocol all
ifeq ($(TARGET), hw)
VPP_FLAGS += --debug.chipscope vortex_afu_1
CONFIGS += -DCHIPSCOPE
else
CONFIGS += -DSIMULATION $(DBG_FLAGS)
VPP_FLAGS += --vivado.prop fileset.sim_1.xsim.elaborate.debug_level=all
endif
else
CONFIGS += -DNDEBUG
VPP_FLAGS += --optimize 3
endif
# Host
EXECUTABLE = ./test
CMD_ARGS = -x $(XCLBIN_CONTAINER)
CXXFLAGS += -std=c++14 -g -O0 -fmessage-length=0 -I$(XILINX_XRT)/include -I$(XILINX_VIVADO)/include -Wall -I../src
LDFLAGS += -L$(XILINX_XRT)/lib -pthread -luuid -lxrt_coreutil
HOST_SRCS += ./src/host.cpp ./src/cmdlineparser.cpp ./src/logger.cpp
# RTL Kernel only supports Hardware and Hardware Emulation.
ifneq ($(TARGET),$(findstring $(TARGET), hw hw_emu))
$(warning WARNING:Application supports only hw hw_emu TARGET. Please use the target for running the application)
endif
.PHONY: all run host clean gen-sources emconfig check-devices
all: check-devices $(XCLBIN_CONTAINER) emconfig host
gen-sources: $(BUILD_DIR)/sources.txt
$(BUILD_DIR)/sources.txt:
mkdir -p $(BUILD_DIR); cd $(BUILD_DIR); ../scripts/gen_sources.sh $(RTL_INCLUDE) $(CONFIGS) > sources.txt
$(XO_CONTAINER): $(BUILD_DIR)/sources.txt ./kernel.xml
mkdir -p $(BUILD_DIR); cd $(BUILD_DIR); $(VIVADO) -mode batch -source ../scripts/gen_xo.tcl -tclargs ../$(XO_CONTAINER) vortex_afu sources.txt ../kernel.xml ../$(BUILD_DIR)
$(XCLBIN_CONTAINER): $(XO_CONTAINER)
mkdir -p $(BIN_DIR); cd $(BUILD_DIR); $(VPP) $(VPP_FLAGS) -o ../$(XCLBIN_CONTAINER) ../$(XO_CONTAINER)
emconfig: $(EMCONFIG)
$(EMCONFIG):
mkdir -p $(BIN_DIR); cd $(BUILD_DIR); emconfigutil --platform $(PLATFORM) --od ../$(BIN_DIR)
host: $(EXECUTABLE)
$(EXECUTABLE): $(HOST_SRCS)
g++ $^ $(CXXFLAGS) $(LDFLAGS) -o $@
run: $(EXECUTABLE)
ifeq ($(TARGET),$(filter $(TARGET),sw_emu hw_emu))
EMCONFIG_PATH=$(BIN_DIR) XCL_EMULATION_MODE=$(TARGET) $(EXECUTABLE) $(CMD_ARGS)
else
EMCONFIG_PATH=$(BIN_DIR) $(EXECUTABLE) $(CMD_ARGS)
endif
chipscope:
debug_hw --xvc_pcie /dev/xfpga/xvc_pub.u2305.0 --hw_server &
debug_hw --vivado --host localhost --ltx_file $(BUILD_DIR)/_x/link/vivado/vpl/prj/prj.runs/impl_1/debug_nets.ltx &
clean:
$(RMDIR) $(BUILD_DIR) $(EXECUTABLE)
# Check the devices avaiable
check-devices:
ifndef PLATFORM
$(error PLATFORM not set. Please set the PLATFORM properly and rerun. Run "make help" for more details.)
endif
ifndef XILINX_VITIS
$(error XILINX_VITIS variable is not set, please set correctly and rerun)
endif

View file

@ -1,15 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<root versionMajor="1" versionMinor="9">
<kernel name="vortex_afu" language="ip" vlnv="xilinx.com:RTLKernel:vortex_afu:1.0" attributes="" preferredWorkGroupSizeMultiple="0" workGroupSize="1" hwControlProtocol="ap_ctrl_hs">
<ports>
<port name="s_axi_ctrl" mode="slave" range="0x1000" dataWidth="32" portType="addressable" base="0x0"/>
<port name="m_axi_mem" mode="master" range="0xFFFFFFFF" dataWidth="512" portType="addressable" base="0x0"/>
</ports>
<args>
<arg id="0" name="DEV" addressQualifier="0" port="s_axi_ctrl" size="0x8" offset="0x010" type="uint" hostOffset="0x0" hostSize="0x8"/>
<arg id="1" name="ISA" addressQualifier="0" port="s_axi_ctrl" size="0x8" offset="0x01C" type="uint" hostOffset="0x0" hostSize="0x8"/>
<arg id="2" name="DCR" addressQualifier="0" port="s_axi_ctrl" size="0x8" offset="0x028" type="uint" hostOffset="0x0" hostSize="0x8"/>
<arg id="3" name="MEM" addressQualifier="1" port="m_axi_mem" size="0x8" offset="0x034" type="void*" hostOffset="0x0" hostSize="0x8"/>
</args>
</kernel>
</root>

View file

@ -1,27 +0,0 @@
if { $::argc != 1 } {
puts "ERROR: Program \"$::argv0\" requires 1 arguments!\n"
puts "Usage: $::argv0 <ip_dir>\n"
exit
}
set ip_dir [lindex $::argv 0]
# IP folder does not exist. Create IP folder
file mkdir ${ip_dir}
# create_ip requires that a project is open in memory.
# Create project but don't do anything with it
create_project -in_memory
create_ip -name floating_point -vendor xilinx.com -library ip -version 7.1 -module_name xil_fdiv -dir ${ip_dir}
set_property -dict [list CONFIG.Component_Name {xil_fdiv} CONFIG.Operation_Type {Divide} CONFIG.Flow_Control {NonBlocking} CONFIG.Has_ACLKEN {true} CONFIG.C_Has_UNDERFLOW {true} CONFIG.C_Has_OVERFLOW {true} CONFIG.C_Has_INVALID_OP {true} CONFIG.C_Has_DIVIDE_BY_ZERO {true} CONFIG.A_Precision_Type {Single} CONFIG.C_A_Exponent_Width {8} CONFIG.C_A_Fraction_Width {24} CONFIG.Result_Precision_Type {Single} CONFIG.C_Result_Exponent_Width {8} CONFIG.C_Result_Fraction_Width {24} CONFIG.C_Mult_Usage {No_Usage} CONFIG.Has_RESULT_TREADY {false} CONFIG.C_Latency {28} CONFIG.C_Rate {1}] [get_ips xil_fdiv]
create_ip -name floating_point -vendor xilinx.com -library ip -version 7.1 -module_name xil_fsqrt -dir ${ip_dir}
set_property -dict [list CONFIG.Component_Name {xil_fsqrt} CONFIG.Operation_Type {Square_root} CONFIG.Flow_Control {NonBlocking} CONFIG.Has_ACLKEN {true} CONFIG.C_Has_INVALID_OP {true} CONFIG.A_Precision_Type {Single} CONFIG.C_A_Exponent_Width {8} CONFIG.C_A_Fraction_Width {24} CONFIG.Result_Precision_Type {Single} CONFIG.C_Result_Exponent_Width {8} CONFIG.C_Result_Fraction_Width {24} CONFIG.C_Mult_Usage {No_Usage} CONFIG.Has_RESULT_TREADY {false} CONFIG.C_Latency {28} CONFIG.C_Rate {1}] [get_ips xil_fsqrt]
create_ip -name floating_point -vendor xilinx.com -library ip -version 7.1 -module_name xil_fma -dir ${ip_dir}
set_property -dict [list CONFIG.Component_Name {xil_fma} CONFIG.Operation_Type {FMA} CONFIG.Add_Sub_Value {Add} CONFIG.Flow_Control {NonBlocking} CONFIG.Has_ACLKEN {true} CONFIG.C_Has_UNDERFLOW {true} CONFIG.C_Has_OVERFLOW {true} CONFIG.C_Has_INVALID_OP {true} CONFIG.Has_A_TUSER {false} CONFIG.A_Precision_Type {Single} CONFIG.C_A_Exponent_Width {8} CONFIG.C_A_Fraction_Width {24} CONFIG.Result_Precision_Type {Single} CONFIG.C_Result_Exponent_Width {8} CONFIG.C_Result_Fraction_Width {24} CONFIG.C_Mult_Usage {Medium_Usage} CONFIG.Has_RESULT_TREADY {false} CONFIG.C_Latency {16} CONFIG.C_Rate {1} CONFIG.A_TUSER_Width {1}] [get_ips xil_fma]
generate_target all [get_ips]
close_project -delete

View file

@ -1,46 +0,0 @@
#!/bin/bash
exclude_list="VX_fpu_fpnew.sv"
macros=()
includes=()
# parse command arguments
while getopts D:I:h flag
do
case "${flag}" in
D) macros+=( ${OPTARG} );;
I) includes+=( ${OPTARG} );;
h) echo "Usage: [-D macro] [-I include] [-h help]"
exit 0
;;
\?)
echo "Invalid option: -$OPTARG" 1>&2
exit 1
;;
esac
done
# dump macros
for value in ${macros[@]}; do
echo "+define+$value"
done
# dump include directories
for dir in ${includes[@]}; do
echo "+incdir+$dir"
done
# dump source files
for dir in ${includes[@]}; do
for file in $(find $dir -maxdepth 1 -name '*.v' -o -name '*.sv' -type f); do
exclude=0
for fe in $exclude_list; do
if [[ $file =~ $fe ]]; then
exclude=1
fi
done
if [[ $exclude == 0 ]]; then
echo $file
fi
done
done

View file

@ -1,27 +0,0 @@
if { $::argc != 5 } {
puts "ERROR: Program \"$::argv0\" requires 5 arguments!\n"
puts "Usage: $::argv0 <xoname> <krnl_name> <vcs_file> <kernel_xml> <build_dir>\n"
exit
}
set xoname [lindex $::argv 0]
set krnl_name [lindex $::argv 1]
set vcs_file [lindex $::argv 2]
set krnl_xml [lindex $::argv 3]
set build_dir [lindex $::argv 4]
set script_path [ file dirname [ file normalize [ info script ] ] ]
if {[file exists "${xoname}"]} {
file delete -force "${xoname}"
}
set argv [list ${build_dir}/ip]
set argc 1
source ${script_path}/gen_ip.tcl
set argv [list ${krnl_name} ${build_dir}]
set argc 2
source ${script_path}/package_kernel.tcl
package_xo -xo_path ${xoname} -kernel_name ${krnl_name} -ip_directory "${build_dir}/xo/packaged_kernel" -kernel_xml ${krnl_xml}

View file

@ -1,141 +0,0 @@
if { $::argc != 2 } {
puts "ERROR: Program \"$::argv0\" requires 2 arguments!\n"
puts "Usage: $::argv0 <krnl_name> <build_dir>\n"
exit
}
set krnl_name [lindex $::argv 0]
set build_dir [lindex $::argv 1]
set script_path [ file dirname [ file normalize [ info script ] ] ]
set path_to_packaged "${build_dir}/xo/packaged_kernel"
set path_to_tmp_project "${build_dir}/xo/project"
source "${script_path}/parse_vcs_list.tcl"
set vlist [parse_vcs_list "${vcs_file}"]
set vsources_list [lindex $vlist 0]
set vincludes_list [lindex $vlist 1]
set vdefines_list [lindex $vlist 2]
#puts ${vsources_list}
#puts ${vdefines_list}
# dump defines into globals.vh
set chipscope 0
set fh [open "${build_dir}/globals.vh" w]
foreach def $vdefines_list {
set fields [split $def "="]
set len [llength $fields]
set name [lindex $fields 0]
puts -nonewline $fh "`define "
if {$len > 1} {
set value [lindex $fields 1]
puts -nonewline $fh $name
puts -nonewline $fh " "
puts $fh $value
} else {
puts $fh $name
if { $name == "CHIPSCOPE" } {
set chipscope 1
}
}
}
close $fh
create_project -force kernel_pack $path_to_tmp_project
set obj [get_filesets sources_1]
add_files -verbose -norecurse -fileset $obj ${vsources_list}
set files [list \
[file normalize "${build_dir}/globals.vh"] \
[file normalize "${build_dir}/ip/xil_fdiv/xil_fdiv.xci"] \
[file normalize "${build_dir}/ip/xil_fma/xil_fma.xci"] \
[file normalize "${build_dir}/ip/xil_fsqrt/xil_fsqrt.xci"] \
]
add_files -verbose -norecurse -fileset $obj $files
set_property include_dirs ${vincludes_list} [current_fileset]
#set_property verilog_define ${vdefines_list} [current_fileset]
set_property -verbose -name "top" -value ${krnl_name} -objects $obj
if { $chipscope == 1 } {
# hw debugging
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} \
CONFIG.C_EN_STRG_QUAL {1} \
CONFIG.C_DATA_DEPTH {4096} \
CONFIG.C_NUM_OF_PROBES {2} \
CONFIG.C_PROBE0_WIDTH {8} \
CONFIG.C_PROBE1_WIDTH {24} \
] [get_ips ila_afu]
generate_target {instantiation_template} [get_files ila_afu.xci]
set_property generate_synth_checkpoint false [get_files ila_afu.xci]
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} \
CONFIG.C_EN_STRG_QUAL {1} \
CONFIG.C_DATA_DEPTH {4096} \
CONFIG.C_NUM_OF_PROBES {5} \
CONFIG.C_PROBE0_WIDTH {128} \
CONFIG.C_PROBE1_WIDTH {128} \
CONFIG.C_PROBE2_WIDTH {128} \
CONFIG.C_PROBE3_WIDTH {128} \
CONFIG.C_PROBE4_WIDTH {128} \
] [get_ips ila_fetch]
generate_target {instantiation_template} [get_files ila_fetch.xci]
set_property generate_synth_checkpoint false [get_files ila_fetch.xci]
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} \
CONFIG.C_EN_STRG_QUAL {1} \
CONFIG.C_DATA_DEPTH {4096} \
CONFIG.C_NUM_OF_PROBES {2} \
CONFIG.C_PROBE0_WIDTH {128} \
CONFIG.C_PROBE1_WIDTH {128} \
] [get_ips ila_issue]
generate_target {instantiation_template} [get_files ila_issue.xci]
set_property generate_synth_checkpoint false [get_files ila_issue.xci]
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} \
CONFIG.C_EN_STRG_QUAL {1} \
CONFIG.C_DATA_DEPTH {4096} \
CONFIG.C_NUM_OF_PROBES {2} \
CONFIG.C_PROBE0_WIDTH {128} \
CONFIG.C_PROBE1_WIDTH {128} \
] [get_ips ila_lsu]
generate_target {instantiation_template} [get_files ila_lsu.xci]
set_property generate_synth_checkpoint false [get_files ila_lsu.xci]
}
update_compile_order -fileset sources_1
update_compile_order -fileset sim_1
ipx::package_project -root_dir $path_to_packaged -vendor xilinx.com -library RTLKernel -taxonomy /KernelIP -import_files -set_current false
ipx::unload_core $path_to_packaged/component.xml
ipx::edit_ip_in_project -upgrade true -name tmp_edit_project -directory $path_to_packaged $path_to_packaged/component.xml
set core [ipx::current_core]
set_property core_revision 2 $core
foreach up [ipx::get_user_parameters] {
ipx::remove_user_parameter [get_property NAME $up] $core
}
ipx::associate_bus_interfaces -busif s_axi_ctrl -clock ap_clk $core
ipx::associate_bus_interfaces -busif m_axi_mem -clock ap_clk $core
set_property xpm_libraries {XPM_CDC XPM_MEMORY XPM_FIFO} $core
set_property sdx_kernel true $core
set_property sdx_kernel_type rtl $core
set_property supported_families { } $core
set_property auto_family_support_level level_2 $core
ipx::create_xgui_files $core
ipx::update_checksums $core
ipx::check_integrity -kernel $core
ipx::save_core $core
close_project -delete

View file

@ -1,33 +0,0 @@
proc parse_vcs_list {flist_path} {
set f [split [string trim [read [open $flist_path r]]] "\n"]
set flist [list ]
set dir_list [list ]
set def_list [list ]
foreach x $f {
if {![string match "" $x]} {
# If the item starts with +incdir+, directory files need to be added
if {[string match "#*" $x]} {
# get rid of comment line
} elseif {[string match "+incdir+*" $x]} {
set trimchars "+incdir+"
set temp [string trimleft $x $trimchars]
set expanded [subst $temp]
lappend dir_list $expanded
} elseif {[string match "+define+*" $x]} {
set trimchars "+define+"
set temp [string trimleft $x $trimchars]
set expanded [subst $temp]
lappend def_list $expanded
} else {
set expanded [subst $x]
lappend flist $expanded
}
}
}
#puts $flist
#puts $dir_list
#puts $def_list
return [list $flist $dir_list $def_list]
}

View file

@ -1,19 +0,0 @@
#
# Copyright 2021 Xilinx, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
log_wave -r *
run all
exit

View file

@ -1,348 +0,0 @@
/**
* Copyright (C) 2019-2021 Xilinx, Inc
*
* Licensed under the Apache License, Version 2.0 (the "License"). You may
* not use this file except in compliance with the License. A copy of the
* License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
#include "cmdlineparser.h"
#include "logger.h"
#include <assert.h>
#include <fstream>
#include <iostream>
#include <stdlib.h>
namespace sda {
namespace utils {
bool is_file(const std::string& name) {
ifstream f(name.c_str());
if (f.good()) {
f.close();
return true;
} else {
f.close();
return false;
}
}
bool is_number(const std::string& s) {
std::string::const_iterator it = s.begin();
while (it != s.end() && std::isdigit(*it)) ++it;
return !s.empty() && it == s.end();
}
bool starts_with(const string& src, const string& sub) {
return (src.find(sub) == 0);
}
CmdLineParser::CmdLineParser() {
// TODO Auto-generated constructor stub
m_strDefaultKey = "";
m_appname = "application.exe";
addSwitch("--help", "-h", "prints this help list", "", true);
}
/*
CmdLineParser::CmdLineParser(int argc, char* argv[]) {
// TODO Auto-generated constructor stub
assert(parse(argc, argv) > 0);
}
*/
CmdLineParser::~CmdLineParser() {
// TODO Auto-generated destructor stub
for (size_t i = 0; i < m_vSwitches.size(); i++) {
delete m_vSwitches[i];
m_vSwitches[i] = nullptr;
}
m_vSwitches.resize(0);
}
bool CmdLineParser::addSwitch(const CmdSwitch& s) {
CmdSwitch cmd = s;
if (cmd.desc.length() == 0) {
LogError("No description provided!");
return false;
}
// check input
if (cmd.key.find("--") != 0 || cmd.key.length() < 3) {
LogError(
"The input key is invalid. Please start with -- and keep a "
"length >= 3");
return false;
}
if (m_mapKeySwitch.find(cmd.key) != m_mapKeySwitch.end()) {
LogError("This key %s is taken already!", cmd.key.c_str());
return false;
}
if (cmd.shortcut.length() == 0) {
string temp = "-" + cmd.key[2];
int i = 3;
while (m_mapShortcutKeys.find(temp) != m_mapShortcutKeys.end() && (size_t)i < cmd.key.length()) {
temp = "-" + s.key[i];
i++;
}
cmd.shortcut = temp;
LogInfo("Automatic shortcut assigned %s to %s", temp.c_str(), cmd.key.c_str());
}
if (s.istoggle) {
cmd.default_value = string("false");
cmd.value = cmd.default_value;
cmd.isvalid = true;
} else {
cmd.value = cmd.default_value;
cmd.isvalid = false;
}
// add
CmdSwitch* pcmd = new CmdSwitch(cmd);
m_vSwitches.push_back(pcmd);
m_mapShortcutKeys[s.shortcut] = cmd.key;
m_mapKeySwitch[s.key] = pcmd;
return true;
}
bool CmdLineParser::addSwitch(
const string& name, const string& shortcut, const string& desc, const string& default_value, bool istoggle) {
CmdSwitch s;
s.key = name;
s.shortcut = shortcut;
s.desc = desc;
s.default_value = default_value;
s.istoggle = istoggle;
return addSwitch(s);
}
bool CmdLineParser::setDefaultKey(const char* key) {
string strKey(key);
if (!starts_with(strKey, "--")) strKey = "--" + strKey;
if (m_mapKeySwitch.find(strKey) != m_mapKeySwitch.end()) {
CmdSwitch* pcmd = m_mapKeySwitch[m_strDefaultKey];
if (pcmd != nullptr) {
if (pcmd->istoggle) {
LogError(
"Boolean command line options can not be used as "
"default keys");
return false;
}
}
// set default key
m_strDefaultKey = strKey;
return true;
} else
return false;
}
int CmdLineParser::parse(int argc, char* argv[]) {
int i = 0;
int ctOptions = 0;
while (i < argc) {
string key, val;
bool iskey = false;
string token = string(argv[i]);
bool isNextTokenKey = false;
if (i + 1 < argc) {
string peeknext = string(argv[i + 1]);
if (starts_with(peeknext, "-") || starts_with(peeknext, "--")) {
string fullkey;
isNextTokenKey = token_to_fullkeyname(peeknext, fullkey);
}
}
// full-key
if (starts_with(token, string("--"))) {
if (m_mapKeySwitch.find(token) == m_mapKeySwitch.end()) {
LogError("Unrecognized key passed %s", token.c_str());
printHelp();
return -1;
}
key = token;
iskey = true;
}
// shortcut
else if (starts_with(token, "-")) {
if (m_mapShortcutKeys.find(token) == m_mapShortcutKeys.end()) {
LogError("Unrecognized shortcut key passed %s", token.c_str());
printHelp();
return -1;
}
key = m_mapShortcutKeys[token];
iskey = true;
}
// default key, the value for default key is the last argument
else if (isNextTokenKey == false && m_strDefaultKey.length() > 0 && i == argc - 2) {
if (m_mapKeySwitch.find(m_strDefaultKey) == m_mapKeySwitch.end()) {
LogError("Unrecognized default key %s", m_strDefaultKey.c_str());
printHelp();
return -1;
}
LogInfo("Using default key: %s", m_strDefaultKey.c_str());
key = m_strDefaultKey;
iskey = true;
}
// if iskey and needs param then read it
if (iskey) {
ctOptions++;
if (key == "--help") {
printHelp();
return 1;
}
// fetch value
CmdSwitch* pcmd = m_mapKeySwitch[key];
// read next
if (pcmd->istoggle) {
pcmd->value = string("true");
pcmd->isvalid = true;
} else {
i++;
pcmd->value = string(argv[i]);
pcmd->isvalid = true;
}
}
// next token
i++;
}
// capture real app name
if (argc > 0) {
m_appname = string(argv[0]);
}
return ctOptions;
}
bool CmdLineParser::token_to_fullkeyname(const string& token, string& fullkey) {
fullkey = "";
int ctDashes = 0;
if (starts_with(token, string("--")))
ctDashes = 2;
else if (starts_with(token, string("-")))
ctDashes = 1;
if (ctDashes == 0) return false;
if (ctDashes == 2) {
if (m_mapKeySwitch.find(token) == m_mapKeySwitch.end()) {
LogError("Unrecognized key passed %s", token.c_str());
return false;
}
fullkey = token;
} else if (ctDashes == 1) {
if (m_mapShortcutKeys.find(token) == m_mapShortcutKeys.end()) {
LogError("Unrecognized shortcut key passed %s", token.c_str());
return false;
}
fullkey = m_mapShortcutKeys[token];
}
return (fullkey.length() > 0);
}
string CmdLineParser::value(const char* key) {
string strKey(key);
if (!starts_with(strKey, "--")) strKey = "--" + strKey;
if (m_mapKeySwitch.find(strKey) != m_mapKeySwitch.end())
return m_mapKeySwitch[strKey]->value;
else {
LogWarn("The input key %s is not recognized!", strKey.c_str());
return string("");
}
}
bool CmdLineParser::value_to_bool(const char* key) {
string strVal = value(key);
if (strVal == "true") return true;
return false;
}
int CmdLineParser::value_to_int(const char* key) {
string strVal = value(key);
if (strVal.length() == 0 || !is_number(strVal)) return -1;
return atoi(strVal.c_str());
}
double CmdLineParser::value_to_double(const char* key) {
string strVal = value(key);
if (strVal.length() == 0) return -1;
return atof(strVal.c_str());
}
bool CmdLineParser::isValid(const char* key) {
string strKey(key);
if (!starts_with(strKey, "--")) strKey = "--" + strKey;
if (m_mapKeySwitch.find(strKey) != m_mapKeySwitch.end())
return m_mapKeySwitch[strKey]->isvalid;
else {
LogWarn("The input key %s is not recognized!", strKey.c_str());
return false;
}
}
void CmdLineParser::printHelp() {
printf("===========================================================\n");
string strAllShortcuts = "";
for (size_t i = 0; i < m_vSwitches.size(); i++) {
CmdSwitch* pcmd = m_vSwitches[i];
if (pcmd && pcmd->shortcut.length() > 0) strAllShortcuts = strAllShortcuts + pcmd->shortcut;
}
// example
printf("Usage: %s -[%s]\n\n", m_appname.c_str(), strAllShortcuts.c_str());
// row by row
for (size_t i = 0; i < m_vSwitches.size(); i++) {
CmdSwitch* pcmd = m_vSwitches[i];
if (pcmd->default_value.length() > 0)
printf("\t%s, %s\t\t%s\t Default: [%s]\n", pcmd->key.c_str(), pcmd->shortcut.c_str(), pcmd->desc.c_str(),
pcmd->default_value.c_str());
else
printf("\t%s, %s\t\t%s\n", pcmd->key.c_str(), pcmd->shortcut.c_str(), pcmd->desc.c_str());
}
}
CmdLineParser::CmdSwitch* CmdLineParser::getCmdSwitch(const char* key) {
string strKey(key);
if (!starts_with(strKey, "--")) strKey = "--" + strKey;
if (m_mapKeySwitch.find(strKey) != m_mapKeySwitch.end())
return m_mapKeySwitch[strKey];
else
return nullptr;
}
} // namespace utils
} // namespace sda

View file

@ -1,110 +0,0 @@
/**
* Copyright (C) 2019-2021 Xilinx, Inc
*
* Licensed under the Apache License, Version 2.0 (the "License"). You may
* not use this file except in compliance with the License. A copy of the
* License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
#ifndef CMDLINEPARSER_H_
#define CMDLINEPARSER_H_
#include <map>
#include <string>
#include <vector>
namespace sda {
namespace utils {
bool is_file(const std::string& name);
/*!
* Synopsis:
* 1.Parses the command line passed in from the user and stores all enabled
* system options.
* 2.Prints help for the user if an option is not valid.
* 3.Stores options and provides a mechanism to read those options
*/
class CmdLineParser {
public:
class CmdSwitch {
public:
std::string key;
std::string shortcut;
std::string default_value;
std::string value;
std::string desc;
bool istoggle;
bool isvalid;
};
public:
CmdLineParser();
// CmdLineParser(int argc, char* argv[]);
virtual ~CmdLineParser();
bool addSwitch(const CmdSwitch& s);
bool addSwitch(const std::string& name,
const std::string& shortcut,
const std::string& desc,
const std::string& default_value = "",
bool istoggle = false);
/*!
* sets default key to be able to read a 2 argumented call
*/
bool setDefaultKey(const char* key);
/*!
* parse and store command line
*/
int parse(int argc, char* argv[]);
/*!
* retrieve value using a key
*/
std::string value(const char* key);
bool value_to_bool(const char* key);
int value_to_int(const char* key);
double value_to_double(const char* key);
/*!
* Returns true if a valid value is supplied by user
*/
bool isValid(const char* key);
/*!
* prints the help menu in case the options are not correct.
*/
virtual void printHelp();
protected:
/*!
* Retrieve command switch
*/
CmdSwitch* getCmdSwitch(const char* key);
bool token_to_fullkeyname(const std::string& token, std::string& fullkey);
private:
std::map<std::string, CmdSwitch*> m_mapKeySwitch;
std::map<std::string, std::string> m_mapShortcutKeys;
std::vector<CmdSwitch*> m_vSwitches;
std::string m_strDefaultKey;
std::string m_appname;
};
// bool starts_with(const string& src, const string& sub);
}
}
#endif /* CMDLINEPARSER_H_ */

View file

@ -1,245 +0,0 @@
/**
* Copyright (C) 2019-2021 Xilinx, Inc
*
* Licensed under the Apache License, Version 2.0 (the "License"). You may
* not use this file except in compliance with the License. A copy of the
* License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
#include "cmdlineparser.h"
#include <iostream>
#include <cstring>
#include <unordered_map>
// XRT includes
#include "experimental/xrt_bo.h"
#include "experimental/xrt_ip.h"
#include "experimental/xrt_device.h"
#include "experimental/xrt_kernel.h"
#include "experimental/xrt_xclbin.h"
#define MMIO_CTL_ADDR 0x00
#define MMIO_DEV_ADDR 0x10
#define MMIO_ISA_ADDR 0x1C
#define MMIO_DCR_ADDR 0x28
#define CTL_AP_START (1<<0)
#define CTL_AP_DONE (1<<1)
#define CTL_AP_IDLE (1<<2)
#define CTL_AP_READY (1<<3)
#define CTL_AP_RESET (1<<4)
#define CTL_AP_RESTART (1<<7)
#define DCR_BASE_STARTUP_ADDR 1
#define BANK_SIZE 0x10000000
#define NUM_BANKS 16
uint32_t count = 16;
uint32_t args_addr = 0x7ffff000;
uint32_t kernel_addr = 0x80000000;
uint32_t src_addr = 0x20000000;
uint32_t dst_addr = 0x10000000;
uint32_t kernel_bin [] = {
0x008000ef, // jal ra,80000008 <main>
0x0000000b, // 0xb
0x7ffff7b7, // lui a5,0x7ffff
0x0007a703, // lw a4,0(a5) # 7ffff000 <reg_t6+0x7fffefe1>
0x0047a683, // lw a3,4(a5)
0x0087a583, // lw a1,8(a5)
0xcc5027f3, // csrr a5,0xcc5
0x02e787b3, // mul a5,a5,a4
0x02070863, // beqz a4,80000050 <main+0x48>
0x00f70733, // add a4,a4,a5
0x00271713, // slli a4,a4,0x2
0x00279793, // slli a5,a5,0x2
0x00d787b3, // add a5,a5,a3
0x00d70733, // add a4,a4,a3
0x40d585b3, // sub a1,a1,a3
0x0007a603, // lw a2,0(a5)
0x00f586b3, // add a3,a1,a5
0x00478793, // addi a5,a5,4
0x00c6a023, // sw a2,0(a3)
0xfef718e3, // bne a4,a5,8000003c <main+0x34>
0x00008067 // ret
};
typedef struct {
uint32_t count;
uint32_t src_addr;
uint32_t dst_addr;
} kernel_args_t;
static int get_bank_info(uint64_t dev_addr, uint32_t* pIdx, uint32_t* pOff) {
uint32_t index = dev_addr / BANK_SIZE;
uint32_t offset = dev_addr % BANK_SIZE;
if (index > NUM_BANKS) {
fprintf(stderr, "[VXDRV] 0xaddress // out of range: 0x%lx\n", dev_addr);
return -1;
}
*pIdx = index;
*pOff = offset;
return 0;
}
class ResourceManager {
public:
xrt::bo get_buffer(xrt::device& device, uint32_t bank_id) {
auto it = xrtBuffers_.find(bank_id);
if (it != xrtBuffers_.end()) {
return it->second;
} else {
xrt::bo xrtBuffer(device, BANK_SIZE, xrt::bo::flags::normal, bank_id);
xrtBuffers_.insert({bank_id, xrtBuffer});
return xrtBuffer;
}
}
private:
struct buf_cnt_t {
xrt::bo xrtBuffer;
uint32_t count;
};
std::unordered_map<uint32_t, xrt::bo> xrtBuffers_;
};
void wait_for_enter(const std::string &msg) {
std::cout << msg << std::endl;
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
int main(int argc, char** argv) {
// Command Line Parser
sda::utils::CmdLineParser parser;
// Switches
//**************//"<Full Arg>", "<Short Arg>", "<Description>", "<Default>"
parser.addSwitch("--xclbin_file", "-x", "input binary file string", "");
parser.addSwitch("--device_id", "-d", "device index", "0");
parser.parse(argc, argv);
// Read settings
std::string binaryFile = parser.value("xclbin_file");
int device_index = stoi(parser.value("device_id"));
if (argc < 3) {
parser.printHelp();
return EXIT_FAILURE;
}
ResourceManager res_mgr;
std::cout << "Open the device" << device_index << std::endl;
auto device = xrt::device(device_index);
std::cout << "Load the xclbin " << binaryFile << std::endl;
auto uuid = device.load_xclbin(binaryFile);
std::cout << "Load the kernel ip" << std::endl;
auto ip = xrt::ip(device, uuid, "vortex_afu");
std::cout << "Reset device..." << std::endl;
ip.write_register(MMIO_CTL_ADDR, CTL_AP_RESET);
// Update DCRs
ip.write_register(MMIO_DCR_ADDR, DCR_BASE_STARTUP_ADDR);
ip.write_register(MMIO_DCR_ADDR + 4, kernel_addr);
uint32_t kernel_idx;
uint32_t kernel_offset;
get_bank_info(kernel_addr, &kernel_idx, &kernel_offset);
auto kernel_bo = res_mgr.get_buffer(device, kernel_idx);
uint32_t args_idx;
uint32_t args_offset;
get_bank_info(args_addr, &args_idx, &args_offset);
auto args_bo = res_mgr.get_buffer(device, args_idx);
uint32_t src_idx;
uint32_t src_offset;
get_bank_info(src_addr, &src_idx, &src_offset);
auto src_bo = res_mgr.get_buffer(device, src_idx);
uint32_t dst_idx;
uint32_t dst_offset;
get_bank_info(dst_addr, &dst_idx, &dst_offset);
auto dst_bo = res_mgr.get_buffer(device, dst_idx);
std::cout << "Upload kernel (bank=" << kernel_idx << ", offset=" << kernel_offset << ")..." << std::endl;
uint32_t kernel_size = sizeof(kernel_bin);
kernel_bo.write(kernel_bin, kernel_size, kernel_offset);
kernel_bo.sync(XCL_BO_SYNC_BO_TO_DEVICE, kernel_size, kernel_offset);
std::cout << "Upload kernel arguments (bank=" << args_idx << ", offset=" << args_offset << ")..." << std::endl;
kernel_args_t kernel_args{count, src_addr, dst_addr};
uint32_t args_size = sizeof(kernel_args);
args_bo.write(&kernel_args, args_size, args_offset);
args_bo.sync(XCL_BO_SYNC_BO_TO_DEVICE, args_size, args_offset);
std::cout << "Upload source buffer (bank=" << src_idx << ", offset=" << src_offset << ")..." << std::endl;
uint32_t src_size = count * sizeof(uint32_t);
{
auto src_map = reinterpret_cast<uint32_t*>(src_bo.map<uint8_t*>() + src_offset);
for (uint32_t i = 0; i < count; ++i)
src_map[i] = i;
}
src_bo.sync(XCL_BO_SYNC_BO_TO_DEVICE, src_size, src_offset);
auto dst_size = count * sizeof(uint32_t);
std::cout << "Clear destination buffer (bank=" << dst_idx << ", offset=" << dst_offset << ")..." << std::endl;
{
auto dst_map = reinterpret_cast<uint32_t*>(dst_bo.map<uint8_t*>() + dst_offset);
for (uint32_t i = 0; i < count; ++i)
dst_map[i] = 0xdeadbeef;
}
dst_bo.sync(XCL_BO_SYNC_BO_TO_DEVICE, dst_size, dst_offset);
// Start execution
//wait_for_enter("\nPress ENTER to continue after setting up ILA trigger...");
std::cout << "IP Start..." << std::endl;
ip.write_register(MMIO_CTL_ADDR, CTL_AP_START);
// Wait until the IP is DONE
uint32_t axi_ctrl = 0;
while ((axi_ctrl & CTL_AP_DONE) != CTL_AP_DONE) {
axi_ctrl = ip.read_register(MMIO_CTL_ADDR);
}
std::cout << "IP Done!" << std::endl;
// check output
uint32_t errors = 0;
std::cout << "Download destination buffer (bank=" << dst_idx << ", offset=" << dst_offset << ")..." << std::endl;
dst_bo.sync(XCL_BO_SYNC_BO_FROM_DEVICE, dst_size, dst_offset);
{
auto dst_map = reinterpret_cast<uint32_t*>(dst_bo.map<uint8_t*>() + dst_offset);
for (uint32_t i = 0; i < count; ++i) {
uint32_t ref = i;
if (dst_map[i] != ref) {
std::cout << "Error (" << i << "): actual=" << dst_map[i] << ", expected=" << ref << std::endl;
++errors;
}
}
}
if (errors != 0) {
std::cout << "FAILED!" << std::endl;
return errors;
}
std::cout << "PASSED!" << std::endl;
return 0;
}

View file

@ -1,179 +0,0 @@
/**
* Copyright (C) 2019-2021 Xilinx, Inc
*
* Licensed under the Apache License, Version 2.0 (the "License"). You may
* not use this file except in compliance with the License. A copy of the
* License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
#include "logger.h"
#include <algorithm>
#include <fstream>
#include <functional>
#include <stdarg.h>
#include <time.h>
#ifdef WINDOWS
#include <direct.h>
#else
#include <unistd.h>
#endif
using namespace std;
namespace sda {
///////////////////////////////////////////////////////////////////////
string GetApplicationPath() {
#ifdef WINDOWS
#define GetCurrentDir _getcwd
#else
#define GetCurrentDir getcwd
#endif
char strCurrentPath[FILENAME_MAX];
if (!GetCurrentDir(strCurrentPath, sizeof(strCurrentPath))) {
return string("");
}
/* not really required */
strCurrentPath[sizeof(strCurrentPath) - 1] = '\0';
return string(strCurrentPath);
}
string ToLower(const string& s) {
string result = s;
std::transform(result.begin(), result.end(), result.begin(), ::tolower);
return result;
}
string ToUpper(const string& s) {
string result = s;
std::transform(result.begin(), result.end(), result.begin(), ::toupper);
return result;
}
string GetTimeStamp() {
return "";
}
// trim from start
string& ltrim(std::string& s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
return s;
}
// trim from end
string& rtrim(std::string& s) {
s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
return s;
}
// trim from both ends
string& trim(std::string& s) {
return ltrim(rtrim(s));
}
string GetFileExt(const string& s) {
string strext = s.substr(s.find_last_of(".") + 1);
return strext;
}
string GetFileTitleOnly(const string& s) {
string temp = s;
string::size_type d = temp.find_last_of("//");
if (d == string::npos) d = temp.find_last_of("\\");
if (d != string::npos) temp = temp.substr(d + 1);
d = temp.find_last_of(".");
if (d != string::npos) temp = temp.substr(0, d);
return temp;
}
void LogWrapper(int etype, const char* file, int line, const char* desc, ...) {
// crop file name from full path
string strFileLoc(file);
strFileLoc = strFileLoc.substr(strFileLoc.find_last_of("\\/") + 1);
string strHeader = "";
{
char header[512];
// source
switch (etype) {
case (sda::etError): {
snprintf(header, sizeof(header), "ERROR: [%s:%d]", strFileLoc.c_str(), line);
break;
}
case (sda::etInfo): {
snprintf(header, sizeof(header), "INFO: [%s:%d]", strFileLoc.c_str(), line);
break;
}
case (sda::etWarning): {
snprintf(header, sizeof(header), "WARN: [%s:%d]", strFileLoc.c_str(), line);
break;
}
}
strHeader = string(header);
}
// time
string strTime = "";
#ifdef ENABLE_LOG_TIME
{
time_t rawtime;
time(&rawtime);
#ifdef ENABLE_SECURE_API
char buffer[64];
struct tm timeinfo;
localtime_s(&timeinfo, &rawtime);
asctime_s(timeinfo, buffer, sizeof(buffer)) snprintf(buffer, sizeof(buffer), "TIME: [%s]", asctime(timeinfo));
strTime = string(buffer);
#else
char buffer[64];
struct tm* timeinfo = localtime(&rawtime);
string temp = string(asctime(timeinfo));
temp = trim(temp);
// strftime(buffer, sizeof(buffer), "TIME: []")
snprintf(buffer, sizeof(buffer), "TIME: [%s]", temp.c_str());
strTime = string(buffer);
#endif
}
#endif
// format the message itself
string strMsg = "";
{
char msg[512];
va_list args;
va_start(args, desc);
vsnprintf(msg, sizeof(msg), desc, args);
va_end(args);
strMsg = string(msg);
}
// combine
string strOut = strHeader + string(" ") + strTime + string(" ") + strMsg + string("\n");
// display
cout << strOut;
// store
#ifdef ENABLE_LOG_TOFILE
std::ofstream outfile;
outfile.open("benchapp.log", std::ios_base::app);
outfile << strOut;
#endif
return;
}
} // namespace sda

View file

@ -1,70 +0,0 @@
/**
* Copyright (C) 2019-2021 Xilinx, Inc
*
* Licensed under the Apache License, Version 2.0 (the "License"). You may
* not use this file except in compliance with the License. A copy of the
* License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
#ifndef LOGGER_H_
#define LOGGER_H_
#include <iomanip>
#include <iostream>
#include <string>
#include <vector>
#define ENABLE_LOG_TOFILE 1
#define ENABLE_LOG_TIME 1
// global logging
#define LogInfo(desc, ...) sda::LogWrapper(0, __FILE__, __LINE__, desc, ##__VA_ARGS__)
#define LogWarn(desc, ...) sda::LogWrapper(1, __FILE__, __LINE__, desc, ##__VA_ARGS__)
#define LogError(desc, ...) sda::LogWrapper(2, __FILE__, __LINE__, desc, ##__VA_ARGS__)
using namespace std;
namespace sda {
enum LOGTYPE { etInfo, etWarning, etError };
// string
string& ltrim(string& s);
string& rtrim(string& s);
string& trim(string& s);
string GetFileExt(const string& s);
string GetFileTitleOnly(const string& s);
string ToLower(const string& s);
string ToUpper(const string& s);
// time
string GetTimeStamp();
// paths
string GetApplicationPath();
// debug
template <typename T>
void PrintPOD(const vector<T>& pod, size_t display_count = 0, const int precision = 4) {
size_t count = pod.size();
if (display_count > 0) count = std::min<size_t>(pod.size(), display_count);
for (size_t i = 0; i < count; i++) {
cout << std::setprecision(precision) << pod[i] << ", ";
}
cout << endl;
}
// logging
void LogWrapper(int etype, const char* file, int line, const char* desc, ...);
}
#endif /* LOGGER_H_ */

View file

@ -1,9 +0,0 @@
[connectivity]
#nk=vortex_afu:1
#sp=vortex_afu_1.m_axi_mem:HBM[0:15]
[vivado]
#prop=fileset.sim_1.xsim.elaborate.debug_level=all
[advanced]
#param=compiler.userPostDebugProfileOverlayTcl=../scripts/post_dbg_profile_overlay.tcl

View file

@ -1,11 +0,0 @@
[Runtime]
runtime_log=console
[Emulation]
#debug_mode=gui
#user_pre_sim_script=xsim.tcl
[Debug]
profile=true
timeline_trace=true
data_transfer_trace=fine