Livt packages
Livt.Bus
Version 2.0.1
Configurable Avalon, AXI4-Lite, and Wishbone memory-mapped masters, interfaces, bridges, and test components.
Published files (67)
src/avalon/testing/AvalonTestMaster32.lvt
namespace Livt.Bus.Avalon.Testing
using Livt.Bus
using Livt.Bus.Avalon
/**
* Assertion-oriented Avalon-MM master for component and register tests.
*/
component AvalonTestMaster32 : IAvalon32Master, IMemoryMappedBus32
{
/**
* Avalon response code for a successful request.
*/
public const RESPONSE_OKAY: Logic[2] = 0b00
/**
* Byte-enable value selecting all four data lanes.
*/
public const ALL_BYTES: Logic[4] = 0b1111
timeoutTicks: uint
lastReadValue: uint
lastResponse: Logic[2]
lastTimedOut: bool
// Scheduled command mailbox; held stable until the engine acknowledges release.
commandAddress: logic[32]
commandWriteData: logic[32]
commandByteEnable: logic[4]
commandIsRead: bool
commandPending: bool
transferComplete: bool
// Single-owner request registers and direct response observations.
requestAddress: logic[32]
requestByteEnable: logic[4]
requestWrite: logic
requestWriteData: logic[32]
requestRead: logic
targetReadData: logic[32]
targetWaitRequest: logic
targetResponse: logic[2]
/**
* Initializes the timeout; reset leaves the bus and command mailbox idle.
*/
new()
{
this.timeoutTicks = this.context.TicksFor(1ms)
}
/**
* Sets the maximum ticks to wait for waitrequest to be deasserted.
* The count is exact; zero times out on the first stalled evaluation.
*/
override fn SetTimeoutTicks(timeoutTicks: uint)
{
this.timeoutTicks = timeoutTicks
}
/**
* Returns the maximum ticks allowed for a request.
*/
override fn GetTimeoutTicks() uint
{
return timeoutTicks
}
/**
* Returns the data captured by the most recently accepted read.
*/
override fn LastReadValue() uint
{
return lastReadValue
}
/**
* Returns the Avalon response captured for the most recent accepted request.
*/
override fn LastResponse() Logic[2]
{
return lastResponse
}
/**
* Returns true when the most recent request timed out.
*/
override fn LastTimedOut() bool
{
return lastTimedOut
}
/**
* Performs one non-pipelined Avalon-MM write using the selected byte lanes.
* Returns true when the request is accepted; inspect LastResponse for status.
* After a timeout, the call holds the request until acceptance before returning.
*/
private fn ExecuteWrite32(address: uint, value: uint, byteEnable: Logic[4]) bool
{
var completed = this.ExecuteTransfer(address, value, byteEnable, false)
return completed
}
/**
* Performs one non-pipelined Avalon-MM read and stores the accepted read data.
* Returns true when the request is accepted; inspect LastResponse for status.
* After a timeout, the call holds the request until acceptance before returning.
*/
private fn ExecuteRead32(address: uint) bool
{
var completed = this.ExecuteTransfer(address, 0, ALL_BYTES, true)
return completed
}
/**
* Provides the non-asserting write operation inherited by the common API.
*/
override fn TryWrite32(address: uint, value: uint, byteEnable: Logic[4]) bool
{
var successful = this.ExecuteWrite32(address, value, byteEnable)
state Settle {}
return successful
}
/**
* Provides the non-asserting read operation inherited by the common API.
*/
override fn TryRead32(address: uint) bool
{
var successful = this.ExecuteRead32(address)
state Settle {}
return successful
}
/**
* Writes one byte and asserts completion with an Avalon OKAY response.
*/
override fn Write8(address: uint, value: byte)
{
var lane = (address & (3 as uint)) as int
var shift = lane * 8
var alignedAddress = address & (0xFFFFFFFC as uint)
var shiftedValue = (value as uint) << shift
var byteEnable: Logic[4] = 0b0001
if (lane == 1) {
byteEnable = 0b0010
} elif (lane == 2) {
byteEnable = 0b0100
} elif (lane == 3) {
byteEnable = 0b1000
}
var completed = this.ExecuteWrite32(alignedAddress, shiftedValue, byteEnable)
assert completed == true
assert lastResponse == RESPONSE_OKAY
}
/**
* Writes one aligned halfword and asserts completion with an Avalon OKAY response.
*/
override fn Write16(address: uint, value: Logic[16])
{
assert (address & (1 as uint)) == (0 as uint)
var lane = (address & (2 as uint)) as int
var shift = lane * 8
var alignedAddress = address & (0xFFFFFFFC as uint)
var shiftedValue = (value as uint) << shift
var byteEnable: Logic[4] = 0b0011
if (lane == 2) {
byteEnable = 0b1100
}
var completed = this.ExecuteWrite32(alignedAddress, shiftedValue, byteEnable)
assert completed == true
assert lastResponse == RESPONSE_OKAY
}
/**
* Writes one word and asserts completion with an Avalon OKAY response.
*/
override fn Write32(address: uint, value: uint)
{
assert (address & (3 as uint)) == (0 as uint)
var completed = this.ExecuteWrite32(address, value, ALL_BYTES)
assert completed == true
assert lastResponse == RESPONSE_OKAY
}
/**
* Writes selected byte lanes and asserts completion with an Avalon OKAY response.
*/
override fn WriteMasked32(address: uint, value: uint, byteEnable: Logic[4])
{
assert (address & (3 as uint)) == (0 as uint)
var completed = this.ExecuteWrite32(address, value, byteEnable)
assert completed == true
assert lastResponse == RESPONSE_OKAY
}
/**
* Reads one byte and asserts completion with an Avalon OKAY response.
*/
override fn Read8(address: uint) byte
{
var lane = (address & (3 as uint)) as int
var shift = lane * 8
var alignedAddress = address & (0xFFFFFFFC as uint)
var completed = this.ExecuteRead32(alignedAddress)
assert completed == true
assert lastResponse == RESPONSE_OKAY
return (lastReadValue >> shift) as byte
}
/**
* Reads one aligned halfword and asserts completion with an Avalon OKAY response.
*/
override fn Read16(address: uint) Logic[16]
{
assert (address & (1 as uint)) == (0 as uint)
var lane = (address & (2 as uint)) as int
var shift = lane * 8
var alignedAddress = address & (0xFFFFFFFC as uint)
var completed = this.ExecuteRead32(alignedAddress)
assert completed == true
assert lastResponse == RESPONSE_OKAY
return (lastReadValue >> shift) as Logic[16]
}
/**
* Reads one word and asserts completion with an Avalon OKAY response.
*/
override fn Read32(address: uint) uint
{
assert (address & (3 as uint)) == (0 as uint)
var completed = this.ExecuteRead32(address)
assert completed == true
assert lastResponse == RESPONSE_OKAY
return lastReadValue
}
/**
* Reads one byte and asserts that it equals the expected value.
*/
override fn Verify8(address: uint, expected: byte)
{
var lane = (address & (3 as uint)) as int
var shift = lane * 8
var alignedAddress = address & (0xFFFFFFFC as uint)
var completed = this.ExecuteRead32(alignedAddress)
assert completed == true
assert lastResponse == RESPONSE_OKAY
assert ((lastReadValue >> shift) as byte) == expected
}
/**
* Reads one halfword and asserts that it equals the expected value.
*/
override fn Verify16(address: uint, expected: Logic[16])
{
assert (address & (1 as uint)) == (0 as uint)
var lane = (address & (2 as uint)) as int
var shift = lane * 8
var alignedAddress = address & (0xFFFFFFFC as uint)
var completed = this.ExecuteRead32(alignedAddress)
assert completed == true
assert lastResponse == RESPONSE_OKAY
assert ((lastReadValue >> shift) as Logic[16]) == expected
}
/**
* Reads one word and asserts that it equals the expected value.
*/
override fn Verify32(address: uint, expected: uint)
{
assert (address & (3 as uint)) == (0 as uint)
var completed = this.ExecuteRead32(address)
assert completed == true
assert lastResponse == RESPONSE_OKAY
assert lastReadValue == expected
}
/**
* Reads one word and compares only bits selected by the mask.
*/
override fn VerifyMasked32(address: uint, expected: uint, mask: uint)
{
assert (address & (3 as uint)) == (0 as uint)
var completed = this.ExecuteRead32(address)
assert completed == true
assert lastResponse == RESPONSE_OKAY
assert (lastReadValue & mask) == (expected & mask)
}
/**
* Submits a stable command and waits for the bus engine to drain the request.
*/
private fn ExecuteTransfer(address: uint, value: uint, byteEnable: logic[4], isRead: bool) bool
{
this.commandAddress = address as logic[32]
this.commandWriteData = value as logic[32]
this.commandByteEnable = byteEnable
this.commandIsRead = isRead
this.commandPending = true
state WaitForCompletion {
if (this.transferComplete) {
goto Release
} else {
goto WaitForCompletion
}
}
state Release {
this.commandPending = false
goto WaitForIdle
}
state WaitForIdle {
if (this.transferComplete) {
goto WaitForIdle
} else {
goto Finish
}
}
state Finish {}
return !this.lastTimedOut
}
/**
* Wires the bus without retiming its acceptance handshake.
*/
process Connect[]()
{
this.address = this.requestAddress
this.byteenable = this.requestByteEnable
this.write = this.requestWrite
this.writedata = this.requestWriteData
this.read = this.requestRead
this.targetReadData = this.readdata
this.targetWaitRequest = this.waitrequest
this.targetResponse = this.response
}
/**
* Owns the bus registers. Acceptance captures the response and lowers the
* request on the same clock edge. A deadline never cancels a stalled transfer.
*/
process Transfer()
{
var elapsed: uint = 0
var deadline: uint = 0
state Idle {
if (this.commandPending) {
elapsed = 0
deadline = this.timeoutTicks
this.lastResponse = RESPONSE_OKAY
this.lastTimedOut = false
this.requestAddress = this.commandAddress
this.requestByteEnable = this.commandByteEnable
this.requestWriteData = this.commandWriteData
if (this.commandIsRead) {
this.lastReadValue = 0
this.requestRead = 0b1
this.requestWrite = 0b0
} else {
this.requestRead = 0b0
this.requestWrite = 0b1
}
goto Active
} else {
goto Idle
}
}
state Active {
if (this.targetWaitRequest == 0b0) {
if (this.commandIsRead) {
this.lastReadValue = this.targetReadData as uint
}
this.lastResponse = this.targetResponse
this.requestRead = 0b0
this.requestWrite = 0b0
this.requestByteEnable = 0b0000
this.transferComplete = true
goto WaitForRelease
} elif ((elapsed + 1) >= deadline) {
this.lastTimedOut = true
goto Recover
} else {
elapsed = elapsed + 1
goto Active
}
}
state Recover {
if (this.targetWaitRequest == 0b0) {
this.requestRead = 0b0
this.requestWrite = 0b0
this.requestByteEnable = 0b0000
this.transferComplete = true
goto WaitForRelease
} else {
goto Recover
}
}
state WaitForRelease {
if (this.commandPending) {
goto WaitForRelease
} else {
this.transferComplete = false
goto Idle
}
}
}
}