Livt packages

Livt.ML

Version 1.6.1

Fixed-size quantized inference, tensor storage, attention, and transformer building blocks for Livt.

Published files (132)

src/pooling/MaxPool8x28To14Stream.lvt

namespace Livt.ML.Pooling

/**
 * Streams a 2x2 stride-two max pool over eight 28x28 uint8 NCHW planes.
 *
 * The input and output use a toggle handshake. A producer changes
 * `inputRequest` after placing `inputData` and `inputLast`; the value has been
 * accepted when `inputAcknowledge` matches it. This component changes
 * `outputRequest` when an output is available and holds the output stable
 * until `outputAcknowledge` matches it.
 *
 * At most one output is pending. Input backpressure is therefore automatic.
 * The implementation stores one 28-byte row rather than complete tensors.
 */
component MaxPool8x28To14Stream
{
	// Input payload and toggle acknowledgment from the producer.
	inputRequest: logic
	inputData: byte
	inputLast: logic
	inputAcknowledge: logic

	// Output payload and toggle acknowledgment; payload stays stable while pending.
	outputRequest: logic
	outputData: byte
	outputLast: logic
	outputAcknowledge: logic

	// Transfer progress and retained request/acknowledgment state.
	inputSeen: logic
	pending: bool

	// Current position and bounds within the configured frame.
	channel: int
	row: int
	column: int

	// Partial pooling-window storage, reused as input values arrive.
	previousRow: byte[28]
	horizontalMaximum: byte

	/**
	 * Binds the input and output toggle-handshake ports. Producers hold input data until
	 * acknowledgment; consumers acknowledge each output before it can be replaced.
	 */
	new(inputRequest: in logic, inputData: in byte, inputLast: in logic,
		inputAcknowledge: out logic, outputRequest: out logic,
		outputData: out byte, outputLast: out logic, outputAcknowledge: in logic)
	{
		this.inputRequest = inputRequest
		this.inputData = inputData
		this.inputLast = inputLast
		inputAcknowledge = this.inputAcknowledge
		outputRequest = this.outputRequest
		outputData = this.outputData
		outputLast = this.outputLast
		this.outputAcknowledge = outputAcknowledge
	}

	/**
	 * Accumulates pooling-window maxima as frame values arrive. Holds a pending output until
	 * acknowledgment before accepting further input; all endpoints must share compatible
	 * clock/reset sequencing.
	 */
	process Main()
	{
		inputAcknowledge = inputSeen

		if (pending) {
			if (outputAcknowledge == outputRequest) {
				pending = false
			}
		} else {
			if (inputRequest != inputSeen) {
				if (row < 1) {
					previousRow[column] = inputData
				} else {
					var verticalMaximum = previousRow[column]

					if (inputData > verticalMaximum) {
						verticalMaximum = inputData
					}

					if (column == 0 ||
						column == 2 ||
						column == 4 ||
						column == 6 ||
						column == 8 ||
						column == 10 ||
						column == 12 ||
						column == 14 ||
						column == 16 ||
						column == 18 ||
						column == 20 ||
						column == 22 ||
						column == 24 ||
						column == 26) {
						horizontalMaximum = verticalMaximum
					} else {
						outputData = horizontalMaximum

						if (verticalMaximum > horizontalMaximum) {
							outputData = verticalMaximum
						}

						outputLast = inputLast
						outputRequest = !outputRequest
						pending = true
					}
				}

				inputSeen = inputRequest

				if (column == 27) {
					column = 0

					if (row == 1) {
						row = 0

						if (channel == 7) {
							channel = 0
						} else {
							channel++
						}
					} else {
						row++
					}
				} else {
					column++
				}
			}
		}
	}
}