Livt packages
Livt.Net
Version 1.4.1
Ethernet, IPv4, TCP, UDP, ARP, TFTP, and Telnet networking components for Livt hardware.
Published files (163)
src/packet/RamPacketData.lvt
namespace Livt.Net
using Livt.IO
/**
* Ram-backed packet storage with a contiguous initialized prefix.
* Publish freezes bytes; Release permits reuse and clears prefix metadata.
* Release only after all readers/regions have finished. Storage is not erased.
* Scheduled calls have no fixed-cycle or combinational-access guarantee.
* STYLE selects the portable RAM backing preference without changing publication semantics.
*/
component RamPacketData<CAPACITY: int = 128, STYLE: MemoryStyle = MemoryStyle.Auto> : IWritablePacketData<PacketDataGeometry<CAPACITY>>
{
static assert CAPACITY > 0, "Packet capacity must be positive"
// Owned RAM; only the contiguous initialized prefix may be published.
const ADDRESS_BITS: int = Bits.RequiredFor(CAPACITY - 1)
storage: SynchronousRam<byte, logic[ADDRESS_BITS], CAPACITY, STYLE>
data: IRam<byte>
// Prefix length and publication state; releasing does not erase storage.
const LENGTH_BITS: int = Bits.RequiredFor(CAPACITY)
written: logic[LENGTH_BITS]
published: bool
/**
* Creates owned storage with an empty, unpublished prefix; bytes need not be erased.
*/
new()
{
this.storage = new SynchronousRam<byte, logic[ADDRESS_BITS], CAPACITY, STYLE>()
this.data = new RamAccess<byte, logic[ADDRESS_BITS], CAPACITY, SynchronousRam<byte, logic[ADDRESS_BITS], CAPACITY, STYLE>>(this.storage)
written = 0
published = false
}
/**
* Returns the fixed storage capacity in bytes; this does not reserve space.
*/
override fn GetCapacity() int
{
return CAPACITY
}
/**
* Returns the contiguous initialized prefix length, including unpublished bytes.
*/
override fn GetWrittenLength() int
{
return (written as uint) as int
}
/**
* Reports whether the initialized prefix is published for readers.
*/
override fn IsReady() bool
{
return published
}
/**
* Returns the published prefix length in bytes, or zero while unpublished.
*/
override fn GetAvailableLength() int
{
if (!published) {
return 0
}
return (written as uint) as int
}
/**
* Append the next byte or overwrite an initialized byte; holes are invalid.
*/
override fn TryWrite(index: int, value: byte) PacketDataResult
{
if (published) {
return PacketDataResult.Busy
}
if (index < 0 || index >= CAPACITY || index > ((written as uint) as int)) {
return PacketDataResult.Invalid
}
data.Write(index, value)
if (index == ((written as uint) as int)) {
written++
}
return PacketDataResult.Success
}
/**
* An empty prefix is valid packet data, though not a valid Ethernet TX.
*/
override fn TryPublish() PacketDataResult
{
if (published) {
return PacketDataResult.Busy
}
published = true
return PacketDataResult.Success
}
/**
* Reads index in 0..written-1 from the published prefix. Returns NotReady
* while unpublished and Invalid outside the prefix; failure leaves output zero.
* The scheduled read must finish before the owner releases storage.
*/
override fn TryRead(index: int, value: out byte) PacketDataResult
{
value = 0x00
if (!published) {
return PacketDataResult.NotReady
}
if (index < 0 || index >= ((written as uint) as int)) {
return PacketDataResult.Invalid
}
var readValue = data.Read(index)
value = readValue
return PacketDataResult.Success
}
/**
* Releases a published prefix and resets its initialized length without erasing
* storage. Returns Invalid if unpublished. Finish all dependent reads first.
*/
override fn TryRelease() PacketDataResult
{
if (!published) {
return PacketDataResult.Invalid
}
published = false
written = 0
return PacketDataResult.Success
}
/**
* Abandon unpublished preparation; cannot discard a published source.
*/
override fn TryClear() PacketDataResult
{
if (published) {
return PacketDataResult.Busy
}
written = 0
return PacketDataResult.Success
}
}