Open-source repository: https://github.com/BJUT-CS316-LAB/ContractHIL-HLS
ContractHIL-HLS is a contract-aligned multi-agent workflow for practical HLS design. The repository contains two reproducible artifacts:
ai_hls_assistant/: the self-written Python tools and prompt templates used to evaluate direct prompting, contract prompting, and the full ContractHIL-HLS prompt regime on HLS-Eval.single_bitstream/anddual_bitstream/: a board-tested ML-KEM-512 + ML-DSA-44 + XOR secure-message accelerator for AMD Kria KV260.
The first artifact reproduces the paper's small-design contract-alignment experiment. The second artifact reproduces the PQC hardware-in-the-loop case study, including single-bitstream and dual-bitstream organizations.
ai_hls_assistant/ Self-written HLS-Eval prompt templates and Python tools
single_bitstream/ One-bitstream PQC accelerator source, Tcl, and PYNQ host flow
dual_bitstream/ Split KEM and DSA/XOR PQC accelerator source, Tcl, and PYNQ host flow
notebooks/ PYNQ notebook/linear demos for board execution
Generated Vivado/HLS projects, logs, API responses, bitstreams, reports, raw benchmarks, and local board data are intentionally ignored by Git unless they are small source artifacts needed for reproduction.
This repository intentionally keeps only one README file: this root
README.md. Subdirectory notes are folded into this document so the GitHub
entry point stays unambiguous.
The workflow was developed with:
- Python 3.10+
- Vitis HLS / Vivado 2025.2.x on the build host
- PYNQ 3.x on AMD Kria KV260 for board execution
- An OpenAI-compatible Responses API for the LLM-based HLS-Eval runs
Before running HLS or Vivado commands, load the Xilinx environment in your shell, for example:
source /tools/Xilinx/Vivado/2025.2/settings64.shFor LLM experiments, create a local API configuration:
cp .env.example .env
# edit .env and set OPENAI_API_KEY, OPENAI_MODEL, and OPENAI_RESPONSES_URLThe .env file is ignored by Git.
This path reproduces the HLS-Eval experiment used to test whether contracts improve small HLS design generation. Run the commands from the repository root.
The committed ai_hls_assistant/ tree contains only:
benchmarks/hlseval/tools/*.py: local preparation, prompting, scoring, and independent synthesis scripts.benchmarks/hlseval/prompts/*.md: direct, contract, and ContractHIL-HLS prompt templates plus the fixed method-prior pack.
It does not commit the HLS-Eval checkout itself, generated task JSON files, model request/response logs, result summaries, or generated HLS workspaces.
The raw HLS-Eval benchmark is external and is not committed into this
repository. Clone it under the ignored raw/ directory:
git clone https://github.com/stefanpie/hls-eval.git \
ai_hls_assistant/benchmarks/hlseval/rawpython3 ai_hls_assistant/benchmarks/hlseval/tools/prepare_full.pyThis creates the locally executable full_valid task set under
ai_hls_assistant/benchmarks/hlseval/generated_tasks/.
Use a dry run first to verify task discovery and prompt rendering without sending API requests:
python3 ai_hls_assistant/benchmarks/hlseval/tools/run_stage1_llm.py \
--task-set full_valid \
--regimes baseline_hlseval,nl_structured_hlseval,nl_structured_lit_hlseval \
--repeats 5 \
--dry-run \
--output-dir ai_hls_assistant/benchmarks/hlseval/results/dryrun_full94_contracthilpython3 ai_hls_assistant/benchmarks/hlseval/tools/run_stage1_llm.py \
--task-set full_valid \
--regimes baseline_hlseval,nl_structured_hlseval,nl_structured_lit_hlseval \
--repeats 5 \
--workers 3 \
--resume \
--output-dir ai_hls_assistant/benchmarks/hlseval/results/hlseval_contracthil_full94_pass5Prompt regimes:
baseline_hlseval: direct HLS-Eval prompt.nl_structured_hlseval: natural language lowered into a structured contract.nl_structured_lit_hlseval: structured contract plus the fixed HLS method-prior pack, corresponding to the full ContractHIL-HLS prompt regime.
python3 ai_hls_assistant/benchmarks/hlseval/tools/score_stage1_outputs.py \
--task-set full_valid \
--results-dir ai_hls_assistant/benchmarks/hlseval/results/hlseval_contracthil_full94_pass5 \
--run-hls \
--timeout-s 180
python3 ai_hls_assistant/benchmarks/hlseval/tools/run_independent_csynth.py \
--results-dir ai_hls_assistant/benchmarks/hlseval/results/hlseval_contracthil_full94_pass5 \
--task-dir ai_hls_assistant/benchmarks/hlseval/generated_tasks/full_validMain metrics:
Can Parse: generated HLS C/C++ can be extracted.Can Compile: C simulation compilation succeeds.Can Pass TB: C simulation/testbench passes.Can Synth: Vitis HLS synthesis succeeds.pass@1: the first candidate succeeds.pass@5: at least one of five candidates succeeds.
Generated tasks are written under
ai_hls_assistant/benchmarks/hlseval/generated_tasks/; generated results are
written under ai_hls_assistant/benchmarks/hlseval/results/. Both directories
are ignored by Git.
The PQC artifact implements an ML-KEM-512 + ML-DSA-44 + XOR secure-message flow. The single-bitstream design is the functional baseline. The dual-bitstream design is the hardware-in-the-loop case-study result used in the paper.
Run C simulation:
g++ -std=c++17 -O2 -Wno-unknown-pragmas -Isingle_bitstream/hls/include \
single_bitstream/hls/top/pqc_accel.cpp \
single_bitstream/hls/tb/tb_pqc_accel.cpp \
-o /tmp/pqc_single_tb
/tmp/pqc_single_tbRun HLS and build the KV260 bitstream:
vitis-run --mode hls --tcl single_bitstream/hls/scripts/run_hls_single_seq.tcl
vivado -mode batch -source single_bitstream/vivado/scripts/build_single_seq_bitstream.tclExpected generated outputs:
single_bitstream/vivado/final/design_1_wrapper.bit
single_bitstream/vivado/final/design_1_wrapper.hwh
single_bitstream/vivado/final/design_1_wrapper.xclbin
single_bitstream/vivado/reports/
Run the PYNQ host flow on KV260:
python3 single_bitstream/host/pynq_flow.py \
--bit single_bitstream/vivado/final/design_1_wrapper.bit \
--xclbin single_bitstream/vivado/final/design_1_wrapper.xclbinRun C simulation for the KEM and DSA/XOR IPs:
g++ -std=c++17 -O2 -Wno-unknown-pragmas -Idual_bitstream/hls/include \
dual_bitstream/hls/top/pqc_kem_accel.cpp \
dual_bitstream/hls/tb/tb_pqc_kem_accel.cpp \
-o /tmp/pqc_kem_tb
/tmp/pqc_kem_tb
g++ -std=c++17 -O2 -Wno-unknown-pragmas -Idual_bitstream/hls/include \
dual_bitstream/hls/top/pqc_dsa_accel.cpp \
dual_bitstream/hls/tb/tb_pqc_dsa_accel.cpp \
-o /tmp/pqc_dsa_tb
/tmp/pqc_dsa_tbRun HLS and build both bitstreams:
vitis-run --mode hls --tcl dual_bitstream/hls/scripts/run_hls_kem.tcl
vivado -mode batch -source dual_bitstream/vivado/scripts/build_kem_bitstream.tcl
vitis-run --mode hls --tcl dual_bitstream/hls/scripts/run_hls_dsa.tcl
vivado -mode batch -source dual_bitstream/vivado/scripts/build_dsa_bitstream.tclExpected generated outputs:
dual_bitstream/vivado/kem/final/design_1_wrapper.bit
dual_bitstream/vivado/kem/final/design_1_wrapper.hwh
dual_bitstream/vivado/dsa/final/design_1_wrapper.bit
dual_bitstream/vivado/dsa/final/design_1_wrapper.hwh
Run the dual-bitstream PYNQ host flow:
python3 dual_bitstream/host/pynq_split_flow.py \
--kem-bit dual_bitstream/vivado/kem/final/design_1_wrapper.bit \
--dsa-bit dual_bitstream/vivado/dsa/final/design_1_wrapper.bitFor a step-by-step demo in the original operator order 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7, use:
python3 notebooks/pqc_dual_8mode_demo_linear.pyThe dual flow stages public keys, secret keys, ciphertexts, signatures, and message buffers in DDR before switching bitstreams, so a reloaded bitstream does not depend on stale PL-local state.
If you prefer notebook execution, copy the generated *.bit and *.hwh files
to the board with this layout:
/root/jupyter_notebooks/ContractHIL-HLS/
notebooks/pqc_8mode_demo.ipynb
notebooks/pqc_dual_8mode_demo.ipynb
notebooks/plaintext.txt
single_bitstream/design_1_wrapper.bit
single_bitstream/design_1_wrapper.hwh
dual_bitstream/kem/design_1_wrapper.bit
dual_bitstream/kem/design_1_wrapper.hwh
dual_bitstream/dsa/design_1_wrapper.bit
dual_bitstream/dsa/design_1_wrapper.hwh
To change the plaintext without editing notebooks, place plaintext.json next
to the notebook:
{"plaintext": "your message here"}or:
{"plaintext_hex": "48656c6c6f"}Before committing, check:
git status --short --ignoredThe following should remain ignored:
.envand API keys- raw HLS-Eval data, generated task JSON files, and generated LLM responses
logs/,reports/,.Xil/- regenerated Vitis HLS and Vivado project directories
*.bit,*.hwh,*.xsa,*.xclbin,*.dcp, and routed reports- local board-reference data under
reference/and helper scratch undertools/
Only source code, prompt templates, notebooks, Tcl scripts, and this root documentation should be committed.