Livt packages
Eccelerators.RiscV
Version 0.3.0
Composable RV32I and Zmmul processors, machine-mode support, and reusable FPGA system components written in Livt.
Published files (120)
- fixtures
- DelayedWordDevice.lvt
- PipelineFetchMemory.lvt
- PipelineWordDevice.lvt
- README.md
- Rv32BusCoreTest.lvt
- Rv32BusProtocolTest.lvt
- Rv32CsrEngineTest.lvt
- Rv32CsrRetirement.lvt
- Rv32DspControlTest.lvt
- Rv32DspEngineTest.lvt
- Rv32DspMultiplierTest.lvt
- Rv32DualReadDistributedTest.lvt
- Rv32DualReadRegisterBankTest.lvt
- Rv32ExternalInterruptTest.lvt
- Rv32FetchBusTest.lvt
- Rv32iConstantsTest.lvt
- Rv32iDecodeTest.lvt
- Rv32InterruptCsrTest.lvt
- Rv32iPackageApiTest.lvt
- Rv32iSemanticsTest.lvt
- Rv32IterativeMultiplierTest.lvt
- Rv32LoadStoreBusTest.lvt
- Rv32MachineCsrsTest.lvt
- Rv32MachineDecoderTest.lvt
- Rv32MultiplyRetirement.lvt
- Rv32MultiplyVectors.lvt
- Rv32PipelineControlTest.lvt
- Rv32PipelineCsrEngineTest.lvt
- Rv32PipelineDspEngineTest.lvt
- Rv32PipelineEngineTest.lvt
- Rv32PipelineExternalInterruptTest.lvt
- Rv32PipelineTimerInterruptTest.lvt
- Rv32PipelineTrapEngineTest.lvt
- Rv32PipelineZmmulEngineTest.lvt
- Rv32RegisterBankTest.lvt
- Rv32SequentialControlTest.lvt
- Rv32SequentialEngineTest.lvt
- Rv32TimerInterruptTest.lvt
- Rv32TrapEngineTest.lvt
- Rv32TrapPolicyTest.lvt
- Rv32ZicsrAccessTest.lvt
- Rv32ZicsrDecoderTest.lvt
- Rv32ZmmulControlTest.lvt
- Rv32ZmmulDecodeTest.lvt
- Rv32ZmmulEngineTest.lvt
- RvExternalInterruptsTest.lvt
- RvMachineSystemTest.lvt
- RvMachineTimerTest.lvt
- RvPipelineSystemTest.lvt
- RvSystemTest.lvt
- RvUartDeviceTest.lvt
- RvUartSystemTest.lvt
tests/Rv32BusCoreTest.lvt
namespace Eccelerators.RiscV.Tests
using Eccelerators.RiscV.Sequential
using Eccelerators.RiscV.Storage
using Eccelerators.RiscV.Presets
using Eccelerators.RiscV.System
using Livt.IO
/**
* Preset-core integration over a two-slot load/store bus: stores and loads
* route to the RAM whose window contains the address, a gap address faults
* with the full address, and restart re-provisions through the ungated slots.
*/
@Test
component Rv32BusCoreTest
{
// Owned instruction ROM and windowed data providers in one reset context.
rom: RvFetchRom<8, 8, MemoryStyle.Block, 0>
ramA: RvLoadStoreRam<4, 10, MemoryStyle.Block, 0>
ramB: RvLoadStoreRam<4, 10, MemoryStyle.Block, 16>
dataBus: Rv32LoadStoreBus<0, 16, 16, 16, false>
core: RvSystem<Rv32iSequentialCore>
/**
* Creates the bus-routed data path and the preset core above it.
*/
new()
{
rom = new RvFetchRom<8, 8, MemoryStyle.Block, 0>()
ramA = new RvLoadStoreRam<4, 10, MemoryStyle.Block, 0>()
ramB = new RvLoadStoreRam<4, 10, MemoryStyle.Block, 16>()
dataBus = new Rv32LoadStoreBus<0, 16, 16, 16, false>(ramA, ramB)
core = new RvSystem<Rv32iSequentialCore>(rom, dataBus)
}
/**
* Halts, drains, restarts and returns the core to a fresh idle state.
*/
fn Prepare()
{
core.run = 0b0
var elapsed: uint = 0
while (core.idle == 0b0 && elapsed < 200) {
state {
elapsed++
}
}
assert core.idle == 0b1
var ticket = ~core.restartAck
state {
core.restartRequest = ticket
}
elapsed = 0
while (core.restartAck != ticket && elapsed < 200) {
state {
elapsed++
}
}
assert core.restartAck == ticket
assert core.halted == 0b0
}
/**
* Provisions one instruction word in the program ROM while paused.
*/
fn Load(index: uint, word: uint)
{
state {
rom.programWrite = 0b1
rom.programIndex = index as logic[8]
rom.programData = word as logic[32]
}
state {
rom.programWrite = 0b0
}
}
/**
* Runs until halt and asserts the last retirement through the bus path A.
*/
@Test
fn TestSlotAExecution()
{
Prepare()
Load(0, 0x00400093)
Load(1, 0x0aa00113)
Load(2, 0x0020a023)
Load(3, 0x0000a183)
Load(4, 0x00100073)
var elapsed: uint = 0
state {
core.run = 0b1
}
while (core.halted == 0b0 && elapsed < 300) {
state {
elapsed++
}
}
assert core.halted == 0b1 && core.faultCause as uint == 3
assert core.retiredRd as uint == 3
assert core.retiredValue as uint == 170
assert core.retiredPc as uint == 12
assert core.pc as uint == 16
}
/**
* The same program shape with a window B address retires through slot B.
*/
@Test
fn TestSlotBExecution()
{
Prepare()
Load(0, 0x01000093)
Load(1, 0x06300113)
Load(2, 0x0020a023)
Load(3, 0x0000a183)
Load(4, 0x00100073)
var elapsed: uint = 0
state {
core.run = 0b1
}
while (core.halted == 0b0 && elapsed < 300) {
state {
elapsed++
}
}
assert core.halted == 0b1 && core.faultCause as uint == 3
assert core.retiredRd as uint == 3
assert core.retiredValue as uint == 99
assert core.retiredPc as uint == 12
}
/**
* A store to a gap address outside both windows faults with the address.
*/
@Test
fn TestGapAddressFault()
{
Prepare()
Load(0, 0x02800093)
Load(1, 0x0020a023)
var elapsed: uint = 0
state {
core.run = 0b1
}
while (core.halted == 0b0 && elapsed < 300) {
state {
elapsed++
}
}
assert core.halted == 0b1 && core.faultCause as uint == 7
assert core.faultValue as uint == 40
assert core.retiredRd as uint == 1
assert core.retiredValue as uint == 40
assert core.retiredPc as uint == 0
assert core.pc as uint == 4
}
}