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/i2c/I2cBusCombinerTest.lvt
namespace Livt.IO.Tests
using Livt.IO
/**
* Test bus adapter that exposes observed line levels and low-drive requests without
* physical board pins.
*/
component TestI2CBusProvider : I2CBus
{
// Shared fixture instances, signals, and observation state.
observed_scl: logic
observed_sda: logic
/**
* Initializes fixture state and constructor bindings. Test cases share the fixture
* instance rather than constructing a fresh subject for each method.
*/
new()
{
this.observed_scl = 0b1
this.observed_sda = 0b1
}
/**
* Publishes the fixture SCL/SDA levels in the test clock context.
*/
process ApplyObservedLines()
{
state {
this.scl = this.observed_scl
this.sda = this.observed_sda
}
}
/**
* Sets the SCL/SDA levels that the fixture will present to the component under test.
*/
public fn SetObservedLines(sclValue: logic, sdaValue: logic)
{
state {
this.observed_scl = sclValue
this.observed_sda = sdaValue
}
}
/**
* Returns the observed SCL low-drive request without changing the bus.
*/
public fn ReadSclDriveLow() logic
{
return this.scl_drive_low
}
/**
* Returns the observed SDA low-drive request without changing the bus.
*/
public fn ReadSdaDriveLow() logic
{
return this.sda_drive_low
}
}
/**
* Test bus adapter that exposes observed line levels and low-drive requests without
* physical board pins.
*/
component AttachmentProbe
{
// Shared fixture instances, signals, and observation state.
bus: I2CBus
scl_drive_low: logic
sda_drive_low: logic
/**
* Initializes fixture state and constructor bindings. Test cases share the fixture
* instance rather than constructing a fresh subject for each method.
*/
new(bus: flip I2CBus)
{
this.bus = bus
this.scl_drive_low = 0b0
this.sda_drive_low = 0b0
}
/**
* Copies the requested low-drive flags to the borrowed bus attachment in the test clock
* context.
*/
process ApplyDrive()
{
state {
this.bus.scl_drive_low = this.scl_drive_low
this.bus.sda_drive_low = this.sda_drive_low
}
}
/**
* Sets both fixture low-drive requests together; the drive process forwards them to the
* attachment.
*/
public fn SetDrive(sclLow: logic, sdaLow: logic)
{
state {
this.scl_drive_low = sclLow
this.sda_drive_low = sdaLow
}
}
/**
* Returns the logical SCL level observed at the borrowed attachment.
*/
public fn ReadScl() logic
{
return this.bus.scl
}
/**
* Returns the logical SDA level observed at the borrowed attachment.
*/
public fn ReadSda() logic
{
return this.bus.sda
}
}
/**
* Exercises I2CBusCombiner with a shared fixture instance. Each scenario establishes the
* inputs and state it needs.
*/
@Test
component I2CBusCombinerTest
{
// Shared fixture instances, signals, and observation state.
root: TestI2CBusProvider
controller: AttachmentProbe
target: AttachmentProbe
combiner: I2CBusCombiner
/**
* Creates the shared fixture instances (TestI2CBusProvider, I2CBusCombiner,
* AttachmentProbe). Tests initialize the state required by their scenario.
*/
new()
{
this.root = new TestI2CBusProvider()
this.combiner = new I2CBusCombiner(this.root)
this.controller = new AttachmentProbe(this.combiner.controller)
this.target = new AttachmentProbe(this.combiner.target)
}
/**
* Checks the released devices release upstream case.
*/
@Test
fn TestReleasedDevicesReleaseUpstream()
{
this.root.SetObservedLines(0b1, 0b1)
this.controller.SetDrive(0b0, 0b0)
this.target.SetDrive(0b0, 0b0)
Simulation.Wait(80)
assert this.root.ReadSclDriveLow() == 0b0
assert this.root.ReadSdaDriveLow() == 0b0
}
/**
* Checks the either device can drive low case.
*/
@Test
fn TestEitherDeviceCanDriveLow()
{
this.root.SetObservedLines(0b1, 0b1)
this.controller.SetDrive(0b1, 0b0)
this.target.SetDrive(0b0, 0b1)
Simulation.Wait(80)
assert this.root.ReadSclDriveLow() == 0b1
assert this.root.ReadSdaDriveLow() == 0b1
}
/**
* Checks the observed lines propagate to both attachments case.
*/
@Test
fn TestObservedLinesPropagateToBothAttachments()
{
this.controller.SetDrive(0b0, 0b0)
this.target.SetDrive(0b0, 0b0)
Simulation.Wait(400)
this.root.SetObservedLines(0b0, 0b1)
Simulation.Wait(400)
assert this.controller.ReadScl() == 0b0
assert this.controller.ReadSda() == 0b1
assert this.target.ReadScl() == 0b0
assert this.target.ReadSda() == 0b1
}
}