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/embedding/Embedding64Stream.lvt

namespace Livt.ML.Embedding

/**
 * Streams one 64-value embedding row from an external scalar memory service.
 *
 * The component converts a valid entry index into 64 consecutive flat memory
 * addresses and forwards returned values with toggle handshakes. It stores no
 * embedding table and is therefore suitable for ROM, Livt.IO RAM, or an
 * external-memory controller.
 */
component Embedding64Stream
{
	// Compile-time dimensions, bounds, and numeric constants.
	public const VECTOR_SIZE: int = 64

	// Entry-selection handshake and invalid-index status.
	entryRequest: logic
	entryIndex: int
	entryAcknowledge: logic

	// Borrowed scalar-memory request/response handshake.
	memoryRequest: logic
	memoryAddress: int
	memoryData: int
	memoryAcknowledge: logic

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

	// Entry-selection handshake and invalid-index status.
	invalidEntry: logic

	// Transfer progress and retained request/acknowledgment state.
	entrySeen: logic

	// Current position and bounds within the configured frame.
	elementIndex: int
	currentEntry: int
	entryCount: int

	// Transfer progress and retained request/acknowledgment state.
	waitingMemory: bool
	pendingOutput: bool
	active: bool

	/**
	 * Binds the borrowed scalar memory service and entry/output handshakes. entryCount defines
	 * valid row indices; memory addresses count scalar elements. Hold request payloads until
	 * acknowledged.
	 */
	new(
		entryCount: int,
		entryRequest: in logic, entryIndex: in int, entryAcknowledge: out logic,
		memoryRequest: out logic, memoryAddress: out int, memoryData: in int,
		memoryAcknowledge: in logic, outputRequest: out logic,
		outputData: out int, outputLast: out logic, outputAcknowledge: in logic,
		invalidEntry: out logic)
	{
		this.entryCount = entryCount
		this.entryRequest = entryRequest
		this.entryIndex = entryIndex
		entryAcknowledge = this.entryAcknowledge
		memoryRequest = this.memoryRequest
		memoryAddress = this.memoryAddress
		this.memoryData = memoryData
		this.memoryAcknowledge = memoryAcknowledge
		outputRequest = this.outputRequest
		outputData = this.outputData
		outputLast = this.outputLast
		this.outputAcknowledge = outputAcknowledge
		invalidEntry = this.invalidEntry
	}

	/**
	 * Accepts one entry request, reads its 64 scalar values, and holds each output until
	 * acknowledged. An invalid entry is acknowledged with invalidEntry and produces no row.
	 */
	process Main()
	{
		entryAcknowledge = entrySeen

		if (pendingOutput) {
			if (outputAcknowledge == outputRequest) {
				pendingOutput = false

				if (elementIndex == 63) {
					elementIndex = 0
					active = false
				} else {
					elementIndex++
					memoryAddress = currentEntry * VECTOR_SIZE + elementIndex
					memoryRequest = !memoryRequest
					waitingMemory = true
				}
			}
		} else {
			if (waitingMemory) {
				if (memoryAcknowledge == memoryRequest) {
					outputData = memoryData
					outputLast = 0b0

					if (elementIndex == 63) {
						outputLast = 0b1
					}

					outputRequest = !outputRequest
					waitingMemory = false
					pendingOutput = true
				}
			} else {
				if (!active && entryRequest != entrySeen) {
					entrySeen = entryRequest
					invalidEntry = 0b0

					if (entryIndex < 0 || entryIndex >= entryCount) {
						invalidEntry = 0b1
					} else {
						currentEntry = entryIndex
						elementIndex = 0
						memoryAddress = entryIndex * VECTOR_SIZE
						memoryRequest = !memoryRequest
						waitingMemory = true
						active = true
					}
				}
			}
		}
	}
}