The lock and reloads. load takes the board lock before it reconfigures, and the session check sees other runs of this tool and its scripts (their own parents excepted), so a reload waits for the job that holds the board. The scripts do not hold the lock across the steps they run. A reload of the same design, which passes the signature and the ID, is seen by the engine's uptime counter and its reset BOUND register: the engine checks both before it takes a workload or a table as loaded and after every job, and refuses a result read across a reload. A batch that comes back short, and a sampled chain whose sweep count is wrong, are refused. The AXI port. It checks the port's write width as well as its read width; it fills a result page with the illegal cell pair before a write-back and refuses a result still holding it; it refuses a transfer whose page moved. It is written against two traits, so a software link tests it off the board: the guard, the DMA, the sequencer's count, the write-back's layout, dropped accesses. Tests. lowered_settle's five cases and 300 random workloads with fields to 2^40 against the reference; the joint test counts against the chains requested and checks the control's cell family. CI gates on the change, requires tests to run, denies clippy warnings, certifies the model member, runs a job on it, builds on linux-arm64, and replays both testbenches in Icarus Verilog (scripts/run_tb.sh). The names check reads .v, .tcl, .xdc and .dat files. The build. The tool version and each block's version are enforced; the multi-core build refuses the AXI link. The documents. The latency table says how each row was timed; the engine's share of a chain is its own clock count; the sampling energy carries its error and its floor; the known answer is placed in time; the step response is reported; derived figures are marked; the scope of the meter, the guard's window and the DMA's locked pages are stated; provenance says what the private code declared; old names are gone; the build and simulator results have a raw record. Co-Authored-By: Claude Opus 5.5 <[email protected]>
121 lines
7 KiB
Tcl
121 lines
7 KiB
Tcl
# SPDX-License-Identifier: Apache-2.0
|
|
# Bitstream build for the energy-landscape engine. Vivado batch mode:
|
|
# vivado -mode batch -source landscape.tcl -tclargs [FREQ <MHz>] [TAG <name>] [JOBS <n>] [CORES <k>] [LINK emio|axi]
|
|
# The part and board are data: PART and BOARD below. There is no programmable-logic I/O: the
|
|
# processing system provides the clock and the link. LINK axi (the default on one engine) gives an
|
|
# AXI-Lite register port, a write-list DMA from DDR and an in-fabric chain sequencer
|
|
# (rtl/landscape_axi.v); LINK emio carries register accesses over the EMIO GPIO lines, and is the
|
|
# only link of the multi-core build. Every block below is the vendor's no-charge processing-system
|
|
# configuration or AXI infrastructure; no licensed IP. The tool and block versions are the ones this
|
|
# design was built and measured with, and a different tool stops the build: set ANY_TOOL to go on,
|
|
# and expect a different bitstream.
|
|
set part xck26-sfvc784-2LV-c
|
|
set board xilinx.com:kv260_som:part0:2.0
|
|
proc arg {name dflt} {
|
|
global argv
|
|
set i [lsearch $argv $name]
|
|
if {$i >= 0 && [llength $argv] > $i + 1} { return [lindex $argv [expr {$i + 1}]] }
|
|
return $dflt
|
|
}
|
|
set freq [arg FREQ 100]
|
|
set tag [arg TAG landscape]
|
|
set jobs [arg JOBS 4]
|
|
set cores [arg CORES 1]
|
|
set link [arg LINK [expr {$cores > 1 ? "emio" : "axi"}]]
|
|
if {$cores > 1 && $link ne "emio"} { error "the multi-core build has the EMIO link only" }
|
|
set tool 2026.1
|
|
if {[version -short] ne $tool && ![info exists ::env(ANY_TOOL)]} {
|
|
error "this design was built and measured with Vivado $tool, not [version -short]: set ANY_TOOL to build anyway"
|
|
}
|
|
# Each block by its exact version.
|
|
proc block {name version} {
|
|
set d [get_ipdefs -all xilinx.com:ip:$name:$version]
|
|
if {$d eq ""} { error "no $name $version in this tool" }
|
|
return [lindex $d 0]
|
|
}
|
|
set here [file dirname [file normalize [info script]]]
|
|
puts "BUILD: tag=$tag freq=$freq jobs=$jobs cores=$cores link=$link here=$here"
|
|
create_project ev_$tag ./ev_$tag -part $part -force
|
|
set_property board_part $board [current_project]
|
|
|
|
create_bd_design sys
|
|
create_bd_cell -type ip -vlnv [block zynq_ultra_ps_e 3.5] ps
|
|
apply_bd_automation -rule xilinx.com:bd_rule:zynq_ultra_ps_e -config {apply_board_preset 1} [get_bd_cells ps]
|
|
set_property -dict [list \
|
|
CONFIG.PSU__FPGA_PL0_ENABLE {1} \
|
|
CONFIG.PSU__CRL_APB__PL0_REF_CTRL__FREQMHZ $freq \
|
|
CONFIG.PSU__USE__M_AXI_GP0 {0} CONFIG.PSU__USE__M_AXI_GP1 {0} CONFIG.PSU__USE__M_AXI_GP2 {0} \
|
|
CONFIG.PSU__GPIO_EMIO__PERIPHERAL__ENABLE {1} \
|
|
CONFIG.PSU__GPIO_EMIO__PERIPHERAL__IO {95} \
|
|
] [get_bd_cells ps]
|
|
create_bd_port -dir O -from 94 -to 0 emio_o
|
|
create_bd_port -dir I -from 94 -to 0 emio_i
|
|
connect_bd_net [get_bd_pins ps/emio_gpio_o] [get_bd_ports emio_o]
|
|
connect_bd_net [get_bd_pins ps/emio_gpio_i] [get_bd_ports emio_i]
|
|
create_bd_port -dir O -type clk pl_clk0
|
|
connect_bd_net [get_bd_pins ps/pl_clk0] [get_bd_ports pl_clk0]
|
|
if {$link eq "axi"} {
|
|
# The two port widths are the ones this board's boot leaves set (src/axi.rs, ps_ports): loading
|
|
# a bitstream through the FPGA manager does not change them, so the design meets them as they
|
|
# are and writes no processor register. M_AXI_HPM0_FPD (128-bit) -> width converter -> protocol
|
|
# converter -> LITE (32-bit) at 0xA000_0000, 256 KiB. DMA (AXI4, 64-bit) -> width converter ->
|
|
# S_AXI_HP0_FPD (128-bit) -> DDR. The reset is the fabric's own (aresetn).
|
|
set_property -dict [list CONFIG.PSU__USE__M_AXI_GP0 {1} CONFIG.PSU__MAXIGP0__DATA_WIDTH {128} \
|
|
CONFIG.PSU__USE__S_AXI_GP2 {1} CONFIG.PSU__SAXIGP2__DATA_WIDTH {128}] [get_bd_cells ps]
|
|
connect_bd_net [get_bd_pins ps/pl_clk0] [get_bd_pins ps/maxihpm0_fpd_aclk]
|
|
connect_bd_net [get_bd_pins ps/pl_clk0] [get_bd_pins ps/saxihp0_fpd_aclk]
|
|
create_bd_port -dir I -type rst aresetn
|
|
set dw [block axi_dwidth_converter 2.1]
|
|
create_bd_cell -type ip -vlnv $dw down
|
|
create_bd_cell -type ip -vlnv $dw up
|
|
set_property -dict [list CONFIG.SI_DATA_WIDTH {128} CONFIG.MI_DATA_WIDTH {32}] [get_bd_cells down]
|
|
set_property -dict [list CONFIG.SI_DATA_WIDTH {64} CONFIG.MI_DATA_WIDTH {128}] [get_bd_cells up]
|
|
create_bd_cell -type ip -vlnv [block axi_protocol_converter 2.1] conv
|
|
set_property -dict [list CONFIG.SI_PROTOCOL {AXI4} CONFIG.MI_PROTOCOL {AXI4LITE} CONFIG.DATA_WIDTH {32}] [get_bd_cells conv]
|
|
foreach c {down up} {
|
|
connect_bd_net [get_bd_pins ps/pl_clk0] [get_bd_pins $c/s_axi_aclk]
|
|
connect_bd_net [get_bd_ports aresetn] [get_bd_pins $c/s_axi_aresetn]
|
|
}
|
|
connect_bd_net [get_bd_pins ps/pl_clk0] [get_bd_pins conv/aclk]
|
|
connect_bd_net [get_bd_ports aresetn] [get_bd_pins conv/aresetn]
|
|
connect_bd_intf_net [get_bd_intf_pins ps/M_AXI_HPM0_FPD] [get_bd_intf_pins down/S_AXI]
|
|
connect_bd_intf_net [get_bd_intf_pins down/M_AXI] [get_bd_intf_pins conv/S_AXI]
|
|
create_bd_intf_port -mode Master -vlnv xilinx.com:interface:aximm_rtl:1.0 LITE
|
|
set_property -dict [list CONFIG.PROTOCOL {AXI4LITE} CONFIG.ADDR_WIDTH {32} CONFIG.DATA_WIDTH {32}] [get_bd_intf_ports LITE]
|
|
connect_bd_intf_net [get_bd_intf_pins conv/M_AXI] [get_bd_intf_ports LITE]
|
|
create_bd_intf_port -mode Slave -vlnv xilinx.com:interface:aximm_rtl:1.0 DMA
|
|
set_property -dict [list CONFIG.PROTOCOL {AXI4} CONFIG.ADDR_WIDTH {49} CONFIG.DATA_WIDTH {64} CONFIG.ID_WIDTH {0} \
|
|
CONFIG.HAS_REGION {0} CONFIG.HAS_QOS {0} CONFIG.HAS_LOCK {0}] [get_bd_intf_ports DMA]
|
|
connect_bd_intf_net [get_bd_intf_ports DMA] [get_bd_intf_pins up/S_AXI]
|
|
connect_bd_intf_net [get_bd_intf_pins up/M_AXI] [get_bd_intf_pins ps/S_AXI_HP0_FPD]
|
|
set_property CONFIG.ASSOCIATED_BUSIF {LITE:DMA} [get_bd_ports pl_clk0]
|
|
set_property CONFIG.ASSOCIATED_RESET {aresetn} [get_bd_ports pl_clk0]
|
|
assign_bd_address
|
|
set lite [get_bd_addr_segs -of_objects [get_bd_addr_spaces ps/Data] -filter {NAME =~ *LITE*}]
|
|
set_property offset 0xA0000000 $lite
|
|
set_property range 256K $lite
|
|
foreach seg [get_bd_addr_segs -of_objects [get_bd_addr_spaces ps/Data]] { puts "ADDR $seg [get_property offset $seg] [get_property range $seg]" }
|
|
}
|
|
validate_bd_design
|
|
make_wrapper -files [get_files sys.bd] -top -import
|
|
generate_target all [get_files sys.bd]
|
|
|
|
if {$cores > 1} {
|
|
add_files [list $here/rtl/landscape_top_multi.v $here/rtl/landscape_multi.v $here/rtl/landscape_core.v]
|
|
set_property verilog_define [list LANDSCAPE_K=$cores] [current_fileset]
|
|
} elseif {$link eq "axi"} {
|
|
add_files [list $here/rtl/landscape_top_axi.v $here/rtl/landscape_axi.v $here/rtl/landscape_core.v]
|
|
} else {
|
|
add_files [list $here/rtl/landscape_top.v $here/rtl/landscape_port.v $here/rtl/landscape_core.v]
|
|
}
|
|
add_files -fileset constrs_1 $here/rtl/landscape.xdc
|
|
set_property top design_top [current_fileset]
|
|
update_compile_order -fileset sources_1
|
|
|
|
launch_runs impl_1 -to_step write_bitstream -jobs $jobs
|
|
wait_on_run impl_1
|
|
puts "IMPL_STATUS: [get_property STATUS [get_runs impl_1]] PROGRESS: [get_property PROGRESS [get_runs impl_1]]"
|
|
open_run impl_1
|
|
report_utilization -file ev_$tag.util.rpt
|
|
report_timing_summary -max_paths 5 -file ev_$tag.timing.rpt
|
|
puts "BITSTREAM: [glob -nocomplain ./ev_$tag/ev_$tag.runs/impl_1/*.bit]"
|