Livt packages
Livt.ML
Version 1.6.1
Fixed-size quantized inference, tensor storage, attention, and transformer building blocks for Livt.
Published files (132)
- DotProductTest.lvt
- Int8BroadcastMac64x8Test.lvt
- Int8Dot64x8Test.lvt
- Int8Linear4x8Test.lvt
- Int8Linear8x3Test.lvt
- Int8LinearAccumulatorTest.lvt
- Int8Mac8Test.lvt
- Int8MatrixAccumulator32StreamTest.lvt
- Int8MatrixAccumulator32Test.lvt
- Linear8x8Test.lvt
- MatrixVectorMultiplicationTest.lvt
- QLinearMatMul256x10RamTest.lvt
- QLinearMatMul256x10StreamTest.lvt
- QuantizedMatrixGroupingTest.lvt
- VecAddTest.lvt
tests/linear/Int8MatrixAccumulator32Test.lvt
namespace Livt.ML.Tests.Linear
using Livt.ML.Linear
/**
* Checks the scheduled live-row API, exact wide values and retained bank failures.
*/
@Test
component Int8MatrixAccumulator32Test
{
// Input is shared only between serialized calls in these tests.
values: logic[512]
matrix: Int8MatrixAccumulator32<32, 1>
staged: Int8MatrixAccumulator32<32, 2>
narrow: Int8MatrixAccumulator32<8, 1>
/**
* Owns independent workers for each supported product pipeline and range checks.
*/
new()
{
matrix = new Int8MatrixAccumulator32<32, 1>()
staged = new Int8MatrixAccumulator32<32, 2>()
narrow = new Int8MatrixAccumulator32<8, 1>()
}
/**
* Packs sixteen equal signed activation lanes with lane zero in the low bits.
*/
fn ActivationRow(value: int) logic[512]
{
var row: logic[512] = 0
for (var lane = 0; lane < 16; lane++) {
row = (row << 32) | ((value as logic[32]) as logic[512])
}
return row
}
/**
* Packs 64 signed byte weights.
*/
fn WeightRow(value: int) logic[512]
{
var row: logic[512] = 0
for (var lane = 0; lane < 64; lane++) {
row = (row << 8) | ((value as logic[8]) as logic[512])
}
return row
}
/**
* Tests both pipelines with values beyond int16 and immediate RAM reads.
*/
@Test
fn WideSumsAndProductStages()
{
assert matrix.Begin(3)
assert staged.Begin(3)
assert matrix.Read(2) == 0
assert staged.Read(2) == 0
values = ActivationRow(1048576)
for (var block = 0; block < 4; block++) {
assert matrix.LoadActivations(block)
assert staged.LoadActivations(block)
}
values = WeightRow(-128)
assert matrix.Accumulate(2)
assert staged.Accumulate(2)
var expected: logic[64] = 0xfffffffe00000000
assert matrix.Read(2) == (expected as logic[65])
assert staged.Read(2) == (expected as logic[65])
values = WeightRow(127)
assert matrix.Accumulate(2)
assert staged.Accumulate(2)
expected = 0xfffffffffc000000
assert matrix.Read(2) == (expected as logic[65])
assert staged.Read(2) == (expected as logic[65])
assert matrix.Read(0) == 0
assert matrix.Seed(1, 0x8000000000000000)
assert matrix.Read(1) == (0x8000000000000000 as logic[65])
assert matrix.Begin(1)
assert matrix.Read(0) == 0
assert (matrix.Read(1) >> 64) != 0
}
/**
* Overflow cannot be hidden by a later cancelling update; Begin recovers.
*/
@Test
fn OverflowPoisonAndRecovery()
{
assert matrix.Begin(1)
assert matrix.Seed(0, 0x7fffffffffffffff)
values = ActivationRow(1)
for (var block = 0; block < 4; block++) {
assert matrix.LoadActivations(block)
}
values = WeightRow(1)
assert !matrix.Accumulate(0)
assert matrix.Read(0) == ((1 as logic[65]) << 64)
values = WeightRow(-1)
assert !matrix.Accumulate(0)
assert !matrix.Seed(0, 0)
assert matrix.Begin(1)
assert matrix.Read(0) == 0
assert !matrix.Accumulate(0)
assert (matrix.Read(0) >> 64) != 0
assert matrix.Begin(1)
assert (matrix.Read(-1) >> 64) != 0
assert matrix.Read(0) == 0
assert !matrix.Begin(1025)
assert (matrix.Read(0) >> 64) != 0
}
/**
* Width validation rejects truncation; every activation block must be loaded.
*/
@Test
fn NarrowRangesAndCapacity()
{
assert narrow.Begin(1024)
assert narrow.Read(1023) == 0
values = ActivationRow(128)
assert !narrow.LoadActivations(0)
values = ActivationRow(-128)
for (var block = 0; block < 4; block++) {
assert narrow.LoadActivations(block)
}
values = WeightRow(-128)
assert narrow.Accumulate(1023)
assert narrow.Read(1023) == 1048576
assert !narrow.Accumulate(1024)
assert (narrow.Read(1023) >> 64) != 0
assert narrow.Begin(1)
assert narrow.Read(0) == 0
}
/**
* Sparse signed weights catch lane order, block order and accumulation across chunks.
*/
@Test
fn MultipleChunksAndLaneOrder()
{
assert matrix.Begin(1)
assert staged.Begin(1)
for (var chunk = 0; chunk < 12; chunk++) {
for (var block = 0; block < 4; block++) {
values = 0
for (var lane = 0; lane < 16; lane++) {
var value = chunk * 64 + block * 16 + lane
values = (values >> 32) | (((value as logic[32]) as logic[512]) << 480)
}
assert matrix.LoadActivations(block)
assert staged.LoadActivations(block)
}
values = 0xf8000000000000000000000000000007fa000000000000000000000000000005fc000000000000000000000000000003fe000000000000000000000000000001
assert matrix.Accumulate(0)
assert staged.Accumulate(0)
if (chunk == 2) {
assert matrix.Read(0) == (((-1956) as logic[64]) as logic[65])
assert staged.Read(0) == (((-1956) as logic[64]) as logic[65])
}
}
assert matrix.Read(0) == (((-21648) as logic[64]) as logic[65])
assert staged.Read(0) == (((-21648) as logic[64]) as logic[65])
}
/**
* Full-width products and negative overflow preserve exact signed behavior.
*/
@Test
fn SignedLimits()
{
assert matrix.Begin(1)
assert staged.Begin(1)
values = ActivationRow(-2147483647 - 1)
for (var block = 0; block < 4; block++) {
assert matrix.LoadActivations(block)
assert staged.LoadActivations(block)
}
values = WeightRow(-128)
assert matrix.Accumulate(0)
assert staged.Accumulate(0)
assert matrix.Read(0) == ((1 as logic[65]) << 44)
assert staged.Read(0) == ((1 as logic[65]) << 44)
assert matrix.Seed(0, 0x8000000000000000)
values = WeightRow(1)
assert !matrix.Accumulate(0)
assert matrix.Read(0) == ((1 as logic[65]) << 64)
}
/**
* Distinct values across address-bit boundaries must never alias other rows.
*/
@Test
fn CapacityAndRowIsolation()
{
var indexes: int[13] = [0, 1, 15, 16, 63, 64, 255, 256, 511, 512, 767, 768, 1023]
assert matrix.Begin(1024)
for (var i = 0; i < 13; i++) {
assert matrix.Seed(indexes[i], (indexes[i] + 123) as logic[64])
}
for (var i = 0; i < 13; i++) {
assert matrix.Read(indexes[i]) == ((indexes[i] + 123) as logic[65])
}
assert matrix.Begin(1)
assert matrix.Read(0) == 0
assert (matrix.Read(1023) >> 64) != 0
}
/**
* Producer holds the row until each serialized call has returned.
*/
process Connect[]()
{
matrix.values = values
staged.values = values
narrow.values = values
}
}