import cocotb
import os
import random
import sys
from math import log
import logging
from cocotb.clock import Clock #useful for sequential logic
from cocotb.triggers import RisingEdge, FallingEdge, ClockCycles, Timer
from pathlib import Path
from cocotb.triggers import Timer
from cocotb.utils import get_sim_time as gst
from cocotb.runner import get_runner
test_file = os.path.basename(__file__).replace(".py","")

@cocotb.test()
async def test_a(dut):
    """cocotb test for debouncer testing"""
    cocotb.start_soon(Clock(dut.clk, 10, "ns").start())
    await ClockCycles(dut.clk, 10)
    dut.rst.value = 1
    dut.dirty.value = 0
    await ClockCycles(dut.clk, 1)
    dut.rst.value = 0
    await ClockCycles(dut.clk, 50)
    dut.dirty.value = 1
    await ClockCycles(dut.clk, 5)
    dut.dirty.value = 0
    await ClockCycles(dut.clk, 50)
    dut.dirty.value = 1
    await ClockCycles(dut.clk, 5)
    dut.dirty.value = 0
    await ClockCycles(dut.clk, 50)
    dut.dirty.value = 1
    await ClockCycles(dut.clk, 500)

def debouncer_runner():
    """Simulate the debouncer using the Python runner."""
    hdl_toplevel_lang = os.getenv("HDL_TOPLEVEL_LANG", "verilog")
    sim = os.getenv("SIM", "icarus")
    proj_path = Path(__file__).resolve().parent.parent
    sys.path.append(str(proj_path / "sim" / "model"))
    sources = [proj_path / "hdl" / "debouncer.sv"]
    build_test_args = ["-Wall"]
    parameters = {"DEBOUNCE_TIME_MS":0.001} #make shorter so sim's dont' take forever
    sys.path.append(str(proj_path / "sim"))
    hdl_toplevel = "debouncer"
    runner = get_runner(sim)
    runner.build(
        sources=sources,
        hdl_toplevel = hdl_toplevel,
        always=True,
        build_args=build_test_args,
        parameters=parameters,
        timescale = ('1ns','1ps'),
        waves=True
    )
    run_test_args = []
    runner.test(
        hdl_toplevel = hdl_toplevel,
        test_module=test_file,
        test_args=run_test_args,
    )

if __name__ == "__main__":
    debouncer_runner()
