Livt packages

Livt.IO

Version 1.8.1

Memory, UART, I2C, SPI, and Ethernet input/output components for Livt hardware designs.

Published files (126)

tests/ethernet/MiiLateAbortTest.lvt

namespace Livt.IO.Tests

using Livt.IO

/**
 * Owns a fresh simulation fixture; its single test exercises reset startup and frame behavior.
 */
@Test
@Context(ClockFrequency = 50MHz, ResetStyle = ResetStyle.Asynchronous)
component MiiLateAbortTest
{
	// Owned media fixture with a shared RX/TX test clock.
	@Context(ClockPeriod = 39ns, ResetStyle = ResetStyle.Asynchronous)
	mediaClock: IContext
	pins: MiiLoopbackPins
	link: MiiTestLink
	adapter: MiiAdapter

	// Accepted bytes and terminal events observed in the MAC domain.
	received: uint
	frames: uint
	errors: uint
	completions: uint
	faults: uint

	// Source enable and count of bytes accepted by the adapter.
	run: bool
	sent: uint

	/**
	 * Constructs the test-owned devices and binds their clock and signal dependencies.
	 */
	new()
	{
		pins = new MiiLoopbackPins()
		link = new MiiTestLink()
		adapter = new MiiAdapter(context, mediaClock, mediaClock, pins, link)
	}

	/**
	 * Connects TX pins to RX pins in the shared test media domain.
	 */
	process Loop[]()
	{
		pins.rxData = pins.txData
		pins.rxValid = pins.txEnable
		pins.rxError = 0b0
	}

	/**
	 * Checks accepted RX bytes and counts frame/terminal events.
	 */
	process Observe()
	{
		state {
			if (adapter.rxValid) {
				assert adapter.rxData == (received & 0xFF) as byte
				received++
			}

			if (adapter.rxEnd) {
				frames++
			}

			if (adapter.rxError) {
				errors++
			}

			if (adapter.txDone) {
				completions++
			}

			if (adapter.txFault) {
				faults++
			}
		}
	}

	/**
	 * Drives the deterministic test traffic without adding a sampling stage.
	 */
	process Drive[]()
	{
		adapter.txData = sent as byte
		adapter.txFirst = (sent & 63) == 0
		adapter.txLast = (sent & 63) == 63
		adapter.txValid = run && sent < 128
		adapter.txAbort = sent == 64 && faults == 0
	}

	/**
	 * Advances the source only when the media adapter accepts a byte.
	 */
	process Send()
	{
		state {
			if (run && sent < 128 && adapter.txReady) {
				sent++
			}
		}
	}

	/**
	 * Exercises this scenario once from the fixture reset state and checks completion and ownership.
	 */
	@Test
	fn KeepsCommittedFrameStableOnLateAbort()
	{
		link.ten = false

		for (var settle = 0; settle < 300; settle++) {
			state {}
		}

		run = true
		var wait = 0

		while (completions < 1 && wait < 10000) {
			state {
				wait++
			}
		}

		assert completions == 1

		for (var settle = 0; settle < 100; settle++) {
			state {}
		}

		assert received == 128
		assert frames == 2
		assert errors == 0
		assert faults == 1
	}
}