Download pcie/Makefile from Snapkitty/bit-string-accelerator: direct link, hf CLI and curl.
- Browser
- Download file 7.29 kB
-
https://huggingface.co/Snapkitty/bit-string-accelerator/resolve/main/pcie/Makefile
- Command line
-
hf download hf://Snapkitty/bit-string-accelerator/pcie/Makefile
-
curl -L -o Makefile https://huggingface.co/Snapkitty/bit-string-accelerator/resolve/main/pcie/Makefile
7.29 kB
| # PCIe accelerator: parallel engine, PCIe-facing core, LiteX SoC for the | |
| # LiteFury, and the host program. | |
| # | |
| # make lint verilator -Wall on the engine and the PCIe core | |
| # make sim engine vs the single-op reference core: several | |
| # geometries and seeds (Icarus); core with 128-bit streams. | |
| # The runs are independent targets: use make -j. | |
| # make sim-verilator the engine testbench under Verilator | |
| # make soc generate the LiteX SoC sources and Linux driver (no Vivado) | |
| # make cosim host program (host/bitacc_pcie.c) against the Verilated core | |
| # through a liblitepcie stand-in (needs `make soc` first) | |
| # make perf engine throughput in clock cycles at the LiteFury geometry | |
| # (8 lanes x 2048 words): host bench against the Verilated core | |
| # make timing open-source place and route for the XC7A100T (nextpnr-xilinx; | |
| # set NEXTPNR and CHIPDB, see timing/run.sh): Fmax estimate | |
| # make bitstream full build with Vivado (not available in CI) | |
| # | |
| # The engine testbench fails unless results and final memory equal the | |
| # reference, and unless out-of-order completion, a full reorder buffer, both | |
| # directions of the range barrier and every operation class (single-bit and | |
| # range; in range, out of range, wrapping, undefined) occurred. | |
| # | |
| # A testbench passes only if vvp exits 0 and prints PASS. (Piping vvp into | |
| # grep would report the grep's status, so a failing run would pass.) | |
| IVERILOG ?= iverilog | |
| VVP ?= vvp | |
| VERILATOR ?= verilator | |
| PYTHON ?= python3 | |
| BUILD ?= build | |
| OPS ?= 4000 | |
| REF := ../rtl/bit_accelerator.sv | |
| ENGINE := rtl/bitacc_engine.sv | |
| CORE := rtl/bitacc_pcie_core.sv | |
| SOC_DIR := $(abspath $(BUILD))/litefury | |
| DRIVER := $(SOC_DIR)/driver | |
| GEOMETRIES := 2x4 4x16 8x16 8x512 | |
| SEEDS := 1 7 | |
| TB_INC := tb/gold_ops.svh tb/range_stim.svh | |
| # plus 16 lanes, a build without the MATCH unit (opcode 15 must be an error), and | |
| # matchers with fewer units than lanes (run-ml-<lanes>x<words>-<units>) | |
| ENGINE_RUNS := $(foreach g,$(GEOMETRIES),$(foreach s,$(SEEDS),run-$(g)-$(s))) run-16x8-1 | |
| # $(call vvp_check,command,log): run, show the summary, fail unless exit 0 and PASS. | |
| define vvp_check | |
| $(1) > $(2) 2>&1; rc=$$?; grep -E '^(stimulus|range coverage|match coverage|checks|PASS|FAIL)' $(2); \ | |
| test $$rc -eq 0 && grep -q '^PASS' $(2) | |
| endef | |
| .DEFAULT_GOAL := all | |
| all: lint sim sim-verilator | |
| lint: | |
| $(VERILATOR) --lint-only -Wall $(ENGINE) | |
| $(VERILATOR) --lint-only -Wall $(ENGINE) $(CORE) --top-module bitacc_pcie_core | |
| sim: sim-engine sim-core | |
| ML_RUNS := run-ml-4x16-1 run-ml-8x16-2 | |
| sim-engine: $(ENGINE_RUNS) run-nomatch $(ML_RUNS) | |
| $(ML_RUNS): run-ml-%: $(BUILD)/tb_ml_%.vvp | |
| @echo "engine $* (lanes x words - MATCH units)" | |
| @$(call vvp_check,$(VVP) -n $< +seed=3 +ops=$(OPS),$(BUILD)/run-ml-$*.log) | |
| $(BUILD)/tb_ml_%.vvp: $(REF) $(ENGINE) tb/tb_engine.sv $(TB_INC) | |
| @mkdir -p $(BUILD) | |
| c=$*; g=$${c%-*}; m=$${c#*-}; \ | |
| $(IVERILOG) -g2012 -Itb -DLANES=$${g%x*} -DWPL=$${g#*x} -DMLANES=$$m -o $@ $(REF) $(ENGINE) tb/tb_engine.sv | |
| # run-<lanes>x<words per lane>-<seed> | |
| .SECONDEXPANSION: | |
| $(ENGINE_RUNS): run-%: $(BUILD)/tb_$$(word 1,$$(subst -, ,$$*)).vvp | |
| @echo "engine $*" | |
| @$(call vvp_check,$(VVP) -n $< +seed=$(word 2,$(subst -, ,$*)) +ops=$(OPS),$(BUILD)/run-$*.log) | |
| run-nomatch: $(BUILD)/tb_nomatch.vvp | |
| @echo "engine 4x16 without MATCH" | |
| @$(call vvp_check,$(VVP) -n $< +seed=1 +ops=$(OPS),$(BUILD)/run-nomatch.log) | |
| $(BUILD)/tb_nomatch.vvp: $(REF) $(ENGINE) tb/tb_engine.sv $(TB_INC) | |
| @mkdir -p $(BUILD) | |
| $(IVERILOG) -g2012 -Itb -DLANES=4 -DWPL=16 -DMATCH=0 -o $@ $(REF) $(ENGINE) tb/tb_engine.sv | |
| $(BUILD)/tb_%.vvp: $(REF) $(ENGINE) tb/tb_engine.sv $(TB_INC) | |
| @mkdir -p $(BUILD) | |
| g=$*; $(IVERILOG) -g2012 -Itb -DLANES=$${g%x*} -DWPL=$${g#*x} -o $@ $(REF) $(ENGINE) tb/tb_engine.sv | |
| sim-core: | |
| @mkdir -p $(BUILD) | |
| $(IVERILOG) -g2012 -Itb -o $(BUILD)/tb_core.vvp $(REF) $(ENGINE) $(CORE) tb/tb_pcie_core.sv | |
| @$(call vvp_check,$(VVP) -n $(BUILD)/tb_core.vvp,$(BUILD)/core.log) | |
| # --output-split-cfuncs 0: Verilator 5.020 splits the testbench's main initial | |
| # block (a coroutine with a fork) across C++ functions and drops the code that | |
| # waits for the join; the binary then crashes (illegal instruction). | |
| sim-verilator: | |
| @mkdir -p $(BUILD) | |
| $(VERILATOR) --binary --timing --timescale 1ns/1ps -Wno-fatal -Wno-lint -Wno-style -Itb --output-split-cfuncs 0 \ | |
| --top-module tb_engine -Mdir $(BUILD)/verilator $(REF) $(ENGINE) tb/tb_engine.sv >/dev/null | |
| @$(call vvp_check,$(BUILD)/verilator/Vtb_engine +ops=$(OPS),$(BUILD)/verilator.log) | |
| soc: | |
| cd litex && $(PYTHON) bitacc_litefury.py --driver --output-dir $(SOC_DIR) | |
| # $(call cosim_build,dir,lanes,words per lane[,MATCH units]): host program + Verilated core + mock. | |
| define cosim_build | |
| @test -d $(DRIVER) || { echo "run 'make soc' first"; exit 1; } | |
| @mkdir -p $(1) | |
| cc -O2 -Wall -Wextra -Werror -I$(DRIVER)/user/liblitepcie -I$(DRIVER)/kernel \ | |
| -c -o $(abspath $(1))/bitacc_pcie.o host/bitacc_pcie.c | |
| $(VERILATOR) --cc --exe --build -O2 --timescale 1ns/1ps -Wno-fatal -Wno-lint \ | |
| -GLANES=$(2) -GWORDS_PER_LANE=$(3) $(if $(4),-GMATCH_LANES=$(4)) --top-module bitacc_pcie_core -Mdir $(1)/obj \ | |
| -CFLAGS "-I$(DRIVER)/user/liblitepcie -I$(DRIVER)/kernel -DMOCK_LANES=$(2) -DMOCK_WPL=$(3) $(if $(4),-DMOCK_MATCH_LANES=$(4))" \ | |
| -LDFLAGS "$(abspath $(1))/bitacc_pcie.o" \ | |
| $(ENGINE) $(CORE) $(abspath host/sim/mock_litepcie.cpp) -o bitacc_pcie_cosim >/dev/null | |
| endef | |
| # Small geometry keeps the co-simulation fast; the host reads it from CSRs. | |
| # Arguments: operations, seed, percentage of range operations. | |
| cosim: | |
| $(call cosim_build,$(BUILD)/cosim,4,64) | |
| $(BUILD)/cosim/obj/bitacc_pcie_cosim selftest 200000 1 5 | |
| $(BUILD)/cosim/obj/bitacc_pcie_cosim selftest 50000 9 50 | |
| # The LiteFury configuration with MATCH: 8 lanes x 2048 words, 2 MATCH units. | |
| # Fails if a bench needs more cycles per descriptor than the design intends: | |
| # single-bit 1 (plus 2%), COUNT/FIND over 16384 words 16384/8 steps of 1 | |
| # cycle, BULK over 8192 words 8192/8 steps of 2 cycles, MATCH over 16384 | |
| # words 16384/2 sub-steps of 1 cycle (plus 1% and a fixed allowance for | |
| # pipeline fill and the MATCH pattern load). | |
| perf: | |
| $(call cosim_build,$(BUILD)/perf,8,2048,2) | |
| $(BUILD)/perf/obj/bitacc_pcie_cosim selftest 20000 3 20 | |
| @for kl in get:1.02 count:2084 find:2084 xor:2084 match:8300; do \ | |
| k=$${kl%:*}; limit=$${kl#*:}; n=$$( [ $$k = get ] && echo 200000 || echo 2048 ); \ | |
| out=$$($(BUILD)/perf/obj/bitacc_pcie_cosim bench $$k $$n 2>&1) || { echo "$$out"; exit 1; }; \ | |
| echo "$$out" | grep -E '^(bench|mock)'; \ | |
| echo "$$out" | awk -v l=$$limit '/^mock:/ { c = $$(NF-1) } END { if (c == "" || c + 0 > l) { print "cycles/descriptor " c " above " l; exit 1 } }' || exit 1; \ | |
| done | |
| TIMING_CONFIGS ?= 8:2048:1:2 8:2048:0 | |
| timing: | |
| @set -e; cd timing; for c in $(TIMING_CONFIGS); do \ | |
| echo "== $$c (lanes:words per lane:MATCH)"; ./run.sh $$(echo $$c | tr ':' ' '); done | |
| bitstream: | |
| cd litex && $(PYTHON) bitacc_litefury.py --build --driver --output-dir $(SOC_DIR) | |
| clean: | |
| rm -rf $(BUILD) host/build_cosim | |