blob: 8715c094d850ad65bf5389a37f0ae2e63ec13588 [file]
// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package kelvin
import chisel3._
import chisel3.simulator.scalatest.ChiselSim
import org.scalatest.freespec.AnyFreeSpec
class CoreAxiCSRSpec extends AnyFreeSpec with ChiselSim {
var p = new Parameters
p.enableVector = false
"Initialization" in {
simulate(new CoreAxiCSR(p)) { dut =>
dut.io.axi.read.addr.ready.expect(1)
dut.io.axi.read.data.valid.expect(0)
dut.io.axi.write.addr.ready.expect(1)
dut.io.axi.write.data.ready.expect(1)
dut.io.axi.write.resp.valid.expect(0)
}
}
"Read" in {
simulate(new CoreAxiCSR(p)) { dut =>
dut.io.internal.poke(false.B)
dut.io.halted.poke(false.B)
dut.io.fault.poke(false.B)
dut.io.kelvin_csr.value(0).poke("xCAFEB0BA".U)
// Send read request
dut.io.axi.read.addr.valid.poke(true.B)
dut.io.axi.read.addr.bits.addr.poke(0x100.U)
dut.io.axi.read.addr.ready.expect(1)
dut.clock.step()
dut.io.axi.read.addr.valid.poke(false.B)
// Wait for response
while (dut.io.axi.read.data.valid.peek().litValue != 1) {
dut.clock.step()
}
dut.io.axi.read.data.valid.expect(1)
dut.io.axi.read.data.bits.data.expect(3405689018L)
dut.io.axi.read.data.bits.last.expect(1)
dut.io.axi.read.data.bits.resp.expect(0)
// Accept response, check that no requests were made after.
dut.io.axi.read.data.ready.poke(true.B)
for (i <- 0 until 10) {
dut.io.axi.read.data.valid.peek()
}
}
}
"Write" in {
simulate(new CoreAxiCSR(p)) { dut =>
dut.io.internal.poke(false.B)
dut.io.halted.poke(false.B)
dut.io.fault.poke(false.B)
// Check initial values.
dut.io.cg.expect(1)
dut.io.reset.expect(1)
dut.io.pcStart.expect(0)
// Configure write address and write data
dut.io.axi.write.addr.valid.poke(true.B)
dut.io.axi.write.addr.bits.addr.poke(0x4)
dut.io.axi.write.addr.bits.len.poke(0.U)
dut.io.axi.write.addr.bits.size.poke(2.U)
dut.io.axi.write.addr.ready.expect(1)
dut.io.axi.write.data.bits.data.poke((BigInt(0x20000000) << 32).U)
dut.io.axi.write.data.bits.strb.poke(0xFF00.U)
dut.io.axi.write.data.bits.last.poke(true.B)
dut.io.axi.write.data.valid.poke(true.B)
dut.io.axi.write.data.ready.expect(1)
dut.clock.step()
dut.io.axi.write.addr.valid.poke(false.B)
dut.io.axi.write.data.valid.poke(false.B)
// Wait for response
while (dut.io.axi.write.resp.valid.peek().litValue != 1) {
dut.clock.step()
}
// Check that only pcStartReg changed.
dut.io.cg.expect(1)
dut.io.reset.expect(1)
dut.io.pcStart.expect(0x20000000)
// Accept write response
dut.io.axi.write.resp.ready.poke(true.B)
dut.clock.step()
dut.io.axi.write.resp.ready.poke(false.B)
for (i <- 0 until 10) {
dut.clock.step()
// Check that only pcStartReg changed.
dut.io.cg.expect(1)
dut.io.reset.expect(1)
dut.io.pcStart.expect(0x20000000)
dut.io.axi.write.resp.valid.expect(0)
}
// Check write result via AXI, as well
dut.io.axi.read.addr.valid.poke(true.B)
dut.io.axi.read.addr.bits.addr.poke(0x4)
dut.io.axi.read.addr.bits.size.poke(2.U)
dut.io.axi.read.addr.bits.len.poke(0.U)
while (dut.io.axi.read.addr.ready.peek().litValue != 1) {
dut.clock.step()
}
dut.clock.step()
dut.io.axi.read.addr.valid.poke(false.B)
// Wait for read data
while (dut.io.axi.read.data.valid.peek().litValue != 1) {
dut.clock.step()
}
assert((dut.io.axi.read.data.bits.data.peek().litValue >> 32) == 0x20000000)
dut.io.axi.read.data.bits.last.expect(1)
dut.io.axi.read.data.bits.resp.expect(0)
// Accept read result, no pending read
dut.io.axi.read.data.ready.poke(true.B)
dut.clock.step()
dut.io.axi.read.data.valid.expect(0)
dut.io.axi.read.data.ready.poke(false.B)
}
}
"WriteInvalid" in {
simulate(new CoreAxiCSR(p)) { dut =>
dut.io.internal.poke(false.B)
dut.io.halted.poke(false.B)
dut.io.fault.poke(false.B)
// Check initial values.
dut.io.cg.expect(1)
dut.io.reset.expect(1)
dut.io.pcStart.expect(0)
// Configure write address and write data
dut.io.axi.write.addr.valid.poke(true.B)
dut.io.axi.write.addr.bits.addr.poke(0x104)
dut.io.axi.write.addr.bits.len.poke(0.U)
dut.io.axi.write.addr.bits.size.poke(2.U)
dut.io.axi.write.addr.ready.expect(1)
dut.io.axi.write.data.bits.data.poke((BigInt(0x20000000) << 32).U)
dut.io.axi.write.data.bits.strb.poke(0xFF00.U)
dut.io.axi.write.data.bits.last.poke(true.B)
dut.io.axi.write.data.valid.poke(true.B)
dut.io.axi.write.data.ready.expect(1)
dut.clock.step()
dut.io.axi.write.addr.valid.poke(false.B)
dut.io.axi.write.data.valid.poke(false.B)
// Wait for response
while (dut.io.axi.write.resp.valid.peek().litValue != 1) {
dut.clock.step()
}
// Check error was raised in response
dut.io.axi.write.resp.bits.resp.expect(2)
// Check that no register changed.
dut.io.cg.expect(1)
dut.io.reset.expect(1)
dut.io.pcStart.expect(0)
// Accept write response
dut.io.axi.write.resp.ready.poke(true.B)
dut.clock.step()
dut.io.axi.write.resp.ready.poke(false.B)
// Check that no register changed.
dut.io.cg.expect(1)
dut.io.reset.expect(1)
dut.io.pcStart.expect(0)
}
}
}