from amaranth import *
from amaranth.sim import *
from amlib.io.serial import *
from uart import *
from tests import BaseTestClass, provide_testcase_name


__all__ = ["TestHarness", "TestUART"]


class TestHarness(Elaboratable):
    def __init__(self):
        self.uut = UART(10e6, fifo_depth=16)
        self.uart = AsyncSerial(divisor=int(10e6 // 115200), divisor_bits=16, data_bits=8, parity="none")


    def elaborate(self, platform):
        assert platform is None

        m = Module()
        m.submodules.uut = self.uut
        m.submodules.uart = self.uart

        # Connect UART lines
        m.d.comb += [
            self.uut.rx.eq(self.uart.tx.o),
            self.uart.rx.i.eq(self.uut.tx),
        ]

        # Connect the data lines so we are always pulling data out... for now
        m.d.comb += [
            self.uart.rx.ack.eq(1),
        ]

        return m


class TestUART(BaseTestClass):
    def setUp(self):
        self.harness = TestHarness()


    @provide_testcase_name
    def test_operation(self, test_name):
        def test():
            for i in range(20):
                yield from self._write_csr(self.harness.uut.bus, 2, i)

            for _ in range(2000):
                yield Tick()

            yield from self._write_csr(self.harness.uut.bus, 0, 1000)

            for _ in range(20000):
                yield Tick()

        self._run_test(test, test_name)
