Axi2AxiSuite.scala 4.61 KB
Newer Older
Jens Korinth's avatar
Jens Korinth committed
1
package chisel.axiutils.axi4
2
import  chisel.axi.Axi4._
Jens Korinth's avatar
Jens Korinth committed
3
4
5
6
import  chisel3._
import  chisel3.util._
import  chisel3.iotesters.{ChiselFlatSpec, Driver, PeekPokeTester}
import  chisel.axi._
Jens Korinth's avatar
Jens Korinth committed
7
8
import  chisel.axiutils._
import  chisel.miscutils.{DecoupledDataSource, Logging}
Jens Korinth's avatar
Jens Korinth committed
9
10
import  org.scalatest.prop.Checkers
import  org.scalacheck.Prop._
Jens Korinth's avatar
Jens Korinth committed
11
import  scala.math.{random, pow}
12

Jens Korinth's avatar
Jens Korinth committed
13
14
15
/** Composite test module:
 *  Uses FifoAxiAdapter to fill SlaveModel; then reads data from
 *  SlaveModel via AxiFifoAdapter.
16
 **/
Jens Korinth's avatar
Jens Korinth committed
17
class Axi2AxiModule(val fifoDepth: Int = 16, val size: Option[Int])
Jens Korinth's avatar
Jens Korinth committed
18
19
                   (implicit axi: Axi4.Configuration, l: Logging.Level)
    extends Module with Logging {
Jens Korinth's avatar
Jens Korinth committed
20
  require (size.isEmpty || log2Ceil(size.get) <= axi.addrWidth,
21
           "size (%d) elements cannot be addressed by %d address bits".format(size.get, axi.addrWidth:Int))
22

Jens Korinth's avatar
Jens Korinth committed
23
24
25
  val io = IO(new Bundle {
    val deq = Decoupled(UInt(axi.dataWidth))
  })
26

27
  val sz = size.getOrElse(pow(2, axi.addrWidth.toDouble).toInt / axi.dataWidth)
Jens Korinth's avatar
Jens Korinth committed
28
  val aw = Seq(axi.addrWidth:Int, log2Ceil(sz * (axi.dataWidth / 8))).min
Jens Korinth's avatar
Jens Korinth committed
29
  cinfo ("Axi2AxiModule: address bits = %d, size = %d".format(aw, sz))
Jens Korinth's avatar
Jens Korinth committed
30
  val cfg = SlaveModel.Configuration(size = Some(sz), readDelay = 0, writeDelay = 0)
31

32
33
  val data = 0 to sz map (n => n % pow(2, axi.dataWidth:Int).toInt)

Jens Korinth's avatar
Jens Korinth committed
34
35
36
37
  val dsrc = Module(new DecoupledDataSource(gen = UInt(axi.dataWidth),
                                            size = sz,
                                            data = data map (_.U),
                                            repeat = false))
38

Jens Korinth's avatar
Jens Korinth committed
39
  val fad  = Module(new FifoAxiAdapter(fifoDepth = sz, burstSize = Some(fifoDepth)))
Jens Korinth's avatar
Jens Korinth committed
40
  val saxi = Module(new SlaveModel(cfg))
Jens Korinth's avatar
Jens Korinth committed
41
42
  val afa  = Module(AxiFifoAdapter(fifoDepth = fifoDepth))
  val base = 0.U(aw.W)
43

Jens Korinth's avatar
Jens Korinth committed
44
45
  fad.io.enable          := true.B
  fad.io.enq             <> dsrc.io.out
46
47
48
49
50
  saxi.io.saxi.writeAddr <> fad.io.maxi.writeAddr
  saxi.io.saxi.writeData <> fad.io.maxi.writeData
  saxi.io.saxi.writeResp <> fad.io.maxi.writeResp
  saxi.io.saxi.readAddr  <> afa.io.maxi.readAddr
  saxi.io.saxi.readData  <> afa.io.maxi.readData
Jens Korinth's avatar
Jens Korinth committed
51
  afa.io.enable := ~dsrc.io.out.valid //| fad.io.count > 0.U
52
53
54
55
56
57
58
59
60
61
62
  fad.io.base := base
  afa.io.base := base
  io.deq <> afa.io.deq
}

