VSRC_DIR    := ./rtl
PICKER      ?= picker
NAME        := Cache
NAME_L      := cache
SIM         := verilator
WAVE_FORMAT := fst
TARGET_LANG := python
PYTHON      ?= $(shell if command -v python3.11 >/dev/null 2>&1; then command -v python3.11; elif [ -x /opt/homebrew/opt/python@3.11/bin/python3.11 ]; then echo /opt/homebrew/opt/python@3.11/bin/python3.11; else command -v python3; fi)
PYTEST      ?= $(PYTHON) -m pytest
PYTHON_ROOT ?= $(shell "$(PYTHON)" -c 'import sys; print(sys.prefix)' 2>/dev/null || true)
CMAKE_ARGS ?= -DPython3_ROOT_DIR=$(PYTHON_ROOT)
PYTHONPATH_BASE := .:./src:./$(NAME):$(HOME)/.local/share/picker/python
BUG         ?= mask_merge
BUG_RTL     := faults/Cache_$(BUG)_bug.v
FAULT_TESTS ?= tests/test_smoke.py tests/test_directed.py

export PATH := $(HOME)/.local/bin:$(PATH)
export PYTHONPATH := $(PYTHONPATH_BASE):$(PYTHONPATH)

.PHONY: help setup env-check gen_dut ensure-dut test test-model test-hw regression report rtl-coverage coverage clean wave inject-bug inject-mask-bug fault-audit fault-audit-all

help:
	@echo "NutShell Cache verification targets:"
	@echo "  make setup       - install Python dependencies"
	@echo "  make env-check   - print Picker/Verilator/Toffee environment"
	@echo "  make gen_dut     - build Picker Python DUT package from rtl/Cache.v"
	@echo "  make test-model  - run pure Python generator/oracle/scoreboard tests"
	@echo "  make test-hw     - run Toffee hardware tests (requires gen_dut)"
	@echo "  make regression  - model tests + gen_dut + hardware tests"
	@echo "  make report      - regenerate functional coverage helper artifacts"
	@echo "  make rtl-coverage - generate Verilator RTL code coverage report"
	@echo "  make inject-bug BUG=mask_merge|mmio_decode|read_data_lsb"
	@echo "  make fault-audit BUG=mask_merge - build a mutant, expect tests to fail, then restore golden DUT"
	@echo "  make fault-audit-all - run all supported RTL mutant audits"

setup:
	$(PYTHON) -m pip install -r requirements.txt

env-check:
	@PYTHON="$(PYTHON)" PICKER="$(PICKER)" ./scripts/check_env.sh

gen_dut:
	@rm -rf $(NAME)
	$(PICKER) export --autobuild=false $(VSRC_DIR)/$(NAME).v \
		-w $(NAME).$(WAVE_FORMAT) \
		--sname $(NAME) \
		--tdir $(NAME) \
		--lang $(TARGET_LANG) \
		--sim $(SIM) \
		-e -c
	$(PYTHON) scripts/patch_picker_makefiles.py $(NAME)
	CMAKE_ARGS="$(CMAKE_ARGS)" make -C $(NAME)

ensure-dut:
	@if [ ! -d "$(NAME)" ]; then \
		echo "ERROR: missing Picker DUT package '$(NAME)/'. Run 'make gen_dut' before hardware tests."; \
		exit 1; \
	fi
	@$(PYTHON) scripts/check_dut_import.py

test: test-model test-hw

test-model:
	$(PYTEST) -q tests/test_model_unit.py

test-hw: ensure-dut
	$(PYTEST) -q tests/test_smoke.py tests/test_directed.py tests/test_coherence.py tests/test_coverage_stress.py tests/test_random_crv.py

regression: test-model gen_dut test-hw

report:
	PYTHONPATH=$(PYTHONPATH_BASE) $(PYTHON) scripts/run_model_regression.py --json reports/model_coverage.json --md reports/model_coverage.md

rtl-coverage:
	./scripts/run_rtl_coverage.sh reports/rtl_coverage reports/rtl_coverage_summary.md

coverage: report rtl-coverage

wave:
	gtkwave -r .gtkwaverc $(NAME_L).$(WAVE_FORMAT)

inject-mask-bug:
	$(PYTHON) scripts/inject_bug.py --bug mask_merge --output faults/Cache_mask_merge_bug.v

inject-bug:
	$(PYTHON) scripts/inject_bug.py --bug $(BUG) --output $(BUG_RTL)

fault-audit: inject-bug
	@mkdir -p reports
	@rm -rf $(NAME)
	@$(PICKER) export --autobuild=false $(BUG_RTL) \
		-w $(NAME).$(WAVE_FORMAT) \
		--sname $(NAME) \
		--tdir $(NAME) \
		--lang $(TARGET_LANG) \
		--sim $(SIM) \
		-e -c > reports/fault_$(BUG)_build.log 2>&1
	@$(PYTHON) scripts/patch_picker_makefiles.py $(NAME) >> reports/fault_$(BUG)_build.log 2>&1
	@CMAKE_ARGS="$(CMAKE_ARGS)" make -C $(NAME) >> reports/fault_$(BUG)_build.log 2>&1
	@set +e; $(PYTEST) -q $(FAULT_TESTS) > reports/fault_$(BUG)_pytest.log 2>&1; rc=$$?; set -e; \
	{ \
	  echo "# Fault Injection Audit: $(BUG)"; \
	  echo; \
	  echo "Command: \`pytest -q $(FAULT_TESTS)\`"; \
	  echo; \
	  if [ $$rc -eq 0 ]; then echo "Result: **FAILED AUDIT** — mutant survived."; else echo "Result: **PASS** — mutant killed; pytest exit code $$rc."; fi; \
	  echo; \
	  echo "\`\`\`text"; \
	  tail -80 reports/fault_$(BUG)_pytest.log; \
	  echo "\`\`\`"; \
	} > reports/fault_$(BUG)_audit.md; \
	make gen_dut > reports/golden_rebuild.log 2>&1; \
	if [ $$rc -eq 0 ]; then echo "ERROR: mutant $(BUG) survived"; exit 1; else echo "PASS: mutant $(BUG) killed and golden DUT restored"; fi

fault-audit-all:
	$(MAKE) fault-audit BUG=mask_merge
	$(MAKE) fault-audit BUG=mmio_decode
	$(MAKE) fault-audit BUG=read_data_lsb

clean:
	-rm -rf $(NAME) *.dat *.fst *.vcd reports/*.log reports/*.xml reports/*.html .pytest_cache __pycache__ src/**/__pycache__ tests/**/__pycache__