/**
 * Axi2AxiTester uses Axi2AxiModule to test full AXI-M roundtrip:
 * Data is send to memory slave via FifoAxiAdapter, then retrieved
 * via AxiFifoAdapter and compared.
 * Does NOT perform any timing checks, only correctness.
 **/
Jens Korinth's avatar
Jens Korinth committed
63
class Axi2AxiTester(m: Axi2AxiModule)
Jens Korinth's avatar
Jens Korinth committed
64
                   (implicit axi: Axi4.Configuration, l: Logging.Level) extends PeekPokeTester(m) {
65
  def toBinaryString(v: BigInt): String =
66
    "b%%%ds".format(axi.dataWidth:Int).format(v.toString(2)).replace(' ', '0')
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
  private val O = 10000
  private var cc = 0
  private var ccc = O
  override def step(n: Int) = {
    super.step(n)
    cc += n
    ccc -= n
    if (ccc <= 0) {
      println ("cc = %d".format(cc))
      ccc = O
    }
  }

  reset (10)
  poke(m.io.deq.ready, true)
  for (i <- 0 until m.sz) {
Jens Korinth's avatar
Jens Korinth committed
83
84
    while (peek(m.io.deq.valid) == 0) step (1)
    val v = peek(m.io.deq.bits)
85
    val e = m.data(i)
86
87
88
89
90
91
92
93
    expect (v == e, "mem[%08d] = %d (%s), expected: %d (%s)"
            .format(i, v, toBinaryString(v), e, toBinaryString(e)))
    step(1) // advance sim
  }
  step (20)
}

/** Test suite using both AxiFifoAdapter and FifoAxiAdapter. **/
Jens Korinth's avatar
Jens Korinth committed
94
class Axi2AxiSuite extends ChiselFlatSpec with Checkers {
Jens Korinth's avatar
Jens Korinth committed
95
  import java.nio.file._
Jens Korinth's avatar
Jens Korinth committed
96
97
  implicit val logLevel = chisel.miscutils.Logging.Level.Info
  behavior of "AxiFifoAdapter and FifoAxiAdapter"
Jens Korinth's avatar
Jens Korinth committed
98

Jens Korinth's avatar
Jens Korinth committed
99
  def run(size: Int, fifoDepth: Int, addrWidth: Int, dataWidth: Int): Boolean = {
Jens Korinth's avatar
Jens Korinth committed
100
101
    implicit val axi = Axi4.Configuration(addrWidth = AddrWidth(addrWidth), dataWidth = DataWidth(dataWidth))
    val dir = Paths.get("test")
102
      .resolve("s%d_aw%d_dw%d".format(size, addrWidth, axi.dataWidth:Int))
Jens Korinth's avatar
Jens Korinth committed
103
      .toString
Jens Korinth's avatar
Jens Korinth committed
104
    try {
Jens Korinth's avatar
Jens Korinth committed
105
106
107
    Driver.execute(Array("--fint-write-vcd", "--target-dir", dir),
                   () => new Axi2AxiModule(fifoDepth = fifoDepth,
                                           size = Some(size)))
108
      { m => new Axi2AxiTester(m) }
Jens Korinth's avatar
Jens Korinth committed
109
110
111
112
    } catch { case ex: Throwable =>
      ex.getStackTrace() foreach (println(_))
      throw ex
    }
113
114
  }

Jens Korinth's avatar
Jens Korinth committed
115
116
117
  it should "be ok" in  { check(run (size = 8, fifoDepth = 4, addrWidth = 32, dataWidth = 8)) }
  //"run8bit" should "be ok" in  { check(run (size = 256, fifoDepth = 4, addrWidth = 32, dataWidth = 8)) }
  /*"run16bit" should "be ok" in { run (size = 256, fifoDepth = 8, addrWidth = 32, dataWidth = 16) }
Jens Korinth's avatar
Jens Korinth committed
118
  "run32bit" should "be ok" in { run (size = 256, fifoDepth = 8, addrWidth = 32, dataWidth = 32) }
Jens Korinth's avatar
Jens Korinth committed
119
  "run64bit" should "be ok" in { run (size = 1024, fifoDepth = 256, addrWidth = 32, dataWidth = 64) }*/
120
}