diff --git a/.scalafmt.conf b/.scalafmt.conf index 92dc1fca15..e5728d5df5 100644 --- a/.scalafmt.conf +++ b/.scalafmt.conf @@ -1,5 +1,40 @@ version = 3.6.0 runner.dialect = scala212 align.preset = some -maxColumn = 120 +align.tokens."+" = [ + { + code = "=" + owners = [{ + regex = "Defn\\.Val" + }] + } + { + code = ":=" + owners = [{ + regex = "Term\\.ApplyInfix" + parents = ["Term\\.Block|Template"] + }] + } + { + code = "#=" + owners = [{ + regex = "Term\\.ApplyInfix" + parents = ["Term\\.Block|Template"] + }] + } + { + code = "port" + owners = [{ + regex = "Term\\.ApplyInfix" + parents = ["Defn\\.Val"] + }] + } + { + code = "->" + owners = [{ + regex = "Term\\.ApplyInfix" + }] + } +] docstrings.wrap = no +docstrings.oneline = fold diff --git a/build.sbt b/build.sbt index 43574ae26b..664f4c8353 100644 --- a/build.sbt +++ b/build.sbt @@ -126,7 +126,7 @@ val defaultSettingsWithPlugin = defaultSettings ++ Seq( }.value ) -lazy val core = (project in file("core")) +lazy val core: Project = (project in file("core")) .dependsOn(idslplugin) .settings( defaultSettingsWithPlugin, @@ -134,6 +134,8 @@ lazy val core = (project in file("core")) libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value, libraryDependencies += "com.github.scopt" %% "scopt" % "3.7.1", libraryDependencies += "com.lihaoyi" %% "sourcecode" % "0.2.7", + Test / unmanagedClasspath ++= (LocalProject("tester") / Compile / fullClasspath).value, + Test / unmanagedClasspath ++= (LocalProject("lib") / Compile / fullClasspath).value, resolvers += Resolver.sonatypeRepo("public"), version := SpinalVersion.core, @@ -153,18 +155,17 @@ lazy val core = (project in file("core")) ) .dependsOn(sim) -lazy val lib = (project in file("lib")) +lazy val lib: Project = (project in file("lib")) .settings( defaultSettingsWithPlugin, name := "SpinalHDL-lib", libraryDependencies += "commons-io" % "commons-io" % "2.4", - version := SpinalVersion.lib + version := SpinalVersion.lib, + Test / unmanagedClasspath ++= (LocalProject("tester") / Compile / fullClasspath).value ) - .dependsOn (sim, core) + .dependsOn(sim, core) - - -lazy val tester = (project in file("tester")) +lazy val tester: Project = (project in file("tester")) .settings( defaultSettingsWithPlugin, name := "SpinalHDL-tester", diff --git a/core/src/test/scala/integration/CommonTester.scala b/core/src/test/scala/integration/CommonTester.scala new file mode 100644 index 0000000000..cea301138b --- /dev/null +++ b/core/src/test/scala/integration/CommonTester.scala @@ -0,0 +1,115 @@ +package integration + +import spinal.tester.SpinalTesterCocotbBase + +import spinal.core._ + +object CommonTester { + class BundleA() extends Bundle { + val bod = new Bundle { + val gggg = Bool() + val aosi = UInt(3 bit) + } + val ahe = Bool() + val zwg = Bool() + } + + case class BundleAA() extends BundleA { + val vsw = Bool() + val lwee = UInt(5 bit) + } + + case class CommonTester() extends Component { + val io = new Bundle { + val conds = in port Vec(Bool(), 8) + + val inUIntA = in port UInt(8 bit) + val inUIntB = in port UInt(8 bit) + val outUIntAdder = out port UInt() + + val inAA = in port BundleAA() + val inAABits = in port Bits(BundleAA().getBitsWidth bit) + val outAA = out port BundleAA() + val outAABits = out port Bits(BundleAA().getBitsWidth bit) + + val complexLiteral = out port UInt(16 bit) + + val assign = new Bundle { + val sel = in port Vec(UInt(4 bit), 4) + val bitDemux = out port Bits(16 bit) + + def doIt(): Unit = { + bitDemux := B(0) + bitDemux(sel(0)) := conds(0) + + when(conds(1)) { + bitDemux(sel(1)) := conds(2) + } elsewhen (conds(3)) { + bitDemux(sel(0)) := conds(4) + } + + when(conds(5)) { + bitDemux(sel(1)) := conds(6) + } + + bitDemux(5) := True + } + } + + def doIt(): Unit = { + assign.doIt() + } + } + + io.doIt() + + io.outAA.assignFromBits(io.inAABits) + io.outAABits := io.inAA.asBits + + io.complexLiteral(15 downto 4) := 0x70 + io.complexLiteral(15 downto 12) := (U(2) + U(1)).resized + io.complexLiteral(6) := True + io.complexLiteral(3) := True + io.complexLiteral(5) := True + io.complexLiteral(3 downto 0) := 2 + io.complexLiteral(13) := False + + def combAdderFunc(x: UInt, y: UInt): UInt = { + val ret = UInt(widthOf(x) max widthOf(y) bits) + val size = io.inUIntA.getWidth + + var c = False + for (i <- 0 until size) { + val a = x(i) + val b = y(i) + ret(i) := a ^ b ^ c + c \= (a & b) | (a & c) | (b & c) + } + + ret + } + + io.outUIntAdder := combAdderFunc(io.inUIntA, io.inUIntB) + + // Clone test + case class MyBundle(paramBool: Bool, asd: Int) extends Bundle { + val a = cloneOf(paramBool) + } + + case class MyBundle2() extends Bundle { + val a = Bool() + } + + cloneOf(MyBundle(True, 1)) + cloneOf(MyBundle2()) + } +} + +class CommonTesterCocotbBoot extends SpinalTesterCocotbBase { + override def getName: String = "CommonTester" + + override def createToplevel: Component = new CommonTester.CommonTester + + override def pythonTestLocation: String = + "tester/src/test/python/spinal/CommonTester" +} diff --git a/tester/src/test/scala/spinal/tester/scalatest/OperatorTester.scala b/core/src/test/scala/integration/OperatorTester.scala similarity index 92% rename from tester/src/test/scala/spinal/tester/scalatest/OperatorTester.scala rename to core/src/test/scala/integration/OperatorTester.scala index b2002b8d25..e91c69b786 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/OperatorTester.scala +++ b/core/src/test/scala/integration/OperatorTester.scala @@ -1,26 +1,8 @@ -/* - * SpinalHDL - * Copyright (c) Dolu, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ - -package spinal.tester.scalatest +package integration + +import spinal.tester.SpinalTesterCocotbBase import spinal.core._ -import spinal.lib._ -import spinal.tester.scalatest.OperatorTester.OperatorTester object OperatorTester { object State extends SpinalEnum{ @@ -295,7 +277,7 @@ object OperatorTester { class OperatorTesterCocotbBoot extends SpinalTesterCocotbBase { override def getName: String = "OperatorTester" - override def createToplevel: Component = new OperatorTester.OperatorTester + override def createToplevel: Component = new OperatorTester.OperatorTester override def pythonTestLocation: String = "tester/src/test/python/spinal/OperatorTester" } diff --git a/tester/src/test/scala/spinal/tester/scalatest/ZeroWidthTester.scala b/core/src/test/scala/integration/ZeroWidthTester.scala similarity index 98% rename from tester/src/test/scala/spinal/tester/scalatest/ZeroWidthTester.scala rename to core/src/test/scala/integration/ZeroWidthTester.scala index b0e6826196..e1ebe0024a 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/ZeroWidthTester.scala +++ b/core/src/test/scala/integration/ZeroWidthTester.scala @@ -16,16 +16,15 @@ * License along with this library. */ -package spinal.tester.scalatest +package integration + +import spinal.tester.SpinalTesterCocotbBase import spinal.core._ -import spinal.lib._ import scala.io.Source object ZeroWidthTester { - - class ZeroWidthTester extends Component { val uint8 = in UInt(8 bits) val sint8 = in SInt(8 bits) @@ -51,8 +50,6 @@ object ZeroWidthTester { val sint08ShiftLeftUint = out(sint0 << uint8) val bits08ShiftLeftUint = out(bits0 << uint8) - - val uint08Equals = out(uint0 === uint8) val uint08NotEquals = out(uint0 =/= uint8) @@ -69,7 +66,6 @@ object ZeroWidthTester { val uint08Bigger = out(uint0 > uint8) val uint08BiggerEquals = out(uint0 >= uint8) - val sint08Equals= out(sint0 === sint8) val sint08NotEquals = out(sint0 =/= sint8) @@ -86,8 +82,6 @@ object ZeroWidthTester { val sint08Bigger = out(sint0 > sint8) val sint08BiggerEquals = out(sint0 >= sint8) - - val bits08Equals= out(0 === bits8) val bits08NotEquals = out(0 =/= bits8) @@ -95,7 +89,6 @@ object ZeroWidthTester { val bits08Or = out(bits0.resized | bits8) val bits08Xor = out(bits0.resized ^ bits8) - val uint80ShiftLeftUint = out(uint8 >> uint0) val sint80ShiftLeftUint = out(sint8 >> uint0) val bits80ShiftLeftUint = out(bits8 >> uint0) @@ -139,14 +132,12 @@ object ZeroWidthTester { val bits80Or = out(bits8 | bits0.resized) val bits80Xor = out(bits8 ^ bits0.resized) - val bitsResizeBigger = out(bits0.resize(16)) val uintResizeBigger = out(uint0.resize(16)) val sintResizeBigger = out(sint0.resize(16)) val bits08Cat = out(bits0 ## bits8) val bits80Cat = out(bits8 ## bits0) - } } @@ -174,4 +165,4 @@ class ZeroWidthTesterCocotbBoot extends SpinalTesterCocotbBase { } } } -} \ No newline at end of file +} diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimAFixTester.scala b/core/src/test/scala/spinal/core/AFix.scala similarity index 99% rename from tester/src/test/scala/spinal/tester/scalatest/SpinalSimAFixTester.scala rename to core/src/test/scala/spinal/core/AFix.scala index 1ca350634b..b8378bb490 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimAFixTester.scala +++ b/core/src/test/scala/spinal/core/AFix.scala @@ -1,9 +1,8 @@ -package spinal.tester.scalatest +package spinal.core -import spinal.core._ -import org.scalatest.funsuite.AnyFunSuite import spinal.core.sim._ +import org.scalatest.funsuite.AnyFunSuite import java.math.MathContext import scala.collection.mutable import scala.math.BigDecimal.RoundingMode diff --git a/core/src/test/scala/spinal/core/Area.scala b/core/src/test/scala/spinal/core/Area.scala new file mode 100644 index 0000000000..6e94b9b8f4 --- /dev/null +++ b/core/src/test/scala/spinal/core/Area.scala @@ -0,0 +1,34 @@ +package spinal.core + +import org.scalatest.funsuite.AnyFunSuite + +import spinal.core.sim._ + +class AreaTester extends AnyFunSuite { + test("SlowArea") { + SimConfig + .withConfig( + SpinalConfig(defaultClockDomainFrequency = FixedFrequency(4000 Hz)) + ) + .compile(new Component { + val counter = out(RegInit(U"0000")) + counter := counter + 1 + assert(clockDomain.samplingRate.getValue.toInt == 4000) + + val slowArea = new SlowArea(4) { + val counter = out(RegInit(U"0000")) + counter := counter + 1 + assert(clockDomain.samplingRate.getValue.toInt == 1000) + } + }) + .doSim { dut => + dut.clockDomain.forkStimulus(10) + + for (i <- 0 until 1000) { + dut.clockDomain.waitSampling() + assert(dut.counter.toInt == i % 16) + assert(dut.slowArea.counter.toInt == (i - 1) / 4 % 16) + } + } + } +} diff --git a/tester/src/test/scala/spinal/tester/scalatest/BlackboxTester.scala b/core/src/test/scala/spinal/core/BlackBox.scala similarity index 89% rename from tester/src/test/scala/spinal/tester/scalatest/BlackboxTester.scala rename to core/src/test/scala/spinal/core/BlackBox.scala index fb2ef241f0..eb65f5d13c 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/BlackboxTester.scala +++ b/core/src/test/scala/spinal/core/BlackBox.scala @@ -1,10 +1,10 @@ -package spinal.tester.scalatest +package spinal.core +import spinal.core.sim._ -import spinal.core._ -import spinal.lib._ +import spinal.tester.{SpinalSimFunSuite, SpinalTesterCocotbBase} -object BlackboxTester { +object BlackBoxTester { case class BBGenerics(aWidth: Int, bWidth: Int) extends Generic @@ -41,14 +41,13 @@ object BlackboxTester { class BlackboxTesterCocotbBoot extends SpinalTesterCocotbBase { override def getName: String = "BlackBoxTester" - override def createToplevel: Component = new BlackboxTester.BlackBoxTester + override def createToplevel: Component = new BlackBoxTester.BlackBoxTester override def pythonTestLocation: String = "tester/src/test/python/spinal/BlackBoxTester" } -import spinal.core.sim._ class SpinalSimBlackboxTester extends SpinalSimFunSuite { test("test"){ - SimConfig.addRtl(s"tester/src/test/python/spinal/BlackBoxTester/BlackBoxToTest.${if(tester.language == VHDL) "vhd" else "v"}").doSim(new BlackboxTester.BlackBoxTester) {dut => + SimConfig.addRtl(s"tester/src/test/python/spinal/BlackBoxTester/BlackBoxToTest.${if(tester.language == VHDL) "vhd" else "v"}").doSim(new BlackBoxTester.BlackBoxTester) {dut => dut.clockDomain.forkStimulus(10) var outA_ref = 0 var outB_ref = 0 diff --git a/tester/src/test/scala/spinal/tester/scalatest/BundleTester.scala b/core/src/test/scala/spinal/core/Bundle.scala similarity index 94% rename from tester/src/test/scala/spinal/tester/scalatest/BundleTester.scala rename to core/src/test/scala/spinal/core/Bundle.scala index a139ebd2a9..4d55d56248 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/BundleTester.scala +++ b/core/src/test/scala/spinal/core/Bundle.scala @@ -16,9 +16,9 @@ * License along with this library. */ -package spinal.tester.scalatest +package spinal.core -import spinal.core._ +import spinal.tester.SpinalTesterCocotbBase object BundleTester { class BundleAA extends BundleA(True,3) { @@ -32,7 +32,7 @@ object BundleTester { } } -import spinal.tester.scalatest.BundleTester._ +import BundleTester._ class BundleTester extends Component { val io = new Bundle { diff --git a/core/src/test/scala/spinal/core/ClockDomain.scala b/core/src/test/scala/spinal/core/ClockDomain.scala new file mode 100644 index 0000000000..a19568a8a4 --- /dev/null +++ b/core/src/test/scala/spinal/core/ClockDomain.scala @@ -0,0 +1,520 @@ +package spinal.core + +import scala.util.Random + +import spinal.core.sim._ +import spinal.lib.{BufferCC, Counter, CounterFreeRun, NoData, ResetCtrl} +import spinal.tester.{SpinalSimFunSuite, SpinalTesterCocotbBase} + +object ClockDomainConfigTester { + class ClockDomainConfigTester() extends Component { + val clk,syncReset,asyncReset,softReset,enable = in Bool() + val clkn,syncResetn,asyncResetn,softResetn,enablen = in Bool() + + class TestArea(cd : ClockDomain,withInit : Boolean = true) extends ClockingArea(cd){ + val regWithoutReset = out(Reg(UInt(8 bits)) randBoot()) + regWithoutReset := regWithoutReset + 1 + val regWithReset = if(withInit) { + val reg = out(Reg(UInt(8 bits)) init(42) randBoot()) + reg := reg + 1 + reg + } else null + } + + val test_clk = new TestArea(ClockDomain( + clock = clk, + config = ClockDomainConfig( + clockEdge = RISING, + resetKind = ASYNC, + resetActiveLevel = HIGH, + softResetActiveLevel = HIGH, + clockEnableActiveLevel= HIGH + ) + ),false) + + val test_clkn = new TestArea(ClockDomain( + clock = clkn, + config = ClockDomainConfig( + clockEdge = FALLING, + resetKind = ASYNC, + resetActiveLevel = HIGH, + softResetActiveLevel = HIGH, + clockEnableActiveLevel= HIGH + ) + ),false) + + + val test_clk_boot = new TestArea(ClockDomain( + clock = clk, + config = ClockDomainConfig( + clockEdge = RISING, + resetKind = BOOT, + resetActiveLevel = HIGH, + softResetActiveLevel = HIGH, + clockEnableActiveLevel= HIGH + ) + )) + + val test_async_reset = new TestArea(ClockDomain( + clock = clk, + reset = asyncReset, + config = ClockDomainConfig( + clockEdge = RISING, + resetKind = ASYNC, + resetActiveLevel = HIGH, + softResetActiveLevel = HIGH, + clockEnableActiveLevel= HIGH + ) + )) + + val test_async_resetn = new TestArea(ClockDomain( + clock = clk, + reset = asyncResetn, + config = ClockDomainConfig( + clockEdge = RISING, + resetKind = ASYNC, + resetActiveLevel = LOW, + softResetActiveLevel = HIGH, + clockEnableActiveLevel= HIGH + ) + )) + + val test_sync_reset = new TestArea(ClockDomain( + clock = clk, + reset = syncReset, + config = ClockDomainConfig( + clockEdge = RISING, + resetKind = SYNC, + resetActiveLevel = HIGH, + softResetActiveLevel = HIGH, + clockEnableActiveLevel= HIGH + ) + )) + + val test_sync_resetn = new TestArea(ClockDomain( + clock = clk, + reset = syncResetn, + config = ClockDomainConfig( + clockEdge = RISING, + resetKind = SYNC, + resetActiveLevel = LOW, + softResetActiveLevel = HIGH, + clockEnableActiveLevel= HIGH + ) + )) + + val test_enable = new TestArea(ClockDomain( + clock = clk, + clockEnable = enable, + config = ClockDomainConfig( + clockEdge = RISING, + resetKind = ASYNC, + resetActiveLevel = HIGH, + softResetActiveLevel = HIGH, + clockEnableActiveLevel= HIGH + ) + ),false) + + val test_enablen = new TestArea(ClockDomain( + clock = clk, + clockEnable = enablen, + config = ClockDomainConfig( + clockEdge = RISING, + resetKind = ASYNC, + resetActiveLevel = HIGH, + softResetActiveLevel = HIGH, + clockEnableActiveLevel= LOW + ) + ),false) + + val test_sync_reset_enable = new TestArea(ClockDomain( + clock = clk, + reset = syncReset, + clockEnable = enable, + config = ClockDomainConfig( + clockEdge = RISING, + resetKind = SYNC, + resetActiveLevel = HIGH, + softResetActiveLevel = HIGH, + clockEnableActiveLevel= HIGH + ) + )) + + val test_softReset = new TestArea(ClockDomain( + clock = clk, + softReset = softReset, + config = ClockDomainConfig( + clockEdge = RISING, + resetKind = ASYNC, + resetActiveLevel = HIGH, + softResetActiveLevel = HIGH, + clockEnableActiveLevel= HIGH + ) + )) + + val test_softResetn = new TestArea(ClockDomain( + clock = clk, + softReset = softResetn, + config = ClockDomainConfig( + clockEdge = RISING, + resetKind = ASYNC, + resetActiveLevel = HIGH, + softResetActiveLevel = LOW, + clockEnableActiveLevel= HIGH + ) + )) + + val test_async_reset_softReset = new TestArea(ClockDomain( + clock = clk, + reset = asyncReset, + softReset = softReset, + config = ClockDomainConfig( + clockEdge = RISING, + resetKind = ASYNC, + resetActiveLevel = HIGH, + softResetActiveLevel = HIGH, + clockEnableActiveLevel= HIGH + ) + )) + + val test_sync_reset_softReset = new TestArea(ClockDomain( + clock = clk, + reset = syncReset, + softReset = softReset, + config = ClockDomainConfig( + clockEdge = RISING, + resetKind = SYNC, + resetActiveLevel = HIGH, + softResetActiveLevel = HIGH, + clockEnableActiveLevel= HIGH + ) + )) + + + + } + +} + +class ClockDomainConfigTesterCocotbBoot extends SpinalTesterCocotbBase { + override def getName: String = "ClockDomainConfigTester" + override def pythonTestLocation: String = "tester/src/test/python/spinal/ClockDomainConfigTester" + override def createToplevel: Component = new ClockDomainConfigTester.ClockDomainConfigTester() +} + +class MultiClockTester extends Component { + import spinal.lib._ + + class BundleA extends Bundle{ + val a = UInt(8 bit) + val b = Bool() + } + + val io = new Bundle { + val clkA = in Bool() + val resetA = in Bool() + val clkB = in Bool() + val resetB = in Bool() + + val slave0 = slave Stream(new BundleA) + val master0 = master Stream(new BundleA) + val fifo0_pushOccupancy = out UInt() + val fifo0_popOccupancy = out UInt() + } + + val clockDomainA = ClockDomain(io.clkA,io.resetA) + val clockDomainB = ClockDomain(io.clkB,io.resetB) + + val fifo0 = new StreamFifoCC(new BundleA,16,clockDomainA,clockDomainB) + fifo0.io.push << io.slave0 + fifo0.io.pop >> io.master0 + io.fifo0_pushOccupancy := fifo0.io.pushOccupancy + io.fifo0_popOccupancy := fifo0.io.popOccupancy + +} + +class MultiClockTesterCocotbBoot extends SpinalTesterCocotbBase { + override def getName: String = "MultiClockTester" + override def pythonTestLocation: String = "tester/src/test/python/spinal/MultiClockTester" + override def createToplevel: Component = new MultiClockTester +} + +object SpinalSimClockDomainTest{ + class SpinalSimClockDomainTest1 extends Component { + val io = new Bundle { + val mClk, mReset = in Bool() + val a, b, c = in UInt (8 bits) + val result = out UInt (8 bits) + } + + val tmpClk, tmpReset = Bool() + tmpClk := io.mClk + tmpReset := io.mReset + ClockDomain(tmpClk, tmpReset){ + io.result := RegNext(io.a + io.b - io.c) init(0) + } + } + + class SpinalSimClockDomainTest2 extends Component { + val io = new Bundle { + val mClk, mReset = in Bool() + val a, b, c = in UInt (8 bits) + val result = out UInt (8 bits) + } + + ClockDomain(io.mClk, io.mReset){ + io.result := RegNext(io.a + io.b - io.c) init(0) + } + } + class SpinalSimClockDomainTest3 extends Component { + val io = new Bundle { + val a, b, c = in UInt (8 bits) + val result = out UInt (8 bits) + } + + io.result := RegNext(io.a + io.b - io.c) init(0) + } + + class SpinalSimClockDomainTest4 extends Component { + val io = new Bundle { + val enable = in Bool() + val result = out UInt (8 bits) + } + + val reg = RegInit(U(42, 8 bits)) + when(io.enable){ + reg := reg + 1 + } + io.result := reg + } +} + +class SpinalSimClockDomainTest extends SpinalSimFunSuite { + val resetKinds = List(SYNC,ASYNC) + test("Test1") { + for (resetKind <- resetKinds) { + val compiled = SimConfig + .withConfig(SpinalConfig(defaultConfigForClockDomains = ClockDomainConfig(resetKind = resetKind))) + .compile(new SpinalSimClockDomainTest.SpinalSimClockDomainTest1().setDefinitionName("SpinalSimClockDomainTest1" + resetKind.getClass.getSimpleName.toString.take(4))) + .doSim(resetKind.toString) { dut => + // dut.clockDomain.forkStimulus(period = 10) + val cd = ClockDomain(dut.io.mClk, dut.io.mReset) + cd.forkStimulus(period = 10) + + for (repeat2 <- 0 until 10000) { + val a, b, c = Random.nextInt(256) + dut.io.a #= a + dut.io.b #= b + dut.io.c #= c + cd.waitActiveEdge(); sleep(0) + if (cd.isResetDeasserted) assert(dut.io.result.toInt == ((a + b - c) & 0xFF)) + } + } + } + } + + test("TestDeltaCycle wake") { + for (resetKind <- resetKinds) { + val compiled = SimConfig + .withConfig(SpinalConfig(defaultConfigForClockDomains = ClockDomainConfig(resetKind = resetKind))) + .compile(new SpinalSimClockDomainTest.SpinalSimClockDomainTest1().setDefinitionName("SpinalSimClockDomainTest1" + resetKind.getClass.getSimpleName.toString.take(4))) + .doSim(resetKind.toString) { dut => + // dut.clockDomain.forkStimulus(period = 10) + val cd = ClockDomain(dut.io.mClk, dut.io.mReset) + dut.io.a #= 0 + dut.io.b #= 0 + dut.io.c #= 0 + sleep(10) + cd.forkStimulus(period = 10) + cd.waitSampling() + cd.waitSampling() + dut.io.a #= 42 + cd.waitSampling() + assert(dut.io.result.toInt == 0) //Wakeup while rising edge, but before FF got the result out + sleep(0) + assert(dut.io.result.toInt == 42) + } + } + } + + + test("Test2") { + for (resetKind <- resetKinds) { + SimConfig + .withConfig(SpinalConfig(defaultConfigForClockDomains = ClockDomainConfig(resetKind = resetKind))) + .compile((new SpinalSimClockDomainTest.SpinalSimClockDomainTest2().setDefinitionName("SpinalSimClockDomainTest2" + resetKind.getClass.getSimpleName.toString.take(4)))) + .doSim(resetKind.toString) { dut => + // dut.clockDomain.forkStimulus(period = 10) + val cd = ClockDomain(dut.io.mClk, dut.io.mReset) + cd.forkStimulus(period = 10) + + var counter = 0 + while (true) { + val a, b, c = Random.nextInt(256) + dut.io.a #= a + dut.io.b #= b + dut.io.c #= c + cd.waitActiveEdge(); + sleep(0) + if (cd.isResetDeasserted) assert(dut.io.result.toInt == ((a + b - c) & 0xFF)) + counter += 1 + if (counter == 10000) simSuccess() + } + } + } + } + + test("Test3") { + for (resetKind <- resetKinds) { + SimConfig + .withConfig(SpinalConfig(defaultConfigForClockDomains = ClockDomainConfig(resetKind = resetKind))) + .compile((new SpinalSimClockDomainTest.SpinalSimClockDomainTest3().setDefinitionName("SpinalSimClockDomainTest3" + resetKind.getClass.getSimpleName.toString.take(4)))) + .doSim(resetKind.toString) { dut => + dut.clockDomain.forkStimulus(period = 10) + var model = BigInt(0) + for (repeat <- 0 until 10000) { + dut.io.a.randomize() + dut.io.b.randomize() + dut.io.c.randomize() + dut.clockDomain.waitActiveEdge() + if (dut.clockDomain.isResetDeasserted) { + assert(dut.io.result.toInt == model) + model = ((dut.io.a.toBigInt + dut.io.b.toLong - dut.io.c.toInt) & 0xFF) + } + } + } + } + } + + + test("Test4") { + SimConfig + .doSim(new SpinalSimClockDomainTest.SpinalSimClockDomainTest4) { dut => + dut.clockDomain.forkStimulus(period = 10) + var model = 42 + for (repeat <- 0 until 10000) { + dut.io.enable.randomize() + dut.clockDomain.waitActiveEdge(); sleep(0) + if (dut.io.enable.toBoolean) model = (model + 1) & 0xFF + assert(dut.io.result.toInt == model) + } + } + } + + test("Test5") { + SimConfig + .doSim(new SpinalSimClockDomainTest.SpinalSimClockDomainTest4) { dut => + dut.clockDomain.forkStimulus(period = 10) + var model = 42 + dut.io.enable #= false + dut.clockDomain.waitActiveEdge(1) + for (repeat <- 0 until 10000) { + dut.io.enable.randomize() + val waited = Random.nextInt(10) + dut.clockDomain.waitActiveEdge(waited); sleep(0) + if (dut.io.enable.toBoolean) model = (model + waited) & 0xFF + assert(dut.io.result.toInt == model) + } + } + } +} + +object InternalClockTester{ + class ClockGeneratorSub extends Component{ + val io = NoData + + val internalClock = CounterFreeRun(16)(0) + + val initCounter = RegInit(U(7)) + val srcReset = initCounter =/= U(0) + when(srcReset){ + initCounter := initCounter - U(1) + } + val internalClk = ClockDomain(internalClock) + val internalReset = Bool() + + val resetBuffer = new ClockingArea(internalClk){ + val internalReset = BufferCC(srcReset) + } + internalReset := resetBuffer.internalReset + + val internalClockDomain = ClockDomain(internalClock,internalReset) + } + + class ClockGenerator extends Component{ + val io = NoData + val sub = new ClockGeneratorSub + } + + class CounterComponentSub extends Component{ + val io = new Bundle{ + val counter = out UInt(8 bit) + } + val counter = Counter(256) + counter.increment() + io.counter := counter + } + + class CounterComponent extends Component{ + val io = new Bundle{ + val counter = out UInt(8 bit) + } + val sub = new CounterComponentSub + io <> sub.io + } +} + +class InternalClockTester extends Component { + val io = new Bundle { + val internalClkCounter = out UInt(8 bit) + } + val clockGenerator = new InternalClockTester.ClockGenerator + + val internClockDomain = new ClockingArea(clockGenerator.sub.internalClockDomain){ + val counterComponent = new InternalClockTester.CounterComponent + io.internalClkCounter := counterComponent.io.counter + } +} + +class InternalClockTesterCocotbBoot extends SpinalTesterCocotbBase { + override def getName: String = "InternalClockTester" + override def pythonTestLocation: String = "tester/src/test/python/spinal/InternalClockTester" + override def createToplevel: Component = new InternalClockTester +} + +object PllAAssertSDeassertTester{ + class PLL extends BlackBox{ + val io = new Bundle{ + val clk_in = in Bool() + val clk_out = out Bool() + } + + noIoPrefix() + } + + class PllAAssertSDeassertTester extends Component{ + val aReset = in Bool() + val clk_100Mhz = in Bool() + + val pllBB = new PLL + pllBB.io.clk_in := clk_100Mhz + + val coreClockDomain = ClockDomain.internal("core") + coreClockDomain.clock := pllBB.io.clk_out + coreClockDomain.reset := ResetCtrl.asyncAssertSyncDeassert( + input = aReset, + clockDomain = coreClockDomain + ) + + val counter = out(coreClockDomain(CounterFreeRun(10).value)).setName("counter") + } +} + +class PllAAssertSDeassertTesterBoot extends SpinalTesterCocotbBase { + override def getName: String = "PllAAssertSDeassertTester" + override def pythonTestLocation: String = "tester/src/test/python/spinal/PllAAssertSDeassertTester" + override def createToplevel: Component = new PllAAssertSDeassertTester.PllAAssertSDeassertTester + + override def backendConfig(config: SpinalConfig): SpinalConfig = config + .copy(defaultConfigForClockDomains = config.defaultConfigForClockDomains.copy(resetKind = SYNC)) +} diff --git a/core/src/test/scala/spinal/core/FixedPoint.scala b/core/src/test/scala/spinal/core/FixedPoint.scala index bd280f8eaa..ea1de95844 100644 --- a/core/src/test/scala/spinal/core/FixedPoint.scala +++ b/core/src/test/scala/spinal/core/FixedPoint.scala @@ -1,9 +1,45 @@ package spinal.core import org.scalatest.funsuite.AnyFunSuite + import spinal.core.sim._ +import spinal.tester.SpinalTesterCocotbBase + +object FixedPointTester { + case class BundleA(width : Int) extends Bundle{ + val a = BundleAA(width) + } + case class BundleAA(width : Int) extends Bundle{ + val sfix = SFix(4 exp,width bit) + } + + class FixedPointTester extends Component { + val io = new Bundle { + val inSFix = in(Vec(Seq(SFix(4 exp,16 bit),SFix(2 exp,12 bit)))) + val outSFix = out(Vec(Seq(SFix(4 exp,16 bit),SFix(8 exp,24 bit)))) + + val inSFix2 = in SFix(0 exp, -8 exp) + val outSFix2 = out(SFix(2 exp, -8 exp)) + + val inBundleA = in(BundleA(8)) + val outBundleA = out(BundleA(6)) + } + io.outSFix(0) := (io.inSFix(0) + io.inSFix(1)) + io.outSFix(1) := (io.inSFix(0) * io.inSFix(1)).truncated + + io.outSFix2 := ((io.inSFix2 <<|1) + io.inSFix2 ) <<|1 + io.inBundleA.a.sfix.addTag(tagTruncated) + io.outBundleA <> io.inBundleA + } +} + +class FixedPointTesterCocotbBoot extends SpinalTesterCocotbBase { + override def getName: String = "FixedPointTester" + override def pythonTestLocation: String = "tester/src/test/python/spinal/FixedPointTester" + override def createToplevel: Component = new FixedPointTester.FixedPointTester +} -class XFixTest extends AnyFunSuite { +class UFixTest extends AnyFunSuite { test("UFix Mux") { case class MuxDut() extends Component { val io = new Bundle { diff --git a/tester/src/test/scala/spinal/tester/scalatest/InOutTester.scala b/core/src/test/scala/spinal/core/IODirection.scala similarity index 98% rename from tester/src/test/scala/spinal/tester/scalatest/InOutTester.scala rename to core/src/test/scala/spinal/core/IODirection.scala index 63e0da0fe1..971a5d1b2b 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/InOutTester.scala +++ b/core/src/test/scala/spinal/core/IODirection.scala @@ -18,13 +18,15 @@ * License along with this library. */ -package spinal.tester.scalatest +package spinal.core import org.scalatest.funsuite.AnyFunSuite -import spinal.core._ + import spinal.lib._ import spinal.lib.io.{TriState, TriStateArray} +import spinal.tester.SpinalTesterCocotbBase + object InOutTester { def analogType = Bool() case class Bus() extends Bundle with IMasterSlave{ diff --git a/tester/src/test/scala/spinal/tester/scalatest/LatchTester.scala b/core/src/test/scala/spinal/core/Latch.scala similarity index 96% rename from tester/src/test/scala/spinal/tester/scalatest/LatchTester.scala rename to core/src/test/scala/spinal/core/Latch.scala index 08c8461b0e..a66b596bd0 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/LatchTester.scala +++ b/core/src/test/scala/spinal/core/Latch.scala @@ -1,9 +1,11 @@ -package spinal.tester.scalatest +package spinal.core import org.scalatest.funsuite.AnyFunSuite -import spinal.core._ + import spinal.core.sim._ +import spinal.tester.SpinalSimTester + class LatchTester extends AnyFunSuite { test("bad latch") { var didRaise = false diff --git a/core/src/test/scala/spinal/core/Mem.scala b/core/src/test/scala/spinal/core/Mem.scala new file mode 100644 index 0000000000..14ecca2a1b --- /dev/null +++ b/core/src/test/scala/spinal/core/Mem.scala @@ -0,0 +1,543 @@ +package spinal.core + +import spinal.core.sim._ +import spinal.lib._ +import spinal.lib.bus.amba3.ahblite._ + +import spinal.tester.{SpinalTesterCocotbBase, SpinalTesterGhdlBase, SpinalSimFunSuite} +import org.scalatest.funsuite.AnyFunSuite +import scala.util.Random + +object MemTester extends App{ + class MemTester extends Component { + val mem = Mem(Bits(32 bits), 16) + mem.initBigInt(List( + 0xbf6c8ffel, + 0x6f431025l, + 0xde894aeel, + 0xb007da48l, + 0xe39eca02l, + 0x1732378dl, + 0xd47822e3l, + 0xac711616l, + 0x0d45b17el, + 0xd863729dl, + 0x2210305el, + 0x73cf58e5l, + 0x80d3c954l, + 0xf56fb952l, + 0x9580e19cl, + 0xdd3b620dl + )) + + val readSync = slave(mem.readSyncPort) + val readAsync = new Bundle { + val address = in UInt(4 bits) + val data = out(mem.readAsync(address)) + } + val write = new Bundle { + val valid = in Bool() + val address = in UInt(4 bits) + val data = in Bits(32 bits) + val mask = in Bits(4 bits) + mem.write(address,data,valid,mask) + } + val readWrite = new Bundle { + val valid = in Bool() + val write = in Bool() + val address = in UInt(4 bits) + val writeData = in Bits(32 bits) + val mask = in Bits(4 bits) + val readData = out(mem.readWriteSync(address,writeData,valid,write,mask)) + + } + } + + SpinalVerilog(new MemTester) + SpinalVhdl(new MemTester) +} + +object RomTester { + object MyEnum extends SpinalEnum{ + val a,b,c = newElement() + } + + class DataStruct extends Bundle{ + val bool = Bool() + val bits = Bits(9 bits) + val uint = UInt(10 bits) + val sint = SInt(11 bits) + val enumeration = MyEnum() + } + + class RomTester extends Component { + def lit(bool : Boolean,bits : Int,uint : Int,sint : Int,enumeration : MyEnum.E) = { + val data = new DataStruct + data.bool := Bool(bool) + data.bits := B(bits) + data.uint := U(uint) + data.sint := S(sint) + data.enumeration := enumeration + data + } + def initValues = List( + lit(false,0,0,0,MyEnum.a), + lit(true,0,0,0,MyEnum.a), + lit(false,0x1FF,0,0,MyEnum.a), + lit(false,0,0x3FF,0,MyEnum.a), + lit(false,0,0,-1,MyEnum.a), + lit(false,0,0,0,MyEnum.c), + lit(false,43,74,88,MyEnum.b) + ) + val rom = Mem(new DataStruct,initValues) + + val address = in UInt(3 bits) + val data = out(rom(address)) + } + + class RomTesterSymbols extends Component { + val rom = Mem(Bits(32 bits),8) init(Seq( + BigInt(0x01234567l), + BigInt(0x12345670l), + BigInt(0x10293857l), + BigInt(0x0abcfe23l), + BigInt(0x02938571l), + BigInt(0xabcfe230l), + BigInt(0x717833aal), + BigInt(0x17833aa6l) + )) + rom.write(U"000",B(0, 32 bits),False,B"0000") + val address = in UInt(3 bits) + val data = out(rom(address)) + } + + class RomTesterSymbolsSInt extends Component { + val rom = Mem(SInt(32 bits),8) init(Seq( + S(0x01234567, 32 bits), + S(0x12345670, 32 bits), + S(0x10293857, 32 bits), + S(0x0abcfe23, 32 bits), + S(0x02938571, 32 bits), + S(0xabcfe230, 32 bits), + S(0x717833aa, 32 bits), + S(0x17833aa6, 32 bits) + )) + rom.write(U"000",S(0, 32 bits),False,B"0000") + val address = in UInt(3 bits) + val data = out(rom(address)) + } +} + +import RomTester.{RomTesterSymbols, RomTesterSymbolsSInt} + +class RomTesterGhdlBoot extends SpinalTesterGhdlBase { + override def getName: String = "RomTester" + override def createToplevel: Component = new RomTester.RomTester +} + +class RomTesterCocotbBoot extends SpinalTesterCocotbBase { + override def getName: String = "RomTester" + override def pythonTestLocation: String = "tester/src/test/python/spinal/RomTester" + override def createToplevel: Component = new RomTester.RomTester + override def noVhdl = true + override def backendConfig(config: SpinalConfig) = config.copy(inlineRom = true) +} + +class RomTesterCocotbBoot2 extends SpinalTesterCocotbBase { + override def getName: String = "RomTester2" + override def pythonTestLocation: String = "tester/src/test/python/spinal/RomTester2" + override def createToplevel: Component = new RomTester.RomTester().setDefinitionName("RomTester2") + override def noVhdl = true + override def backendConfig(config: SpinalConfig) = config.copy(inlineRom = false) + + override def genVerilog: Unit = { + super.genVerilog + import scala.sys.process._ + s"rm $pythonTestLocation/RomTester2.v_toplevel_rom.bin".! + s"cp RomTester2.v_toplevel_rom.bin $pythonTestLocation".! + } +} + +class RomTesterCocotbBoot3 extends SpinalTesterCocotbBase { + override def getName: String = "RomTester2" + override def pythonTestLocation: String = "tester/src/test/python/spinal/RomTester3" + override def createToplevel: Component = new RomTester.RomTesterSymbols().setDefinitionName("RomTester3") + override def noVhdl = true + override def backendConfig(config: SpinalConfig) = config.copy(inlineRom = false) + + override def genVerilog: Unit = { + super.genVerilog + import scala.sys.process._ + for(i <- 0 to 3) { + s"rm $pythonTestLocation/RomTester3.v_toplevel_rom_symbol$i.bin".! + s"cp RomTester3.v_toplevel_rom_symbol$i.bin $pythonTestLocation".! + } + } +} + +class SpinalSimRomTester extends AnyFunSuite { + test("test1"){ + import spinal.core.sim._ + import spinal.sim._ + SimConfig.compile(new RomTesterSymbols()).doSim{ dut => + val rom = Seq( + BigInt(0x01234567l), + BigInt(0x12345670l), + BigInt(0x10293857l), + BigInt(0x0abcfe23l), + BigInt(0x02938571l), + BigInt(0xabcfe230l), + BigInt(0x717833aal), + BigInt(0x17833aa6l) + ) + + for(repeat <- 0 until 100){ + dut.address.randomize() + sleep(1) + assert(dut.data.toBigInt == rom(dut.address.toInt)) + } + + } + } + + test("testSInt"){ + import spinal.core.sim._ + import spinal.sim._ + SimConfig.compile(new RomTesterSymbolsSInt()).doSim{ dut => + val rom = Seq( + BigInt(0x01234567), + BigInt(0x12345670), + BigInt(0x10293857), + BigInt(0x0abcfe23), + BigInt(0x02938571), + BigInt(0xabcfe230), + BigInt(0x717833aa), + BigInt(0x17833aa6) + ) + + for(repeat <- 0 until 100){ + dut.address.randomize() + sleep(1) + assert(dut.data.toBigInt == rom(dut.address.toInt)) + } + } + } +} + +class SpinalSimOneEntryRamTester extends SpinalSimFunSuite{ + test("general") { + SimConfig.doSim(new Component { + val mem = Mem(Bits(8 bits), 1).randBoot() + val writePort = slave(mem.writePort) + val readSyncPort = slave(mem.readSyncPort) + val readAsyncPort = new Area { + val address = in(UInt(0 bits)) + val data = out(mem(address)) + } + }) { dut => + dut.clockDomain.forkStimulus(10) + + dut.writePort.valid #= true + dut.writePort.data #= 42 + dut.clockDomain.waitSampling() + dut.writePort.valid #= false + dut.readSyncPort.cmd.valid #= true + dut.clockDomain.waitSampling() + + var readSyncModel = 42 + var ramModel = 42 + for (repeat <- 0 to 100) { + dut.writePort.randomize() + dut.readSyncPort.cmd.randomize() + dut.readAsyncPort.address.randomize() + + dut.clockDomain.waitSampling() + assert(dut.readSyncPort.rsp.toInt == readSyncModel) + assert(dut.readAsyncPort.data.toInt == ramModel) + if (dut.readSyncPort.cmd.valid.toBoolean) { + readSyncModel = ramModel + } + if (dut.writePort.valid.toBoolean) { + ramModel = dut.writePort.data.toInt + } + sleep(1) + assert(dut.readAsyncPort.data.toInt == ramModel) + } + } + } + + test("rwPort") { + SimConfig.doSim(new Component { + val mem = Mem(Bits(8 bits), 1).randBoot() + val readWrite = new Area { + val address = U"" + val writeData = in Bits (8 bits) + val enable, write = in Bool() + val readData = out(mem.readWriteSync(address, writeData, enable, write)) + } + val readSyncPort = slave(mem.readSyncPort) + val readAsyncPort = new Area { + val address = in(UInt(0 bits)) + val data = out(mem(address)) + } + }) { dut => + dut.clockDomain.forkStimulus(10) + + dut.readWrite.enable #= true + dut.readWrite.write #= true + dut.readWrite.writeData #= 42 + dut.clockDomain.waitSampling() + dut.readWrite.write #= true + dut.readSyncPort.cmd.valid #= true + dut.clockDomain.waitSampling() + + var readWriteModel = 42 + var readSyncModel = 42 + var ramModel = 42 + for (repeat <- 0 until 100) { + dut.readWrite.enable.randomize() + dut.readWrite.write.randomize() + dut.readWrite.writeData.randomize() + dut.readSyncPort.cmd.randomize() + dut.readAsyncPort.address.randomize() + + dut.clockDomain.waitSampling() + assert(dut.readSyncPort.rsp.toInt == readSyncModel) + assert(dut.readAsyncPort.data.toInt == ramModel) + if (dut.readSyncPort.cmd.valid.toBoolean) { + readSyncModel = ramModel + } + if (dut.readWrite.enable.toBoolean && !dut.readWrite.write.toBoolean) { + readWriteModel = ramModel + } + if (dut.readWrite.enable.toBoolean && dut.readWrite.write.toBoolean) { + ramModel = dut.readWrite.writeData.toInt + } + sleep(1) + assert(dut.readAsyncPort.data.toInt == ramModel) + } + } + } + + test("rom") { + SimConfig.doSim(new Component { + val mem = Mem(Bits(8 bits), 1) init (Seq(B"xAA")) + val readSyncPort = slave(mem.readSyncPort) + val readAsyncPort = new Area { + val address = in(UInt(0 bits)) + val data = out(mem(address)) + } + }) { dut => + dut.clockDomain.forkStimulus(10) + + dut.clockDomain.waitSampling() + dut.readSyncPort.cmd.valid #= true + dut.clockDomain.waitSampling() + + var readSyncModel = 0xAA + var ramModel = 0xAA + for (repeat <- 0 until 100) { + dut.readSyncPort.cmd.randomize() + dut.readAsyncPort.address.randomize() + + dut.clockDomain.waitSampling() + assert(dut.readSyncPort.rsp.toInt == readSyncModel) + assert(dut.readAsyncPort.data.toInt == ramModel) + if (dut.readSyncPort.cmd.valid.toBoolean) { + readSyncModel = ramModel + } + sleep(1) + assert(dut.readAsyncPort.data.toInt == ramModel) + } + } + } +} + + +class SpinalSimRamTester extends AnyFunSuite { + test("general") { + SimConfig.withConfig(SpinalConfig(device = Device.XILINX)).compile(new Component { + val ram = Mem(Bits(32 bits), 256) + + val wrEnable = in Bool() + val wrAddress = in UInt(8 bits) + val wrData = in Bits(32 bits) + val wrMask = in Bits(4 bits) + + ram.write(wrAddress, wrData, wrEnable, wrMask) + + val rdAddress = in UInt(8 bits) + val rdData = out Bits(32 bits) + rdData := ram.readAsync(rdAddress) + }).doSim{dut => + dut.clockDomain.forkStimulus(10) + + + def wr(address : Int, data : Long, mask : Long): Unit ={ + dut.clockDomain.waitSampling() + dut.wrEnable #= true + dut.wrAddress #= address + dut.wrData #= data + dut.wrMask #= mask + dut.clockDomain.waitSampling() + } + + wr(42, 0x00112233l, 0x1) + wr(43, 0x44556677l, 0x3) + wr(44, 0x8899AABBl, 0xF) + wr(42, 0xFFFFFFFFl, 0xE) + wr(43, 0xFFFFFFFFl, 0xC) + wr(44, 0xFFFFFFFFl, 0x0) + + dut.clockDomain.waitSampling() + dut.clockDomain.waitSampling() + + def rdCheck(address : Int, data : Long, mask : Long): Unit ={ + dut.rdAddress #= address + sleep(1) + assert((dut.rdData.toLong & mask) == (data & mask)) + } + + rdCheck(42, 0x00112233l, 0x000000FF) + rdCheck(43, 0x44556677l, 0x0000FFFF) + rdCheck(44, 0x8899AABBl, 0xFFFFFFFF) + } + } +} + +class SpinalSimRamAccessTester extends SpinalSimFunSuite { + ghdlEnabled = false //TODO + + test("test1") { + SimConfig.compile(new Component{ + val mem = Mem(UInt(16 bits), 32).simPublic() + val write = slave(mem.writePort) + val read = new Area{ + val address = in(mem.addressType()) + val data = out(mem.readAsync(address)) + } + }).doSim{ dut => + val model = Array.fill(32)(Random.nextInt(1024*64)) + for ((v, i) <- model.zipWithIndex) dut.mem.setBigInt(i, v) + + def simWrite() { + val address = Random.nextInt(32) + val data = Random.nextInt(1024*64) + dut.mem.setBigInt(address, data) + model(address) = data + sleep(1) + } + def simCheck() = { + val address = Random.nextInt(32) + val readed = dut.mem.getBigInt(address) + assert(readed == model(address)) + } + + dut.write.valid #= false + def dutWrite() { + dut.clockDomain.waitSampling() + val address = Random.nextInt(32) + val data = Random.nextInt(1024*64) + dut.write.valid #= true + dut.write.address #= address + dut.write.data #= data + dut.clockDomain.waitSampling() + dut.write.valid #= false + dut.clockDomain.waitSampling() + model(address) = data + } + def dutCheck() = { + sleep(1) + val address = Random.nextInt(32) + dut.read.address #= address + sleep(1) + if(Random.nextBoolean()) sleep(1) else dut.clockDomain.waitSampling() + assert(dut.read.data.toInt == model(address)) + } + + + dut.clockDomain.forkStimulus(10) + dut.clockDomain.waitSampling(10) + for(i <- 0 until 1000) Random.nextInt(4) match { + case 0 => simWrite() + case 1 => simCheck() + case 2 => dutWrite() + case 3 => dutCheck() + } + println(simTime()) + } + } + + test("test2") { + SimConfig.compile(new Component{ + val mem = Mem(UInt(16 bits), 32).simPublic() + val write = new Area{ + val valid = in Bool() + val address = in(mem.addressType()) + val data = in(mem.wordType()) + val mask = in Bits(4 bits) + mem.write(address, data, enable = valid, mask = mask) + } + val read = new Area{ + val address = in(mem.addressType()) + val data = out(mem.readAsync(address)) + } + }).doSim{ dut => + val model = Array.fill(32)(Random.nextInt(1024*64)) + for ((v, i) <- model.zipWithIndex) dut.mem.setBigInt(i, v) + + def simWrite() { + val address = Random.nextInt(32) + val data = Random.nextInt(1024*64) + dut.mem.setBigInt(address, data) + model(address) = data + sleep(1) + } + def simCheck() = { + val address = Random.nextInt(32) + assert(dut.mem.getBigInt(address) == model(address)) + } + + dut.write.valid #= false + def dutWrite() { + dut.clockDomain.waitSampling() + val address = Random.nextInt(32) + val data = Random.nextInt(1024*64) + val mask = Random.nextInt(16) + dut.write.valid #= true + dut.write.address #= address + dut.write.data #= data + dut.write.mask #= mask + dut.clockDomain.waitSampling() + dut.write.valid #= false + dut.clockDomain.waitSampling() + var buffer = model(address) + for(i <- 0 until 4 if (mask & (1 << i)) != 0){ + val m = 0xF << 4*i + buffer = (buffer & ~m) | (data & m) + } + model(address) = buffer + } + def dutCheck() = { + sleep(1) + val address = Random.nextInt(32) + dut.read.address #= address + sleep(1) + if(Random.nextBoolean()) sleep(1) else dut.clockDomain.waitSampling() + assert(dut.read.data.toInt == model(address)) + } + + + dut.clockDomain.forkStimulus(10) + dut.clockDomain.waitSampling(10) + for(i <- 0 until 1000) Random.nextInt(4) match { + case 0 => simWrite() + case 1 => simCheck() + case 2 => dutWrite() + case 3 => dutCheck() + case _ => + } + println(simTime()) + } + } +} diff --git a/core/src/test/scala/spinal/core/Reg.scala b/core/src/test/scala/spinal/core/Reg.scala new file mode 100644 index 0000000000..b094b48bc6 --- /dev/null +++ b/core/src/test/scala/spinal/core/Reg.scala @@ -0,0 +1,75 @@ +package spinal.core + +import org.scalatest.funsuite.AnyFunSuite + +import spinal.core.sim._ + +class RegTester extends AnyFunSuite { + test("getAheadValue") { + SimConfig + .compile(new Component { + val conds = in(Vec.fill(8)(Bool())) + val a, b, c, d, e = out(Reg(UInt(8 bits)) init (0)) + + when(conds(0)) { + a := 1 + when(conds(1)) { + a := 2 + b := 11 + } otherwise { + a := 3 + c := 21 + } + } + when(conds(2)) { + a := 4 + b := 12 + c := 22 + d := 31 + } + + val x = out(a.getAheadValue) + val y = out(a.getAheadValue) + val z = out(b.getAheadValue) + + when(d.getAheadValue() === 0) { + e := 1 + } + }) + .doSim(seed = 42) { dut => + var an, bn, cn, a, b, c = 0 + dut.conds.foreach(_ #= false) + dut.clockDomain.forkStimulus(10) + dut.clockDomain.waitSampling() + + for (i <- 0 until 1000) { + if (dut.conds(0).toBoolean) { + an = 1 + if (dut.conds(1).toBoolean) { + an = 2 + bn = 11 + } else { + an = 3 + cn = 21 + } + } + if (dut.conds(2).toBoolean) { + an = 4 + bn = 12 + cn = 22 + } + assert(dut.x.toInt == an) + assert(dut.y.toInt == an) + assert(dut.z.toInt == bn) + assert(dut.a.toInt == a) + assert(dut.b.toInt == b) + assert(dut.c.toInt == c) + a = an + b = bn + c = cn + dut.clockDomain.waitSampling() + dut.conds.foreach(_.randomize()) + } + } + } +} diff --git a/core/src/test/scala/spinal/core/UInt.scala b/core/src/test/scala/spinal/core/UInt.scala new file mode 100644 index 0000000000..c6acb9e488 --- /dev/null +++ b/core/src/test/scala/spinal/core/UInt.scala @@ -0,0 +1,44 @@ +package spinal.core + +import org.scalatest.funsuite.AnyFunSuite + +import spinal.core.sim._ + +import scala.util.Random + +class UIntTester extends AnyFunSuite { + test("wrap_comparison") { + val width = 8 + SimConfig + .compile(new Component { + val x, y = in port UInt(width bits) + val lt, gt = out port Bool() + val le, ge = out port Bool() + + lt := x.wrap < y + gt := x.wrap > y + le := x.wrap <= y + ge := x.wrap >= y + }) + .doSim(seed = 42) { dut => + val quarter = 1 << (width - 2) + for (i <- 0 until 2000) { + val x = dut.x.randomize() + // ensure two datas' distance are not beyond a quarter. + val d = Random.nextInt(2 * quarter) - quarter + val y = (x + d).abs % (4 * quarter) + dut.y #= y + + sleep(1) + + val rev = (x - y).abs > 3 * quarter + assert(dut.lt.toBoolean == (if (rev) x > y else x < y)) + assert(dut.gt.toBoolean == (if (rev) x < y else x > y)) + assert(dut.le.toBoolean == (if (rev) x >= y else x <= y)) + assert(dut.ge.toBoolean == (if (rev) x <= y else x >= y)) + + sleep(1) + } + } + } +} diff --git a/core/src/test/scala/spinal/core/Vec.scala b/core/src/test/scala/spinal/core/Vec.scala new file mode 100644 index 0000000000..452d2dbd66 --- /dev/null +++ b/core/src/test/scala/spinal/core/Vec.scala @@ -0,0 +1,33 @@ +package spinal.core + +import spinal.core.sim._ + +import org.scalatest.funsuite.AnyFunSuite + +class VecBitwisePimperTester extends AnyFunSuite { + for (n <- 0 until 12) { + test("Vec (op) Vec on " + n + " elements") { + SimConfig.noOptimisation + .compile(new Component { + val a, b = in Vec (SInt(8 bits), n) + val xor = out(a ^ b) + val or = out(a | b) + val and = out(a & b) + val not = out(~a) + }) + .doSim(seed = 42) { dut => + for (_ <- 0 until 100) { + dut.a.randomize() + dut.b.randomize() + sleep(1) + for (i <- 0 until n) { + assert(dut.xor(i).toInt == (dut.a(i).toInt ^ dut.b(i).toInt)) + assert(dut.or(i).toInt == (dut.a(i).toInt | dut.b(i).toInt)) + assert(dut.and(i).toInt == (dut.a(i).toInt & dut.b(i).toInt)) + assert(dut.not(i).toInt == ~dut.a(i).toInt) + } + } + } + } + } +} diff --git a/tester/src/test/scala/spinal/tester/scalatest/FormalSimpleTester.scala b/core/src/test/scala/spinal/core/formal/FormalBootstraps.scala similarity index 92% rename from tester/src/test/scala/spinal/tester/scalatest/FormalSimpleTester.scala rename to core/src/test/scala/spinal/core/formal/FormalBootstraps.scala index 11a3664acc..dca86a0667 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/FormalSimpleTester.scala +++ b/core/src/test/scala/spinal/core/formal/FormalBootstraps.scala @@ -1,13 +1,10 @@ -package spinal.tester.scalatest +package spinal.core.formal import spinal.core._ import spinal.lib._ import spinal.lib.formal._ class FormalSimpleTester extends SpinalFormalFunSuite { - import spinal.core.formal._ - import spinal.core.GenerationFlags._ - def startDoneTest(maxDelay : Int): Unit ={ class StartDoneDut() extends Component { val start = in(Bool()) diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimVerilatorIoTest.scala b/core/src/test/scala/spinal/core/sim/SimBootstraps.scala similarity index 52% rename from tester/src/test/scala/spinal/tester/scalatest/SpinalSimVerilatorIoTest.scala rename to core/src/test/scala/spinal/core/sim/SimBootstraps.scala index 5d497a8d02..80ceaed0c0 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimVerilatorIoTest.scala +++ b/core/src/test/scala/spinal/core/sim/SimBootstraps.scala @@ -1,14 +1,203 @@ -package spinal.tester.scalatest +package spinal.core.sim import org.scalatest.funsuite.AnyFunSuite +import spinal.tester.{SpinalSimFunSuite, SpinalSimTester} + import spinal.core._ -import spinal.sim._ -import spinal.core.sim._ -import spinal.tester.scalatest.SpinalSimVerilatorIoTest.SpinalSimVerilatorIoTestTop + +import java.io.File +import org.apache.commons.io.FileUtils +import spinal.lib.Delay +import java.io.PrintStream import scala.concurrent.{Await, Future} import scala.util.Random +object VerilatorCacheTester { + case class ComponentA(n: Int, x: BigInt) extends Component { + val io = new Bundle { + val x = out Bits(n bits) + val something = in Bits(n bits) + val dummy = out Bits(n bits) + } + + io.x := x + + io.dummy := Delay(io.something, 4000) + } + + + class VerilatorCacheUsedChecker(out: PrintStream) extends PrintStream(out) { + var verilatorCompilationRunning = false + var verilatorCompilationDone = false + var verilatorCacheUsed = false + + def reset(): Unit = { + verilatorCompilationRunning = false + verilatorCompilationDone = false + verilatorCacheUsed = false + } + + def test(shouldUseCache: Boolean): Unit = { + assert(verilatorCompilationRunning == false, "Verilator compilation should not be running now") + assert(verilatorCompilationDone == true, "Verilator compilation should be done now") + + if (shouldUseCache) { + assert(verilatorCacheUsed == true, "Verilator cache not used but it should be used") + } else { + assert(verilatorCacheUsed == false, "Verilator cache used but it should not be used") + } + } + + override def println(x: Any): Unit = { + if (x.isInstanceOf[String]) { + val str = x.asInstanceOf[String] + + if (str == "[Progress] Verilator compilation started") { + verilatorCompilationRunning = true + verilatorCompilationDone = false + verilatorCacheUsed = false + } else if (str.startsWith("[Progress] Verilator compilation done in ")) { + verilatorCompilationRunning = false + verilatorCompilationDone = true + } + + if (verilatorCompilationRunning) { + if (str == "[info] Found cached verilator binaries") { + verilatorCacheUsed = true + } + } + + super.println(x) + } else { + super.println(x) + } + } + } +} + +class VerilatorCacheTester extends AnyFunSuite { + import VerilatorCacheTester._ + + val cacheDir = new File(SimConfig._workspacePath + "/.cache_cachetest") + + def deleteCache(): Unit = { + if (cacheDir.exists()) { + FileUtils.forceDelete(cacheDir) + } + } + + def testComponentA(verilatorCacheUsedChecker: VerilatorCacheUsedChecker, n: Int, x: BigInt, shouldUseCache: Boolean, disableCache: Boolean = false, maxCacheEntries: Int = -1, waveDepth: Int = -1): Long = { + var cfg = SimConfig.cachePath(cacheDir.getAbsolutePath()) + if (disableCache) cfg = cfg.disableCache + if (maxCacheEntries >= 0) cfg = cfg.maxCacheEntries(maxCacheEntries) + if (waveDepth >= 0) cfg = cfg.withWave(waveDepth) + + verilatorCacheUsedChecker.reset() + + val tStart = System.nanoTime() + cfg.compile(ComponentA(n, x)).doSim(dut => assert(dut.io.x.toBigInt == x)) + val duration = System.nanoTime()-tStart + + verilatorCacheUsedChecker.test(shouldUseCache) + + duration + } + + test("verilator cache") { + deleteCache() + + var durationWithoutCacheTotal: Double = 0 + var durationWithoutCacheCount = 0 + + var durationWithCacheTotal: Double = 0 + var durationWithCacheCount = 0 + + val verilatorCacheUsedChecker = new VerilatorCacheUsedChecker(Console.out) + Console.withOut(verilatorCacheUsedChecker) { + // first compilation with cache disabled + durationWithoutCacheTotal += testComponentA(verilatorCacheUsedChecker, n=3, x=0, shouldUseCache=false, disableCache=true) + durationWithoutCacheCount += 1 + + // first compilation with cache enabled + durationWithoutCacheTotal += testComponentA(verilatorCacheUsedChecker, n=3, x=0, shouldUseCache=false) + durationWithoutCacheCount += 1 + + // now cache should be used + durationWithCacheTotal += testComponentA(verilatorCacheUsedChecker, n=3, x=0, shouldUseCache=true) + durationWithCacheCount += 1 + + // nothing changed, cache should be used again + durationWithCacheTotal += testComponentA(verilatorCacheUsedChecker, n=3, x=0, shouldUseCache=true) + durationWithCacheCount += 1 + + // change component, should not use cache + durationWithoutCacheTotal += testComponentA(verilatorCacheUsedChecker, n=3, x=1, shouldUseCache=false) + durationWithoutCacheCount += 1 + + // now the cache should be used again + durationWithCacheTotal += testComponentA(verilatorCacheUsedChecker, n=3, x=1, shouldUseCache=true) + durationWithCacheCount += 1 + + // nothing changed, cache should be used again + durationWithCacheTotal += testComponentA(verilatorCacheUsedChecker, n=3, x=1, shouldUseCache=true) + durationWithCacheCount += 1 + + // cache disabled, cache should not be used + durationWithoutCacheTotal += testComponentA(verilatorCacheUsedChecker, n=3, x=1, shouldUseCache=false, disableCache=true) + durationWithoutCacheCount += 1 + + // cache reenabled, cache should be used + durationWithCacheTotal += testComponentA(verilatorCacheUsedChecker, n=3, x=1, shouldUseCache=true) + durationWithCacheCount += 1 + + // restore previous component configuration, should use cache + durationWithCacheTotal += testComponentA(verilatorCacheUsedChecker, n=3, x=0, shouldUseCache=true) + durationWithCacheCount += 1 + + // 2 cache entries used till now, should not use cache and generate 2 new cache entries + durationWithoutCacheTotal += testComponentA(verilatorCacheUsedChecker, n=4, x=0, shouldUseCache=false, maxCacheEntries=4) + durationWithoutCacheTotal += testComponentA(verilatorCacheUsedChecker, n=4, x=1, shouldUseCache=false, maxCacheEntries=4) + durationWithoutCacheCount += 2 + + // 4 (=max) cache entries used, should use cache + durationWithCacheTotal += testComponentA(verilatorCacheUsedChecker, n=3, x=0, shouldUseCache=true, maxCacheEntries=4) + Thread.sleep(1100) // ensure different timestamps + durationWithCacheTotal += testComponentA(verilatorCacheUsedChecker, n=3, x=1, shouldUseCache=true, maxCacheEntries=4) + Thread.sleep(1100) // ensure different timestamps + durationWithCacheTotal += testComponentA(verilatorCacheUsedChecker, n=4, x=0, shouldUseCache=true, maxCacheEntries=4) + Thread.sleep(1100) // ensure different timestamps + durationWithCacheTotal += testComponentA(verilatorCacheUsedChecker, n=4, x=1, shouldUseCache=true, maxCacheEntries=4) + Thread.sleep(1100) // ensure different timestamps + durationWithCacheCount += 4 + + // 4 (=max) cache entries used, new configuration, should not use cache + durationWithoutCacheTotal += testComponentA(verilatorCacheUsedChecker, n=4, x=2, shouldUseCache=false, maxCacheEntries=4) + durationWithoutCacheCount += 1 + + // cache entry deleted in previous test, should not use cache + durationWithoutCacheTotal += testComponentA(verilatorCacheUsedChecker, n=3, x=0, shouldUseCache=false, maxCacheEntries=5) + durationWithoutCacheCount += 1 + + // other cache entries (+ new cache entry) should not have been deleted, should use cache + durationWithCacheTotal += testComponentA(verilatorCacheUsedChecker, n=3, x=1, shouldUseCache=true, maxCacheEntries=5) + durationWithCacheTotal += testComponentA(verilatorCacheUsedChecker, n=4, x=0, shouldUseCache=true, maxCacheEntries=5) + durationWithCacheTotal += testComponentA(verilatorCacheUsedChecker, n=4, x=1, shouldUseCache=true, maxCacheEntries=5) + durationWithCacheTotal += testComponentA(verilatorCacheUsedChecker, n=4, x=2, shouldUseCache=true, maxCacheEntries=5) + durationWithCacheCount += 4 + + // change sim config, should not use cache + durationWithoutCacheTotal += testComponentA(verilatorCacheUsedChecker, n=4, x=2, shouldUseCache=false, waveDepth=1) + durationWithoutCacheCount += 1 + } + + val durationWithoutCacheAvg = durationWithoutCacheTotal / durationWithoutCacheCount + val durationWithCacheAvg = durationWithCacheTotal / durationWithCacheCount + + assert(durationWithCacheAvg < durationWithoutCacheAvg, "Verilator compilation needs more time when using the cache") + } +} + object SpinalSimVerilatorIoTest{ object State extends SpinalEnum{ val A,B,C,D,E = newElement() @@ -70,6 +259,8 @@ object SpinalSimVerilatorIoTest{ } class SpinalSimVerilatorIoTest extends AnyFunSuite { + import SpinalSimVerilatorIoTest._ + SpinalSimTester { env => import env._ var compiled: SimCompiled[SpinalSimVerilatorIoTestTop] = null @@ -186,8 +377,6 @@ class SpinalSimVerilatorIoTest extends AnyFunSuite { () => Random.shuffle((0 to 127)).map(n => -BigInt("0" + "1" * n, 2) - 1).foreach(value => checkBigInt(value, dut.io.s128)) ) - - import SpinalSimVerilatorIoTest._ def newEnumTest(test: newEnumTest) = { for (i <- 0 until 40) { val e = State.elements(Random.nextInt(State.elements.length)) @@ -208,7 +397,7 @@ class SpinalSimVerilatorIoTest extends AnyFunSuite { } test(prefix + "compile") { - compiled = SimConfig.compile(new SpinalSimVerilatorIoTest.SpinalSimVerilatorIoTestTop) + compiled = env.SimConfig.compile(new SpinalSimVerilatorIoTestTop) } test(prefix + "test1") { @@ -237,3 +426,62 @@ class SpinalSimVerilatorIoTest extends AnyFunSuite { } } + +class SpinalSimMultiThreadingDut(offset : Int) extends Component { + val io = new Bundle { + val a, b, c = in UInt (8 bits) + val result = out UInt (8 bits) + } + + io.result := RegNext(io.a + io.b - io.c + offset) init (0) +} + +class SpinalSimMultiThreadingTest extends SpinalSimFunSuite { + test("Test1") { + var faild = false + val threads = for (t <- 0 to 3) yield { + new Thread { + override def run() = { + for (i <- 0 to 5) { + try { + SimConfig + .withConfig(SpinalConfig(defaultConfigForClockDomains = ClockDomainConfig(resetKind = SYNC))) + // .compile() + // .withWave + .doSim(new SpinalSimMultiThreadingDut(i + t).setDefinitionName(s"SpinalSimMultiThreadingDut_${t}_${i}")) { dut => + dut.clockDomain.forkStimulus(period = 10) + + for (repeat <- 0 until (100000*durationFactor).toInt) { + val a, b, c = Random.nextInt(256) + dut.io.a #= a + dut.io.b #= b + dut.io.c #= c + dut.clockDomain.waitSampling(); sleep(0) + if (dut.clockDomain.isResetDeasserted) assert(dut.io.result.toInt == ((a + b - c + i + t) & 0xFF)) + } + } + } catch { + case e: Throwable => { + faild = true + println(e) + println("FAILURE") + throw e + } + } + } + } + } + } + + for (thread <- threads) { + thread.start() + Thread.sleep(1000) + } + + for (thread <- threads) { + thread.join() + } + + assert(!faild) + } +} diff --git a/core/src/test/scala/spinal/core/sim/package.scala b/core/src/test/scala/spinal/core/sim/package.scala new file mode 100644 index 0000000000..23d93448d0 --- /dev/null +++ b/core/src/test/scala/spinal/core/sim/package.scala @@ -0,0 +1,177 @@ +package spinal.core.sim + +import org.scalatest.funsuite.AnyFunSuite + +import spinal.core._ +import spinal.tester.SpinalSimTester + +class SimBigIntPimperTest extends AnyFunSuite { + def toBytes(bi: BigInt, bits: Int = -1, endian: Endianness = LITTLE) = + bi.toBytes(bits, endian).map(i => f"$i%02x").mkString(" ") + test("positive") { + // simple cases + assert(toBytes(0xff) == "ff") + assert(toBytes(0x80ff) == "ff 80") + // check result is prepended if necessary + assert(toBytes(0xff, 4*8) == "ff 00 00 00") + // check with BIG endian + assert(toBytes(0x80ff, endian=BIG) == "80 ff") + assert(toBytes(0x80ff, 4*8, endian=BIG) == "00 00 80 ff") + // check that bit length != n*8 works + assert(toBytes(0x3ff, 10) == "ff 03") + // also needs to work for BigInt bigger than Int + assert(toBytes(0x1122334455667788L) == "88 77 66 55 44 33 22 11") + // ... and longer than a Long + assert(toBytes(BigInt("112233445566778899aabbccddeeff", 16)) == "ff ee dd cc bb aa 99 88 77 66 55 44 33 22 11") + + // negative numbers are sign extended to full bytes by default + assert(toBytes(-1) == "ff") + // result must be prepended correctly if expanded + assert(toBytes(-1, 16) == "ff ff") + // sign extend is only up to given number of bytes + assert(toBytes(-1, 4) == "0f") + // negative numbers also need to be extended to big bitwidths + assert(toBytes(-1, 7*8) == "ff ff ff ff ff ff ff") + } + test("negative") { + // must throw if too little space is given + assertThrows[java.lang.AssertionError] { toBytes(0xffff, 8) } + // length must be checked precisely + assertThrows[java.lang.AssertionError] { toBytes(0x07, 2) } + // space for sign bit must be available + assertThrows[java.lang.AssertionError] { toBytes(-256, 8) } + } +} + +object SpinalSimAccessSubComponents { + class SubSub extends Component { + val io = new Bundle { + val a,b = in UInt(8 bits) + val result = out UInt(8 bits) + } + + io.result := io.a ^ io.b + val miaou = (io.a & io.b) + + val miaouVec = Vec(UInt(8 bits), 4) + miaouVec := Vec(io.a,io.b,io.result,miaou) + } + + class Sub extends Component { + val io = new Bundle { + val a,b = in UInt(8 bits) + val result = out UInt(8 bits) + } + val subSubInst = new SubSub + subSubInst.io.a <> io.a + subSubInst.io.b <> io.b + subSubInst.io.result <> io.result + } + + class Dut extends Component { + val io = new Bundle { + val a,b = in UInt(8 bits) + val result = out UInt(8 bits) + } + + val subInst = new Sub + subInst.io.a <> io.a + subInst.io.b <> io.b + subInst.io.result <> io.result + } + +} + +class SpinalSimAccessSubComponents extends AnyFunSuite { + SpinalSimTester { env => + import env._ + + var compiled: SimCompiled[SpinalSimAccessSubComponents.Dut] = null + test(prefix + "compile") { + compiled = env.SimConfig.compile { + val dut = new SpinalSimAccessSubComponents.Dut + dut.subInst.subSubInst.miaouVec.simPublic() + dut.subInst.subSubInst.io.a.simPublic() + dut.subInst.subSubInst.miaou.simPublic() + dut.subInst.subSubInst.miaou.pull() + dut.subInst.subSubInst.io.pull() + dut.subInst.subSubInst.miaouVec.pull() + dut.subInst.subSubInst.miaouVec.pull() + dut.subInst.subSubInst.miaouVec.pull() + dut.subInst.subSubInst.miaouVec.pull() + dut + } + } + + test(prefix + "simulate") { + compiled.doSim { dut => + for (repeat <- 0 until 1000) { + dut.io.a.randomize() + dut.io.b.randomize() + sleep(1) + assert(dut.io.result.toInt == (dut.io.a.toInt ^ dut.io.b.toInt)) + assert(dut.subInst.subSubInst.miaou.toInt == (dut.io.a.toInt & dut.io.b.toInt)) + assert(dut.subInst.subSubInst.io.a.toInt == (dut.io.a.toInt)) + assert(dut.subInst.subSubInst.miaouVec(0).toInt == (dut.io.a.toInt)) + assert(dut.subInst.subSubInst.miaouVec(1).toInt == (dut.io.b.toInt)) + assert(dut.subInst.subSubInst.miaouVec(2).toInt == (dut.io.a.toInt ^ dut.io.b.toInt)) + assert(dut.subInst.subSubInst.miaouVec(3).toInt == (dut.io.a.toInt & dut.io.b.toInt)) + } + } + } + } +} + + +object SomeEnum extends SpinalEnum { + val sIdle, sStart, sData, sParity, sStop = newElement() +} + +case class SimRandomizeTester() extends Component { + val io = new Bundle { + val b = in(Bool()) + val ui = in(UInt(4 bit)) + val uil = in(UInt(33 bit)) + val si = in(SInt(4 bit)) + val sil = in(UInt(33 bit)) + val e = in(SomeEnum()) + val uf = in(UFix(peak = 8 exp, resolution = -2 exp)) + val sf = in(SFix(peak = 8 exp, resolution = -2 exp)) + val af = in(AFix.UQ(2 bit, 2 bit)) + val af_out_of_range = in(AFix(8, -4, -2 exp)) + } +} + +class SpinalSimRandomizeTest extends AnyFunSuite { + val dut = SimConfig.compile { SimRandomizeTester() } + + test("randomize returns the value driven next") { + dut.doSim("randomize returns the value driven next") { dut => + for (_ <- 0 to 100) { + val b = dut.io.b.randomize() + val ui = dut.io.ui.randomize() + val uil = dut.io.uil.randomize() + val si = dut.io.si.randomize() + val sil = dut.io.sil.randomize() + val e = dut.io.e.randomize() + val uf = dut.io.uf.randomize() + val sf = dut.io.sf.randomize() + val af = dut.io.af.randomize() + val af_out_of_range = dut.io.af_out_of_range.randomize(inRange = false) + + sleep(10) + + assert(b == dut.io.b.toBoolean) + assert(ui == dut.io.ui.toBigInt) + assert(uil == dut.io.uil.toBigInt) + assert(si == dut.io.si.toBigInt) + assert(sil == dut.io.sil.toBigInt) + assert(e == dut.io.e.toEnum) + assert(uf == dut.io.uf.toBigDecimal) + assert(sf == dut.io.sf.toBigDecimal) + assert(af == dut.io.af.toBigDecimal) + assert(af_out_of_range == dut.io.af_out_of_range.toBigDecimal) + } + } + } +} diff --git a/tester/src/test/scala/spinal/tester/scalatest/WhenTester.scala b/core/src/test/scala/spinal/core/when.scala similarity index 97% rename from tester/src/test/scala/spinal/tester/scalatest/WhenTester.scala rename to core/src/test/scala/spinal/core/when.scala index 8b77f6d07f..ee3f73b394 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/WhenTester.scala +++ b/core/src/test/scala/spinal/core/when.scala @@ -16,9 +16,10 @@ * License along with this library. */ -package spinal.tester.scalatest +package spinal.core + +import spinal.tester.SpinalTesterCocotbBase -import spinal.core._ class WhenTester extends Component { val io = new Bundle { val conds = in Vec(Bool(),8) diff --git a/tester/src/test/scala/spinal/demo/general/GrayCounter.scala b/lib/src/main/scala/spinal/lib/GrayCounter.scala similarity index 57% rename from tester/src/test/scala/spinal/demo/general/GrayCounter.scala rename to lib/src/main/scala/spinal/lib/GrayCounter.scala index 07c30dba28..ac2b2b4ad7 100644 --- a/tester/src/test/scala/spinal/demo/general/GrayCounter.scala +++ b/lib/src/main/scala/spinal/lib/GrayCounter.scala @@ -1,14 +1,15 @@ -package spinal.demo.general +package spinal.lib + import spinal.core._ object GrayCounter { - def apply(n: Int, enable: Bool): UInt = { - val gray = RegInit(U(0, n bit)) + def apply(width: Int, enable: Bool): UInt = { + val gray = RegInit(U(0, width bit)) val even = RegInit(True) - val word = Cat(True, gray(n-3 downto 0), even) + val word = Cat(True, gray(width - 3 downto 0), even) when(enable) { var found = False - for (i <- 0 until n) { + for (i <- 0 until width) { when(word(i) && !found) { gray(i) := !gray(i) found \= True diff --git a/lib/src/main/scala/spinal/lib/Utils.scala b/lib/src/main/scala/spinal/lib/Utils.scala index 57f0d1076e..9a0eb54dfc 100644 --- a/lib/src/main/scala/spinal/lib/Utils.scala +++ b/lib/src/main/scala/spinal/lib/Utils.scala @@ -383,26 +383,6 @@ object fromGray { } } -object GrayCounter { - def apply(width: Int, enable: Bool): UInt = { - val gray = RegInit(U(0, width bit)) - val even = RegInit(True) - val word = Cat(True, gray(width - 3 downto 0), even) - when(enable) { - var found = False - for (i <- 0 until width) { - when(word(i) && !found) { - gray(i) := !gray(i) - found \= True - } - } - even := !even - } - return gray - } -} - - /****************************************************************************** * Big-Endian <-> Little-Endian */ diff --git a/lib/src/main/scala/spinal/lib/bus/amba3/ahblite/AhbLite3Interconnect.scala b/lib/src/main/scala/spinal/lib/bus/amba3/ahblite/AhbLite3CrossbarFactory.scala similarity index 100% rename from lib/src/main/scala/spinal/lib/bus/amba3/ahblite/AhbLite3Interconnect.scala rename to lib/src/main/scala/spinal/lib/bus/amba3/ahblite/AhbLite3CrossbarFactory.scala diff --git a/lib/src/main/scala/spinal/lib/com/spi/xdr/Apb3SpiXdrMasterCtrl.scala b/lib/src/main/scala/spinal/lib/com/spi/ddr/Apb3SpiXdrMasterCtrl.scala similarity index 100% rename from lib/src/main/scala/spinal/lib/com/spi/xdr/Apb3SpiXdrMasterCtrl.scala rename to lib/src/main/scala/spinal/lib/com/spi/ddr/Apb3SpiXdrMasterCtrl.scala diff --git a/lib/src/main/scala/spinal/lib/com/spi/xdr/BmbSpiXdrMasterCtrl.scala b/lib/src/main/scala/spinal/lib/com/spi/ddr/BmbSpiXdrMasterCtrl.scala similarity index 100% rename from lib/src/main/scala/spinal/lib/com/spi/xdr/BmbSpiXdrMasterCtrl.scala rename to lib/src/main/scala/spinal/lib/com/spi/ddr/BmbSpiXdrMasterCtrl.scala diff --git a/lib/src/main/scala/spinal/lib/com/spi/xdr/SpiXdrMasterCtrl.scala b/lib/src/main/scala/spinal/lib/com/spi/ddr/SpiXdrMasterCtrl.scala similarity index 100% rename from lib/src/main/scala/spinal/lib/com/spi/xdr/SpiXdrMasterCtrl.scala rename to lib/src/main/scala/spinal/lib/com/spi/ddr/SpiXdrMasterCtrl.scala diff --git a/lib/src/main/scala/spinal/lib/com/usb/udc/UsbDeviceCtrl.scala b/lib/src/main/scala/spinal/lib/com/usb/udc/UsbDeviceCtrl.scala index bd67eb5a94..23547f516b 100644 --- a/lib/src/main/scala/spinal/lib/com/usb/udc/UsbDeviceCtrl.scala +++ b/lib/src/main/scala/spinal/lib/com/usb/udc/UsbDeviceCtrl.scala @@ -1,13 +1,12 @@ package spinal.lib.com.usb.udc import spinal.core._ -import spinal.lib import spinal.lib._ + import spinal.lib.bus.bmb._ import spinal.lib.bus.misc.MaskMapping -import spinal.lib.com.eth.{Crc, CrcKind} import spinal.lib.com.usb._ -import spinal.lib.com.usb.ohci.{OhciPortParameter, UsbOhci, UsbOhciParameter, UsbPid} +import spinal.lib.com.usb.ohci.UsbPid import spinal.lib.eda.bench.{Bench, Rtl, XilinxStdTargets} import spinal.lib.fsm._ diff --git a/tester/src/test/scala/spinal/tester/scalatest/GrayCounterTester.scala b/lib/src/test/scala/spinal/lib/GrayCounter.scala similarity index 78% rename from tester/src/test/scala/spinal/tester/scalatest/GrayCounterTester.scala rename to lib/src/test/scala/spinal/lib/GrayCounter.scala index f27aa119a7..7c237c7857 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/GrayCounterTester.scala +++ b/lib/src/test/scala/spinal/lib/GrayCounter.scala @@ -1,21 +1,14 @@ -package spinal.tester.scalatest +package spinal.lib import spinal.core._ -import spinal.lib._ -import spinal.tester.scalatest.GrayCounterTester.GrayCounterTester -import language.postfixOps - -object GrayCounterTester { +import spinal.tester.SpinalTesterCocotbBase +object GrayCounterTester { class GrayCnt(size : Int = 4) extends Component { - - // All IO signals for the Gray counter val io = new Bundle { - // Counter output port val gval = out UInt(size bits) - } // Helper bit for toggling @@ -32,7 +25,6 @@ object GrayCounterTester { // Handle all 'middle' bits for(i <- 1 to size - 2) { - // This equation checks the 0^* pattern val tmp = cnt(i - 1) && cnt(i - 2 downto 0).asBools.fold(True)((lastResult,cntBit) => lastResult && !cntBit) && toggle @@ -46,7 +38,6 @@ object GrayCounterTester { // Map the register to the output logic; io.gval := cnt - } class GrayCounterTester(n: Int) extends Component { @@ -58,16 +49,8 @@ object GrayCounterTester { } - -//class GrayCounterTesterGhdlBoot extends SpinalTesterGhdlBase { -// override def getName: String = "GrayCounterTester" -// -// withWaveform = true -// override def createToplevel: Component = new GrayCounterTester(8) -//} - class GrayCounterTesterCocotbBoot extends SpinalTesterCocotbBase { override def getName: String = "GrayCounterTester" override def pythonTestLocation: String = "tester/src/test/python/spinal/GrayCounterTester" - override def createToplevel: Component = new GrayCounterTester(8) + override def createToplevel: Component = new GrayCounterTester.GrayCounterTester(8) } \ No newline at end of file diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimPackedBundleTester.scala b/lib/src/test/scala/spinal/lib/PackedBundle.scala similarity index 98% rename from tester/src/test/scala/spinal/tester/scalatest/SpinalSimPackedBundleTester.scala rename to lib/src/test/scala/spinal/lib/PackedBundle.scala index 1897f81292..5ff8fc6acf 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimPackedBundleTester.scala +++ b/lib/src/test/scala/spinal/lib/PackedBundle.scala @@ -1,8 +1,8 @@ -package spinal.tester.scalatest +package spinal.lib import org.scalatest.funsuite.AnyFunSuite + import spinal.core._ -import spinal.lib._ import spinal.core.sim._ class SpinalSimPackedBundleTester extends AnyFunSuite { diff --git a/lib/src/test/scala/spinal/lib/Stream.scala b/lib/src/test/scala/spinal/lib/Stream.scala new file mode 100644 index 0000000000..afeec803a2 --- /dev/null +++ b/lib/src/test/scala/spinal/lib/Stream.scala @@ -0,0 +1,2578 @@ +package spinal.lib + +import spinal.core._ +import spinal.core.sim._ +import spinal.core.formal._ +import spinal.lib.formal._ +import spinal.lib.sim._ +import spinal.lib.graphic.Rgb + +import spinal.tester.{SpinalTesterCocotbBase, SpinalTesterGhdlBase, SpinalSimFunSuite} + +import org.scalatest.funsuite.AnyFunSuite +import scala.collection.mutable +import scala.util.Random + +object StreamTester{ + case class BundleA(aaa : Int) extends Bundle{ + val a = UInt(8 bit) + val b = Bool() + } +} + +import StreamTester._ + +class StreamTester extends Component { + val io = new Bundle { + val slave0 = slave Stream new BundleA(8) + val master0 = master Stream new BundleA(8) + val fifo0_occupancy = out UInt() + } + + val fifo0 = new StreamFifo(new BundleA(8),16) + fifo0.io.push << io.slave0 + fifo0.io.pop >/-> io.master0 + io.fifo0_occupancy := fifo0.io.occupancy + + assert(3 == LatencyAnalysis(io.slave0.a,io.master0.a)) + assert(2 == LatencyAnalysis(io.master0.ready,io.slave0.ready)) + + + + val forkInput = slave Stream(Bits(8 bits)) + val forkOutputs = Vec(master Stream(Bits(8 bits)),3) + (forkOutputs , StreamFork(forkInput,3)).zipped.foreach(_ << _) + + val dispatcherInOrderInput = slave Stream(Bits(8 bits)) + val dispatcherInOrderOutputs = Vec(master Stream(Bits(8 bits)),3) + (dispatcherInOrderOutputs , StreamDispatcherSequencial(dispatcherInOrderInput,3)).zipped.foreach(_ << _) + + val streamFlowArbiterInputStream = slave Stream(Bits(8 bits)) + val streamFlowArbiterInputFlow = slave Flow(Bits(8 bits)) + val streamFlowArbiterOutput = master Flow(Bits(8 bits)) + streamFlowArbiterOutput << StreamFlowArbiter(streamFlowArbiterInputStream,streamFlowArbiterInputFlow) + + val arbiterInOrderInputs = Vec(slave Stream(Bits(8 bits)),3) + val arbiterInOrderOutput = master Stream(Bits(8 bits)) + arbiterInOrderOutput << StreamArbiterFactory.sequentialOrder.on(arbiterInOrderInputs) + + val arbiterLowIdPortFirstInputs = Vec(slave Stream(Bits(8 bits)),3) + val arbiterLowIdPortFirstOutput = master Stream(Bits(8 bits)) + arbiterLowIdPortFirstOutput << StreamArbiterFactory.lowerFirst.on(arbiterLowIdPortFirstInputs) + + val arbiterRoundRobinInputs = Vec(slave Stream(Bits(8 bits)),3) + val arbiterRoundRobinOutput = master Stream(Bits(8 bits)) + arbiterRoundRobinOutput << StreamArbiterFactory.roundRobin.on(arbiterRoundRobinInputs) + + + val arbiterLowIdPortFirstNoLockInputs = Vec(slave Stream(Bits(8 bits)),3) + val arbiterLowIdPortFirstNoLockOutput = master Stream(Bits(8 bits)) + arbiterLowIdPortFirstNoLockOutput << StreamArbiterFactory.lowerFirst.noLock.on(arbiterLowIdPortFirstNoLockInputs) + + val arbiterLowIdPortFirstFragmentLockInputs = Vec(slave Stream(Fragment(Bits(8 bits))),3) + val arbiterLowIdPortFirstFragmentLockOutput = master Stream(Fragment(Bits(8 bits))) + arbiterLowIdPortFirstFragmentLockOutput << StreamArbiterFactory.lowerFirst.fragmentLock.on(arbiterLowIdPortFirstFragmentLockInputs) + + + // val muxSelect = in UInt(2 bits) +// val muxInputs = Vec(slave Stream(Bits(8 bits)),3) +// val muxOutput = master Stream(Bits(8 bits)) +// muxOutput << StreamMux(muxSelect,muxInputs) + +// val joinInputs = Vec(slave Stream(Bits(8 bits)),3) +// val joinOutput = master.Event +// joinOutput << StreamJoin(joinInputs) +} + + + +class StreamTesterGhdlBoot extends SpinalTesterGhdlBase { + override def getName: String = "StreamTester" + override def createToplevel: Component = new StreamTester +} + +class StreamTesterCocotbBoot extends SpinalTesterCocotbBase { + override def getName: String = "StreamTester" + override def pythonTestLocation: String = "tester/src/test/python/spinal/StreamTester" + override def createToplevel: Component = new StreamTester + override def noVhdl = true +} + +object StreamTester2 { + case class BundleA() extends Bundle{ + val a = UInt(8 bit) + val b = Bool() + } + + class StreamTester2 extends Component{ + val fifoA = new StreamFifo(BundleA(),16) + val fifoAPush = slave(cloneOf(fifoA.io.push)) + val fifoAPop = master(cloneOf(fifoA.io.pop)) + val fifoAOccupancy = out(cloneOf(fifoA.io.occupancy)) + fifoA.io.push << fifoAPush + fifoA.io.pop >> fifoAPop + fifoA.io.occupancy <> fifoAOccupancy + assert(2 == LatencyAnalysis(fifoAPush.a,fifoAPop.a)) + assert(1 == LatencyAnalysis(fifoAPop.ready,fifoAPush.ready)) + + + val fifoB = new StreamFifoLowLatency(BundleA(),16) + val fifoBPush = slave(cloneOf(fifoB.io.push)) + val fifoBPop = master(cloneOf(fifoB.io.pop)) + val fifoBOccupancy = out(cloneOf(fifoB.io.occupancy)) + fifoB.io.push << fifoBPush + fifoB.io.pop >> fifoBPop + fifoB.io.occupancy <> fifoBOccupancy + assert(0 == LatencyAnalysis(fifoBPush.a,fifoBPop.a)) + assert(1 == LatencyAnalysis(fifoBPop.ready,fifoBPush.ready)) + } +} + +class StreamTester2CocotbBoot extends SpinalTesterCocotbBase { + override def getName: String = "StreamTester2" + override def pythonTestLocation: String = "tester/src/test/python/spinal/StreamTester2" + override def createToplevel: Component = new StreamTester2.StreamTester2 + override def backendConfig(config: SpinalConfig): SpinalConfig = config +} + +class FormalArbiterTester extends SpinalFormalFunSuite { + def usualVerify[T <: Data]( + inputs: Vec[Stream[T]], + output: Stream[T], + portCount: Int, + select: UInt, + selectOH: Bits, + reset: Bool, + withLock: Boolean, + locked: Bool + ) = new Area { + output.formalCovers(2) + when(reset || past(reset)) { + for (i <- 0 until portCount) { + assume(inputs(i).valid === False) + } + assert(select === 0) + if (withLock) assert(!locked) + } + + for (i <- 0 until portCount) { + inputs(i).formalAssumesSlave() + } + + assert(select < portCount) + assert(select === OHToUInt(selectOH)) + assert(selectOH === OHMasking.first(selectOH)) + assert(output.fire === inputs(select).fire) + assert(output.payload === inputs(select).payload) + } + + def prepareContext(withLock: Boolean) = new Area { + val portCount = 5 + val select = UInt(log2Up(portCount) bit) + val selectOH = Bits(portCount bit) + val dataType = Bits(8 bits) + val locked = Bool() + + val reset = ClockDomain.current.isResetActive + val notReset = !(reset || past(reset)) + cover(notReset) + assumeInitial(reset) + + val inputs = Vec(slave(Stream(dataType)), portCount) + val output = master(Stream(dataType)) + val usual = usualVerify(inputs, output, portCount, select, selectOH, reset, withLock, locked) + + val inputsValid = Vec(inputs.map(_.valid)) + val selStableCond = past(output.isStall) && notReset + val selectUnLockCond = !locked || past(output.fire) + } + + def prepareContextFragment(withLock: Boolean) = new Area { + val portCount = 5 + val select = UInt(log2Up(portCount) bit) + val selectOH = Bits(portCount bit) + val dataType = Fragment(Bits(8 bits)) + val locked = Bool() + + val reset = ClockDomain.current.isResetActive + val notReset = !(reset || past(reset)) + cover(notReset) + assumeInitial(reset) + + val inputs = Vec(slave(Stream(dataType)), portCount) + val output = master(Stream(dataType)) + val usual = usualVerify(inputs, output, portCount, select, selectOH, reset, withLock, locked) + + val inputsValid = Vec(inputs.map(_.valid)) + val selStableCond = !past((inputsValid.asBits === 0) || output.last || reset) + val selectUnLockCond = !locked || past(output.last && output.fire) + } + + def sequentialOrderVerify(select: UInt, portCount: Int) = new Area { + val d1 = anyconst(UInt(log2Up(portCount) bit)) + assume(d1 < portCount) + val d2 = UInt(log2Up(portCount) bit) + d2 := (d1 + 1) % portCount + + val cntSeqCheck = changed(select) && (select === d2) + cover(cntSeqCheck) + when(cntSeqCheck) { + assert(past(select) === d1) + } + } + + def lowFirstVerify( + selectOH: Bits, + inputsvalid: Vec[Bool], + unLockCond: Bool + ) = new Area { + val inputsLowerFirst = OHMasking.first(inputsvalid).asBits + cover(unLockCond) + when(unLockCond) { + assert(selectOH === inputsLowerFirst) + } + } + + def roundRobinVerify( + selectOH: Bits, + inputsValid: Vec[Bool], + portCount: Int, + maskLocked: Vec[Bool], + unLockCond: Bool + ) = new Area { + val requests = inputsValid.asBits.asUInt + val uGranted = selectOH.asUInt + val doubleRequests = requests @@ requests + val doubleGrant = doubleRequests & ~(doubleRequests - uGranted) + val masked = doubleGrant(portCount, portCount bits) | doubleGrant(0, portCount bits) + val inputsRoundRobinOH = masked.asBits + + cover(unLockCond) + when(unLockCond) { + assert(selectOH === inputsRoundRobinOH) + } + // used for Prove + assert(maskLocked === OHMasking.first(maskLocked)) + } + + def selStableVerify(selectOH: Bits, selStableCond: Bool, withLock: Boolean) = new Area { + if (withLock) { + cover(selStableCond) + when(selStableCond) { + assert(stable(selectOH)) + } + } + } + + def withAssertsVerify[T <: Data](outisStall: Bool, verifyCond: Vec[Bool], output: Stream[T], withLock: Boolean) = + new Area { + if (withLock) { + val stallStableSel = outisStall && stable(verifyCond) + cover(stallStableSel) + when(stallStableSel) { + output.formalAssertsMaster() + } + } + } + + test("Arbiter-sequentialOrder-verify") { + FormalConfig + .withBMC(20) + .withProve(20) + .withCover(20) + // .withDebug + .doVerify(new Component { + val withLock = true + val context = prepareContext(withLock) + val dut = FormalDut( + new StreamArbiter(context.dataType, context.portCount)( + StreamArbiter.Arbitration.sequentialOrder, + StreamArbiter.Lock.none + ) + ) + + context.select := dut.io.chosen + context.selectOH := dut.io.chosenOH + context.locked := dut.locked + context.output << dut.io.output + for (i <- 0 until context.portCount) { + context.inputs(i) >> dut.io.inputs(i) + } + + val withAssert = withAssertsVerify(context.output.isStall, context.inputsValid, context.output, withLock) + val selStable = selStableVerify(context.selectOH, context.selStableCond, withLock) + val sequentialOrder = sequentialOrderVerify(context.select, context.portCount) + }) + } + + test("Arbiter-lowerfirst-none-verify") { + FormalConfig + .withBMC(20) + .withProve(20) + .withCover(20) + // .withDebug + .doVerify(new Component { + val withLock = false + val context = prepareContext(withLock) + val dut = FormalDut( + new StreamArbiter(context.dataType, context.portCount)( + StreamArbiter.Arbitration.lowerFirst, + StreamArbiter.Lock.none + ) + ) + + context.select := dut.io.chosen + context.selectOH := dut.io.chosenOH + context.locked := dut.locked + context.output << dut.io.output + for (i <- 0 until context.portCount) { + context.inputs(i) >> dut.io.inputs(i) + } + + val withAssert = withAssertsVerify(context.output.isStall, context.inputsValid, context.output, withLock) + val selStable = selStableVerify(context.selectOH, context.selStableCond, withLock) + val lowFirst = lowFirstVerify(context.selectOH, context.inputsValid, context.selectUnLockCond) + }) + } + + test("Arbiter-lowerfirst-transactionLock-verify") { + FormalConfig + .withBMC(20) + .withProve(20) + .withCover(20) + // .withDebug + .doVerify(new Component { + + val withLock = true + val context = prepareContext(withLock) + val dut = FormalDut( + new StreamArbiter(context.dataType, context.portCount)( + StreamArbiter.Arbitration.lowerFirst, + StreamArbiter.Lock.transactionLock + ) + ) + + context.select := dut.io.chosen + context.selectOH := dut.io.chosenOH + context.locked := dut.locked + context.output << dut.io.output + for (i <- 0 until context.portCount) { + context.inputs(i) >> dut.io.inputs(i) + } + // used for Prove + when(context.notReset) { + assert(past(context.output.isStall) === dut.locked) + } + + val withAssert = withAssertsVerify(context.output.isStall, context.inputsValid, context.output, withLock) + val selStable = selStableVerify(context.selectOH, context.selStableCond, withLock) + val lowFirst = lowFirstVerify(context.selectOH, context.inputsValid, context.selectUnLockCond) + }) + } + + test("Arbiter-lowerfirst-fragment-verify") { + FormalConfig + .withBMC(20) + .withProve(20) + .withCover(20) + // .withDebug + .doVerify(new Component { + val withLock = true + val context = prepareContextFragment(withLock) + val dut = FormalDut( + new StreamArbiter(context.dataType, context.portCount)( + StreamArbiter.Arbitration.lowerFirst, + StreamArbiter.Lock.fragmentLock + ) + ) + + context.select := dut.io.chosen + context.selectOH := dut.io.chosenOH + context.locked := dut.locked + context.output << dut.io.output + for (i <- 0 until context.portCount) { + context.inputs(i) >> dut.io.inputs(i) + } + + val withAssert = withAssertsVerify(context.output.isStall, context.inputsValid, context.output, withLock) + val selStable = selStableVerify(context.selectOH, context.selStableCond, withLock) + val lowFirst = lowFirstVerify(context.selectOH, context.inputsValid, context.selectUnLockCond) + }) + } + + test("Arbiter-roundrobin-none-verify") { + FormalConfig + .withBMC(20) + .withProve(20) + .withCover(20) + // .withDebug + .doVerify(new Component { + val withLock = false + val context = prepareContext(withLock) + val dut = FormalDut( + new StreamArbiter(context.dataType, context.portCount)( + StreamArbiter.Arbitration.roundRobin, + StreamArbiter.Lock.none + ) + ) + + context.select := dut.io.chosen + context.selectOH := dut.io.chosenOH + context.locked := dut.locked + context.output << dut.io.output + for (i <- 0 until context.portCount) { + context.inputs(i) >> dut.io.inputs(i) + } + + val roundRobin = roundRobinVerify( + context.selectOH, + context.inputsValid, + context.portCount, + dut.maskLocked, + context.selectUnLockCond + ) + val withAssert = withAssertsVerify(context.output.isStall, roundRobin.masked.asBools, context.output, withLock) + val selStable = selStableVerify(context.selectOH, context.selStableCond, withLock) + }) + } + + test("Arbiter-roundrobin-transactionLock-verify") { + FormalConfig + .withBMC(20) + .withProve(20) + .withCover(20) + .withDebug + .doVerify(new Component { + val withLock = true + val context = prepareContext(withLock) + val dut = FormalDut( + new StreamArbiter(context.dataType, context.portCount)( + StreamArbiter.Arbitration.roundRobin, + StreamArbiter.Lock.transactionLock + ) + ) + + context.select := dut.io.chosen + context.selectOH := dut.io.chosenOH + context.locked := dut.locked + context.output << dut.io.output + for (i <- 0 until context.portCount) { + context.inputs(i) >> dut.io.inputs(i) + } + // used for Prove + when(context.notReset) { + assert(past(context.output.isStall) === dut.locked) + } + val roundRobin = roundRobinVerify( + context.selectOH, + context.inputsValid, + context.portCount, + dut.maskLocked, + context.selectUnLockCond + ) + val withAssert = withAssertsVerify(context.output.isStall, roundRobin.masked.asBools, context.output, withLock) + val selStable = selStableVerify(context.selectOH, context.selStableCond, withLock) + }) + } + + test("Arbiter-roundrobin-fragment-verify") { + FormalConfig + .withBMC(20) + .withProve(20) + .withCover(20) + // .withDebug + .doVerify(new Component { + val withLock = true + val context = prepareContextFragment(withLock) + val dut = FormalDut( + new StreamArbiter(context.dataType, context.portCount)( + StreamArbiter.Arbitration.roundRobin, + StreamArbiter.Lock.fragmentLock + ) + ) + + context.select := dut.io.chosen + context.selectOH := dut.io.chosenOH + context.locked := dut.locked + context.output << dut.io.output + for (i <- 0 until context.portCount) { + context.inputs(i) >> dut.io.inputs(i) + } + + val roundRobin = roundRobinVerify( + context.selectOH, + context.inputsValid, + context.portCount, + dut.maskLocked, + context.selectUnLockCond + ) + val withAssert = withAssertsVerify(context.output.isStall, roundRobin.masked.asBools, context.output, withLock) + val selStable = selStableVerify(context.selectOH, context.selStableCond, withLock) + }) + } +} + +class FormalDeMuxTester extends SpinalFormalFunSuite { + def formaldemux(selWithCtrl: Boolean = false) = { + FormalConfig + .withBMC(20) + .withProve(20) + .withCover(20) + // .withDebug + .doVerify(new Component { + val portCount = 5 + val dataType = Bits(8 bits) + val dut = FormalDut(new StreamDemux(dataType, portCount)) + + val reset = ClockDomain.current.isResetActive + + assumeInitial(reset) + + val demuxSelect = anyseq(UInt(log2Up(portCount) bit)) + val demuxInput = slave(Stream(dataType)) + val demuxOutputs = Vec(master(Stream(dataType)), portCount) + + dut.io.select := demuxSelect + demuxInput >> dut.io.input + + when(reset || past(reset)) { + assume(demuxInput.valid === False) + } + + val selStableCond = if (selWithCtrl) past(demuxOutputs(demuxSelect).isStall) else null + if (selWithCtrl) { + cover(selStableCond) + when(selStableCond) { + assume(stable(demuxSelect)) + } + } + + assumeInitial(demuxSelect < portCount) + cover(demuxInput.fire) + demuxInput.formalAssumesSlave() + demuxInput.formalCovers(5) + + val inputFireStableSelChanged = past(demuxInput.fire) && demuxInput.fire && changed(demuxSelect) + cover(inputFireStableSelChanged) + + for (i <- 0 until portCount) { + demuxOutputs(i) << dut.io.outputs(i) + demuxOutputs(i).formalAssertsMaster() + demuxOutputs(i).formalCovers(5) + } + + for (i <- 0 until portCount) { + assert(demuxOutputs(i).payload === demuxInput.payload) + when(i =/= demuxSelect) { + assert(demuxOutputs(i).valid === False) + } + } + when(demuxSelect < portCount) { + assert(demuxOutputs(demuxSelect) === demuxInput) + } + }) + } + test("demux_sel_with_control") { + formaldemux(true) + } + test("demux_sel_without_control") { + shouldFail(formaldemux(false)) + } + + test("demux_with_selector") { + FormalConfig + .withProve(20) + .withCover(20) + .doVerify(new Component { + val portCount = 5 + val dataType = Bits(8 bits) + val dut = FormalDut(new StreamDemux(dataType, portCount)) + val selector = dut.io.createSelector() + + val reset = ClockDomain.current.isResetActive + assumeInitial(reset) + + val demuxSelector = slave(Stream(UInt(log2Up(portCount) bit))) + demuxSelector >> selector + val demuxInput = slave(Stream(dataType)) + demuxInput >> dut.io.input + val demuxOutputs = Vec(master(Stream(dataType)), portCount) + for (i <- 0 until portCount) { + demuxOutputs(i) << dut.io.outputs(i) + } + + when(reset || past(reset)) { + assume(demuxInput.valid === False) + assume(demuxSelector.valid === False) + } + + assumeInitial(demuxSelector.payload < portCount) + demuxSelector.formalAssumesSlave() + demuxInput.formalAssumesSlave() + demuxInput.formalCovers(5) + + val inputFireStableSelChanged = past(demuxInput.fire) && demuxInput.fire && changed(dut.io.select) + cover(inputFireStableSelChanged) + + for (i <- 0 until portCount) { + demuxOutputs(i).formalAssertsMaster() + demuxOutputs(i).formalCovers(5) + } + + for (i <- 0 until portCount) { + when(i =/= dut.io.select) { + assert(demuxOutputs(i).valid === False) + } + } + when(dut.io.select < portCount) { + assert(demuxOutputs(dut.io.select) === demuxInput) + } + }) + } +} + +class FormalDispatcherSequencialTester extends SpinalFormalFunSuite { + test("DispatcherSequencial-verify") { + FormalConfig + .withBMC(20) + .withProve(20) + .withCover(40) + // .withDebug + .doVerify(new Component { + val portCount = 5 + val dataType = Bits(8 bits) + val reset = ClockDomain.current.isResetActive + val dut = FormalDut(new StreamDispatcherSequencial(dataType, portCount)) + + assumeInitial(reset) + + val muxInput = slave(Stream(dataType)) + val muxOutputs = Vec(master(Stream(dataType)), portCount) + + muxInput >> dut.io.input + for (i <- 0 until portCount) { + muxOutputs(i) << dut.io.outputs(i) + } + + when(reset || past(reset)) { + assume(muxInput.valid === False) + } + + cover(muxInput.fire) + + muxInput.formalAssumesSlave() + muxInput.formalCovers(3) + + for (i <- 0 until portCount) { + cover(dut.counter.value === i) + muxOutputs(i).formalAssertsMaster() + muxOutputs(i).formalCovers() + } + + for (i <- 0 until portCount) { + when(dut.counter.value =/= i) { + assert(muxOutputs(i).valid === False) + } otherwise { + assert(muxOutputs(i) === muxInput) + } + } + + val d1 = anyconst(UInt(log2Up(portCount) bit)) + assume(d1 < portCount) + val d2 = UInt(log2Up(portCount) bit) + d2 := (d1 + 1) % portCount + + val cntSeqCheck = changed(dut.counter.value) && (dut.counter.value === d2) + cover(cntSeqCheck) + when(cntSeqCheck) { + assert(past(dut.counter.value) === d1) + } + }) + } +} + +class FormalFifoCCTester extends SpinalFormalFunSuite { + def formalContext(pushPeriod: Int, popPeriod: Int, seperateReset: Boolean = false) = new Area { + val back2backCycles = 2 + val fifoDepth = 4 + + val pushClock = ClockDomain.current + val reset = pushClock.isResetActive + val popClock = ClockDomain.external("pop") + val popReset = popClock.isResetActive + + val inValue = in(UInt(3 bits)) + val inValid = in(Bool()) + val outReady = in(Bool()) + val gclk = GlobalClock() + + assumeInitial(reset) + assumeInitial(popReset) + + gclk.assumeClockTiming(pushClock, pushPeriod) + gclk.assumeResetReleaseSync(pushClock) + if (!seperateReset) { + gclk.keepBoolLeastCycles(reset, popPeriod) + } + + gclk.assumeClockTiming(popClock, popPeriod) + if (seperateReset) { + gclk.assumeResetReleaseSync(popClock) + gclk.alignAsyncResetStart(pushClock, popClock) + } + + val dut = FormalDut(new StreamFifoCC(cloneOf(inValue), fifoDepth, pushClock, popClock, !seperateReset)) + gclk.assumeIOSync2Clock(pushClock, dut.io.push.valid) + gclk.assumeIOSync2Clock(pushClock, dut.io.push.payload) + gclk.assumeIOSync2Clock(popClock, dut.io.pop.ready) + + dut.io.push.payload := inValue + dut.io.push.valid := inValid + dut.io.pop.ready := outReady + + // assume no valid while reset and one clock later. + when(reset || past(reset)) { + assume(inValid === False) + } + + dut.formalAsserts(gclk.domain) + + val pushArea = new ClockingArea(pushClock) { + dut.io.push.formalAssumesSlave() + dut.io.push.formalCovers() + } + + // back to back transaction cover test. + val popCheckDomain = if (seperateReset) popClock else popClock.copy(reset = reset) + val popArea = new ClockingArea(popCheckDomain) { + dut.io.pop.formalCovers(back2backCycles) + dut.io.pop.formalAssertsMaster() + } + } + + def testMain(pushPeriod: Int, popPeriod: Int, seperateReset: Boolean = false) = { + val proveCycles = 8 + val coverCycles = 8 + val maxPeriod = Math.max(pushPeriod, popPeriod) + + FormalConfig + .withProve(maxPeriod * proveCycles) + .withCover(maxPeriod * coverCycles) + .withAsync + .doVerify(new Component { + val context = formalContext(pushPeriod, popPeriod, seperateReset) + }) + } + + test("fifo-verify fast pop") { + testMain(5, 3) + } + + test("fifo-verify fast push") { + testMain(3, 5) + } + +// test("fifo-verify ultra fast pop") { +// testMain(11, 2) +// } + +// test("fifo-verify ultra fast push") { +// testMain(2, 11) +// } + + test("fifo-verify fast pop reset seperately") { + testMain(5, 3, true) + } + + test("fifo-verify fast push reset seperately") { + testMain(3, 5, true) + } + +// test("fifo-verify ultra fast pop reset seperately") { +// testMain(11, 2, true) +// } + +// test("fifo-verify ultra fast push reset seperately") { +// testMain(2, 11, true) +// } + + def testNoLoss(pushPeriod: Int, popPeriod: Int, seperateReset: Boolean = false) = { + val proveCycles = 8 + val coverCycles = 8 + val maxPeriod = Math.max(pushPeriod, popPeriod) + + FormalConfig + .withCover(maxPeriod * coverCycles) + .withAsync + .withDebug + .doVerify(new Component { + val context = formalContext(pushPeriod, popPeriod, seperateReset) + + val d1 = anyconst(cloneOf(context.inValue)) + val d1_in = RegInit(False) + when(context.inValue === d1 & context.dut.io.push.fire) { + d1_in := True + } + when(d1_in) { assume(context.inValue =/= d1) } + + val popCheckArea = new ClockingArea(context.popCheckDomain) { + val d1_inCC = BufferCC(d1_in) + val cond = d1_inCC & context.dut.io.pop.fire + val hist = History(context.dut.io.pop.payload, context.fifoDepth, cond) + val counter = Counter(context.fifoDepth, inc = cond) + when(!d1_inCC) { counter.clear() } + cover(counter.willOverflow & !hist.sContains(d1)) + } + + val globalCheckArea = new ClockingArea(context.popCheckDomain) { + def checkValidData(cond: UInt => Bool): Seq[Bool] = context.dut.rework { + val maps = for (i <- 0 until context.fifoDepth) yield { + val index = context.dut.popCC.popPtr + i + val out = False + when(i < context.dut.pushCC.pushPtr - context.dut.popCC.popPtr) { + out := cond(context.dut.ram(index.resized)) + } + out + } + maps + } + val fits = checkValidData(_ === d1.pull()) + val containD1 = fits.reduce(_ || _) + when(!d1_in) { assume(!containD1) } + } + }) + } + + test("noloss fast pop") { + shouldFail(testNoLoss(5, 3)) + } + + test("noloss fast push") { + shouldFail(testNoLoss(3, 5)) + } + + // test("noloss ultra fast pop") { + // shouldFail(testNoLoss(11, 2)) + // } + + // test("noloss ultra fast push") { + // shouldFail(testNoLoss(2, 11)) + // } + + test("noloss fast pop reset seperately") { + shouldFail(testNoLoss(5, 3, true)) + } + + test("noloss fast push reset seperately") { + shouldFail(testNoLoss(3, 5, true)) + } + + // test("noloss ultra fast pop reset seperately") { + // shouldFail(testNoLoss(11, 2, true)) + // } + + // test("noloss ultra fast push reset seperately") { + // shouldFail(testNoLoss(2, 11, true)) + // } + +} + +class FormalFifoTester extends SpinalFormalFunSuite { + test("fifo-verify all") { + val initialCycles = 2 + val inOutDelay = 2 + val coverCycles = 10 + FormalConfig + .withBMC(10) + .withProve(10) + .withCover(coverCycles) + // .withDebug + .doVerify(new Component { + val depth = 4 + val dut = FormalDut(new StreamFifo(UInt(7 bits), depth)) + val reset = ClockDomain.current.isResetActive + + assumeInitial(reset) + + val inValue = anyseq(UInt(7 bits)) + val inValid = anyseq(Bool()) + val outReady = anyseq(Bool()) + dut.io.push.payload := inValue + dut.io.push.valid := inValid + dut.io.pop.ready := outReady + + // assume no valid while reset and one clock later. + when(reset || past(reset)) { + assume(inValid === False) + } + + dut.io.push.formalAssumesSlave() + dut.io.pop.formalAssertsMaster() + + dut.io.push.formalCovers() + // back to back transaction cover test. + dut.io.pop.formalCovers(coverCycles - initialCycles - inOutDelay - 1) + + val d1 = anyconst(UInt(7 bits)) + val d2 = anyconst(UInt(7 bits)) + + val (d1_in, d2_in) = dut.io.push.formalAssumesOrder(d1, d2) + val (d1_out, d2_out) = dut.io.pop.formalAssertsOrder(d1, d2) + + when(!d1_in) { assume(!dut.formalContains(d1)) } + when(d1_in && !d1_out) { assert(dut.formalCount(d1) === 1) } + + when(!d2_in) { assume(!dut.formalContains(d2)) } + when(d2_in && !d2_out) { assert(dut.formalCount(d2) === 1) } + + when(d1_in && d2_in && !d1_out) { assert(!d2_out) } + + def getCompId(x: UInt): UInt = { + val id = OHToUInt(dut.formalCheck(_ === x.pull()).asBits) + val extId = id +^ depth + val compId = CombInit(extId) + when(id >= dut.logic.popPtr) { + compId := id.resized + } + compId + } + when(d1_in && d2_in && !d1_out && !d2_out) { + assert(getCompId(d1) < getCompId(d2)) + } + }) + } +} + +class FormalForkTester extends SpinalFormalFunSuite { + def formalfork (synchronous: Boolean = false, back2BackCheck: Boolean = false ) = { + FormalConfig + .withBMC(20) + .withProve(20) + .withCover(20) + // .withDebug + .doVerify(new Component { + val portCount = 2 + val dataType = Bits(8 bits) + val dut = FormalDut(new StreamFork(dataType, portCount, synchronous)) + + val reset = ClockDomain.current.isResetActive + + assumeInitial(reset) + + val input = slave(Stream(dataType)) + val outputs = Vec(master(Stream(dataType)), portCount) + + input >> dut.io.input + for (i <- 0 until portCount) { + outputs(i) << dut.io.outputs(i) + } + + when(reset || past(reset)) { + assume(input.valid === False) + } + + cover(input.fire) + + input.formalAssumesSlave() + if(back2BackCheck) input.formalCovers(3) + + for (i <- 0 until portCount) { + assert(outputs(i).payload === input.payload) + outputs(i).formalAssertsMaster() + if(back2BackCheck) outputs(i).formalCovers(3) + } + + val fired = if(!synchronous)Vec(RegInit(True), portCount) else null // store fire status, + val outputsFireAsync = if(!synchronous){fired(0) =/= fired(1)} else null + val out0FireFirst = if(!synchronous){fired(1) && !fired(0)} else null + val out1FireFirst = if(!synchronous){fired(0) && !fired(1)} else null + val out0FireLast = if(!synchronous){~(input.fire ^ outputs(0).fire)} else null + val out1FireLast = if(!synchronous){~(input.fire ^ outputs(1).fire)} else null + + if(synchronous){ + for (i <- 0 until portCount) { + assert(outputs(i).fire === input.fire) + + } + } + else{ + for(i <- 0 until portCount){ + cover(input.ready) + when(input.ready){ + fired(i) := True + } + cover(!input.ready && outputs(i).fire) + when(!input.ready && outputs(i).fire){ + fired(i) := False + } + + assert(fired(i) === dut.logic.linkEnable(i)) + } + + cover(out0FireFirst && !outputs(1).fire) + cover(out1FireFirst && !outputs(0).fire) + + when(outputsFireAsync) { + assert(!past(input.fire)) + } + + when(out0FireFirst) { + assert(out1FireLast) + assert(!outputs(0).valid) + } + + when(out1FireFirst) { + assert(out0FireLast) + assert(!outputs(1).valid) + } + } + }) + } + + test("fork-verify sync") { + formalfork(true,false) + } + + test("fork-verify sync back2Back fail") { + shouldFail(formalfork(true,true)) + } + + test("fork-verify async") { + formalfork(false,true) + } +} + +class Join[T1 <: Data, T2 <: Data](dataType_0: T1, dataType_1: T2) extends Component { + val io = new Bundle { + val inputs_0 = slave(Stream (dataType_0)) + val inputs_1 = slave(Stream (dataType_1)) + val output = master(Stream(TupleBundle2( + dataType_0, + dataType_1 + ))) + } + val logic = StreamJoin(io.inputs_0,io.inputs_1) + io.output << logic +} + +class FormalJoinTester extends SpinalFormalFunSuite { + test("StreamJoinTester-verify") { + FormalConfig + .withBMC(20) + .withProve(20) + .withCover(20) + + // .withDebug + .doVerify(new Component { + val portCount = 5 + val dataType_0 = Bits(8 bits) + val dataType_1 = Bits(16 bits) + val dut = FormalDut(new Join(dataType_0, dataType_1)) + val reset = ClockDomain.current.isResetActive + + assumeInitial(reset) + + val inputs_0 = slave Stream (dataType_0) + val inputs_1 = slave Stream (dataType_1) + val output = master( + Stream( + TupleBundle2( + dataType_0, + dataType_1 + ) + ) + ) + + inputs_0 >> dut.io.inputs_0 + inputs_1 >> dut.io.inputs_1 + output << dut.io.output + + when(reset || past(reset)) { + assume(inputs_0.valid === False) + assume(inputs_1.valid === False) + } + + inputs_0.formalAssumesSlave() + inputs_1.formalAssumesSlave() + output.formalAssertsMaster() + output.formalCovers(3) + + assert(inputs_0.fire === inputs_1.fire) + assert(output.fire === inputs_0.fire) + assert(output.payload._1 === inputs_0.payload) + assert(output.payload._2 === inputs_1.payload) + }) + } +} + +class FormalMuxTester extends SpinalFormalFunSuite { + def formalmux(selWithCtrl: Boolean = false) = { + FormalConfig + .withBMC(20) + .withProve(20) + .withCover(20) + // .withDebug + .doVerify(new Component { + val portCount = 5 + val dataType = Bits(8 bits) + val dut = FormalDut(new StreamMux(dataType, portCount)) + + val reset = ClockDomain.current.isResetActive + + assumeInitial(reset) + + val muxSelect = anyseq(UInt(log2Up(portCount) bit)) + val muxInputs = Vec(slave(Stream(dataType)), portCount) + val muxOutput = master(Stream(dataType)) + + dut.io.select := muxSelect + muxOutput << dut.io.output + + assumeInitial(muxSelect < portCount) + val selStableCond = if (selWithCtrl) past(muxOutput.isStall) else null + + when(reset || past(reset)) { + for (i <- 0 until portCount) { + assume(muxInputs(i).valid === False) + } + } + + if (selWithCtrl) { + cover(selStableCond) + when(selStableCond) { + assume(stable(muxSelect)) + } + } + muxOutput.formalAssertsMaster() + muxOutput.formalCovers(5) + + for (i <- 0 until portCount) { + muxInputs(i) >> dut.io.inputs(i) + muxInputs(i).formalAssumesSlave() + } + + cover(muxOutput.fire) + + for (i <- 0 until portCount) { + cover(dut.io.select === i) + muxInputs(i).formalAssumesSlave() + } + + when(muxSelect < portCount) { + assert(muxOutput === muxInputs(muxSelect)) + } + }) + } + test("mux_sel_with_control") { + formalmux(true) + } + test("mux_sel_without_control") { + shouldFail(formalmux(false)) + } + + test("mux_with_selector") { + FormalConfig + .withProve(20) + .withCover(20) + .doVerify(new Component { + val portCount = 5 + val dataType = Bits(8 bits) + val dut = FormalDut(new StreamMux(dataType, portCount)) + val selector = dut.io.createSelector() + + val reset = ClockDomain.current.isResetActive + assumeInitial(reset) + + val muxSelector = slave(cloneOf(selector)) + muxSelector >> selector + val muxInputs = Vec(slave(Stream(dataType)), portCount) + for (i <- 0 until portCount) { + muxInputs(i) >> dut.io.inputs(i) + } + val muxOutput = master(Stream(dataType)) + muxOutput << dut.io.output + + assumeInitial(muxSelector.payload < portCount) + muxSelector.formalAssumesSlave() + + when(reset || past(reset)) { + for (i <- 0 until portCount) { + assume(muxInputs(i).valid === False) + } + assume(muxSelector.valid === False) + } + + muxOutput.formalAssertsMaster() + muxOutput.formalCovers(5) + cover(dut.io.select =/= muxSelector.payload) + cover(changed(muxSelector.payload) & stable(muxSelector.valid) & muxSelector.valid) + val readyBits = muxInputs.map(_.ready).asBits() + assert((readyBits === 0) || (CountOne(readyBits) === 1)) + + for (i <- 0 until portCount) { + cover(dut.io.select === i) + muxInputs(i).formalAssumesSlave() + } + + when(dut.io.select < portCount) { + assert(muxOutput === muxInputs(dut.io.select)) + } + }) + + } +} + +class FormalStreamExtender extends SpinalFormalFunSuite { + def counterTester() { + FormalConfig + // .withBMC(10) + .withProve(10) + .withCover(10) + .doVerify(new Component { + val inStream = slave Stream (UInt(2 bits)) + val outStream = master Stream (UInt(2 bits)) + val count = in UInt (3 bits) + val dut = FormalDut(StreamTransactionCounter(inStream, outStream, count, false)) + + val inReady = in Bool () + inStream.ready := inReady + val outValid = in Bool () + outStream.valid := outValid + val outPayload = in UInt (2 bits) + outStream.payload := outPayload + + val reset = ClockDomain.current.isResetActive + assumeInitial(reset) + + val countHist = History(count, 2, inStream.fire, init = count.getZero) + when(!dut.io.available) { assume(inReady === False) } + + when(pastValid & past(!reset & inStream.fire)) { assert(dut.io.working) } + when(pastValid & past(dut.io.done & !inStream.fire)) { assert(!dut.io.working) } + + when(dut.io.done) { assert(dut.counter.value >= countHist(1)) } + when(dut.io.working) { + assert(countHist(1) === dut.expected) // key to sync verification logic and internal logic. + when(dut.counter.value === countHist(1) & outStream.fire) { assert(dut.io.done) } + when(!dut.io.done) { assert(!dut.io.available) } + .otherwise { assert(dut.io.available) } + } + .otherwise { assert(dut.io.available) } + val counterHelper = dut.formalAsserts() + + cover(inStream.fire & outStream.fire & dut.io.done) + cover(pastValid & past(dut.io.working) & !dut.io.working) + + inStream.formalAssumesSlave() + outStream.formalAssumesSlave() + + for(i <- 1 until 2) { + inStream.formalCovers(i) + outStream.formalCovers(i) + } + }) + } + + def counterNoDelayTester() { + FormalConfig + // .withBMC(10) + .withProve(10) + .withCover(10) + .doVerify(new Component { + val inStream = slave Stream (UInt(2 bits)) + val outStream = master Stream (UInt(2 bits)) + val count = in UInt (3 bits) + val dut = FormalDut(StreamTransactionCounter(inStream, outStream, count, true)) + + val inReady = in Bool () + inStream.ready := inReady + val outValid = in Bool () + outStream.valid := outValid + val outPayload = in UInt (2 bits) + outStream.payload := outPayload + + val reset = ClockDomain.current.isResetActive + assumeInitial(reset) + + val countHist = History(count, 2, inStream.fire, init = count.getZero) + val expected = countHist(1).getAheadValue() + when(!dut.io.available) { assume(inReady === False) } + + when(inStream.fire) { assert(dut.io.working) } + when(pastValid & past(dut.io.done) & !inStream.fire) { assert(!dut.io.working) } + + when(dut.io.done) { assert(dut.counter.value >= expected) } + when(dut.io.working) { + assert(expected === dut.expected) // key to sync verification logic and internal logic. + when(dut.counter.value === expected & outStream.fire) { assert(dut.io.done) } + when(!inStream.fire) { assert(!dut.io.available) } + .otherwise { assert(dut.io.available) } + } + .otherwise { assert(dut.io.available) } + cover(pastValid & past(dut.io.done) & inStream.fire) + cover(pastValid & past(dut.io.working) & !dut.io.working) + + inStream.formalAssumesSlave() + outStream.formalAssumesSlave() + + for(i <- 1 until 2) { + inStream.formalCovers(i) + outStream.formalCovers(i) + } + }) + } + + def extenderTester() { + FormalConfig + // .withBMC(10) + .withProve(10) + .withCover(10) + .doVerify(new Component { + val inStream = slave Stream (UInt(2 bits)) + val outStream = master Stream (UInt(2 bits)) + val count = in UInt (3 bits) + val dut = FormalDut(StreamTransactionExtender(inStream, outStream, count) { (_, p, _) => p }) + + val reset = ClockDomain.current.isResetActive + assumeInitial(reset) + + val countHist = History(count, 2, inStream.fire, init = count.getZero) + + when(pastValid & past(!reset & inStream.fire)) { assert(dut.io.working) } + when(pastValid & past(dut.io.done & !inStream.fire)) { assert(!dut.io.working) } + + when(dut.io.done) { assert(dut.counter.counter.value >= countHist(1)) } + when(dut.io.working) { + assert(countHist(1) === dut.counter.expected) // key to sync verification logic and internal logic. + when(dut.counter.counter.value === countHist(1) & outStream.fire) { assert(dut.io.done) } + when(!dut.io.done) { assert(!inStream.ready) } + } + cover(inStream.fire & outStream.fire & dut.io.done) + cover(pastValid & past(dut.io.working) & !dut.io.working) + + inStream.formalAssumesSlave() + outStream.formalAssertsMaster() + + for(i <- 1 until 2) { + inStream.formalCovers(i) + outStream.formalCovers(i) + } + }) + } + + + def extenderNoDelayTester() { + FormalConfig + // .withBMC(10) + .withProve(10) + .withCover(10) + .doVerify(new Component { + val inStream = slave Stream (UInt(2 bits)) + val outStream = master Stream (UInt(2 bits)) + val count = in UInt (3 bits) + val dut = FormalDut(StreamTransactionExtender(inStream, outStream, count, true) { (_, p, _) => p }) + + val reset = ClockDomain.current.isResetActive + assumeInitial(reset) + + val countHist = History(count, 2, inStream.fire, init = count.getZero) + val expected = countHist(1).getAheadValue() + + when(inStream.fire) { assert(dut.io.working) } + when(pastValid & past(dut.io.done) & !inStream.fire) { assert(!dut.io.working) } + + when(dut.io.done) { assert(dut.counter.counter.value >= expected) } + when(dut.io.working) { + assert(expected === dut.counter.expected) // key to sync verification logic and internal logic. + when(dut.counter.counter.value === expected & outStream.fire) { assert(dut.io.done) } + when(!inStream.fire) { assert(!dut.counter.io.available) } + .otherwise { assert(dut.counter.io.available) } + when(!dut.io.input.fire) { assert(!inStream.ready) } + when(dut.io.input.fire) { assert(dut.io.input.payload === dut.io.output.payload) } + .otherwise { assert(dut.io.output.payload === dut.payloadReg) } + } + cover(pastValid & past(dut.io.done) & inStream.fire) + cover(pastValid & past(dut.io.working) & !dut.io.working) + + inStream.formalAssumesSlave() + outStream.formalAssertsMaster() + + for(i <- 1 until 2) { + inStream.formalCovers(i) + outStream.formalCovers(i) + } + }) + } + + test("transaction counter") { + counterTester() + } + + test("transaction counter without delay") { + counterNoDelayTester() + } + + test("transaction extender") { + extenderTester() + } + + test("transaction extender without delay") { + extenderNoDelayTester() + } +} + +class SpinalSimStreamWidthAdapterTester extends SpinalSimFunSuite { + test("test2xOut") { + //Compile the simulator + val baseWidth = 32 + val compiled = SimConfig.allOptimisation.compile(rtl = new Component{ + val input = slave Stream(UInt(baseWidth bits)) + val output = master Stream(UInt(baseWidth*2 bits)) + val rtl = StreamWidthAdapter(input, output) + } + ) + + //Run the simulation + compiled.doSimUntilVoid { dut => + val queueModel = mutable.Queue[BigInt]() + + SimTimeout(1000000 * 8) + dut.clockDomain.forkStimulus(2) + + val driver = StreamDriver(dut.input, dut.clockDomain) { _ => + true + } + val inMonitor = StreamMonitor(dut.input, dut.clockDomain) { p => + queueModel.enqueue(p.toBigInt) + } + + val ready = StreamReadyRandomizer(dut.output, dut.clockDomain) + val outMonitor = StreamMonitor(dut.output, dut.clockDomain) { p => + assert(queueModel.nonEmpty) + val low = queueModel.dequeue() + assert(queueModel.nonEmpty) + val high = queueModel.dequeue() + val value = (high << baseWidth) + low + assert(p.toBigInt == value) + } + + dut.clockDomain.waitSampling(10000) + simSuccess() + } + } + + test("test2xIn") { + //Compile the simulator + val baseWidth = 32 + val compiled = SimConfig.allOptimisation.compile(rtl = new Component{ + val input = slave Stream(UInt(baseWidth*2 bits)) + val output = master Stream(UInt(baseWidth bits)) + val rtl = StreamWidthAdapter(input, output) + } + ) + + //Run the simulation + compiled.doSimUntilVoid { dut => + val inQueue = mutable.Queue[BigInt]() + val lowQueue = mutable.Queue[BigInt]() + val highQueue = mutable.Queue[BigInt]() + + SimTimeout(1000000 * 8) + dut.clockDomain.forkStimulus(2) + def check(){ + if(inQueue.nonEmpty && lowQueue.nonEmpty && highQueue.nonEmpty){ + val low = lowQueue.dequeue() + val high = highQueue.dequeue() + val value = (high << baseWidth) + low + assert(inQueue.dequeue() == value) + } + } + + val driver = StreamDriver(dut.input, dut.clockDomain) { p => + true + } + val inMonitor = StreamMonitor(dut.input, dut.clockDomain) { p => + inQueue.enqueue(p.toBigInt) + check() + } + + val ready = StreamReadyRandomizer(dut.output, dut.clockDomain) + val outMonitor = StreamMonitor(dut.output, dut.clockDomain) { p => + if (lowQueue.length <= highQueue.length){ + lowQueue.enqueue(p.toBigInt) + } else { + highQueue.enqueue(p.toBigInt) + } + check() + } + + dut.clockDomain.waitSampling(10000) + simSuccess() + } + } + + test("test2xOutHighFirst") { + //Compile the simulator + val baseWidth = 32 + val compiled = SimConfig.allOptimisation.compile(rtl = new Component{ + val input = slave Stream(UInt(baseWidth bits)) + val output = master Stream(UInt(baseWidth*2 bits)) + val rtl = StreamWidthAdapter(input, output, order = HIGHER_FIRST) + } + ) + + //Run the simulation + compiled.doSimUntilVoid { dut => + val queueModel = mutable.Queue[BigInt]() + + SimTimeout(1000000 * 8) + dut.clockDomain.forkStimulus(2) + + val driver = StreamDriver(dut.input, dut.clockDomain) { _ => + true + } + val inMonitor = StreamMonitor(dut.input, dut.clockDomain) { p => + queueModel.enqueue(p.toBigInt) + } + + val ready = StreamReadyRandomizer(dut.output, dut.clockDomain) + val outMonitor = StreamMonitor(dut.output, dut.clockDomain) { p => + assert(queueModel.nonEmpty) + val high = queueModel.dequeue() + assert(queueModel.nonEmpty) + val low = queueModel.dequeue() + val value = (high << baseWidth) + low + assert(p.toBigInt == value) + } + + dut.clockDomain.waitSampling(10000) + simSuccess() + } + } + + test("test2xInHighFirst") { + //Compile the simulator + val baseWidth = 32 + val compiled = SimConfig.allOptimisation.compile(rtl = new Component{ + val input = slave Stream(UInt(baseWidth*2 bits)) + val output = master Stream(UInt(baseWidth bits)) + val rtl = StreamWidthAdapter(input, output, order = HIGHER_FIRST) + } + ) + + //Run the simulation + compiled.doSimUntilVoid { dut => + val inQueue = mutable.Queue[BigInt]() + val lowQueue = mutable.Queue[BigInt]() + val highQueue = mutable.Queue[BigInt]() + + SimTimeout(1000000 * 8) + dut.clockDomain.forkStimulus(2) + def check(){ + if(inQueue.nonEmpty && lowQueue.nonEmpty && highQueue.nonEmpty){ + val low = lowQueue.dequeue() + val high = highQueue.dequeue() + val value = (high << baseWidth) + low + assert(inQueue.dequeue() == value) + } + } + + val driver = StreamDriver(dut.input, dut.clockDomain) { p => + true + } + val inMonitor = StreamMonitor(dut.input, dut.clockDomain) { p => + inQueue.enqueue(p.toBigInt) + check() + } + + val ready = StreamReadyRandomizer(dut.output, dut.clockDomain) + val outMonitor = StreamMonitor(dut.output, dut.clockDomain) { p => + if (lowQueue.length > highQueue.length){ + lowQueue.enqueue(p.toBigInt) + } else { + highQueue.enqueue(p.toBigInt) + } + check() + } + + dut.clockDomain.waitSampling(10000) + simSuccess() + } + } + + test("test2xOutWithNegPadding") { + //Compile the simulator + val baseWidth = 16 + val extraWidth = -2 + val compiled = SimConfig.allOptimisation.compile(rtl = new Component{ + val input = slave Stream(UInt(baseWidth bits)) + val output = master Stream(UInt(baseWidth*2+extraWidth bits)) + val rtl = StreamWidthAdapter(input, output, padding=true) + } + ) + + //Run the simulation + compiled.doSimUntilVoid { dut => + val queueModel = mutable.Queue[BigInt]() + + SimTimeout(1000000 * 8) + dut.clockDomain.forkStimulus(2) + + val driver = StreamDriver(dut.input, dut.clockDomain) { _ => + true + } + val inMonitor = StreamMonitor(dut.input, dut.clockDomain) { p => + queueModel.enqueue(p.toBigInt) + } + + val ready = StreamReadyRandomizer(dut.output, dut.clockDomain) + val outMonitor = StreamMonitor(dut.output, dut.clockDomain) { p => + assert(queueModel.nonEmpty) + val low = queueModel.dequeue() + assert(queueModel.nonEmpty) + val high = queueModel.dequeue() + val mask = ((BigInt(1) << dut.output.payload.getBitsWidth) - 1) + val value = ((high << baseWidth) + low) & mask + assert(p.toBigInt == value) + } + + dut.clockDomain.waitSampling(10000) + simSuccess() + } + } + + test("test2xInWithNegPadding") { + //Compile the simulator + val baseWidth = 16 + val extraWidth = -2 + val compiled = SimConfig.allOptimisation.compile(rtl = new Component{ + val input = slave Stream(UInt(baseWidth*2+extraWidth bits)) + val output = master Stream(UInt(baseWidth bits)) + val rtl = StreamWidthAdapter(input, output, padding=true) + } + ) + + //Run the simulation + compiled.doSimUntilVoid { dut => + val inQueue = mutable.Queue[BigInt]() + val lowQueue = mutable.Queue[BigInt]() + val highQueue = mutable.Queue[BigInt]() + + SimTimeout(1000000 * 8) + dut.clockDomain.forkStimulus(2) + def check(){ + if(inQueue.nonEmpty && lowQueue.nonEmpty && highQueue.nonEmpty){ + val low = lowQueue.dequeue() + val high = highQueue.dequeue() + val value = (high << baseWidth) + low + assert(inQueue.dequeue() == value) + } + } + + val driver = StreamDriver(dut.input, dut.clockDomain) { p => + true + } + val inMonitor = StreamMonitor(dut.input, dut.clockDomain) { p => + inQueue.enqueue(p.toBigInt) + check() + } + + val ready = StreamReadyRandomizer(dut.output, dut.clockDomain) + val outMonitor = StreamMonitor(dut.output, dut.clockDomain) { p => + if (lowQueue.length <= highQueue.length){ + lowQueue.enqueue(p.toBigInt) + } else { + highQueue.enqueue(p.toBigInt) + } + check() + } + + dut.clockDomain.waitSampling(10000) + simSuccess() + } + } + + test("test2xInWithPosPadding") { + //Compile the simulator + val baseWidth = 16 + val extraWidth = 2 + val compiled = SimConfig.allOptimisation.compile(rtl = new Component{ + val input = slave Stream(UInt(baseWidth*2+extraWidth bits)) + val output = master Stream(UInt(baseWidth bits)) + val rtl = StreamWidthAdapter(input, output, padding=true) + } + ) + + //Run the simulation + compiled.doSimUntilVoid { dut => + val inQueue = mutable.Queue[BigInt]() + val lowQueue = mutable.Queue[BigInt]() + val midQueue = mutable.Queue[BigInt]() + val highQueue = mutable.Queue[BigInt]() + + SimTimeout(1000000 * 8) + dut.clockDomain.forkStimulus(2) + def check(){ + if(inQueue.nonEmpty && lowQueue.nonEmpty && midQueue.nonEmpty && highQueue.nonEmpty){ + val low = lowQueue.dequeue() + val mid = midQueue.dequeue() + val high = highQueue.dequeue() + val value = (high << baseWidth*2) + (mid << baseWidth) + low + assert(inQueue.dequeue() == value) + } + } + + val driver = StreamDriver(dut.input, dut.clockDomain) { p => + true + } + val inMonitor = StreamMonitor(dut.input, dut.clockDomain) { p => + inQueue.enqueue(p.toBigInt) + check() + } + + val ready = StreamReadyRandomizer(dut.output, dut.clockDomain) + val outMonitor = StreamMonitor(dut.output, dut.clockDomain) { p => + if (lowQueue.isEmpty || lowQueue.length < midQueue.length){ + lowQueue.enqueue(p.toBigInt) + } else if (midQueue.isEmpty || midQueue.length < highQueue.length){ + midQueue.enqueue(p.toBigInt) + } else { + highQueue.enqueue(p.toBigInt) + } + check() + } + + dut.clockDomain.waitSampling(10000) + simSuccess() + } + } + + test("test2xOutWithPosPadding") { + //Compile the simulator + val baseWidth = 16 + val extraWidth = 2 + val compiled = SimConfig.allOptimisation.compile(rtl = new Component{ + val input = slave Stream(UInt(baseWidth bits)) + val output = master Stream(UInt(baseWidth*2+extraWidth bits)) + val rtl = StreamWidthAdapter(input, output, padding=true) + } + ) + + //Run the simulation + compiled.doSimUntilVoid { dut => + val queueModel = mutable.Queue[BigInt]() + + SimTimeout(1000000 * 8) + dut.clockDomain.forkStimulus(2) + + val driver = StreamDriver(dut.input, dut.clockDomain) { _ => + true + } + val inMonitor = StreamMonitor(dut.input, dut.clockDomain) { p => + queueModel.enqueue(p.toBigInt) + } + + val ready = StreamReadyRandomizer(dut.output, dut.clockDomain) + val outMonitor = StreamMonitor(dut.output, dut.clockDomain) { p => + assert(queueModel.nonEmpty) + val low = queueModel.dequeue() + assert(queueModel.nonEmpty) + val mid = queueModel.dequeue() + assert(queueModel.nonEmpty) + val high = queueModel.dequeue() + val mask = ((BigInt(1) << dut.output.payload.getBitsWidth) - 1) + val value = ((high << baseWidth*2) + (mid << baseWidth) + low) & mask + assert(p.toBigInt == value) + } + + dut.clockDomain.waitSampling(10000) + simSuccess() + } + } + + test("test2xOutHighFirstPadding") { + //Compile the simulator + val baseWidth = 32 + val extraWidth = -2 + val compiled = SimConfig.allOptimisation.compile(rtl = new Component{ + val input = slave Stream(UInt(baseWidth bits)) + val output = master Stream(UInt(baseWidth*2+extraWidth bits)) + val rtl = StreamWidthAdapter(input, output, order = HIGHER_FIRST, padding=true) + } + ) + + //Run the simulation + compiled.doSimUntilVoid { dut => + val queueModel = mutable.Queue[BigInt]() + + SimTimeout(1000000 * 8) + dut.clockDomain.forkStimulus(2) + + val driver = StreamDriver(dut.input, dut.clockDomain) { _ => + true + } + val inMonitor = StreamMonitor(dut.input, dut.clockDomain) { p => + queueModel.enqueue(p.toBigInt) + } + + val ready = StreamReadyRandomizer(dut.output, dut.clockDomain) + val outMonitor = StreamMonitor(dut.output, dut.clockDomain) { p => + assert(queueModel.nonEmpty) + val high = queueModel.dequeue() + assert(queueModel.nonEmpty) + val low = queueModel.dequeue() + val mask = ((BigInt(1) << dut.output.payload.getBitsWidth) - 1) + val value = ((high << baseWidth) + low) & mask + assert(p.toBigInt == value) + } + + dut.clockDomain.waitSampling(10000) + simSuccess() + } + } + + test("test2xInHighFirstPadding") { + //Compile the simulator + val baseWidth = 32 + val extraWidth = -2 + val compiled = SimConfig.allOptimisation.compile(rtl = new Component{ + val input = slave Stream(UInt(baseWidth*2+extraWidth bits)) + val output = master Stream(UInt(baseWidth bits)) + val rtl = StreamWidthAdapter(input, output, order = HIGHER_FIRST, padding=true) + } + ) + + //Run the simulation + compiled.doSimUntilVoid { dut => + val inQueue = mutable.Queue[BigInt]() + val lowQueue = mutable.Queue[BigInt]() + val highQueue = mutable.Queue[BigInt]() + + SimTimeout(1000000 * 8) + dut.clockDomain.forkStimulus(2) + def check(){ + if(inQueue.nonEmpty && lowQueue.nonEmpty && highQueue.nonEmpty){ + val low = lowQueue.dequeue() + val high = highQueue.dequeue() + val mask = ((BigInt(1) << dut.output.payload.getBitsWidth) - 1) + val value = ((high << baseWidth) + low) & mask + assert(inQueue.dequeue() == value) + } + } + + val driver = StreamDriver(dut.input, dut.clockDomain) { p => + true + } + val inMonitor = StreamMonitor(dut.input, dut.clockDomain) { p => + inQueue.enqueue(p.toBigInt) + check() + } + + val ready = StreamReadyRandomizer(dut.output, dut.clockDomain) + val outMonitor = StreamMonitor(dut.output, dut.clockDomain) { p => + if (lowQueue.length > highQueue.length){ + lowQueue.enqueue(p.toBigInt) + } else { + highQueue.enqueue(p.toBigInt) + } + check() + } + + dut.clockDomain.waitSampling(10000) + simSuccess() + } + } +} + +class SpinalSimStreamExtenderTester extends SpinalSimFunSuite { + def prepare( + dut: StreamTransactionExtender[UInt, UInt], + alwaysInput: Boolean = false, + alwaysOutput: Boolean = false, + inQueue: mutable.Queue[BigInt], + outQueue: mutable.Queue[BigInt], + countQueue: mutable.Queue[BigInt], + lastQueue: mutable.Queue[Boolean] + ) { + dut.clockDomain.forkStimulus(period = 10) + dut.io.input.valid #= false + + if (alwaysOutput) { + dut.io.output.ready #= true + } else { + val randomReady = StreamReadyRandomizer(dut.io.output, dut.clockDomain) + } + + val driver = StreamDriver(dut.io.input, dut.clockDomain) { payload => + if (inQueue.nonEmpty) { + payload #= inQueue.dequeue() + dut.io.count #= countQueue.dequeue() + true + } else { + false + } + } + driver.transactionDelay = () => { + if (!alwaysInput) { + val x = Random.nextDouble() + (x * x * 10).toInt + } else { + 0 + } + } + + val monitor = StreamMonitor(dut.io.output, dut.clockDomain) { payload => + { + val address = outQueue.dequeue() + val last = lastQueue.dequeue() + // println("##pop out queue:" + address.toString(16)) + val data = payload.toBigInt + assert((data >> 1) == address) + assert(((data & 1) == 1) == last) + } + } + + for (j <- 0 until 10000) { + val count = Random.nextInt(20) + val address = Random.nextInt(0xffffff) + + inQueue.enqueue(address) + countQueue.enqueue(count) + + for (i <- 0 to count) { + outQueue.enqueue(address) + lastQueue.enqueue(i == count) + } + } + } + + test("testRandomInOut") { + val lastQueue = mutable.Queue[Boolean]() + val compiled = SimConfig.allOptimisation.compile { + val dut = new StreamTransactionExtender( + UInt(32 bits), + UInt(33 bits), + 12, + false, + (id, payload: UInt, last) => payload @@ last + ) + dut + } + compiled.doSimUntilVoid { dut => + val inQueue = mutable.Queue[BigInt]() + val outQueue = mutable.Queue[BigInt]() + val countQueue = mutable.Queue[BigInt]() + prepare(dut, false, false, inQueue, outQueue, countQueue, lastQueue) + dut.clockDomain.waitSampling((1 KiB).toInt) + simSuccess() + } + } + + test("testRandomIn") { + val lastQueue = mutable.Queue[Boolean]() + val compiled = SimConfig.allOptimisation.compile { + val dut = new StreamTransactionExtender( + UInt(32 bits), + UInt(33 bits), + 12, + false, + (id, payload: UInt, last) => payload @@ last + ) + dut + } + compiled.doSimUntilVoid { dut => + val inQueue = mutable.Queue[BigInt]() + val outQueue = mutable.Queue[BigInt]() + val countQueue = mutable.Queue[BigInt]() + prepare(dut, false, true, inQueue, outQueue, countQueue, lastQueue) + dut.clockDomain.waitSampling((1 KiB).toInt) + simSuccess() + } + } + + test("testRandomOut") { + val lastQueue = mutable.Queue[Boolean]() + val compiled = SimConfig.allOptimisation.compile { + val dut = new StreamTransactionExtender( + UInt(32 bits), + UInt(33 bits), + 12, + false, + (id, payload: UInt, last) => payload @@ last + ) + dut + } + compiled.doSimUntilVoid { dut => + val inQueue = mutable.Queue[BigInt]() + val outQueue = mutable.Queue[BigInt]() + val countQueue = mutable.Queue[BigInt]() + prepare(dut, true, false, inQueue, outQueue, countQueue, lastQueue) + dut.clockDomain.waitSampling((1 KiB).toInt) + simSuccess() + } + } + + test("testFullPipeline") { + val lastQueue = mutable.Queue[Boolean]() + val compiled = SimConfig.allOptimisation.compile { + val dut = new StreamTransactionExtender( + UInt(32 bits), + UInt(33 bits), + 12, + false, + (id, payload: UInt, last) => payload @@ last + ) + dut + } + compiled.doSimUntilVoid { dut => + val inQueue = mutable.Queue[BigInt]() + val outQueue = mutable.Queue[BigInt]() + val countQueue = mutable.Queue[BigInt]() + prepare(dut, true, true, inQueue, outQueue, countQueue, lastQueue) + dut.clockDomain.waitSampling((1 KiB).toInt) + simSuccess() + } + } +} + +class SpinalSimStreamFifoCCTester extends SpinalSimFunSuite { + +// onlyVerilator() + + def testbench(dut : StreamFifoCC[Bits]): Unit ={ + val queueModel = mutable.Queue[Long]() + + //Push data randomly and fill the queueModel with pushed transactions + val pushThread = fork{ + while(true){ + dut.io.push.valid.randomize() + dut.io.push.payload.randomize() + dut.pushClock.waitSampling() + if(dut.io.push.valid.toBoolean && dut.io.push.ready.toBoolean){ + queueModel.enqueue(dut.io.push.payload.toLong) + } + } + } + + //Pop data randomly and check that it match with the queueModel + val popThread = fork{ + dut.io.pop.ready #= false + dut.pushClock.waitSampling() + dut.popClock.waitSampling() + for(repeat <- 0 until 10000){ + dut.io.pop.ready.randomize() + dut.popClock.waitSampling() + if(dut.io.pop.valid.toBoolean && dut.io.pop.ready.toBoolean){ + assert(dut.io.pop.payload.toLong == queueModel.dequeue()) + } + } + simSuccess() + } + } + + for(pushResetLevel <- List(LOW, HIGH); + popResetLevel <- List(LOW, HIGH); + popResetEnable <- List(false, true)) { + val postfix = s"${pushResetLevel}_${popResetLevel}_${popResetEnable}" + test("testAsyncReset_" + postfix) { + //Compile the simulator + val compiled = SimConfig.allOptimisation.compile( + rtl = new StreamFifoCC( + dataType = Bits(32 bits), + depth = 32, + pushClock = ClockDomain.external("clkA", config = ClockDomainConfig(resetActiveLevel = pushResetLevel)), + popClock = ClockDomain.external("clkB", withReset = popResetEnable, config = ClockDomainConfig(resetActiveLevel = popResetLevel)), + withPopBufferedReset = !popResetEnable + ) + ) + + //Run the simulation + compiled.doSimUntilVoid { dut => + fork { + //Clear clock domains signals, to be sure the simulation capture their first edge. + dut.pushClock.fallingEdge() + dut.popClock.fallingEdge() + dut.pushClock.deassertReset() + if(popResetEnable) dut.popClock.deassertReset() + sleep(0) + + //Do the resets + dut.pushClock.assertReset() + if(popResetEnable)dut.popClock.assertReset() + sleep(10) + dut.pushClock.deassertReset() + if(popResetEnable)dut.popClock.deassertReset() + sleep(1) + + //Forever, randomly toggle one of the clocks (will create asynchronous clocks without fixed frequencies) + while (true) { + if (Random.nextBoolean()) { + dut.pushClock.clockToggle() + } else { + dut.popClock.clockToggle() + } + sleep(1) + } + } + testbench(dut) + } + } + + test("testSyncReset_" + postfix) { + //Compile the simulator + val compiled = SimConfig.withConfig(SpinalConfig(defaultConfigForClockDomains = ClockDomainConfig(resetKind = SYNC))).allOptimisation.compile( + rtl = new StreamFifoCC( + dataType = Bits(32 bits), + depth = 32, + pushClock = ClockDomain.external("clkA", config = ClockDomainConfig(resetActiveLevel = pushResetLevel)), + popClock = ClockDomain.external("clkB", withReset = popResetEnable, config = ClockDomainConfig(resetActiveLevel = popResetLevel)), + withPopBufferedReset = !popResetEnable + ) + ) + + //Run the simulation + compiled.doSimUntilVoid { dut => + dut.pushClock.fallingEdge() + dut.popClock.fallingEdge() + dut.pushClock.deassertReset() + if(popResetEnable) dut.popClock.deassertReset() + fork { + //Clear clock domains signals, to be sure the simulation capture their first edge. + sleep(0) + + //Do the resets + dut.pushClock.assertReset() + if(popResetEnable) dut.popClock.assertReset() + sleep(10) + dut.pushClock.deassertReset() + if(popResetEnable) dut.popClock.deassertReset() + sleep(1) + } + + fork { + sleep(1) + for (i <- 0 until 5) { + dut.pushClock.clockToggle() + dut.popClock.clockToggle() + sleep(1) + } + //Forever, randomly toggle one of the clocks (will create asynchronous clocks without fixed frequencies) + while (true) { + if (Random.nextBoolean()) { + dut.pushClock.clockToggle() + } else { + dut.popClock.clockToggle() + } + sleep(1) + } + } + testbench(dut) + } + } + } + + test("testBootReset") { + //Compile the simulator + val compiled = SimConfig.withConfig(SpinalConfig(defaultConfigForClockDomains = ClockDomainConfig(resetKind = BOOT))).allOptimisation.compile( + rtl = new StreamFifoCC( + dataType = Bits(32 bits), + depth = 32, + pushClock = ClockDomain.external("clkA"), + popClock = ClockDomain.external("clkB", withReset = false) + ) + ) + + //Run the simulation + compiled.doSimUntilVoid { dut => + fork { + dut.pushClock.fallingEdge() + dut.popClock.fallingEdge() + sleep(1) + //Forever, randomly toggle one of the clocks (will create asynchronous clocks without fixed frequencies) + while (true) { + if (Random.nextBoolean()) { + dut.pushClock.clockToggle() + } else { + dut.popClock.clockToggle() + } + sleep(1) + } + } + testbench(dut) + } + } +} + + +object TesterBugPlay extends App{ + + def testbench(dut : StreamFifoCC[Bits]): Unit ={ + val queueModel = mutable.Queue[Long]() + + //Push data randomly and fill the queueModel with pushed transactions + val pushThread = fork{ + while(true){ + dut.io.push.valid.randomize() + dut.io.push.payload.randomize() + dut.pushClock.waitSampling() + if(dut.io.push.valid.toBoolean && dut.io.push.ready.toBoolean){ + queueModel.enqueue(dut.io.push.payload.toLong) + } + } + } + + //Pop data randomly and check that it match with the queueModel + val popThread = fork{ + for(repeat <- 0 until 10000){ + dut.io.pop.ready.randomize() + dut.popClock.waitSampling() + if(dut.io.pop.valid.toBoolean && dut.io.pop.ready.toBoolean){ + assert(dut.io.pop.payload.toLong == queueModel.dequeue()) + } + } + simSuccess() + } + } + val compiled = SimConfig.withIVerilog.withConfig(SpinalConfig(defaultConfigForClockDomains = ClockDomainConfig(resetKind = SYNC))).allOptimisation.compile( + rtl = new StreamFifoCC( + dataType = Bits(32 bits), + depth = 32, + pushClock = ClockDomain.external("clkA"), + popClock = ClockDomain.external("clkB", withReset = false) + ) + ) + + for(i <- 132 until 1000) { + + //Run the simulation + compiled.doSimUntilVoid(seed = i) { dut => + dut.pushClock.fallingEdge() + dut.popClock.fallingEdge() + dut.pushClock.deassertReset() +// dut.popClock.deassertReset() + fork { + //Clear clock domains signals, to be sure the simulation capture their first edge. + sleep(0) + + //Do the resets + dut.pushClock.assertReset() +// dut.popClock.assertReset() + sleep(10) + dut.pushClock.deassertReset() +// dut.popClock.deassertReset() + sleep(1) + } + + fork { + sleep(1) + for(i <- 0 until 5) { + dut.pushClock.clockToggle() + dut.popClock.clockToggle() + sleep(1) + } + //Forever, randomly toggle one of the clocks (will create asynchronous clocks without fixed frequencies) + while (true) { + if (Random.nextBoolean()) { + dut.pushClock.clockToggle() + } else { + dut.popClock.clockToggle() + } + sleep(1) + } + } + testbench(dut) + } + } +} + +class SpinalSimStreamFifoMultiChannelSharedSpaceTester extends AnyFunSuite { + test("t1") { + SimConfig.compile(new StreamFifoMultiChannelSharedSpace(Bits(32 bits), 4, 16)).doSimUntilVoid(seed = 42) { dut => + val queueModel = mutable.ArrayBuffer.fill(4)(mutable.Queue[Long]()) + + SimTimeout(1000000) + dut.clockDomain.forkStimulus(2) + //Push data randomly and fill the queueModel with pushed transactions + dut.io.push.stream.valid #= false + dut.io.pop.stream.ready #= true + + val successCount = Array.fill(4)(0) + dut.clockDomain.onSamplings { + assert(!(dut.io.push.full.toBoolean && (dut.io.availability.toInt > 1))) + + if (dut.io.push.stream.valid.toBoolean && dut.io.push.stream.ready.toBoolean) { + queueModel(log2Up(dut.io.push.channel.toInt)).enqueue(dut.io.push.stream.payload.toLong) + } + if (dut.io.pop.stream.valid.toBoolean && dut.io.pop.stream.ready.toBoolean) { + val channel = log2Up(dut.io.pop.channel.toInt) + assert(dut.io.pop.stream.payload.toLong == queueModel(channel).dequeue()) + successCount(channel) += 1 + if (successCount.forall(_ > 20000)) simSuccess() + } + dut.io.push.stream.valid.randomize() + dut.io.push.stream.payload.randomize() + dut.io.push.channel #= (1 << Random.nextInt(dut.channelCount)) + dut.io.pop.stream.ready.randomize() + dut.io.pop.channel #= (1 << Random.nextInt(dut.channelCount)) + } + } + } +} + +class SpinalSimStreamFifoTester extends SpinalSimFunSuite { + test("testBits") { + //Compile the simulator + val compiled = SimConfig.allOptimisation.compile( + rtl = new StreamFifo( + dataType = Bits(32 bits), + depth = 32 + ) + ) + + //Run the simulation + compiled.doSimUntilVoid { dut => + val queueModel = mutable.Queue[Long]() + + SimTimeout(1000000 * 8) + dut.clockDomain.forkStimulus(2) + + dut.io.flush #= false + + //Push data randomly and fill the queueModel with pushed transactions + dut.io.push.valid #= false + dut.clockDomain.onSamplings { + if (dut.io.push.valid.toBoolean && dut.io.push.ready.toBoolean) { + queueModel.enqueue(dut.io.push.payload.toLong) + } + dut.io.push.valid.randomize() + dut.io.push.payload.randomize() + } + + //Pop data randomly and check that it match with the queueModel + val popThread = fork { + dut.io.pop.ready #= true + for (repeat <- 0 until 10000) { + dut.io.pop.ready.randomize() + dut.clockDomain.waitSampling() + if (dut.io.pop.valid.toBoolean && dut.io.pop.ready.toBoolean) { + assert(dut.io.pop.payload.toLong == queueModel.dequeue()) + } + } + simSuccess() + } + } + } + + + test("testOne") { + //Compile the simulator + val compiled = SimConfig.allOptimisation.compile( + rtl = new StreamFifo( + dataType = Bits(32 bits), + depth = 1 + ) + ) + + //Run the simulation + compiled.doSimUntilVoid { dut => + val queueModel = mutable.Queue[Long]() + + SimTimeout(1000000 * 8) + dut.clockDomain.forkStimulus(2) + + dut.io.flush #= false + + //Push data randomly and fill the queueModel with pushed transactions + dut.io.push.valid #= false + dut.clockDomain.onSamplings { + if (dut.io.push.valid.toBoolean && dut.io.push.ready.toBoolean) { + queueModel.enqueue(dut.io.push.payload.toLong) + } + dut.io.push.valid.randomize() + dut.io.push.payload.randomize() + } + + //Pop data randomly and check that it match with the queueModel + val popThread = fork { + dut.io.pop.ready #= true + for (repeat <- 0 until 10000) { + dut.io.pop.ready.randomize() + dut.clockDomain.waitSampling() + if (dut.io.pop.valid.toBoolean && dut.io.pop.ready.toBoolean) { + assert(dut.io.pop.payload.toLong == queueModel.dequeue()) + } + } + simSuccess() + } + } + } + + + test("testBundle") { + //Bundle used as fifo payload + case class Transaction() extends Bundle { + val flag = Bool() + val data = Bits(8 bits) + val color = Rgb(5, 6, 5) + + override def clone = Transaction() + } + + val compiled = SimConfig.allOptimisation.compile( + rtl = new StreamFifo( + dataType = Transaction(), + depth = 32 + ) + ) + + //Run the simulation + compiled.doSim { dut => + //Inits + SimTimeout(1000000 * 8) + dut.clockDomain.forkStimulus(2) + dut.clockDomain.forkSimSpeedPrinter() + dut.io.flush #= false + + val scoreboard = ScoreboardInOrder[SimData]() + + //Drivers + StreamDriver(dut.io.push, dut.clockDomain) { payload => + payload.randomize() + true + } + StreamReadyRandomizer(dut.io.pop, dut.clockDomain) + + //Monitors + StreamMonitor(dut.io.push, dut.clockDomain) { payload => + scoreboard.pushRef(payload) + } + StreamMonitor(dut.io.pop, dut.clockDomain) { payload => + scoreboard.pushDut(payload) + } + + waitUntil(scoreboard.matches == 10000) + } + } + + test("testTwoDepth") { + //Bundle used as fifo payload + case class Transaction() extends Bundle { + val flag = Bool() + val data = Bits(8 bits) + val color = Rgb(5, 6, 5) + } + + val compiled = SimConfig.allOptimisation.compile( + rtl = new StreamFifo( + dataType = Transaction(), + depth = 2 + ) + ) + + //Run the simulation + compiled.doSim { dut => + //Inits + SimTimeout(1000000 * 8) + dut.clockDomain.forkStimulus(2) + dut.clockDomain.forkSimSpeedPrinter() + dut.io.flush #= false + + val scoreboard = ScoreboardInOrder[SimData]() + + //Drivers + StreamDriver(dut.io.push, dut.clockDomain) { payload => + payload.randomize() + true + } + StreamReadyRandomizer(dut.io.pop, dut.clockDomain) + + //Monitors + StreamMonitor(dut.io.push, dut.clockDomain) { payload => + scoreboard.pushRef(payload) + } + StreamMonitor(dut.io.pop, dut.clockDomain) { payload => + scoreboard.pushDut(payload) + } + + waitUntil(scoreboard.matches == 10000) + } + } + + + test("lowLatency_0") { + //Bundle used as fifo payload + case class Transaction() extends Bundle { + val flag = Bool() + val data = Bits(8 bits) + val color = Rgb(5, 6, 5) + } + + val compiled = SimConfig.allOptimisation.compile( + rtl = new StreamFifoLowLatency( + dataType = Transaction(), + depth = 2, + latency = 0 + ) + ) + + //Run the simulation + compiled.doSim { dut => + //Inits + SimTimeout(1000000 * 8) + dut.clockDomain.forkStimulus(2) + dut.clockDomain.forkSimSpeedPrinter() + dut.io.flush #= false + + val scoreboard = ScoreboardInOrder[SimData]() + + //Drivers + StreamDriver(dut.io.push, dut.clockDomain) { payload => payload.randomize(); true } + StreamReadyRandomizer(dut.io.pop, dut.clockDomain) + + //Monitors + StreamMonitor(dut.io.push, dut.clockDomain) { payload => scoreboard.pushRef(payload) } + StreamMonitor(dut.io.pop, dut.clockDomain) { payload => scoreboard.pushDut(payload) } + + waitUntil(scoreboard.matches == 10000) + } + } + + + test("lowLatency_1") { + //Bundle used as fifo payload + case class Transaction() extends Bundle { + val flag = Bool() + val data = Bits(8 bits) + val color = Rgb(5, 6, 5) + } + + val compiled = SimConfig.allOptimisation.compile( + rtl = new StreamFifoLowLatency( + dataType = Transaction(), + depth = 4, + latency = 1 + ) + ) + + //Run the simulation + compiled.doSim { dut => + //Inits + SimTimeout(1000000 * 8) + dut.clockDomain.forkStimulus(2) + dut.clockDomain.forkSimSpeedPrinter() + dut.io.flush #= false + + val scoreboard = ScoreboardInOrder[SimData]() + + //Drivers + StreamDriver(dut.io.push, dut.clockDomain) { payload => payload.randomize(); true } + StreamReadyRandomizer(dut.io.pop, dut.clockDomain) + + //Monitors + StreamMonitor(dut.io.push, dut.clockDomain) { payload => scoreboard.pushRef(payload) } + StreamMonitor(dut.io.pop, dut.clockDomain) { payload => scoreboard.pushDut(payload) } + + waitUntil(scoreboard.matches == 10000) + } + } +} diff --git a/tester/src/test/scala/spinal/tester/scalatest/FormalHistoryTester.scala b/lib/src/test/scala/spinal/lib/Utils.scala similarity index 50% rename from tester/src/test/scala/spinal/tester/scalatest/FormalHistoryTester.scala rename to lib/src/test/scala/spinal/lib/Utils.scala index 6134c2237c..7853fc67e9 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/FormalHistoryTester.scala +++ b/lib/src/test/scala/spinal/lib/Utils.scala @@ -1,10 +1,14 @@ -package spinal.tester.scalatest +package spinal.lib import spinal.core._ +import spinal.core.sim._ import spinal.core.formal._ -import spinal.lib._ import spinal.lib.formal._ +import spinal.tester.SpinalTesterCocotbBase +import org.scalatest.funsuite.AnyFunSuite +import scala.util.Random + class FormalHistoryModifyableTester extends SpinalFormalFunSuite { test("pop_any") { FormalConfig @@ -90,3 +94,120 @@ class FormalHistoryModifyableTester extends SpinalFormalFunSuite { }) } } + +class SpinalSimLibTester extends AnyFunSuite { + for (bitCount <- 0 until 12) { + test("CountOnes" + bitCount) { + LutInputs(Random.nextInt(5) + 2).on { + SimConfig.noOptimisation + .compile(new Component { + val input = in Bits (bitCount bits) + val output = out(CountOne(input)) + }) + .doSim(seed = 42) { dut => + for (_ <- 0 until 100 + (1 << bitCount) * 4) { + dut.input.randomize() + sleep(1) + assert(dut.output.toInt === dut.input.toBigInt.bitCount) + } + } + } + } + } + + for (bitCount <- 0 until 12) { + test("CountOneOnEach" + bitCount) { + SimConfig.noOptimisation + .compile(new Component { + val input = in Bits (bitCount bits) + val output = out Vec (CountOneOnEach(input)) + }) + .doSim(seed = 42) { dut => + for (_ <- 0 until 100 + (1 << bitCount) * 4) { + dut.input.randomize() + sleep(1) + val input = dut.input.toBigInt + for (i <- 0 until bitCount; mask = ((1 << i + 1) - 1)) + assert(dut.output(i).toInt === (input & mask).bitCount) + } + } + } + } +} + + +class TraversableOncePimpedTester extends AnyFunSuite { + test("reverse_by_shuffle") { + SimConfig + .compile(new Component { + val data = in port Bits(64 bits) + val outData = out port UInt(64 bits) + + val outSet = data.subdivideIn(8 bits) + + outData := outSet.shuffle(outSet.length - 1 - _).asBits.asUInt + }) + .doSim(seed = 42) { dut => + for (j <- 0 until 1000) { + val data = dut.data.randomize() + + sleep(1) + val outData = dut.outData.toBigInt + + for (i <- 0 until 8) { + val in = (data >> i * 8) & 0xff + val out = (outData >> (7 - i) * 8) & 0xff + assert(in == out) + } + } + } + } + + test("reverse_by_shuffle_with_size") { + SimConfig + .compile(new Component { + val data = in port Bits(64 bits) + val outData = out port UInt(64 bits) + + outData := U( + B(data.subdivideIn(8 bits).shuffleWithSize((n, i) => n - 1 - i)) + ) + }) + .doSim(seed = 42) { dut => + for (j <- 0 until 1000) { + val data = dut.data.randomize() + + sleep(1) + val outData = dut.outData.toBigInt + + for (i <- 0 until 8) { + val in = (data >> i * 8) & 0xff + val out = (outData >> (7 - i) * 8) & 0xff + assert(in == out) + } + } + } + } +} + +object LatencyAnalysisTester{ + import spinal.lib.math.SIntMath + + class LibTester extends Component { + val io = new Bundle { + val inSIntA = in SInt (16 bit) + val inSIntB = in SInt (16 bit) + val outSInt = out SInt (32 bit) + val outSIntRef = out SInt (32 bit) + } + io.outSInt := SIntMath.mul(io.inSIntA, io.inSIntB, 4, 0,1,(s,l) => RegNext(s)) + io.outSIntRef := Delay(io.inSIntA * io.inSIntB, LatencyAnalysis(io.inSIntA, io.outSInt)) + } +} + +class LibTesterCocotbBoot extends SpinalTesterCocotbBase { + override def getName: String = "LibTester" + override def pythonTestLocation: String = "tester/src/test/python/spinal/LibTester" + override def createToplevel: Component = new LatencyAnalysisTester.LibTester + withWaveform = true +} diff --git a/tester/src/test/scala/spinal/tester/scalatest/AhbLite3InterconnectTester.scala b/lib/src/test/scala/spinal/lib/bus/amba3/ahblite/AhbLite3CrossbarFactory.scala similarity index 94% rename from tester/src/test/scala/spinal/tester/scalatest/AhbLite3InterconnectTester.scala rename to lib/src/test/scala/spinal/lib/bus/amba3/ahblite/AhbLite3CrossbarFactory.scala index 685e01e713..652797cf3f 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/AhbLite3InterconnectTester.scala +++ b/lib/src/test/scala/spinal/lib/bus/amba3/ahblite/AhbLite3CrossbarFactory.scala @@ -1,9 +1,8 @@ -package spinal.tester.scalatest +package spinal.lib.bus.amba3.ahblite import spinal.core._ import spinal.lib._ -import spinal.lib.bus.amba3.ahblite.{AhbLite3CrossbarFactory, AhbLite3, AhbLite3Master, AhbLite3Config} - +import spinal.tester.SpinalTesterCocotbBase object AhbLite3CrossbarTester{ class AhbLite3CrossbarTester extends Component { diff --git a/tester/src/test/scala/spinal/tester/scalatest/AhbLite3OnChipRamTester.scala b/lib/src/test/scala/spinal/lib/bus/amba3/ahblite/AhbLite3OnChipRam.scala similarity index 90% rename from tester/src/test/scala/spinal/tester/scalatest/AhbLite3OnChipRamTester.scala rename to lib/src/test/scala/spinal/lib/bus/amba3/ahblite/AhbLite3OnChipRam.scala index 3eb66d45b6..131fb425bd 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/AhbLite3OnChipRamTester.scala +++ b/lib/src/test/scala/spinal/lib/bus/amba3/ahblite/AhbLite3OnChipRam.scala @@ -1,10 +1,8 @@ -package spinal.tester.scalatest +package spinal.lib.bus.amba3.ahblite import spinal.core._ import spinal.lib._ -import spinal.lib.bus.amba3.ahblite._ - - +import spinal.tester.SpinalTesterCocotbBase object AhbLite3OnChipRamTester{ class AhbLite3OnChipRamTester extends Component { diff --git a/tester/src/test/scala/spinal/tester/scalatest/BusSlaveFactoryDoubleRead.scala b/lib/src/test/scala/spinal/lib/bus/amba3/apb/Apb3SlaveFactory.scala similarity index 93% rename from tester/src/test/scala/spinal/tester/scalatest/BusSlaveFactoryDoubleRead.scala rename to lib/src/test/scala/spinal/lib/bus/amba3/apb/Apb3SlaveFactory.scala index 396965329e..662b2673e8 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/BusSlaveFactoryDoubleRead.scala +++ b/lib/src/test/scala/spinal/lib/bus/amba3/apb/Apb3SlaveFactory.scala @@ -1,12 +1,10 @@ -package spinal.tester.scalatest - +package spinal.lib.bus.amba3.apb import org.scalatest.funsuite.AnyFunSuite -import org.scalatest.{Assertions} +import org.scalatest.Assertions + import spinal.core._ import spinal.lib._ -import spinal.lib.bus.amba3.apb._ - object TestTopLevel { diff --git a/tester/src/test/scala/spinal/tester/scalatest/Axi4AdapterTester.scala b/lib/src/test/scala/spinal/lib/bus/amba4/axi/Axi4AdapterTester.scala similarity index 98% rename from tester/src/test/scala/spinal/tester/scalatest/Axi4AdapterTester.scala rename to lib/src/test/scala/spinal/lib/bus/amba4/axi/Axi4AdapterTester.scala index 2fe7e811a7..45c8638432 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/Axi4AdapterTester.scala +++ b/lib/src/test/scala/spinal/lib/bus/amba4/axi/Axi4AdapterTester.scala @@ -1,16 +1,17 @@ -package spinal.tester.scalatest +package spinal.lib.bus.amba4.axi + +import scala.collection.mutable +import scala.util.Random import spinal.core._ import spinal.core.sim._ -import org.scalatest.funsuite.AnyFunSuite -import spinal.core.sim.SimCompiled import spinal.lib.bus.amba4.axi.sim.{Axi4ReadOnlyMasterAgent, Axi4ReadOnlyMonitor, Axi4ReadOnlySlaveAgent, Axi4WriteOnlyMasterAgent, Axi4WriteOnlyMonitor, Axi4WriteOnlySlaveAgent} -import spinal.lib.bus.amba4.axi.{Axi4, Axi4Config, Axi4ReadOnly, Axi4ReadOnlyDownsizer, Axi4ReadOnlyIdRemover, Axi4ReadOnlyUpsizer, Axi4SharedIdRemover, Axi4WriteOnly, Axi4WriteOnlyDownsizer, Axi4WriteOnlyIdRemover, Axi4WriteOnlyUpsizer} import spinal.lib.bus.misc.SizeMapping import spinal.lib.{master, slave} -import scala.collection.mutable -import scala.util.Random +import spinal.tester.SpinalTesterCocotbBase + +import org.scalatest.funsuite.AnyFunSuite class Axi4UpsizerTester extends AnyFunSuite { diff --git a/tester/src/test/scala/spinal/tester/scalatest/Axi4InterconnectTester2.scala b/lib/src/test/scala/spinal/lib/bus/amba4/axi/Axi4CrossbarFactory.scala similarity index 66% rename from tester/src/test/scala/spinal/tester/scalatest/Axi4InterconnectTester2.scala rename to lib/src/test/scala/spinal/lib/bus/amba4/axi/Axi4CrossbarFactory.scala index 7a32e1228f..0f989ee342 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/Axi4InterconnectTester2.scala +++ b/lib/src/test/scala/spinal/lib/bus/amba4/axi/Axi4CrossbarFactory.scala @@ -1,9 +1,40 @@ -package spinal.tester.scalatest +package spinal.lib.bus.amba4.axi import spinal.core._ import spinal.lib._ -import spinal.lib.bus.amba4.axi._ -import scala.collection.Seq + +import spinal.tester.SpinalTesterCocotbBase + +object Axi4CrossbarTester{ + class Axi4CrossbarTester extends Component { + val axiMasterConfig = Axi4Config(addressWidth = 13,dataWidth = 32,idWidth = 4) + val axiSlaveConfig = Axi4Config(addressWidth = 13,dataWidth = 32,idWidth = 6) + + val axiMasters = Vec(slave(Axi4(axiMasterConfig)),3) + val axiSlaves = Vec(master(Axi4(axiSlaveConfig)),4) + + val crossbarFactory = Axi4CrossbarFactory() + .addSlaves( + axiSlaves(0) -> (0x000,0x400), + axiSlaves(1) -> (0x400,0x400), + axiSlaves(2) -> (0x800,0x400), + axiSlaves(3) -> (0xC00,0x400) + ) + .addConnections( + axiMasters(0) -> List(axiSlaves(1),axiSlaves(2),axiSlaves(3)), + axiMasters(1) -> List(axiSlaves(0),axiSlaves(2),axiSlaves(3)), + axiMasters(2) -> List(axiSlaves(0),axiSlaves(1),axiSlaves(3)) + ) + + val readCrossbar = crossbarFactory.build() + } +} + +class Axi4CrossbarTesterCocotbBoot extends SpinalTesterCocotbBase { + override def getName: String = "Axi4CrossbarTester" + override def pythonTestLocation: String = "tester/src/test/python/spinal/Axi4CrossbarTester" + override def createToplevel: Component = new Axi4CrossbarTester.Axi4CrossbarTester +} object Axi4CrossbarTester2{ class Axi4CrossbarTester2 extends Component { @@ -53,4 +84,4 @@ class Axi4CrossbarTester2CocotbBoot extends SpinalTesterCocotbBase { override def pythonTestLocation: String = "tester/src/test/python/spinal/Axi4CrossbarTester2" override def createToplevel: Component = new Axi4CrossbarTester2.Axi4CrossbarTester2 override def backendConfig(config: SpinalConfig): SpinalConfig = super.backendConfig(config) -} \ No newline at end of file +} diff --git a/tester/src/test/scala/spinal/tester/scalatest/FormalAxi4DownsizerTester.scala b/lib/src/test/scala/spinal/lib/bus/amba4/axi/Axi4Downsizer.scala similarity index 99% rename from tester/src/test/scala/spinal/tester/scalatest/FormalAxi4DownsizerTester.scala rename to lib/src/test/scala/spinal/lib/bus/amba4/axi/Axi4Downsizer.scala index 8d92b9c419..08864b84fa 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/FormalAxi4DownsizerTester.scala +++ b/lib/src/test/scala/spinal/lib/bus/amba4/axi/Axi4Downsizer.scala @@ -1,10 +1,9 @@ -package spinal.tester.scalatest +package spinal.lib.bus.amba4.axi import spinal.core._ import spinal.core.formal._ import spinal.lib._ import spinal.lib.formal._ -import spinal.lib.bus.amba4.axi._ object Util { def size2Ratio(size: UInt): UInt = { diff --git a/lib/src/test/scala/spinal/lib/bus/amba4/axi/Axi4SharedOnChipRam.scala b/lib/src/test/scala/spinal/lib/bus/amba4/axi/Axi4SharedOnChipRam.scala new file mode 100644 index 0000000000..6b2260fd78 --- /dev/null +++ b/lib/src/test/scala/spinal/lib/bus/amba4/axi/Axi4SharedOnChipRam.scala @@ -0,0 +1,10 @@ +package spinal.lib.bus.amba4.axi + +import spinal.tester.SpinalTesterCocotbBase + +class Axi4SharedOnChipRamTester extends SpinalTesterCocotbBase { + override def getName = "Axi4SharedOnChipRamTester" + override def pythonTestLocation = "tester/src/test/python/spinal/Axi4SharedOnChipRamTester" + override def createToplevel = Axi4SharedOnChipRam(32, 4096, 4).setDefinitionName(getName) + override def noVhdl = true +} diff --git a/tester/src/test/scala/spinal/tester/scalatest/Axi4SharedOnChipRamTester.scala b/lib/src/test/scala/spinal/lib/bus/amba4/axi/Axi4SharedOnChipRamMultiPort.scala similarity index 94% rename from tester/src/test/scala/spinal/tester/scalatest/Axi4SharedOnChipRamTester.scala rename to lib/src/test/scala/spinal/lib/bus/amba4/axi/Axi4SharedOnChipRamMultiPort.scala index ef5ac77760..dfa04f4eee 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/Axi4SharedOnChipRamTester.scala +++ b/lib/src/test/scala/spinal/lib/bus/amba4/axi/Axi4SharedOnChipRamMultiPort.scala @@ -5,14 +5,6 @@ import spinal.core._ import spinal.lib._ import spinal.lib.bus.amba4.axi._ - -class Axi4SharedOnChipRamTester extends SpinalTesterCocotbBase { - override def getName: String = "Axi4SharedOnChipRamTester" - override def pythonTestLocation: String = "tester/src/test/python/spinal/Axi4SharedOnChipRamTester" - override def createToplevel: Component = Axi4SharedOnChipRam(32,4096,4).setDefinitionName(getName) - override def noVhdl = true -} - import scala.collection.mutable import scala.util.Random import org.scalatest.funsuite.AnyFunSuite diff --git a/tester/src/test/scala/spinal/tester/scalatest/Axi4SlaveFactoryTester.scala b/lib/src/test/scala/spinal/lib/bus/amba4/axi/Axi4SlaveFactory.scala similarity index 91% rename from tester/src/test/scala/spinal/tester/scalatest/Axi4SlaveFactoryTester.scala rename to lib/src/test/scala/spinal/lib/bus/amba4/axi/Axi4SlaveFactory.scala index 35418196e9..725238f252 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/Axi4SlaveFactoryTester.scala +++ b/lib/src/test/scala/spinal/lib/bus/amba4/axi/Axi4SlaveFactory.scala @@ -1,8 +1,9 @@ -package spinal.tester.scalatest +package spinal.lib.bus.amba4.axi import spinal.core._ import spinal.lib._ -import spinal.lib.bus.amba4.axi.{Axi4, Axi4Config, Axi4SlaveFactory} + +import spinal.tester.SpinalTesterCocotbBase object Axi4SlaveFactoryTester { def axi4Config = Axi4Config( diff --git a/tester/src/test/scala/spinal/tester/scalatest/Axi4UnburstTester.scala b/lib/src/test/scala/spinal/lib/bus/amba4/axi/Axi4Unburster.scala similarity index 98% rename from tester/src/test/scala/spinal/tester/scalatest/Axi4UnburstTester.scala rename to lib/src/test/scala/spinal/lib/bus/amba4/axi/Axi4Unburster.scala index 90823de1b0..2d2c49063b 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/Axi4UnburstTester.scala +++ b/lib/src/test/scala/spinal/lib/bus/amba4/axi/Axi4Unburster.scala @@ -1,8 +1,9 @@ -package spinal.tester.scalatest +package spinal.lib.bus.amba4.axi import org.scalatest.funsuite.AnyFunSuite + import spinal.core.sim._ -import spinal.lib.bus.amba4.axi._ + import spinal.lib.bus.amba4.axi.sim.{Axi4ReadOnlyMasterAgent, Axi4ReadOnlyMonitor, Axi4ReadOnlySlaveAgent, Axi4WriteOnlyMasterAgent, Axi4WriteOnlyMonitor, Axi4WriteOnlySlaveAgent} import spinal.lib.bus.misc.SizeMapping import spinal.lib.sim.ScoreboardInOrder diff --git a/tester/src/test/scala/spinal/tester/scalatest/Axi4SimAgentTester.scala b/lib/src/test/scala/spinal/lib/bus/amba4/axi/sim/Agent.scala similarity index 96% rename from tester/src/test/scala/spinal/tester/scalatest/Axi4SimAgentTester.scala rename to lib/src/test/scala/spinal/lib/bus/amba4/axi/sim/Agent.scala index ed2aa79897..8ca49d37a2 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/Axi4SimAgentTester.scala +++ b/lib/src/test/scala/spinal/lib/bus/amba4/axi/sim/Agent.scala @@ -1,18 +1,11 @@ -package spinal.tester.scalatest +package spinal.lib.bus.amba4.axi.sim import spinal.core._ import spinal.core.sim._ + import org.scalatest.funsuite.AnyFunSuite -import spinal.core.sim.SimCompiled + import spinal.lib._ -import spinal.lib.bus.amba4.axi.sim.{ - Axi4ReadOnlyMasterAgent, - Axi4ReadOnlyMonitor, - Axi4ReadOnlySlaveAgent, - Axi4WriteOnlyMasterAgent, - Axi4WriteOnlyMonitor, - Axi4WriteOnlySlaveAgent -} import spinal.lib.bus.amba4.axi.{Axi4, Axi4Config} import spinal.lib.bus.misc.SizeMapping diff --git a/tester/src/test/scala/spinal/tester/scalatest/AxiLite4SlaveFactoryTester.scala b/lib/src/test/scala/spinal/lib/bus/amba4/axilite/AxiLite4SlaveFactory.scala similarity index 90% rename from tester/src/test/scala/spinal/tester/scalatest/AxiLite4SlaveFactoryTester.scala rename to lib/src/test/scala/spinal/lib/bus/amba4/axilite/AxiLite4SlaveFactory.scala index d848a3f5b6..b66cc3c96e 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/AxiLite4SlaveFactoryTester.scala +++ b/lib/src/test/scala/spinal/lib/bus/amba4/axilite/AxiLite4SlaveFactory.scala @@ -1,8 +1,9 @@ -package spinal.tester.scalatest +package spinal.lib.bus.amba4.axilite import spinal.core._ import spinal.lib._ -import spinal.lib.bus.amba4.axilite.{AxiLite4SlaveFactory, AxiLite4, AxiLite4Config} + +import spinal.tester.SpinalTesterCocotbBase object AxiLite4SlaveFactoryTester{ def axiLite4Config = AxiLite4Config( diff --git a/tester/src/test/scala/spinal/tester/scalatest/Axi4StreamTester.scala b/lib/src/test/scala/spinal/lib/bus/amba4/axis/Axi4Stream.scala similarity index 97% rename from tester/src/test/scala/spinal/tester/scalatest/Axi4StreamTester.scala rename to lib/src/test/scala/spinal/lib/bus/amba4/axis/Axi4Stream.scala index a0442035f8..acde93b474 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/Axi4StreamTester.scala +++ b/lib/src/test/scala/spinal/lib/bus/amba4/axis/Axi4Stream.scala @@ -1,10 +1,10 @@ -package spinal.tester.scalatest +package spinal.lib.bus.amba4.axis import org.scalatest.funsuite.AnyFunSuite + import spinal.core._ -import spinal.lib._ import spinal.core.sim._ -import spinal.lib.bus.amba4.axis._ +import spinal.lib._ case class Axi4StreamEndianFixture[T <: Data](config: Axi4StreamConfig, outType: HardType[T]) extends Component { val io = new Bundle { diff --git a/tester/src/test/scala/spinal/tester/scalatest/Axi4StreamSimpleWidthAdapterTester.scala b/lib/src/test/scala/spinal/lib/bus/amba4/axis/Axi4StreamSimpleWidthAdapter.scala similarity index 94% rename from tester/src/test/scala/spinal/tester/scalatest/Axi4StreamSimpleWidthAdapterTester.scala rename to lib/src/test/scala/spinal/lib/bus/amba4/axis/Axi4StreamSimpleWidthAdapter.scala index 0e9a9b543e..60615f31f7 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/Axi4StreamSimpleWidthAdapterTester.scala +++ b/lib/src/test/scala/spinal/lib/bus/amba4/axis/Axi4StreamSimpleWidthAdapter.scala @@ -1,14 +1,13 @@ -package spinal.tester.scalatest +package spinal.lib.bus.amba4.axis import org.scalatest.funsuite.AnyFunSuite + import spinal.core._ -import spinal.lib._ import spinal.core.sim._ -import spinal.lib.bus.amba4.axis.Axi4Stream.{Axi4Stream, Axi4StreamBundle} -import spinal.lib.bus.amba4.axis._ +import spinal.lib._ + import spinal.lib.sim.{ScoreboardInOrder, StreamDriver, StreamMonitor, StreamReadyRandomizer} -import scala.BigInt import scala.collection.mutable.ListBuffer case class Axi4StreamSimpleWidthAdapterFixture(inSize: Int, outSize: Int, useLast: Boolean = true) extends Component { @@ -80,7 +79,7 @@ class Axi4StreamSimpleWidthAdapterTester extends AnyFunSuite { } }) - def copyCheckByte(axisBundle: Axi4StreamBundle, idx: Int): Axi4CheckByte = { + def copyCheckByte(axisBundle: Axi4Stream.Axi4StreamBundle, idx: Int): Axi4CheckByte = { val data = (axisBundle.data.toBigInt >> 8*idx) & BigInt(0xFF) val strb = if (axisBundle.config.useStrb) axisBundle.strb.toBigInt.testBit(idx) else true val keep = if (axisBundle.config.useKeep) axisBundle.keep.toBigInt.testBit(idx) else true @@ -94,7 +93,7 @@ class Axi4StreamSimpleWidthAdapterTester extends AnyFunSuite { Axi4CheckByte(data = data, strb = strb, keep = keep, last = last, id = id, dest = dest, user = user) } - def streamByteTransactionMonitor(stream: Axi4Stream, clockDomain: ClockDomain)(callback: (Seq[Axi4CheckByte]) => Unit) = { + def streamByteTransactionMonitor(stream: Axi4Stream.Axi4Stream, clockDomain: ClockDomain)(callback: (Seq[Axi4CheckByte]) => Unit) = { var currentTransaction = ListBuffer[Axi4CheckByte]() StreamMonitor(stream, clockDomain)(p => { diff --git a/tester/src/test/scala/spinal/tester/scalatest/Axi4StreamWidthAdapterTester.scala b/lib/src/test/scala/spinal/lib/bus/amba4/axis/Axi4StreamWidthAdapter.scala similarity index 94% rename from tester/src/test/scala/spinal/tester/scalatest/Axi4StreamWidthAdapterTester.scala rename to lib/src/test/scala/spinal/lib/bus/amba4/axis/Axi4StreamWidthAdapter.scala index 60bee2a6d1..aa135a90bb 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/Axi4StreamWidthAdapterTester.scala +++ b/lib/src/test/scala/spinal/lib/bus/amba4/axis/Axi4StreamWidthAdapter.scala @@ -1,15 +1,14 @@ -package spinal.tester.scalatest +package spinal.lib.bus.amba4.axis + +import scala.collection.mutable.ListBuffer import org.scalatest.funsuite.AnyFunSuite + import spinal.core._ -import spinal.lib._ import spinal.core.sim._ -import spinal.lib.bus.amba4.axis.Axi4Stream.{Axi4Stream, Axi4StreamBundle} -import spinal.lib.bus.amba4.axis._ -import spinal.lib.sim.{ScoreboardInOrder, StreamDriver, StreamMonitor, StreamReadyRandomizer} +import spinal.lib._ -import scala.BigInt -import scala.collection.mutable.ListBuffer +import spinal.lib.sim.{ScoreboardInOrder, StreamDriver, StreamMonitor, StreamReadyRandomizer} case class Axi4StreamWidthAdapterFixture(inSize: Int, outSize: Int, compact: Boolean) extends Component { var inputConfig = Axi4StreamConfig(dataWidth = inSize, @@ -78,7 +77,7 @@ class Axi4StreamWidthAdapterTester extends AnyFunSuite { } }) - def copyCheckByte(axisBundle: Axi4StreamBundle, idx: Int): Axi4CheckByte = { + def copyCheckByte(axisBundle: Axi4Stream.Axi4StreamBundle, idx: Int): Axi4CheckByte = { val data = (axisBundle.data.toBigInt >> 8*idx) & BigInt(0xFF) val strb = if (axisBundle.config.useStrb) axisBundle.strb.toBigInt.testBit(idx) else true val keep = if (axisBundle.config.useKeep) axisBundle.keep.toBigInt.testBit(idx) else true @@ -92,7 +91,7 @@ class Axi4StreamWidthAdapterTester extends AnyFunSuite { Axi4CheckByte(data = data, strb = strb, keep = keep, last = last, id = id, dest = dest, user = user) } - def streamByteTransactionMonitor(stream: Axi4Stream, clockDomain: ClockDomain)(callback: (Seq[Axi4CheckByte]) => Unit) = { + def streamByteTransactionMonitor(stream: Axi4Stream.Axi4Stream, clockDomain: ClockDomain)(callback: (Seq[Axi4CheckByte]) => Unit) = { var currentTransaction = ListBuffer[Axi4CheckByte]() StreamMonitor(stream, clockDomain)(p => { diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimAvalonSTTester.scala b/lib/src/test/scala/spinal/lib/bus/avalon/AvalonST.scala similarity index 96% rename from tester/src/test/scala/spinal/tester/scalatest/SpinalSimAvalonSTTester.scala rename to lib/src/test/scala/spinal/lib/bus/avalon/AvalonST.scala index 6afb9279d0..21778b538b 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimAvalonSTTester.scala +++ b/lib/src/test/scala/spinal/lib/bus/avalon/AvalonST.scala @@ -1,12 +1,12 @@ -package spinal.tester.scalatest +package spinal.lib.bus.avalon import org.scalatest.funsuite.AnyFunSuite + import spinal.core._ import spinal.core.sim._ -import spinal.lib.bus.avalon._ import spinal.lib._ import spinal.lib.bus.avalon.sim.{AvalonSTDriver, AvalonSTMonitor} -import spinal.lib.sim.{ScoreboardInOrder, SimData} +import spinal.lib.sim.SimData import scala.collection.mutable diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimBmbDecoderOutOfOrderTester.scala b/lib/src/test/scala/spinal/lib/bus/bmb/BmbDecoder.scala similarity index 94% rename from tester/src/test/scala/spinal/tester/scalatest/SpinalSimBmbDecoderOutOfOrderTester.scala rename to lib/src/test/scala/spinal/lib/bus/bmb/BmbDecoder.scala index 606c30b3cb..488d38b49a 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimBmbDecoderOutOfOrderTester.scala +++ b/lib/src/test/scala/spinal/lib/bus/bmb/BmbDecoder.scala @@ -1,21 +1,14 @@ -package spinal.tester.scalatest +package spinal.lib.bus.bmb import org.scalatest.funsuite.AnyFunSuite + import spinal.core._ import spinal.core.sim._ -import spinal.lib.{StreamFifoMultiChannelSharedSpace, master, slave} -import spinal.lib.bus.bmb.sim.{BmbInterconnectTester, BmbMasterAgent, BmbMemoryAgent, BmbMemoryTester} -import spinal.lib.bus.bmb.{Bmb, BmbAccessParameter, BmbDecoder, BmbDecoderOutOfOrder, BmbDecoderPerSource, BmbParameter, BmbSourceParameter} +import spinal.lib.{master, slave} +import spinal.lib.bus.bmb.sim.BmbInterconnectTester import spinal.lib.bus.misc.{DefaultMapping, SizeMapping} import spinal.lib.eda.bench.{Bench, Rtl, XilinxStdTargets} -import scala.collection.mutable -import scala.collection.mutable.ArrayBuffer -import scala.util.Random - - - - class SpinalSimBmbDecoderOutOfOrderTester extends AnyFunSuite { def doIt(outputCount : Int, sourceCount : Int, withDefault : Boolean): Unit ={ val p = BmbParameter( diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimBmbDownSizerBridgeTester.scala b/lib/src/test/scala/spinal/lib/bus/bmb/BmbDownSizerBridge.scala similarity index 83% rename from tester/src/test/scala/spinal/tester/scalatest/SpinalSimBmbDownSizerBridgeTester.scala rename to lib/src/test/scala/spinal/lib/bus/bmb/BmbDownSizerBridge.scala index 197e4b8333..e6fc7866f1 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimBmbDownSizerBridgeTester.scala +++ b/lib/src/test/scala/spinal/lib/bus/bmb/BmbDownSizerBridge.scala @@ -1,16 +1,9 @@ -package spinal.tester.scalatest +package spinal.lib.bus.bmb -import org.scalatest.funsuite.AnyFunSuite -import spinal.core.sim._ -import spinal.lib.bus.amba3.apb.Apb3Config -import spinal.lib.bus.amba3.apb.sim.Apb3Monitor -import spinal.lib.bus.bmb.{BmbDownSizerBridge, BmbParameter, BmbToApb3Bridge} -import spinal.lib.bus.bmb.sim.{BmbBridgeTester, BmbMasterAgent, BmbMemoryAgent, BmbRegionAllocator} -import spinal.lib.bus.misc.SizeMapping -import spinal.lib.sim._ +import spinal.tester.SpinalSimFunSuite -import scala.collection.mutable -import scala.util.Random +import spinal.core.sim._ +import spinal.lib.bus.bmb.sim.BmbBridgeTester class SpinalSimBmbDownSizerBridgeTester extends SpinalSimFunSuite{ test("test1"){ diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimBmbExclusiveMonitorTester.scala b/lib/src/test/scala/spinal/lib/bus/bmb/BmbExclusiveMonitor.scala similarity index 92% rename from tester/src/test/scala/spinal/tester/scalatest/SpinalSimBmbExclusiveMonitorTester.scala rename to lib/src/test/scala/spinal/lib/bus/bmb/BmbExclusiveMonitor.scala index da0b19f16b..5b7e5b64ee 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimBmbExclusiveMonitorTester.scala +++ b/lib/src/test/scala/spinal/lib/bus/bmb/BmbExclusiveMonitor.scala @@ -1,20 +1,14 @@ -package spinal.tester.scalatest +package spinal.lib.bus.bmb import org.scalatest.funsuite.AnyFunSuite + import spinal.core.sim._ import spinal.lib.Fragment -import spinal.lib.bus.amba3.apb.Apb3Config -import spinal.lib.bus.amba3.apb.sim.Apb3Monitor -import spinal.lib.bus.bmb.{Bmb, BmbAccessParameter, BmbCmd, BmbDownSizerBridge, BmbExclusiveMonitor, BmbInvalidationParameter, BmbParameter, BmbRsp, BmbSourceParameter, BmbToApb3Bridge} -import spinal.lib.bus.bmb.sim.{BmbBridgeTester, BmbMasterAgent, BmbMemoryAgent, BmbRegionAllocator} -import spinal.lib.bus.misc.SizeMapping import spinal.lib.sim._ import scala.collection.mutable import scala.util.Random - - private object IDLE private object READ_CMD private object READ_RSP diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimBmbInterconnectGeneratorTester.scala b/lib/src/test/scala/spinal/lib/bus/bmb/BmbInterconnectGenerator.scala similarity index 95% rename from tester/src/test/scala/spinal/tester/scalatest/SpinalSimBmbInterconnectGeneratorTester.scala rename to lib/src/test/scala/spinal/lib/bus/bmb/BmbInterconnectGenerator.scala index 9d599ae227..8a63c9d698 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimBmbInterconnectGeneratorTester.scala +++ b/lib/src/test/scala/spinal/lib/bus/bmb/BmbInterconnectGenerator.scala @@ -1,21 +1,24 @@ -package spinal.tester.scalatest +package spinal.lib.bus.bmb import org.scalatest.funsuite.AnyFunSuite +import spinal.tester.RepeatabilitySuite + import spinal.core._ import spinal.core.fiber._ import spinal.core.sim._ import spinal.lib._ +import spinal.lib.generator._ import spinal.lib.bus.bmb.sim._ -import spinal.lib.bus.bmb._ import spinal.lib.bus.misc.SizeMapping -import spinal.lib.generator._ import spinal.lib.sim.Phase +import spinal.tester.SpinalSimFunSuite + import scala.collection.mutable import scala.util.Random object SpinalSimBmbInterconnectGeneratorTester { - def f() = { + def component() = { new Component{ val interconnect = BmbInterconnectGenerator() @@ -180,10 +183,10 @@ object SpinalSimBmbInterconnectGeneratorTester { } //TODO handle generation when a master has no slave -class SpinalSimBmbInterconnectGeneratorTester extends SpinalSimFunSuite{ +class SpinalSimBmbInterconnectGeneratorTester extends SpinalSimFunSuite { test("test1") { - SimConfig.allOptimisation.compile(SpinalSimBmbInterconnectGeneratorTester.f).doSimUntilVoid("test1", 42) { dut => //TODO remove seed + SimConfig.allOptimisation.compile(SpinalSimBmbInterconnectGeneratorTester.component).doSimUntilVoid("test1", 42) { dut => //TODO remove seed Phase.boot() Phase.setup { dut.clockDomain.forkStimulus(10) @@ -266,3 +269,9 @@ class SpinalSimBmbInterconnectGeneratorTester extends SpinalSimFunSuite{ } } } + +class RepeatabilityTester extends RepeatabilitySuite { + test("BmbInterconnectVerilog") { + checkOutputHash(SpinalSimBmbInterconnectGeneratorTester.component) + } +} diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimBmbOnChipRamTester.scala b/lib/src/test/scala/spinal/lib/bus/bmb/BmbOnChipRam.scala similarity index 74% rename from tester/src/test/scala/spinal/tester/scalatest/SpinalSimBmbOnChipRamTester.scala rename to lib/src/test/scala/spinal/lib/bus/bmb/BmbOnChipRam.scala index 4bf5500971..095a4d413c 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimBmbOnChipRamTester.scala +++ b/lib/src/test/scala/spinal/lib/bus/bmb/BmbOnChipRam.scala @@ -1,19 +1,12 @@ -package spinal.tester.scalatest +package spinal.lib.bus.bmb + +import spinal.tester.SpinalSimFunSuite -import org.scalatest.funsuite.AnyFunSuite -import spinal.core.sim._ -import spinal.lib.sim._ import spinal.core._ -import spinal.lib._ -import spinal.lib.bus.bmb.{Bmb, BmbOnChipRam, BmbParameter} -import spinal.lib.bus.bmb.sim.{BmbMasterAgent, BmbMemoryAgent, BmbMemoryTester, BmbRegionAllocator} -import spinal.lib.bus.misc.SizeMapping +import spinal.lib.bus.bmb.sim.BmbMemoryTester import scala.util.Random - - - class SpinalSimBmbOnChipRamTester extends SpinalSimFunSuite { test("test1") { val memInit = new Array[Byte](64 * 1024) diff --git a/lib/src/test/scala/spinal/lib/bus/bmb/BmbSpecificBridges.scala b/lib/src/test/scala/spinal/lib/bus/bmb/BmbSpecificBridges.scala new file mode 100644 index 0000000000..9e88598568 --- /dev/null +++ b/lib/src/test/scala/spinal/lib/bus/bmb/BmbSpecificBridges.scala @@ -0,0 +1,297 @@ +package spinal.lib.bus.bmb + +import org.scalatest.funsuite.AnyFunSuite +import spinal.tester.SpinalSimFunSuite + +import spinal.core._ +import spinal.core.sim.SimConfig +import spinal.lib.bus.bmb.sim.BmbBridgeTester + +class SpinalSimBmbAlignerTester extends AnyFunSuite { + for(w <- List(false, true); r <- List(false, true); if w || r) { + val header = "_" + (if(w) "w" else "") + (if(r) "r" else "") + test("BmbAligner_bypass" + header) { + SimConfig.compile { + val c = BmbAligner( + ip = BmbParameter( + addressWidth = 16, + dataWidth = 32, + lengthWidth = 6, + sourceWidth = 4, + contextWidth = 3, + canRead = r, + canWrite = w, + alignment = BmbParameter.BurstAlignement.WORD + ), + alignmentWidth = 2 + ) + c.rework { + RegNext(True) init (False) setName ("dummy") + } + c + }.doSimUntilVoid("test") { dut => + new BmbBridgeTester( + master = dut.io.input, + masterCd = dut.clockDomain, + slave = dut.io.output, + slaveCd = dut.clockDomain + ) + } + } + + test("BmbAligner_4" + header) { + SimConfig.compile { + BmbAligner( + ip = BmbParameter( + addressWidth = 16, + dataWidth = 32, + lengthWidth = 6, + sourceWidth = 4, + contextWidth = 3, + canRead = r, + canWrite = w, + alignment = BmbParameter.BurstAlignement.WORD + ), + alignmentWidth = 4 + ) + }.doSimUntilVoid("test") { dut => + new BmbBridgeTester( + master = dut.io.input, + masterCd = dut.clockDomain, + slave = dut.io.output, + slaveCd = dut.clockDomain + ) + } + } + + test("BmbAligner_3" + header) { + SimConfig.compile { + BmbAligner( + ip = BmbParameter( + addressWidth = 16, + dataWidth = 32, + lengthWidth = 6, + sourceWidth = 4, + contextWidth = 3, + canRead = r, + canWrite = w, + alignment = BmbParameter.BurstAlignement.WORD + ), + alignmentWidth = 3 + ) + }.doSimUntilVoid("test") { dut => + new BmbBridgeTester( + master = dut.io.input, + masterCd = dut.clockDomain, + slave = dut.io.output, + slaveCd = dut.clockDomain + ) + } + } + + test("BmbAligner_1" + header) { + SimConfig.compile { + val c = BmbAligner( + ip = BmbParameter( + addressWidth = 16, + dataWidth = 32, + lengthWidth = 6, + sourceWidth = 4, + contextWidth = 3, + canRead = r, + canWrite = w, + alignment = BmbParameter.BurstAlignement.WORD + ), + alignmentWidth = 1 + ) + c.rework { + RegNext(True) init (False) setName ("dummy") + } + c + }.doSimUntilVoid("test") { dut => + new BmbBridgeTester( + master = dut.io.input, + masterCd = dut.clockDomain, + slave = dut.io.output, + slaveCd = dut.clockDomain + ) + } + } + } +} + +class SpinalSimBmbLengthFixerTester extends SpinalSimFunSuite { + test("bypass") { + SimConfig.compile { + val c = BmbLengthFixer( + ip = BmbParameter( + addressWidth = 16, + dataWidth = 32, + lengthWidth = 6, + sourceWidth = 4, + contextWidth = 3, + alignmentMin = 2, + canRead = true, + canWrite = true, + alignment = BmbParameter.BurstAlignement.WORD + ), + fixedWidth = 2 + ) + c + }.doSimUntilVoid("test") { dut => + new BmbBridgeTester( + master = dut.io.input, + masterCd = dut.clockDomain, + slave = dut.io.output, + slaveCd = dut.clockDomain, + alignmentMinWidth = dut.ip.access.alignmentMin + ) + } + } + + test("3") { + SimConfig.compile { + val c = BmbLengthFixer( + ip = BmbParameter( + addressWidth = 16, + dataWidth = 32, + lengthWidth = 6, + sourceWidth = 4, + contextWidth = 3, + alignmentMin = 3, + canRead = true, + canWrite = true, + alignment = BmbParameter.BurstAlignement.WORD + ), + fixedWidth = 3 + ) + c + }.doSimUntilVoid("test") { dut => + new BmbBridgeTester( + master = dut.io.input, + masterCd = dut.clockDomain, + slave = dut.io.output, + slaveCd = dut.clockDomain, + alignmentMinWidth = dut.ip.access.alignmentMin + ) + } + } + + test("4") { + SimConfig.compile { + val c = BmbLengthFixer( + ip = BmbParameter( + addressWidth = 16, + dataWidth = 32, + lengthWidth = 6, + sourceWidth = 4, + contextWidth = 3, + alignmentMin = 4, + canRead = true, + canWrite = true, + alignment = BmbParameter.BurstAlignement.WORD + ), + fixedWidth = 4 + ) + c + }.doSimUntilVoid("test") { dut => + new BmbBridgeTester( + master = dut.io.input, + masterCd = dut.clockDomain, + slave = dut.io.output, + slaveCd = dut.clockDomain, + alignmentMinWidth = dut.ip.access.alignmentMin + ) + } + } + +} + +class SpinalSimBmbLengthSpliterTester extends AnyFunSuite { + for(w <- List(false, true); r <- List(false, true); if w || r) { + val header = "_" + (if (w) "w" else "") + (if (r) "r" else "") + test("bypass" + header) { + SimConfig.compile { + val c = BmbAlignedSpliter( + ip = BmbAccessParameter( + addressWidth = 16, + dataWidth = 32 + ).addSources(16, BmbSourceParameter( + lengthWidth = 6, + contextWidth = 3, + alignmentMin = 0, + canRead = r, + canWrite = w, + alignment = BmbParameter.BurstAlignement.WORD + )).toBmbParameter(), + lengthMax = 4 + ) + c + }.doSimUntilVoid("test") { dut => + new BmbBridgeTester( + master = dut.io.input, + masterCd = dut.clockDomain, + slave = dut.io.output, + slaveCd = dut.clockDomain, + alignmentMinWidth = dut.ip.access.alignmentMin + ) + } + } + + test("8" + header) { + SimConfig.withWave.compile { + val c = BmbAlignedSpliter( + ip = BmbAccessParameter( + addressWidth = 16, + dataWidth = 32 + ).addSources(16, BmbSourceParameter( + lengthWidth = 6, + contextWidth = 8, + alignmentMin = 0, + canRead = r, + canWrite = w, + alignment = BmbParameter.BurstAlignement.WORD + )).toBmbParameter(), + lengthMax = 8 + ) + c + }.doSimUntilVoid("test", 42) { dut => + new BmbBridgeTester( + master = dut.io.input, + masterCd = dut.clockDomain, + slave = dut.io.output, + slaveCd = dut.clockDomain, + alignmentMinWidth = dut.ip.access.alignmentMin + ) + } + } + + test("16" + header) { + SimConfig.compile { + val c = BmbAlignedSpliter( + ip = BmbAccessParameter( + addressWidth = 16, + dataWidth = 32 + ).addSources(16, BmbSourceParameter( + lengthWidth = 6, + contextWidth = 8, + alignmentMin = 0, + canRead = r, + canWrite = w, + alignment = BmbParameter.BurstAlignement.WORD + )).toBmbParameter(), + lengthMax = 16 + ) + c + }.doSimUntilVoid("test") { dut => + new BmbBridgeTester( + master = dut.io.input, + masterCd = dut.clockDomain, + slave = dut.io.output, + slaveCd = dut.clockDomain, + alignmentMinWidth = dut.ip.access.alignmentMin + ) + } + } + } +} diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimBmbToApb3BridgeTester.scala b/lib/src/test/scala/spinal/lib/bus/bmb/BmbToApb3Bridge.scala similarity index 96% rename from tester/src/test/scala/spinal/tester/scalatest/SpinalSimBmbToApb3BridgeTester.scala rename to lib/src/test/scala/spinal/lib/bus/bmb/BmbToApb3Bridge.scala index 7d8ce94109..2a93bef949 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimBmbToApb3BridgeTester.scala +++ b/lib/src/test/scala/spinal/lib/bus/bmb/BmbToApb3Bridge.scala @@ -1,11 +1,10 @@ -package spinal.tester.scalatest +package spinal.lib.bus.bmb + +import spinal.tester.SpinalSimFunSuite -import org.scalatest.funsuite.AnyFunSuite -import spinal.core._ import spinal.core.sim._ import spinal.lib.bus.amba3.apb.Apb3Config import spinal.lib.bus.amba3.apb.sim.Apb3Monitor -import spinal.lib.bus.bmb.{BmbOnChipRam, BmbToApb3Bridge} import spinal.lib.bus.bmb.sim.{BmbMasterAgent, BmbMemoryAgent, BmbRegionAllocator} import spinal.lib.bus.misc.SizeMapping import spinal.lib.sim._ diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimBmbUnburstifyTester.scala b/lib/src/test/scala/spinal/lib/bus/bmb/BmbUnburstify.scala similarity index 92% rename from tester/src/test/scala/spinal/tester/scalatest/SpinalSimBmbUnburstifyTester.scala rename to lib/src/test/scala/spinal/lib/bus/bmb/BmbUnburstify.scala index 54d2a654c2..b52130218d 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimBmbUnburstifyTester.scala +++ b/lib/src/test/scala/spinal/lib/bus/bmb/BmbUnburstify.scala @@ -1,9 +1,9 @@ -package spinal.tester.scalatest +package spinal.lib.bus.bmb import org.scalatest.funsuite.AnyFunSuite + import spinal.core.sim.SimConfig import spinal.lib.bus.bmb.sim.BmbBridgeTester -import spinal.lib.bus.bmb.{BmbAccessParameter, BmbLengthFixer, BmbParameter, BmbSourceParameter, BmbUnburstify} class SpinalSimBmbUnburstifyTester extends AnyFunSuite { test("miaou") { diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimBmbUpSizerBridgeTester.scala b/lib/src/test/scala/spinal/lib/bus/bmb/BmbUpSizerBridge.scala similarity index 92% rename from tester/src/test/scala/spinal/tester/scalatest/SpinalSimBmbUpSizerBridgeTester.scala rename to lib/src/test/scala/spinal/lib/bus/bmb/BmbUpSizerBridge.scala index b8c1aba5ad..f785c6fb4c 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimBmbUpSizerBridgeTester.scala +++ b/lib/src/test/scala/spinal/lib/bus/bmb/BmbUpSizerBridge.scala @@ -1,11 +1,8 @@ -package spinal.tester.scalatest +package spinal.lib.bus.bmb -import org.scalatest.funsuite.AnyFunSuite -import spinal.core.sim._ -import spinal.lib.bus.bmb.sim.BmbBridgeTester -import spinal.lib.bus.bmb.{BmbAccessParameter, BmbParameter, BmbSourceParameter, BmbUpSizerBridge} +import spinal.tester.SpinalSimFunSuite -import scala.collection.mutable +import spinal.lib.bus.bmb.sim.BmbBridgeTester class SpinalSimBmbUpSizerBridgeTester extends SpinalSimFunSuite{ for((canRead, canWrite) <- List((true,true),(true, false), (false, true))) { diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimBsbTester.scala b/lib/src/test/scala/spinal/lib/bus/bsb/Bsb.scala similarity index 88% rename from tester/src/test/scala/spinal/tester/scalatest/SpinalSimBsbTester.scala rename to lib/src/test/scala/spinal/lib/bus/bsb/Bsb.scala index e86f1df8fc..c9869d6f91 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimBsbTester.scala +++ b/lib/src/test/scala/spinal/lib/bus/bsb/Bsb.scala @@ -1,15 +1,11 @@ -package spinal.tester.scalatest +package spinal.lib.bus.bsb import org.scalatest.funsuite.AnyFunSuite -import spinal.core.HardType + import spinal.core._ import spinal.core.sim._ -import spinal.lib.bus.bmb.sim.{BmbDriver, BmbMemoryAgent} -import spinal.lib.bus.bmb.{Bmb, BmbParameter, BmbSlaveFactory} -import spinal.lib.bus.bsb.{Bsb, BsbDownSizerAlignedMultiWidth, BsbDownSizerSparse, BsbParameter, BsbUpSizerDense, BsbUpSizerSparse} -import spinal.lib.bus.bsb.sim.BsbBridgeTester import spinal.lib._ -import spinal.lib.system.dma.sg.{DmaSg, DmaSgTester, SgDmaTestsParameter} +import spinal.lib.bus.bsb.sim.BsbBridgeTester class SpinalSimBsbTester extends AnyFunSuite{ test("upsizerSparse"){ diff --git a/tester/src/test/scala/spinal/tester/scalatest/RegIfAxiLite4Tester.scala b/lib/src/test/scala/spinal/lib/bus/regif/AxiLite4BusInterface.scala similarity index 98% rename from tester/src/test/scala/spinal/tester/scalatest/RegIfAxiLite4Tester.scala rename to lib/src/test/scala/spinal/lib/bus/regif/AxiLite4BusInterface.scala index bf89a054e7..6f8637184f 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/RegIfAxiLite4Tester.scala +++ b/lib/src/test/scala/spinal/lib/bus/regif/AxiLite4BusInterface.scala @@ -1,15 +1,14 @@ -package spinal.tester.scalatest +package spinal.lib.bus.regif import org.scalatest.funsuite.AnyFunSuite + import spinal.core._ import spinal.core.sim._ import spinal.lib._ import spinal.lib.bus.amba4.axilite._ import spinal.lib.bus.amba4.axilite.sim.{AxiLite4Driver, AxiLite4ReadOnlyMonitor, AxiLite4WriteOnlyMonitor} -import spinal.lib.bus.regif.{AccessType, BusInterface} import scala.collection.mutable -import scala.math.{BigInt} import scala.util.Random class RegIfTester extends Component { diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimWishboneSimTester.scala b/lib/src/test/scala/spinal/lib/bus/wishbone/Wishbone.scala similarity index 98% rename from tester/src/test/scala/spinal/tester/scalatest/SpinalSimWishboneSimTester.scala rename to lib/src/test/scala/spinal/lib/bus/wishbone/Wishbone.scala index f83731a273..abdd5b85e5 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimWishboneSimTester.scala +++ b/lib/src/test/scala/spinal/lib/bus/wishbone/Wishbone.scala @@ -1,11 +1,10 @@ -package spinal.tester.scalatest +package spinal.lib.bus.wishbone import org.scalatest.funsuite.AnyFunSuite + import spinal.core._ -import spinal.core.sim.{SimCompiled, _} -import spinal.sim._ +import spinal.core.sim._ import spinal.lib._ -import spinal.lib.bus.wishbone._ import spinal.lib.wishbone.sim._ import spinal.lib.sim._ diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimWishboneAdapterTester.scala b/lib/src/test/scala/spinal/lib/bus/wishbone/WishboneAdapter.scala similarity index 97% rename from tester/src/test/scala/spinal/tester/scalatest/SpinalSimWishboneAdapterTester.scala rename to lib/src/test/scala/spinal/lib/bus/wishbone/WishboneAdapter.scala index 2161f16920..926da0ec2b 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimWishboneAdapterTester.scala +++ b/lib/src/test/scala/spinal/lib/bus/wishbone/WishboneAdapter.scala @@ -1,13 +1,13 @@ -package spinal.tester.scalatest +package spinal.lib.bus.wishbone import org.scalatest.funsuite.AnyFunSuite + import spinal.core._ import spinal.core.sim._ -import spinal.sim._ import spinal.lib._ -import spinal.lib.bus.wishbone._ import spinal.lib.wishbone.sim._ import spinal.lib.sim._ + import scala.util.Random class WishboneSimpleBusAdapted( configIn : WishboneConfig, diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimWishboneArbiterTester.scala b/lib/src/test/scala/spinal/lib/bus/wishbone/WishboneArbiter.scala similarity index 98% rename from tester/src/test/scala/spinal/tester/scalatest/SpinalSimWishboneArbiterTester.scala rename to lib/src/test/scala/spinal/lib/bus/wishbone/WishboneArbiter.scala index bd82641359..9cfae8a39e 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimWishboneArbiterTester.scala +++ b/lib/src/test/scala/spinal/lib/bus/wishbone/WishboneArbiter.scala @@ -1,13 +1,15 @@ -package spinal.tester.scalatest +package spinal.lib.bus.wishbone import org.scalatest.funsuite.AnyFunSuite + import spinal.core._ import spinal.core.sim._ -import spinal.sim._ import spinal.lib._ -import spinal.lib.bus.wishbone._ import spinal.lib.wishbone.sim._ import spinal.lib.sim._ + +import spinal.sim._ + import scala.util.Random import scala.collection.Seq diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimWishboneDecoderTester.scala b/lib/src/test/scala/spinal/lib/bus/wishbone/WishboneDecoder.scala similarity index 97% rename from tester/src/test/scala/spinal/tester/scalatest/SpinalSimWishboneDecoderTester.scala rename to lib/src/test/scala/spinal/lib/bus/wishbone/WishboneDecoder.scala index 8dc707d216..c170b4c0d3 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimWishboneDecoderTester.scala +++ b/lib/src/test/scala/spinal/lib/bus/wishbone/WishboneDecoder.scala @@ -1,14 +1,14 @@ -package spinal.tester.scalatest +package spinal.lib.bus.wishbone import org.scalatest.funsuite.AnyFunSuite + import spinal.core._ import spinal.core.sim._ -import spinal.sim._ import spinal.lib._ import spinal.lib.bus.misc._ -import spinal.lib.bus.wishbone._ import spinal.lib.wishbone.sim._ import spinal.lib.sim._ + import scala.util.Random class WishboneDecoderComponent(config : WishboneConfig,decodings : Seq[SizeMapping]) extends Component{ diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimWishboneSimInterconTester.scala b/lib/src/test/scala/spinal/lib/bus/wishbone/WishboneSimIntercon.scala similarity index 95% rename from tester/src/test/scala/spinal/tester/scalatest/SpinalSimWishboneSimInterconTester.scala rename to lib/src/test/scala/spinal/lib/bus/wishbone/WishboneSimIntercon.scala index 9739e05bb4..f2e90834e6 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimWishboneSimInterconTester.scala +++ b/lib/src/test/scala/spinal/lib/bus/wishbone/WishboneSimIntercon.scala @@ -1,15 +1,15 @@ -package spinal.tester.scalatest +package spinal.lib.bus.wishbone import org.scalatest.funsuite.AnyFunSuite -import spinal.tester + import spinal.core._ import spinal.core.sim._ import spinal.sim._ import spinal.lib._ import spinal.lib.bus.misc._ -import spinal.lib.bus.wishbone._ import spinal.lib.wishbone.sim._ import spinal.lib.sim._ + import scala.util.Random import scala.collection.Seq @@ -55,7 +55,7 @@ class SpinalSimWishboneSimInterconTester extends AnyFunSuite{ } } - scala.util.Random.shuffle(slaves).foreach{slave => + Random.shuffle(slaves).foreach{slave => driver_slave(slave).slaveSink() monitor_slave(slave, scoreboard_master) (0 to req).foreach{x => sequencer_master.addTransaction(WishboneTransaction(data=id).randomAdressInRange(slave._2))} @@ -91,7 +91,7 @@ class SpinalSimWishboneSimInterconTester extends AnyFunSuite{ val masterPool = scala.collection.mutable.ListBuffer[SimThread]() val sss = scala.collection.mutable.ListBuffer[((Wishbone,Int),(Wishbone,SizeMapping))]() - scala.util.Random.shuffle(masters.zipWithIndex).foreach{master => + Random.shuffle(masters.zipWithIndex).foreach{master => masterPool += fork{ send_transaction(master._2,master._1,slaves,1) } diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimWishboneSlaveFactoryTester.scala b/lib/src/test/scala/spinal/lib/bus/wishbone/WishboneSlaveFactory.scala similarity index 94% rename from tester/src/test/scala/spinal/tester/scalatest/SpinalSimWishboneSlaveFactoryTester.scala rename to lib/src/test/scala/spinal/lib/bus/wishbone/WishboneSlaveFactory.scala index e39e2bac61..6a3e5d699b 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimWishboneSlaveFactoryTester.scala +++ b/lib/src/test/scala/spinal/lib/bus/wishbone/WishboneSlaveFactory.scala @@ -1,14 +1,12 @@ -package spinal.tester.scalatest +package spinal.lib.bus.wishbone import org.scalatest.funsuite.AnyFunSuite + import spinal.core._ import spinal.core.sim._ -import spinal.sim._ import spinal.lib._ -import spinal.lib.bus.wishbone._ import spinal.lib.wishbone.sim._ import spinal.lib.sim._ -import scala.util.Random class WishboneSimpleSlave(config : WishboneConfig) extends Component{ val io = new Bundle{ diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimMacTester.scala b/lib/src/test/scala/spinal/lib/com/eth/MacRx.scala similarity index 98% rename from tester/src/test/scala/spinal/tester/scalatest/SpinalSimMacTester.scala rename to lib/src/test/scala/spinal/lib/com/eth/MacRx.scala index 714098fbc2..6bcc4d23cd 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimMacTester.scala +++ b/lib/src/test/scala/spinal/lib/com/eth/MacRx.scala @@ -1,11 +1,10 @@ -package spinal.tester.scalatest +package spinal.lib.com.eth import org.scalatest.funsuite.AnyFunSuite + import spinal.core._ import spinal.core.sim._ -import spinal.lib._ -import spinal.lib.com.eth._ -import spinal.lib.sim.{FlowMonitor, StreamDriver, StreamMonitor, StreamReadyRandomizer} +import spinal.lib.sim.{StreamDriver, StreamMonitor, StreamReadyRandomizer} import scala.collection.mutable import scala.util.Random diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimApbI2C.scala b/lib/src/test/scala/spinal/lib/com/i2c/Apb3I2cCtrl.scala similarity index 90% rename from tester/src/test/scala/spinal/tester/scalatest/SpinalSimApbI2C.scala rename to lib/src/test/scala/spinal/lib/com/i2c/Apb3I2cCtrl.scala index e14fb6b840..4b379a9052 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimApbI2C.scala +++ b/lib/src/test/scala/spinal/lib/com/i2c/Apb3I2cCtrl.scala @@ -1,17 +1,46 @@ -package spinal.tester.scalatest +/* + * SpinalHDL + * Copyright (c) Dolu, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ + +package spinal.lib.com.i2c - -import org.scalatest.funsuite.AnyFunSuite import spinal.core._ -import spinal.core.internals.GraphUtils import spinal.core.sim._ -import spinal.lib.bus.amba3.apb.Apb3 -import spinal.lib.com.i2c._ -import spinal.sim._ import spinal.lib._ +import spinal.lib.bus.amba3.apb.Apb3 + +import spinal.tester.{SpinalSimFunSuite, SpinalTesterCocotbBase} import scala.collection.mutable.ListBuffer +class Apb3I2cSlaveTester extends SpinalTesterCocotbBase { + override def getName: String = "Apb3I2cSlaveTester" + override def pythonTestLocation: String = "tester/src/test/python/spinal/I2CTester2/Apb3I2cSlaveTester" + override def createToplevel: Component = new Apb3I2cCtrl( + I2cSlaveMemoryMappedGenerics( + ctrlGenerics = I2cSlaveGenerics( + samplingWindowSize = 3, + samplingClockDividerWidth = 10 bits, + timeoutWidth = 20 bits + ), + addressFilterCount = 4 + ) + ).setDefinitionName("Apb3I2cSlave") +} trait I2CEvent @@ -485,4 +514,3 @@ class SpinalSimApbI2C extends SpinalSimFunSuite { } } } - diff --git a/tester/src/test/scala/spinal/tester/scalatest/I2CSlaveTester.scala b/lib/src/test/scala/spinal/lib/com/i2c/I2CSlave.scala similarity index 80% rename from tester/src/test/scala/spinal/tester/scalatest/I2CSlaveTester.scala rename to lib/src/test/scala/spinal/lib/com/i2c/I2CSlave.scala index 76bab804c7..ce8daddab0 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/I2CSlaveTester.scala +++ b/lib/src/test/scala/spinal/lib/com/i2c/I2CSlave.scala @@ -16,25 +16,24 @@ * License along with this library. */ -package spinal.tester.scalatest +package spinal.lib.com.i2c import spinal.core._ -import spinal.lib._ -import spinal.lib.com.i2c._ +import spinal.tester.SpinalTesterCocotbBase class I2cSlaveTester extends SpinalTesterCocotbBase { override def getName: String = "I2cSlaveTester" override def pythonTestLocation: String = "tester/src/test/python/spinal/I2CTester2/I2cSlaveTester" override def createToplevel: Component = { - val ret = new I2cSlave(I2cSlaveGenerics( - samplingWindowSize = 3, - samplingClockDividerWidth = 10 bits, - timeoutWidth = 20 bits - )) + val ret = new I2cSlave( + I2cSlaveGenerics( + samplingWindowSize = 3, + samplingClockDividerWidth = 10 bits, + timeoutWidth = 20 bits + ) + ) ret.io.bus.cmd.kind.fixEncoding(binarySequential) ret } - } - diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimEncoding8b10b.scala b/lib/src/test/scala/spinal/lib/com/linecode/Encoding8b10b.scala similarity index 99% rename from tester/src/test/scala/spinal/tester/scalatest/SpinalSimEncoding8b10b.scala rename to lib/src/test/scala/spinal/lib/com/linecode/Encoding8b10b.scala index 86adaefdfa..a30fcb7ab5 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimEncoding8b10b.scala +++ b/lib/src/test/scala/spinal/lib/com/linecode/Encoding8b10b.scala @@ -1,11 +1,8 @@ -package spinal.tester.scalatest +package spinal.lib.com.linecode import org.scalatest.funsuite.AnyFunSuite -import spinal.sim._ -import spinal.core._ import spinal.core.sim._ -import spinal.lib.com.linecode.Encoding8b10b class Encoding8b10bTest extends AnyFunSuite { @@ -480,7 +477,5 @@ class Encoding8b10bTest extends AnyFunSuite { decodeTestCaseError(dut, "00000011", "1001110000", true) } - - } } diff --git a/tester/src/test/scala/spinal/tester/scalatest/Apb3SpiMasterCtrlTester.scala b/lib/src/test/scala/spinal/lib/com/spi/Apb3SpiMasterCtrl.scala similarity index 88% rename from tester/src/test/scala/spinal/tester/scalatest/Apb3SpiMasterCtrlTester.scala rename to lib/src/test/scala/spinal/lib/com/spi/Apb3SpiMasterCtrl.scala index 8c9bb05371..aaa6a06937 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/Apb3SpiMasterCtrlTester.scala +++ b/lib/src/test/scala/spinal/lib/com/spi/Apb3SpiMasterCtrl.scala @@ -16,12 +16,11 @@ * License along with this library. */ -package spinal.tester.scalatest +package spinal.lib.com.spi import spinal.core._ -import spinal.lib.com.i2c._ -import spinal.lib.com.spi.{SpiMasterCtrlGenerics, Apb3SpiMasterCtrl, SpiMasterCtrlMemoryMappedConfig} +import spinal.tester.SpinalTesterCocotbBase class Apb3SpiMasterCtrlTester extends SpinalTesterCocotbBase { override def getName: String = "Apb3SpiMasterCtrlTester" diff --git a/tester/src/test/scala/spinal/tester/scalatest/Apb3SpiSlaveCtrlTester.scala b/lib/src/test/scala/spinal/lib/com/spi/Apb3SpiSlaveCtrl.scala similarity index 90% rename from tester/src/test/scala/spinal/tester/scalatest/Apb3SpiSlaveCtrlTester.scala rename to lib/src/test/scala/spinal/lib/com/spi/Apb3SpiSlaveCtrl.scala index aa9cdb617f..8e875357ba 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/Apb3SpiSlaveCtrlTester.scala +++ b/lib/src/test/scala/spinal/lib/com/spi/Apb3SpiSlaveCtrl.scala @@ -16,11 +16,11 @@ * License along with this library. */ -package spinal.tester.scalatest +package spinal.lib.com.spi import spinal.core._ -import spinal.lib.com.spi.{Apb3SpiSlaveCtrl, SpiSlaveCtrlGenerics, SpiSlaveCtrlMemoryMappedConfig} +import spinal.tester.SpinalTesterCocotbBase class Apb3SpiSlaveCtrlTester extends SpinalTesterCocotbBase { override def getName: String = "Apb3SpiSlaveCtrlTester" diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimSpiXdr.scala b/lib/src/test/scala/spinal/lib/com/spi/ddr/SpiXdrMasterCtrl.scala similarity index 89% rename from tester/src/test/scala/spinal/tester/scalatest/SpinalSimSpiXdr.scala rename to lib/src/test/scala/spinal/lib/com/spi/ddr/SpiXdrMasterCtrl.scala index b5c0254751..704348668f 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimSpiXdr.scala +++ b/lib/src/test/scala/spinal/lib/com/spi/ddr/SpiXdrMasterCtrl.scala @@ -1,40 +1,15 @@ -package spinal.tester.scalatest +package spinal.lib.com.spi.ddr import org.scalatest.funsuite.AnyFunSuite +import spinal.tester.SpinalSimTester + import spinal.core._ import spinal.core.sim._ -import spinal.lib.bus.amba3.apb.Apb3 -import spinal.lib.com.i2c._ -import spinal.sim._ import spinal.lib._ -import spinal.lib.com.spi.ddr._ -import spinal.lib.sim.{FlowMonitor, ScoreboardInOrder, SimData} +import spinal.lib.sim.{FlowMonitor, ScoreboardInOrder} -import scala.collection.mutable.ListBuffer import scala.util.Random - -//case class SpiDdrSlave(spi: SpiDdrMaster) { -// fork{ -// while(true){ -// waitUntil(spi.sclk.) -// } -// } -// def expectWrite(data: Int, mod: ParameterMod): Unit = { -// -// } -// -// def read(data: Int, mod: ParameterMod): Unit = { -// -// } -//} -// -// -//case class SpinalSimSpiDdrCmdData(read: Boolean, write: Boolean, data: Int) -//case class SpinalSimSpiDdrCmdSs(id : Int, enable : Boolean) - - - class SpinalSimSpiXdrMaster extends AnyFunSuite { SpinalSimTester { env => import env._ diff --git a/tester/src/test/scala/spinal/tester/scalatest/UartTester.scala b/lib/src/test/scala/spinal/lib/com/uart/UartCtrl.scala similarity index 90% rename from tester/src/test/scala/spinal/tester/scalatest/UartTester.scala rename to lib/src/test/scala/spinal/lib/com/uart/UartCtrl.scala index 9d1adcf728..df3ac550e1 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/UartTester.scala +++ b/lib/src/test/scala/spinal/lib/com/uart/UartCtrl.scala @@ -1,7 +1,8 @@ -package spinal.tester.scalatest +package spinal.lib.com.uart import spinal.core._ -import spinal.lib.com.uart._ + +import spinal.tester.SpinalTesterCocotbBase class UartTester extends Component { val io = new Bundle { diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimUsbHostTester.scala b/lib/src/test/scala/spinal/lib/com/usb/ohci/SpinalSimUsbHostTester.scala similarity index 99% rename from tester/src/test/scala/spinal/tester/scalatest/SpinalSimUsbHostTester.scala rename to lib/src/test/scala/spinal/lib/com/usb/ohci/SpinalSimUsbHostTester.scala index 0e5673e3ac..e867abf28a 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimUsbHostTester.scala +++ b/lib/src/test/scala/spinal/lib/com/usb/ohci/SpinalSimUsbHostTester.scala @@ -1,17 +1,15 @@ -package spinal.tester.scalatest +package spinal.lib.com.usb.ohci import org.scalatest.funsuite.AnyFunSuite + import spinal.core._ import spinal.core.sim._ -import spinal.lib._ + +import spinal.lib.com.usb._ import spinal.lib.bus.bmb.sim.{BmbDriver, BmbMemoryAgent} import spinal.lib.bus.bmb.{BmbAccessParameter, BmbParameter, BmbSourceParameter} -import spinal.lib.com.usb._ -import spinal.lib.com.usb.ohci._ -import spinal.lib.com.usb.phy.{UsbHubLsFs, UsbLsFsPhy} -import spinal.lib.eda.bench.{AlteraStdTargets, Bench, Rtl, XilinxStdTargets} -import spinal.lib.sim._ +import spinal.lib.eda.bench.{Bench, Rtl, XilinxStdTargets} import scala.collection.mutable import scala.collection.mutable.ArrayBuffer diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimUsbHostTesterUtils.scala b/lib/src/test/scala/spinal/lib/com/usb/ohci/SpinalSimUsbHostTesterUtils.scala similarity index 96% rename from tester/src/test/scala/spinal/tester/scalatest/SpinalSimUsbHostTesterUtils.scala rename to lib/src/test/scala/spinal/lib/com/usb/ohci/SpinalSimUsbHostTesterUtils.scala index fd43edc491..08b6262676 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimUsbHostTesterUtils.scala +++ b/lib/src/test/scala/spinal/lib/com/usb/ohci/SpinalSimUsbHostTesterUtils.scala @@ -1,20 +1,17 @@ -package spinal.tester.scalatest +package spinal.lib.com.usb.ohci import spinal.core._ import spinal.core.sim._ + import spinal.lib.bus.bmb._ import spinal.lib.bus.bmb.sim._ -import spinal.lib.bus.misc.SizeMapping -import spinal.lib.com.usb.ohci._ -import spinal.lib.com.usb.phy.UsbHubLsFs.CtrlCc import spinal.lib.com.usb.phy._ -import spinal.lib.com.usb.sim.{UsbDeviceAgent, UsbDeviceAgentListener, UsbLsFsPhyAbstractIoAgent, UsbLsFsPhyAbstractIoListener} +import spinal.lib.com.usb.sim.{UsbDeviceAgent, UsbDeviceAgentListener, UsbLsFsPhyAbstractIoAgent} import spinal.lib.sim._ import scala.collection.mutable -import scala.collection.mutable.ArrayBuffer -import scala.util.Random import scala.collection.Seq +import scala.util.Random class UsbOhciTbTop(val p : UsbOhciParameter) extends Component { val ohci = UsbOhci(p, BmbParameter( @@ -32,7 +29,7 @@ class UsbOhciTbTop(val p : UsbOhciParameter) extends Component { val ctrl = ohci.io.ctrl.toIo val dma = ohci.io.dma.toIo - val phyCc = CtrlCc(p.portCount, ClockDomain.current, phyCd) + val phyCc = UsbHubLsFs.CtrlCc(p.portCount, ClockDomain.current, phyCd) phyCc.input <> ohci.io.phy phyCc.output <> phy.io.ctrl val usb = phy.io.usb.toIo diff --git a/tester/src/test/scala/spinal/tester/scalatest/UsbDeviceCtrlTester.scala b/lib/src/test/scala/spinal/lib/com/usb/udc/UsbDeviceCtrl.scala similarity index 99% rename from tester/src/test/scala/spinal/tester/scalatest/UsbDeviceCtrlTester.scala rename to lib/src/test/scala/spinal/lib/com/usb/udc/UsbDeviceCtrl.scala index 3f1bc99956..9f8fa3d188 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/UsbDeviceCtrlTester.scala +++ b/lib/src/test/scala/spinal/lib/com/usb/udc/UsbDeviceCtrl.scala @@ -1,8 +1,13 @@ -package spinal.tester.scalatest +package spinal.lib.com.usb.udc import org.scalatest.funsuite.AnyFunSuite + +import scala.collection.mutable +import scala.util.Random + import spinal.core._ import spinal.core.sim._ + import spinal.lib.bus.bmb.BmbParameter import spinal.lib.bus.bmb.sim.BmbDriver import spinal.lib.bus.misc.SizeMapping @@ -10,12 +15,8 @@ import spinal.lib.com.usb.ohci.UsbPid import spinal.lib.com.usb.phy.UsbDevicePhyNative import spinal.lib.com.usb.sim.UsbLsFsPhyAbstractIoAgent import spinal.lib.com.usb.udc.UsbDeviceCtrl.{Regs, Status} -import spinal.lib.com.usb.udc.{UsbDeviceCtrl, UsbDeviceCtrlParameter} import spinal.lib.sim.MemoryRegionAllocator -import scala.collection.mutable -import scala.util.Random - case class UsbDeviceCtrlTesterTop() extends Component { val ctrlCd = ClockDomain.external("ctrlCd", frequency = FixedFrequency(100 MHz)) val phyCd = ClockDomain.external("phyCd", frequency = FixedFrequency(48 MHz)) diff --git a/lib/src/test/scala/spinal/lib/experimental/chisel/Test1.scala b/lib/src/test/scala/spinal/lib/experimental/chisel/Test1.scala deleted file mode 100644 index 5c275848da..0000000000 --- a/lib/src/test/scala/spinal/lib/experimental/chisel/Test1.scala +++ /dev/null @@ -1,15 +0,0 @@ -package spinal.lib.experimental.chisel - - -object Test1 { - class TopLevel extends Module{ - val io = new Bundle{ - val a,b,c = new Bool().asInput() - val result = new Bool().asOutput() - } - io.result := io.a || io.b || io.c - } - def main(args: Array[String]) { - spinal.core.SpinalVerilog(new TopLevel) - } -} diff --git a/tester/src/test/scala/spinal/tester/scalatest/SerdesSerialTester.scala b/lib/src/test/scala/spinal/lib/experimental/com/serial/SerdesSerialTester.scala similarity index 90% rename from tester/src/test/scala/spinal/tester/scalatest/SerdesSerialTester.scala rename to lib/src/test/scala/spinal/lib/experimental/com/serial/SerdesSerialTester.scala index db51044ff7..f420ad53c6 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/SerdesSerialTester.scala +++ b/lib/src/test/scala/spinal/lib/experimental/com/serial/SerdesSerialTester.scala @@ -1,20 +1,17 @@ -package spinal.tester.scalatest +package spinal.lib.experimental.com.serial import spinal.core._ import spinal.lib._ -import spinal.lib.experimental.com.serial._ -object SerdesSerialTester { +import spinal.tester.SpinalTesterGhdlBase +object SerdesSerialTester { class BundleA extends Bundle { val a = UInt(8 bit) val b = Bool() } - } -import spinal.tester.scalatest.StreamTester._ - class SerdesSerialTester extends Component { val io = new Bundle { val rx = slave Flow (Bits(8 bit)) diff --git a/tester/src/test/scala/spinal/tester/scalatest/FloatingTester.scala b/lib/src/test/scala/spinal/lib/experimental/math/Floating.scala similarity index 96% rename from tester/src/test/scala/spinal/tester/scalatest/FloatingTester.scala rename to lib/src/test/scala/spinal/lib/experimental/math/Floating.scala index 5960f94a1a..5a150f0f45 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/FloatingTester.scala +++ b/lib/src/test/scala/spinal/lib/experimental/math/Floating.scala @@ -1,8 +1,8 @@ -package spinal.tester.scalatest +package spinal.lib.experimental.math import spinal.core._ -import spinal.lib._ -import spinal.lib.experimental.math._ + +import spinal.tester.SpinalTesterCocotbBase class FloatingTester extends Component { val io = new Bundle { diff --git a/tester/src/test/scala/spinal/tester/scalatest/Axi4SharedSdramCtrlTester.scala b/lib/src/test/scala/spinal/lib/memory/sdram/sdr/Axi4SharedSdramCtrl.scala similarity index 80% rename from tester/src/test/scala/spinal/tester/scalatest/Axi4SharedSdramCtrlTester.scala rename to lib/src/test/scala/spinal/lib/memory/sdram/sdr/Axi4SharedSdramCtrl.scala index 5406a6fdda..83b7329565 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/Axi4SharedSdramCtrlTester.scala +++ b/lib/src/test/scala/spinal/lib/memory/sdram/sdr/Axi4SharedSdramCtrl.scala @@ -1,10 +1,8 @@ -package spinal.tester.scalatest +package spinal.lib.memory.sdram.sdr import spinal.core._ -import spinal.lib._ -import spinal.lib.memory.sdram._ -import spinal.lib.memory.sdram.sdr.{Axi4SharedSdramCtrl, MT48LC16M16A2} +import spinal.tester.SpinalTesterCocotbBase class Axi4SharedSdramCtrlTesterCocotbBoot extends SpinalTesterCocotbBase { override def getName: String = "Axi4SharedSdramCtrlTester" diff --git a/tester/src/test/scala/spinal/tester/scalatest/SdramCtrlTester.scala b/lib/src/test/scala/spinal/lib/memory/sdram/sdr/SdramCtrl.scala similarity index 54% rename from tester/src/test/scala/spinal/tester/scalatest/SdramCtrlTester.scala rename to lib/src/test/scala/spinal/lib/memory/sdram/sdr/SdramCtrl.scala index 2761dbc5d6..68f419ccc9 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/SdramCtrlTester.scala +++ b/lib/src/test/scala/spinal/lib/memory/sdram/sdr/SdramCtrl.scala @@ -1,18 +1,17 @@ -package spinal.tester.scalatest +package spinal.lib.memory.sdram.sdr import spinal.core._ -import spinal.lib._ -import spinal.lib.memory.sdram._ -import spinal.lib.memory.sdram.sdr.{MT48LC16M16A2, SdramCtrl} +import spinal.tester.SpinalTesterCocotbBase class SdramCtrlTesterCocotbBoot extends SpinalTesterCocotbBase { override def getName: String = "SdramCtrlTester" override def pythonTestLocation: String = "tester/src/test/python/spinal/SdramCtrlTester" override def createToplevel: Component = { val device = MT48LC16M16A2 - SdramCtrl(device.layout,device.timingGrade7.copy(tPOW = 5 us),CAS = 2,UInt(8 bits)).setDefinitionName(getName) + SdramCtrl(device.layout, device.timingGrade7.copy(tPOW = 5 us), CAS = 2, UInt(8 bits)).setDefinitionName(getName) } - override def backendConfig(config: SpinalConfig): SpinalConfig = config.copy(defaultClockDomainFrequency = FixedFrequency(133 MHz)) + override def backendConfig(config: SpinalConfig): SpinalConfig = + config.copy(defaultClockDomainFrequency = FixedFrequency(133 MHz)) override def noVhdl = true -} \ No newline at end of file +} diff --git a/tester/src/test/scala/spinal/tester/scalatest/SdramXdrSdrSpinalSim.scala b/lib/src/test/scala/spinal/lib/memory/sdram/xdr/CtrlWithPhy.scala similarity index 98% rename from tester/src/test/scala/spinal/tester/scalatest/SdramXdrSdrSpinalSim.scala rename to lib/src/test/scala/spinal/lib/memory/sdram/xdr/CtrlWithPhy.scala index 417a1603de..b1042a868d 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/SdramXdrSdrSpinalSim.scala +++ b/lib/src/test/scala/spinal/lib/memory/sdram/xdr/CtrlWithPhy.scala @@ -1,17 +1,14 @@ -package spinal.tester.scalatest +package spinal.lib.memory.sdram.xdr import spinal.core._ -import spinal.core.sim.SpinalSimConfig -import spinal.lib.bus.bmb._ -import spinal.lib.memory.sdram.sdr.{MT41K128M16JT, MT47H64M16HR, MT48LC16M16A2, SdramInterface} -import spinal.lib.memory.sdram.xdr.{BmbPortParameter, CoreParameter, CtrlParameter, CtrlWithPhy, CtrlWithoutPhy, PhyLayout, SdramTiming, SoftConfig, mt48lc16m16a2_model} import spinal.lib._ + +import spinal.lib.bus.bmb.{Bmb, BmbParameter} +import spinal.lib.memory.sdram.sdr.{MT41K128M16JT, MT47H64M16HR, MT48LC16M16A2} import spinal.lib.bus.amba3.apb.Apb3 import spinal.lib.bus.amba3.apb.sim.Apb3Driver import spinal.lib.bus.bmb.sim.{BmbMemoryMultiPort, BmbMemoryMultiPortTester} import spinal.lib.eda.bench.Rtl -import spinal.lib.memory.sdram.SdramLayout -import spinal.lib.memory.sdram.sdr.sim.SdramModel import spinal.lib.memory.sdram.xdr.phy.{Ecp5Sdrx2Phy, RtlPhy, RtlPhyInterface, SdrInferedPhy, XilinxS7Phy} import spinal.lib.sim.Phase @@ -550,7 +547,6 @@ object SdramXdrTesterHelpers{ } } - object SdramXdrDdr3SpinalSim extends App{ import spinal.core.sim._ @@ -595,9 +591,6 @@ object SdramXdrDdr3SpinalSim extends App{ } } - - - object SdramXdrDdr2SpinalSim extends App{ import spinal.core.sim._ @@ -640,8 +633,6 @@ object SdramXdrDdr2SpinalSim extends App{ } } - - object SdramXdrSdrSpinalSim extends App{ import spinal.core.sim._ @@ -687,15 +678,8 @@ object SdramXdrSdrSpinalSim extends App{ } } - - - - - -import spinal.core._ -import spinal.lib.eda.bench._ - -object SdramSdrSyntBench extends App{ +object SdramSdrSyntBench extends App { + import spinal.lib.eda.bench._ val ports4 = new Rtl { override def getName(): String = "Port4" @@ -773,7 +757,6 @@ object SdramSdrSyntBench extends App{ }) } - val rtls = List(ports4) val targets = XilinxStdTargets( @@ -781,13 +764,8 @@ object SdramSdrSyntBench extends App{ ) Bench(rtls, targets) - - - - } - object SdramSdrGen extends App{ SpinalVerilog({ val sl = MT48LC16M16A2.layout.copy(bankWidth = 3) @@ -860,4 +838,4 @@ object SdramSdrGen extends App{ val c = new CtrlWithoutPhy(cp, SdrInferedPhy.phyLayout(sl)) c }) -} \ No newline at end of file +} diff --git a/tester/src/test/scala/spinal/tester/scalatest/PDMTester.scala b/lib/src/test/scala/spinal/lib/misc/PDM.scala similarity index 88% rename from tester/src/test/scala/spinal/tester/scalatest/PDMTester.scala rename to lib/src/test/scala/spinal/lib/misc/PDM.scala index 844e5848c7..77ef977c33 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/PDMTester.scala +++ b/lib/src/test/scala/spinal/lib/misc/PDM.scala @@ -1,8 +1,7 @@ -package spinal.tester.scalatest +package spinal.lib.misc.pdm import spinal.core._ -import spinal.lib._ -import spinal.lib.misc.pdm._ +import spinal.tester.SpinalTesterCocotbBase class PDMTester extends Component { val io = new Bundle { diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimSigmaDeltaTester.scala b/lib/src/test/scala/spinal/lib/misc/analog/DacSigmaDelta.scala similarity index 76% rename from tester/src/test/scala/spinal/tester/scalatest/SpinalSimSigmaDeltaTester.scala rename to lib/src/test/scala/spinal/lib/misc/analog/DacSigmaDelta.scala index 2d69aad905..7ed6d1fa64 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimSigmaDeltaTester.scala +++ b/lib/src/test/scala/spinal/lib/misc/analog/DacSigmaDelta.scala @@ -1,20 +1,17 @@ -package spinal.tester.scalatest +package spinal.lib.misc.analog import org.scalatest.funsuite.AnyFunSuite -import spinal.core._ + import spinal.core.sim._ -import spinal.lib._ import spinal.lib.bus.bmb.sim.BmbDriver -import spinal.lib.bus.bmb.{BmbAccessCapabilities, BmbParameter} -import spinal.lib.bus.bsb.sim.{BsbBridgeTester, BsbDriver, BsbPacket} -import spinal.lib.bus.bsb.{Bsb, BsbDownSizerSparse, BsbParameter, BsbUpSizerDense, BsbUpSizerSparse} -import spinal.lib.misc.analog.{BmbBsbToDeltaSigma, BsbToDeltaSigmaParameter} +import spinal.lib.bus.bmb.BmbParameter +import spinal.lib.bus.bsb.sim.{BsbDriver, BsbPacket} +import spinal.lib.bus.bsb.{Bsb, BsbParameter} import spinal.lib.sim.StreamDriver -import spinal.lib.system.dma.sg.DmaSg import scala.collection.mutable -class SpinalSimSigmaDeltaTester extends AnyFunSuite{ +class SpinalSimDeltaSigmaTester extends AnyFunSuite{ test("a"){ SimConfig.compile( BmbBsbToDeltaSigma( diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimPlicTester.scala b/lib/src/test/scala/spinal/lib/misc/plic/PlicMapper.scala similarity index 96% rename from tester/src/test/scala/spinal/tester/scalatest/SpinalSimPlicTester.scala rename to lib/src/test/scala/spinal/lib/misc/plic/PlicMapper.scala index 82dc6c56ef..8396d772a3 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimPlicTester.scala +++ b/lib/src/test/scala/spinal/lib/misc/plic/PlicMapper.scala @@ -1,19 +1,16 @@ -package spinal.tester.scalatest +package spinal.lib.misc.plic + +import spinal.tester.SpinalSimFunSuite -import org.scalatest.funsuite.AnyFunSuite import spinal.core._ import spinal.core.sim._ import spinal.lib._ -import spinal.lib.bus.amba3.apb.sim.Apb3Driver import spinal.lib.bus.amba3.apb.{Apb3, Apb3SlaveFactory} -import spinal.lib.misc.plic.{PlicGatewayActiveHigh, PlicMapper, PlicMapping, PlicTarget} -import spinal.lib.sim._ -import spinal.sim._ +import spinal.lib.bus.amba3.apb.sim.Apb3Driver import scala.collection.mutable.ArrayBuffer import scala.util.Random - class SpinalSimPlicTester extends SpinalSimFunSuite { test("test1") { //Compile the simulator diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimPhaseTester.scala b/lib/src/test/scala/spinal/lib/sim/Misc.scala similarity index 96% rename from tester/src/test/scala/spinal/tester/scalatest/SpinalSimPhaseTester.scala rename to lib/src/test/scala/spinal/lib/sim/Misc.scala index fd85b2d86a..2059bf6965 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimPhaseTester.scala +++ b/lib/src/test/scala/spinal/lib/sim/Misc.scala @@ -1,8 +1,9 @@ -package spinal.tester.scalatest +package spinal.lib.sim import org.scalatest.funsuite.AnyFunSuite +import spinal.tester.SpinalSimFunSuite + import spinal.core.sim._ -import spinal.lib.sim._ import spinal.core._ import spinal.lib._ import spinal.lib.graphic.Rgb diff --git a/lib/src/test/scala/spinal/lib/soc/pinsec/Pinsec.scala b/lib/src/test/scala/spinal/lib/soc/pinsec/Pinsec.scala new file mode 100644 index 0000000000..5699bbea29 --- /dev/null +++ b/lib/src/test/scala/spinal/lib/soc/pinsec/Pinsec.scala @@ -0,0 +1,55 @@ +package spinal.lib.soc.pinsec + +import org.scalatest.{Stepwise, Sequential, Suites} +import spinal.tester.SpinalTesterCocotbBase + +import spinal.core._ +import spinal.lib._ +import spinal.lib.io.TriStateArray +import spinal.lib.com.jtag.Jtag +import spinal.lib.com.uart.Uart + +class PinsecTesterCocotbBoot extends SpinalTesterCocotbBase { + override def getName: String = "PinsecTester" + + override def pythonTests: Seq[(String, String)] = List( + "jtag" -> "tester/src/test/python/spinal/Pinsec/jtag", + "uart" -> "tester/src/test/python/spinal/Pinsec/uart" + ) + + override def createToplevel: Component = { + val pinsec = new Pinsec(PinsecConfig.default.copy(axiFrequency = 133 MHz)) + pinsec.axi.ram.ram.randBoot() + + val sdramPowerupCounter = pinsec.axi.sdramCtrl.ctrl.powerup.counter + sdramPowerupCounter.component.rework( + sdramPowerupCounter init sdramPowerupCounter.maxValue - 100 + ) + + val miaou = pinsec.axi.ram.rework(new Area { + import pinsec.axi.ram._ + + val port = ram.writePort + port.valid.setName("ram_port0_write") := False + port.address.setName("ram_port0_address") := 0 + port.data.setName("ram_port0_writeData") := 0 + + val a = Bool().setName("ram_port0_enable") + val b = Bits(4 bits).setName("ram_port0_mask") + a := False + b := 0 + }) + + miaou.a.pull() + miaou.b.pull() + pinsec + } + + override def backendConfig(config: SpinalConfig) = config.mode match { + case `Verilog` => + config.copy(mergeAsyncProcess = false) // avoid iverilog bug + case _ => config + } + + override def noVhdl = true +} diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimDmaSgTester.scala b/lib/src/test/scala/spinal/lib/system/dma/sg/DmaSg.scala similarity index 54% rename from tester/src/test/scala/spinal/tester/scalatest/SpinalSimDmaSgTester.scala rename to lib/src/test/scala/spinal/lib/system/dma/sg/DmaSg.scala index 8948fe7674..ed9bb1b099 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimDmaSgTester.scala +++ b/lib/src/test/scala/spinal/lib/system/dma/sg/DmaSg.scala @@ -1,14 +1,8 @@ -package spinal.tester.scalatest +package spinal.lib.system.dma.sg import org.scalatest.funsuite.AnyFunSuite -import spinal.core.HardType -import spinal.lib.bus.bmb.{Bmb, BmbParameter, BmbSlaveFactory} -import spinal.lib.bus.bmb.sim.{BmbDriver, BmbMemoryAgent} -import spinal.lib.system.dma.sg.{DmaSg, DmaSgTester, SgDmaTestsParameter} -import spinal.core.sim._ import scala.util.Random -import org.scalatest.{ParallelTestExecution, BeforeAndAfterAll} class SpinalSimDmaSgTester extends AnyFunSuite { Random.setSeed(42) diff --git a/tester/src/main/scala/spinal/tester/GenerationShould.scala b/tester/src/main/scala/spinal/tester/GenerationShould.scala new file mode 100644 index 0000000000..0a887ef78b --- /dev/null +++ b/tester/src/main/scala/spinal/tester/GenerationShould.scala @@ -0,0 +1,24 @@ +package spinal.tester + +import spinal.core._ + +object GenerationShould { + private def fails(f: => Unit): Boolean = { + var failed = false + try { f } + catch { + case e: Throwable => failed = true + } + failed + } + + def fail(gen: => Component): Unit = { + assert(fails { SpinalVhdl(gen) }) + assert(fails { SpinalVerilog(gen) }) + } + + def pass(gen: => Component): Unit = { + assert(!fails { SpinalVhdl(gen) }) + assert(!fails { SpinalVerilog(gen) }) + } +} diff --git a/tester/src/main/scala/spinal/tester/RepeatabilitySuite.scala b/tester/src/main/scala/spinal/tester/RepeatabilitySuite.scala new file mode 100644 index 0000000000..023d86baf1 --- /dev/null +++ b/tester/src/main/scala/spinal/tester/RepeatabilitySuite.scala @@ -0,0 +1,32 @@ +package spinal.tester + +import org.scalatest.funsuite.AnyFunSuite + +import spinal.core._ + +import java.io.File +import org.apache.commons.io.FileUtils + +class RepeatabilitySuite extends AnyFunSuite { + var checkOutputHashCounter = 0 + def checkOutputHash(gen: => Component): Unit = { + checkOutputHashCounter = checkOutputHashCounter + 1 + var ref = "" + for (i <- 0 until 8) { + val report = + SpinalConfig(defaultClockDomainFrequency = FixedFrequency(50 MHz)) + .generateVerilog( + gen.setDefinitionName(s"checkOutputHash_${checkOutputHashCounter}") + ) + FileUtils.copyFile( + new File(report.generatedSourcesPaths.head), + new File(report.generatedSourcesPaths.head + "_" + i + ".v") + ) + + import sys.process._ + val hash = s"md5sum ${report.generatedSourcesPaths.head}".!! + if (i == 0) ref = hash + else assert(ref == hash) + } + } +} diff --git a/tester/src/main/scala/spinal/tester/SpinalSimFunSuite.scala b/tester/src/main/scala/spinal/tester/SpinalSimFunSuite.scala new file mode 100644 index 0000000000..ccd8723f56 --- /dev/null +++ b/tester/src/main/scala/spinal/tester/SpinalSimFunSuite.scala @@ -0,0 +1,34 @@ +package spinal.tester + +import org.scalatest.funsuite.AnyFunSuite + +class SpinalSimFunSuite extends AnyFunSuite { + var tester: SpinalSimTester = null + def SimConfig = tester.SimConfig + var durationFactor = 0.0 + var ghdlEnabled = true + var iverilogEnabled = true + + def onlyVerilator(): Unit = { + iverilogEnabled = false + ghdlEnabled = false + } + + def test(testName: String)(testFun: => Unit): Unit = { + super.test("verilator_" + testName) { + tester = SpinalSimTester.Verilator + durationFactor = SpinalSimTester.Verilator.durationFactor + testFun + } + if (ghdlEnabled) super.test("ghdl_" + testName) { + tester = SpinalSimTester.Ghdl + durationFactor = SpinalSimTester.Ghdl.durationFactor + testFun + } + if (iverilogEnabled) super.test("iverilog_" + testName) { + tester = SpinalSimTester.IVerilog + durationFactor = SpinalSimTester.IVerilog.durationFactor + testFun + } + } +} diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimMiscTester.scala b/tester/src/main/scala/spinal/tester/SpinalSimMiscTester.scala similarity index 76% rename from tester/src/test/scala/spinal/tester/scalatest/SpinalSimMiscTester.scala rename to tester/src/main/scala/spinal/tester/SpinalSimMiscTester.scala index 8dede4724d..d896b21ff3 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimMiscTester.scala +++ b/tester/src/main/scala/spinal/tester/SpinalSimMiscTester.scala @@ -1,16 +1,12 @@ -package spinal.tester.scalatest +package spinal.tester -import org.scalatest.{FixtureContext, Succeeded} import org.scalatest.funsuite.AnyFunSuite -import spinal.core._ +import scala.util.Random + import spinal.sim._ -import spinal.core.sim.{SpinalSimConfig, _} +import spinal.core._ +import spinal.core.sim._ import spinal.lib.{BufferCC, OHMasking, SetFromFirstOne} -import spinal.tester -import spinal.tester.scalatest - -import scala.concurrent.{Await, Future} -import scala.util.Random object SpinalSimMiscTester{ class SpinalSimMiscTesterCounter extends Component{ @@ -28,91 +24,10 @@ object SpinalSimMiscTester{ } -abstract class SpinalSimTester{ - def SimConfig : SpinalSimConfig - def durationFactor : Double - def designFactor : Double - def prefix : String - def language : SpinalMode -} - -object SpinalSimTesterGhdl extends SpinalSimTester{ - override def SimConfig: SpinalSimConfig = spinal.core.sim.SimConfig.withGhdl - override def durationFactor: Double = 0.005 - override def designFactor: Double = 0.05 - override def prefix: String = "ghdl_" - override def language: SpinalMode = VHDL -} - -object SpinalSimTesterIVerilog extends SpinalSimTester{ - override def SimConfig: SpinalSimConfig = spinal.core.sim.SimConfig.withIVerilog - override def durationFactor: Double = 0.005 - override def designFactor: Double = 0.05 - override def prefix: String = "iverilog_" - override def language: SpinalMode = Verilog -} - -object SpinalSimTesterVerilator extends SpinalSimTester{ - override def SimConfig: SpinalSimConfig = spinal.core.sim.SimConfig.withVerilator - override def durationFactor: Double = 0.5 - override def designFactor: Double = 0.5 - override def prefix: String = "verilator_" - override def language: SpinalMode = Verilog -} - -object SpinalSimTester{ - - def apply(body : => SpinalSimTester => Unit): Unit = { - body(SpinalSimTesterGhdl) - body(SpinalSimTesterIVerilog) - body(SpinalSimTesterVerilator) - } -} - -class SpinalSimTesterTest extends AnyFunSuite { - SpinalSimTester{ env => - import env._ - - test(prefix + "a"){ - println(SimConfig._backend + " " + durationFactor) - } - } -} - -class SpinalSimFunSuite extends AnyFunSuite{ - var tester : SpinalSimTester = null - def SimConfig = tester.SimConfig - var durationFactor = 0.0 - var ghdlEnabled = true - var iverilogEnabled = true - - def onlyVerilator(): Unit ={ - iverilogEnabled = false - ghdlEnabled = false - } - def test(testName: String)(testFun: => Unit): Unit = { - super.test("verilator_" + testName) { - tester = SpinalSimTesterVerilator - durationFactor = SpinalSimTesterVerilator.durationFactor - testFun - } - if(ghdlEnabled) super.test("ghdl_" + testName) { - tester = SpinalSimTesterGhdl - durationFactor = SpinalSimTesterGhdl.durationFactor - testFun - } - if(iverilogEnabled) super.test("iverilog_" + testName) { - tester = SpinalSimTesterIVerilog - durationFactor = SpinalSimTesterIVerilog.durationFactor - testFun - } - } -} - class SpinalSimMiscTester extends AnyFunSuite { SpinalSimTester { env => import env._ - var compiled: SimCompiled[tester.scalatest.SpinalSimMiscTester.SpinalSimMiscTesterCounter] = null + var compiled: SimCompiled[SpinalSimMiscTester.SpinalSimMiscTesterCounter] = null test(prefix + "testForkSensitive") { SimConfig.compile(new Component { @@ -137,7 +52,7 @@ class SpinalSimMiscTester extends AnyFunSuite { test(prefix + "compile") { - compiled = SimConfig.compile(new tester.scalatest.SpinalSimMiscTester.SpinalSimMiscTesterCounter) + compiled = SimConfig.compile(new SpinalSimMiscTester.SpinalSimMiscTesterCounter) } def doStdtest(name: String): Unit = { @@ -292,7 +207,7 @@ class SpinalSimMiscTester extends AnyFunSuite { } test(prefix + "testRecompile1") { - SimConfig.doSim(new tester.scalatest.SpinalSimMiscTester.SpinalSimMiscTesterCounter)(dut => { + SimConfig.doSim(new SpinalSimMiscTester.SpinalSimMiscTesterCounter)(dut => { dut.clockDomain.forkStimulus(10) var counterModel = 0 @@ -311,7 +226,7 @@ class SpinalSimMiscTester extends AnyFunSuite { test(prefix + "testRecompile2") { - SimConfig.doSim(new tester.scalatest.SpinalSimMiscTester.SpinalSimMiscTesterCounter)(dut => { + SimConfig.doSim(new SpinalSimMiscTester.SpinalSimMiscTesterCounter)(dut => { dut.clockDomain.forkStimulus(10) var counterModel = 0 diff --git a/tester/src/main/scala/spinal/tester/SpinalSimTester.scala b/tester/src/main/scala/spinal/tester/SpinalSimTester.scala new file mode 100644 index 0000000000..e228650db3 --- /dev/null +++ b/tester/src/main/scala/spinal/tester/SpinalSimTester.scala @@ -0,0 +1,44 @@ +package spinal.tester + +import spinal.core.sim.SpinalSimConfig +import spinal.core.{SpinalMode, Verilog, VHDL} + +abstract class SpinalSimTester { + def SimConfig: SpinalSimConfig + def durationFactor: Double + def designFactor: Double + def prefix: String + def language: SpinalMode +} + +object SpinalSimTester { + def apply(body: => SpinalSimTester => Unit): Unit = { + body(Ghdl) + body(IVerilog) + body(Verilator) + } + + object Ghdl extends SpinalSimTester { + override def SimConfig: SpinalSimConfig = spinal.core.sim.SimConfig.withGhdl + override def durationFactor: Double = 0.005 + override def designFactor: Double = 0.05 + override def prefix: String = "ghdl_" + override def language: SpinalMode = VHDL + } + + object IVerilog extends SpinalSimTester { + override def SimConfig: SpinalSimConfig = spinal.core.sim.SimConfig.withIVerilog + override def durationFactor: Double = 0.005 + override def designFactor: Double = 0.05 + override def prefix: String = "iverilog_" + override def language: SpinalMode = Verilog + } + + object Verilator extends SpinalSimTester { + override def SimConfig: SpinalSimConfig = spinal.core.sim.SimConfig.withVerilator + override def durationFactor: Double = 0.5 + override def designFactor: Double = 0.5 + override def prefix: String = "verilator_" + override def language: SpinalMode = Verilog + } +} diff --git a/tester/src/main/scala/spinal/tester/SpinalSimTesterTest.scala b/tester/src/main/scala/spinal/tester/SpinalSimTesterTest.scala new file mode 100644 index 0000000000..1c9c9d8265 --- /dev/null +++ b/tester/src/main/scala/spinal/tester/SpinalSimTesterTest.scala @@ -0,0 +1,13 @@ +package spinal.tester + +import org.scalatest.funsuite.AnyFunSuite + +class SpinalSimTesterTest extends AnyFunSuite { + SpinalSimTester{ env => + import env._ + + test(prefix + "a"){ + println(SimConfig._backend + " " + durationFactor) + } + } +} diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalTesterCocotbBase.scala b/tester/src/main/scala/spinal/tester/SpinalTesterCocotbBase.scala similarity index 99% rename from tester/src/test/scala/spinal/tester/scalatest/SpinalTesterCocotbBase.scala rename to tester/src/main/scala/spinal/tester/SpinalTesterCocotbBase.scala index 90f97b7e3a..19d05dc5ea 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalTesterCocotbBase.scala +++ b/tester/src/main/scala/spinal/tester/SpinalTesterCocotbBase.scala @@ -1,4 +1,4 @@ -package spinal.tester.scalatest +package spinal.tester import java.io.File import java.nio.charset.Charset diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalTesterGhdlBase.scala b/tester/src/main/scala/spinal/tester/SpinalTesterGhdlBase.scala similarity index 98% rename from tester/src/test/scala/spinal/tester/scalatest/SpinalTesterGhdlBase.scala rename to tester/src/main/scala/spinal/tester/SpinalTesterGhdlBase.scala index 3e97c49c51..d61badb871 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalTesterGhdlBase.scala +++ b/tester/src/main/scala/spinal/tester/SpinalTesterGhdlBase.scala @@ -1,6 +1,7 @@ -package spinal.tester.scalatest +package spinal.tester import org.scalatest.funsuite.AnyFunSuite + import spinal.core._ import scala.sys.process._ diff --git a/tester/src/test/scala/spinal/tester/scalatest/Issue963Tester.scala b/tester/src/test/scala/fixes/Issue963.scala similarity index 96% rename from tester/src/test/scala/spinal/tester/scalatest/Issue963Tester.scala rename to tester/src/test/scala/fixes/Issue963.scala index 3b9eea9be7..07579f2b8a 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/Issue963Tester.scala +++ b/tester/src/test/scala/fixes/Issue963.scala @@ -1,10 +1,10 @@ -package spinal.tester.scalatest +package fixes import org.scalatest.funsuite.AnyFunSuite import spinal.core._ -import spinal.lib._ import spinal.core.sim._ +import spinal.lib._ // unit test for issue #963 @@ -27,7 +27,7 @@ import spinal.core.sim._ // [info] Tests: succeeded 0, failed 1, canceled 0, ignored 0, pending 0 // [info] *** 1 TEST FAILED *** -class Issue963Tester extends AnyFunSuite { +class Issue963 extends AnyFunSuite { test("Minimal example for Issue963 which fails Spinal elaboration") { class Dut extends Component { val io = new Bundle { diff --git a/tester/src/test/scala/spinal/tester/scalatest/PR990TesterDut.scala b/tester/src/test/scala/fixes/Pr990.scala similarity index 95% rename from tester/src/test/scala/spinal/tester/scalatest/PR990TesterDut.scala rename to tester/src/test/scala/fixes/Pr990.scala index 4733811f17..8e01b7dc64 100644 --- a/tester/src/test/scala/spinal/tester/scalatest/PR990TesterDut.scala +++ b/tester/src/test/scala/fixes/Pr990.scala @@ -1,4 +1,6 @@ -package spinal.tester.scalatest +package fixes + +import spinal.tester.SpinalSimFunSuite import spinal.core._ import spinal.core.sim._ @@ -34,7 +36,7 @@ class PR990TesterDut extends Component { ) } -class PR990Tester extends SpinalSimFunSuite { +class Pr990 extends SpinalSimFunSuite { test("ccexercise") { val sim =SpinalSimConfig().allOptimisation.compile(new PR990TesterDut) sim.doSimUntilVoid("ccexercise") { dut => diff --git a/tester/src/test/scala/spinal/demo/mandelbrot/Common.scala b/tester/src/test/scala/spinal/demo/mandelbrot/Common.scala deleted file mode 100644 index 0625fd31e1..0000000000 --- a/tester/src/test/scala/spinal/demo/mandelbrot/Common.scala +++ /dev/null @@ -1,33 +0,0 @@ -package spinal.demo.mandelbrot - -import spinal.core._ - -import scala.util.Random - -//This class is used everywhere into the mandelbrot core as "generic" "construction" parameter -case class MandelbrotCoreParameters(iterationLimit: Int, - pixelTaskSolverCount: Int, - screenResX: Int, - screenResY: Int, - fixExp: Int, - fixWidth: Int) { - def fix = SFix(fixExp exp, fixWidth bit) - def iterationWidth = log2Up(iterationLimit + 1) - - val uid : Int = Random.nextInt() -} - - -case class FrameTask(p: MandelbrotCoreParameters) extends Bundle { - val start = SFix2D(p.fixExp exp, p.fixWidth bit) - val inc = SFix2D(p.fixExp - 4 exp, p.fixWidth + 8 bit) - - def fullRangeSFix = SFix(p.fixExp exp, p.fixWidth + 12 bit) -} - -case class PixelTask(p: MandelbrotCoreParameters) extends Bundle { - val mandelbrotPosition = SFix2D(p.fix) -} -case class PixelResult(p: MandelbrotCoreParameters) extends Bundle { - val iteration = UInt(p.iterationWidth bit) -} \ No newline at end of file diff --git a/tester/src/test/scala/spinal/demo/mandelbrot/FrameTaskSolver.scala b/tester/src/test/scala/spinal/demo/mandelbrot/FrameTaskSolver.scala deleted file mode 100644 index 86c29ab7e7..0000000000 --- a/tester/src/test/scala/spinal/demo/mandelbrot/FrameTaskSolver.scala +++ /dev/null @@ -1,192 +0,0 @@ -package spinal.demo.mandelbrot - -import spinal.core._ -import spinal.lib._ -import spinal.lib.math.SIntMath - - -class FrameTaskSolver(p: MandelbrotCoreParameters) extends Component { - val io = new Bundle { - val frameTask = slave Stream FrameTask(p) - val pixelResult = master Stream Fragment(PixelResult(p)) - } - - val pixelTaskGenerator = new PixelTaskGenerator(p) - val pixelTaskDispatcher = new StreamDispatcherSequencial(Fragment(PixelTask(p)), p.pixelTaskSolverCount) - val pixelTaskSolver = List.fill(p.pixelTaskSolverCount)(new PixelTaskSolver(p)) - val pixelResultArbiter = StreamArbiterFactory.sequentialOrder.build(Fragment(PixelResult(p)), p.pixelTaskSolverCount) - - pixelTaskGenerator.io.frameTask << io.frameTask - pixelTaskDispatcher.io.input <-/< pixelTaskGenerator.io.pixelTask - for (solverId <- 0 until p.pixelTaskSolverCount) { - pixelTaskSolver(solverId).io.pixelTask << pixelTaskDispatcher.io.outputs(solverId) - pixelResultArbiter.io.inputs(solverId) << pixelTaskSolver(solverId).io.pixelResult - } - io.pixelResult <-< pixelResultArbiter.io.output -} - -// The scala-like way to do the FrameTaskSolver stuff is : - -// val pixelTaskGenerator = new PixelTaskGenerator(p) -// pixelTaskGenerator.io.frameTask << io.frameTask -// -// val pixelTaskDispatcher = new DispatcherInOrder(Fragment(PixelTask(p)), p.unitCount) -// pixelTaskDispatcher.io.input <-/< pixelTaskGenerator.io.pixelTask -// -// val pixelTaskSolver = List.fill(p.pixelTaskSolverCount)(new PixelTaskSolver(p)) -// (pixelTaskSolver, pixelTaskDispatcher.io.outputs).zipped.foreach(_.io.pixelTask <-/< _) -// -// val pixelTaskResultArbiter = StreamArbiter.inOrder.build(Fragment(PixelResult(p)), p.unitCount) -// (pixelTaskSolver, pixelTaskResultArbiter.io.inputs).zipped.foreach(_.io.result >/> _) -// -// pixelTaskResultArbiter.io.output >-> io.pixelResult - - -class PixelTaskGenerator(p: MandelbrotCoreParameters) extends Component { - val io = new Bundle { - val frameTask = slave Stream FrameTask(p) - val pixelTask = master Stream Fragment(PixelTask(p)) - } - - val positionOnScreen = Reg(UInt2D(log2Up(p.screenResX) bit, log2Up(p.screenResY) bit)) - val positionOnMandelbrot = Reg(SFix2D(io.frameTask.fullRangeSFix)) - val setup = RegInit(True) - - val solverTask = Stream(Fragment(PixelTask(p))) - - io.frameTask.ready := !io.frameTask.valid - - - when(io.frameTask.ready) { - setup := True - } - - when(io.frameTask.valid && solverTask.ready) { - when(setup) { - setup := False - positionOnScreen.x := 0 - positionOnScreen.y := 0 - positionOnMandelbrot := io.frameTask.start - }otherwise { - when(positionOnScreen.x =/= p.screenResX - 1) { - positionOnScreen.x := positionOnScreen.x + 1 - positionOnMandelbrot.x := positionOnMandelbrot.x + io.frameTask.inc.x - }otherwise { - positionOnScreen.x := 0 - positionOnMandelbrot.x := io.frameTask.start.x - when(positionOnScreen.y =/= p.screenResY - 1) { - positionOnScreen.y := positionOnScreen.y + 1 - positionOnMandelbrot.y := positionOnMandelbrot.y + io.frameTask.inc.y - }otherwise { - positionOnMandelbrot.y := io.frameTask.start.y - io.frameTask.ready := True //Asynchronous acknoledge into synchronous space <3 - } - } - } - } - - solverTask.valid := io.frameTask.valid && !setup; - solverTask.last := io.frameTask.ready - solverTask.fragment.mandelbrotPosition := positionOnMandelbrot.truncated - solverTask >-> io.pixelTask - -} - -class PixelTaskSolver(p: MandelbrotCoreParameters) extends Component { - val io = new Bundle { - val pixelTask = slave Stream Fragment(PixelTask(p)) - val pixelResult = master Stream Fragment(PixelResult(p)) - } - - //It's the context definition used by each stage of the pipeline, Each task are translated to context ("thread") - class Context extends Bundle { - val task = PixelTask(p) - val lastPixel = Bool() - val done = Bool() - val order = UInt(5 bit) - //Used to reorder result in same oder than input task - val iteration = UInt(p.iterationWidth bit) - val z = SFix2D(p.fix) - } - - //Extended context with x*x y*y x*y result - class Stage2Context extends Context { - val zXzX = p.fix - val zYzY = p.fix - val zXzY = p.fix - } - - val insertTaskOrder = Counter(32, io.pixelTask.fire) - - //Task to insert into the pipeline - val taskToInsert: Stream[Context] = io.pixelTask.translateInto(Stream(new Context))((to, from) => { - to.task := from.fragment - to.lastPixel := from.last - to.done := False - to.order := insertTaskOrder - to.iteration := 0 - to.z := from.fragment.mandelbrotPosition - }) - val loopBack = RegFlow(new Context) - //Loop back from end of pipeline - val stage0 = StreamFlowArbiter(taskToInsert, loopBack) //First stage - - - //Stage1 is a routing stage - val stage1 = DelayWithInit(stage0, 2)((reg) => reg.valid.init(False)) - - - - //Stage2 get multiplication result of x*x y*y and x*y - val stage2 = RegFlow(new Stage2Context) - - def fixMul(a: SFix, b: SFix): SFix = { - val ret = SFix(a.maxExp + b.maxExp + 1 exp, a.bitCount + b.bitCount bit) - // SIntMath.mul is a pipelined implementation of the signed multiplication operator - //(leftSigned, rightSigned, number of bit per multiplicator, trunk bits bellow this limit, ...) - ret.raw := SIntMath.mul(a.raw, b.raw, 17, p.fixWidth - p.fixExp, 1, (stage, level) => RegNext(stage)) - ret - - // return a*b - } - - - stage2.zXzX := fixMul(stage1.z.x, stage1.z.x).truncated - stage2.zYzY := fixMul(stage1.z.y, stage1.z.y).truncated - stage2.zXzY := fixMul(stage1.z.x, stage1.z.y).truncated - val stage1ToStage2Latency = LatencyAnalysis(stage1.z.x.raw, stage2.zXzX.raw) - 1 - stage2 assignSomeByName DelayWithInit(stage1, stage1ToStage2Latency)((reg) => reg.valid.init(False)) - - //Stage3 calculate next position of the iteration (zX,zY) - // Increment the iteration count if was not done - // calculate if the "Thread" has rush a end condition (iteration > N, x*x+y*y + 4) - val stage3 = RegFlow(new Context) - stage3 assignAllByName stage2 - stage3.allowOverride - stage3.z.x := stage2.zXzX - stage2.zYzY + stage2.task.mandelbrotPosition.x - stage3.z.y := ((stage2.zXzY << 1) + stage2.task.mandelbrotPosition.y).truncated - when(!stage2.done) { - stage3.iteration := stage2.iteration + 1 - } - when(stage2.iteration >= p.iterationLimit | stage2.zXzX + stage2.zYzY >= 4.0) { - stage3.done := True - } - - - //End Stage put to the output the result if it's finished and in right order - // else put it into the feedback to redo iteration or to waiting - val result = Stream(Fragment(PixelResult(p))) - val resultOrder = Counter(32, result.fire) - val readyForResult = stage3.done && resultOrder === stage3.order - - - result.valid := stage3.valid && readyForResult - result.last := stage3.lastPixel - result.fragment.iteration := stage3.iteration - 1 - - - result >-> io.pixelResult - - loopBack.valid := stage3.valid && ((!readyForResult) || (!result.ready)) - loopBack.payload := stage3.payload -} diff --git a/tester/src/test/scala/spinal/demo/mandelbrot/MandelbrotCore.scala b/tester/src/test/scala/spinal/demo/mandelbrot/MandelbrotCore.scala deleted file mode 100644 index e4aa529da4..0000000000 --- a/tester/src/test/scala/spinal/demo/mandelbrot/MandelbrotCore.scala +++ /dev/null @@ -1,102 +0,0 @@ -package spinal.demo.mandelbrot - -import spinal.core._ -import spinal.lib._ - -case class MandelbrotCoreConfig(p: MandelbrotCoreParameters) extends Bundle { - val frameTaskFilterEnable = Bool() -} - -class CmdInterface(p: MandelbrotCoreParameters) extends Component { - val io = new Bundle { - val cmdPort = slave Flow Fragment(Bits(8 bit)) - val retPort = master Stream Fragment(Bits(8 bit)) - val frameTask = master Flow FrameTask(p) - val coreConfig = out(MandelbrotCoreConfig(p)) - } - - io.frameTask << io.cmdPort.filterHeader(0x01).toFlowOf(FrameTask(p)) - io.coreConfig := io.cmdPort.filterHeader(0x02).toRegOf(MandelbrotCoreConfig(p)) - io.coreConfig.frameTaskFilterEnable init (False) - - val passport = io.cmdPort.eventOn(0xFF).translateWith(S(p.uid, 32 bit)).fragmentTransaction(8) - io.retPort << passport -} - -class FrameTaskFilter(p: MandelbrotCoreParameters) extends Component { - val io = new Bundle { - val input = slave Flow FrameTask(p) - val output = master Flow FrameTask(p) - } - - val filterIn = io.input.toReg - filterIn.start.x init (-1.0) - filterIn.start.y init (-1.0) - filterIn.inc.x init (2.0 / p.screenResX) - filterIn.inc.y init (2.0 / p.screenResY) - - def rcFilter(in: SFix, tao: Double, enable: Bool, enableHz: Double): SFix = { - val shiftRight = log2Up(BigDecimal(enableHz * tao).toBigInt) - val out = Reg(in) init (0) - when(enable) { - out := RegNext(((in - out) >>| shiftRight)) + out - } - out - } - def rcChainFilter(in: SFix, taos: Seq[Double], enable: Bool, enableHz: Double): SFix = { - var ptr = in - for (tao <- taos) { - ptr = rcFilter(ptr, tao, enable, enableHz) - } - ptr - } - - val clkHz = ClockDomain.current.frequency.getValue - val filterTaos = Seq(1.0, 2.0) - val filterHz = 120.0 - - val filterEnable = RegNext(CounterFreeRun((clkHz / filterHz).toInt).willOverflow) //TODO periodic pulse lib - - io.output.valid := True - io.output.start.x := rcChainFilter(filterIn.start.x, filterTaos, filterEnable, filterHz) - io.output.start.y := rcChainFilter(filterIn.start.y, filterTaos, filterEnable, filterHz) - io.output.inc.x := rcChainFilter(filterIn.inc.x, filterTaos, filterEnable, filterHz) - io.output.inc.y := rcChainFilter(filterIn.inc.y, filterTaos, filterEnable, filterHz) -} - - -class MandelbrotCore(p: MandelbrotCoreParameters) extends Component { - val io = new Bundle { - val cmdPort = slave Flow Fragment(Bits(8 bit)) - val retPort = master Stream Fragment(Bits(8 bit)) - - val pixelResult = master Stream Fragment(PixelResult(p)) - } - - val cmdInterface = new CmdInterface(p) - cmdInterface.io.cmdPort << io.cmdPort - cmdInterface.io.retPort >> io.retPort - - val frameTaskFilter = new FrameTaskFilter(p) - frameTaskFilter.io.input << cmdInterface.io.frameTask - - val frameTaskFilterBypass = Mux( - cmdInterface.io.coreConfig.frameTaskFilterEnable, - frameTaskFilter.io.output, - cmdInterface.io.frameTask - ) - - val frameTaskSolver = new FrameTaskSolver(p) - frameTaskSolver.io.frameTask <-< frameTaskFilterBypass.toStream - - // Force a initial frametask into the system. - // By this way, when the system is reseted, it draw directly something - frameTaskSolver.io.frameTask.valid init (True) - frameTaskSolver.io.frameTask.start.x init (-1.0) - frameTaskSolver.io.frameTask.start.y init (-1.0) - frameTaskSolver.io.frameTask.inc.x init (2.0 / p.screenResX) - frameTaskSolver.io.frameTask.inc.y init (2.0 / p.screenResY) - - io.pixelResult << frameTaskSolver.io.pixelResult - -} diff --git a/tester/src/test/scala/spinal/demo/mandelbrot/MandelbrotGui.scala b/tester/src/test/scala/spinal/demo/mandelbrot/MandelbrotGui.scala deleted file mode 100644 index 8eadf46784..0000000000 --- a/tester/src/test/scala/spinal/demo/mandelbrot/MandelbrotGui.scala +++ /dev/null @@ -1,199 +0,0 @@ -//package spinal.demo.mandelbrot -// -//import net.liftweb.json.DefaultFormats -//import net.liftweb.json.JsonAST.JValue -//import spinal.debugger.gui._ -//import spinal.lib.BitAggregator -// -//import scalafx.Includes._ -//import scalafx.application.Platform -//import scalafx.event.ActionEvent -//import scalafx.scene.canvas.Canvas -//import scalafx.scene.control.RadioButton -//import scalafx.scene.input.{MouseButton, MouseEvent} -//import scalafx.scene.layout.VBox -//import scalafx.scene.{Group, Scene} -//import scalafx.stage.Stage -// -// -//class MandelbrotManager(address: Seq[Byte], hal: IBytePacketHal, r: JValue) extends PeripheralManager(address, hal) { -// -// implicit val formats = DefaultFormats // Brings in default date formats etc. -// -// val p = r.\("p").extract[MandelbrotCoreParameters] -// -// sendConfig -// sendCoord(-1.0, -1.0, 1.0, 1.0) -// -// openGui -// // sendCoord(-1.0,-1.0,0.0,1.0) -// // sendCoord(-1.0,-1.0,1.0,1.0) -// implicit def easyByte(i: Int) = i.toByte -// def sendCoord(xStart: Double, yStart: Double, xEnd: Double, yEnd: Double) { -// val aggregator = new BitAggregator -// aggregator.add(0x01, 8) -// aggregator.add(BigDecimal(xStart * Math.pow(2, p.fixWidth - p.fixExp - 1)).toBigInt, p.fixWidth) -// aggregator.add(BigDecimal(yStart * Math.pow(2, p.fixWidth - p.fixExp - 1)).toBigInt, p.fixWidth) -// aggregator.add(BigDecimal((xEnd - xStart) / p.screenResX * Math.pow(2, p.fixWidth + 8 - 1 - (p.fixExp - 4))).toBigInt, p.fixWidth + 8) -// aggregator.add(BigDecimal((yEnd - yStart) / p.screenResY * Math.pow(2, p.fixWidth + 8 - 1 - (p.fixExp - 4))).toBigInt, p.fixWidth + 8) -// tx(aggregator.toBytes) -// } -// -// def sendConfig: Unit = { -// val aggregator = new BitAggregator -// aggregator.add(0x02, 8) -// aggregator.add(frameTaskFilterEnable) -// tx(aggregator.toBytes) -// } -// -// override def rx(packet: Seq[Byte]): Unit = { -// -// } -// -// var xStart = -1.0 -// var yStart = -1.0 -// var xEnd = 1.0 -// var yEnd = 1.0 -// var frameTaskFilterEnable = true -// -// -// def openGui: Unit = { -// Platform.runLater { -// -// val canvasBack = new Canvas(p.screenResX/2,p.screenResY/2) -// val canvasFront = new Canvas(p.screenResX/2,p.screenResY/2) -// def resX = canvasFront.getWidth.toInt -// def resY = canvasFront.getHeight.toInt -// val frameTaskFilterEnableBt = new RadioButton() { -// maxWidth = 200 -// maxHeight = 50 -// text = "Frame task filter" -// -// onAction = { -// e: ActionEvent => { -// frameTaskFilterEnable = delegate.isSelected -// sendConfig -// } -// } -// } -// -// val rootPane = new Group -// rootPane.children = List(canvasBack, canvasFront) -// canvasFront.toFront() -// val backGc = canvasBack.graphicsContext2D -// val frontGc = canvasFront.graphicsContext2D -// -// def drawMandelbrot: Unit = { -// val w = backGc.getPixelWriter -// val incX = (xEnd - xStart) / resX -// val incY = (yEnd - yStart) / resY -// for (y <- 0 until resY) { -// for (x <- 0 until resX) { -// val cx = xStart + incX * x -// val cy = yStart + incY * y -// def getIterCount: Int = { -// var mx = 0.0 -// var my = 0.0 -// val iterMax = 255 -// for (i <- 0 until iterMax) { -// val temp = mx * mx - my * my + cx -// my = 2.0 * mx * my + cy -// mx = temp -// if (mx * mx + my * my > 4) return i -// } -// return iterMax -// } -// w.setArgb(x, y, getIterCount + (0xFF000000)) -// } -// } -// } -// drawMandelbrot -// -// var dragStartX = 0.0 -// var dragStartY = 0.0 -// canvasFront.onMousePressed = (e: MouseEvent) => { -// // if (e.button == MouseButton.PRIMARY) { -// // dragStartX = e.x -// // dragStartY = e.y -// // } -// if (e.button == MouseButton.PRIMARY) { -// val newXStart = xStart + (xEnd - xStart) * (e.x / resX) * 0.5 -// val newYStart = yStart + (yEnd - yStart) * (e.y / resY) * 0.5 -// -// xEnd = xEnd - (xEnd - xStart) * (1 - (e.x / resX)) * 0.5 -// yEnd = yEnd - (yEnd - yStart) * (1 - (e.y / resY)) * 0.5 -// -// xStart = newXStart -// yStart = newYStart -// -// drawMandelbrot -// sendCoord(xStart, yStart, xEnd, yEnd) -// } -// if (e.button == MouseButton.SECONDARY) { -// val newXStart = xStart - (xEnd - xStart) * (e.x / resX) -// val newYStart = yStart - (yEnd - yStart) * (e.y / resY) -// -// xEnd = xEnd + (xEnd - xStart) * (1 - (e.x / resX)) -// yEnd = yEnd + (yEnd - yStart) * (1 - (e.y / resY)) -// -// xStart = newXStart -// yStart = newYStart -// -// drawMandelbrot -// sendCoord(xStart, yStart, xEnd, yEnd) -// } -// } -// -// // canvasFront.onMouseDragged = (e: MouseEvent) => { -// // if (e.button == MouseButton.PRIMARY) { -// // frontGc.clearRect(0, 0, resX, resY) -// // frontGc.setStroke(Color.White); -// // frontGc.strokeRect(dragStartX, dragStartY, -dragStartX + e.x, -dragStartY + e.y) -// // } -// // } -// // -// // canvasFront.onMouseReleased = (e: MouseEvent) => { -// // if (e.button == MouseButton.PRIMARY) { -// // frontGc.clearRect(0, 0, resX, resY) -// // val newXStart = xStart + (xEnd - xStart) * (dragStartX / resX) -// // val newYStart = yStart + (yEnd - yStart) * (dragStartY / resY) -// // -// // xEnd = xStart + (xEnd - xStart) * (e.x / resX) -// // yEnd = yStart + (yEnd - yStart) * (e.y / resY) -// // -// // xStart = newXStart -// // yStart = newYStart -// // -// // drawMandelbrot -// // sendCoord(xStart, yStart, xEnd, yEnd) -// // } -// // } -// -// -// val stage = new Stage { -// title = "Mandelbrot" -// scene = new Scene { -// val vBox = new VBox() { -// children = Seq( -// rootPane, -// frameTaskFilterEnableBt) -// } -// root = vBox -// } -// show() -// } -// } -// } -//} -// -//object MandelbrotGuiMain { -// def main(args: Array[String]) { -// PeripheralManagerFactoryRegistry.peripheralManagerFactories += new IPeripheralManagerFactory { -// override def newPeripheral(address: Seq[Byte], hal: IBytePacketHal, r: JValue): Unit = new MandelbrotManager(address, hal, r) -// override def getPassportKind(): String = "mandelbrotCore" -// } -// -// DebuggerGui.main(args) -// } -//} -// diff --git a/tester/src/test/scala/spinal/demo/mandelbrot/MandelbrotSblDemo.scala b/tester/src/test/scala/spinal/demo/mandelbrot/MandelbrotSblDemo.scala deleted file mode 100644 index 3d2d8e5ee4..0000000000 --- a/tester/src/test/scala/spinal/demo/mandelbrot/MandelbrotSblDemo.scala +++ /dev/null @@ -1,155 +0,0 @@ -package spinal.demo.mandelbrot - - -import java.awt.Color - -import spinal.core._ -import spinal.lib._ -import spinal.lib.experimental.bus.sbl._ -import spinal.lib.com.uart._ -import spinal.lib.graphic.{RgbConfig, Rgb} -import spinal.lib.graphic.vga._ - - -class MandelbrotSblDemo(frameAddressOffset: Int, p: MandelbrotCoreParameters, coreClk: ClockDomain, vgaMemoryClk: ClockDomain, vgaClk: ClockDomain) extends Component { - val memoryBusConfig = SblConfig(30, 32) - val rgbConfig = RgbConfig(8, 8, 8) - - val io = new Bundle { - val uart = master(Uart()) - - val mandelbrotWriteCmd = master Stream SblWriteCmd(memoryBusConfig) - - val vgaReadCmd = master Stream SblReadCmd(memoryBusConfig) - val vgaReadRet = slave Flow SblReadRet(memoryBusConfig) - - val vga = master(Vga(rgbConfig)) - } - val core = new ClockingArea(coreClk) { - val uart = new Area { - val ctrl = new UartCtrl() - ctrl.io.config.clockDivider := BigInt((coreClk.frequency.getValue / 57.6e3 / 8).toLong) - ctrl.io.config.frame.dataLength := 7 - ctrl.io.config.frame.parity := UartParityType.NONE - ctrl.io.config.frame.stop := UartStopType.ONE - ctrl.io.uart <> io.uart - - val (flowFragment, _) = ctrl.io.read.toFlow.toFlowFragmentBitsAndReset() - } - val mandelbrot = new Area { - val core = new MandelbrotCore(p) - core.io.cmdPort << uart.flowFragment - core.io.retPort.toStreamBits() >> uart.ctrl.io.write - - //Mandelbrot iteration to color palette definition - val palette = Seq( - (0/255.0 -> new Color(0,0,0)), - (64/255.0 -> new Color(128,0,255)), - (100/255.0 -> new Color(180,32,0)), - (128/255.0 -> new Color(200,64,0)), - (150/255.0 -> new Color(220,100,0)), - (255/255.0 -> new Color(255,255,0))) - - //Create the rom for the mandelbrot iteration count to color transformation - val paletteRom = Mem((0 to p.iterationLimit).map(iteration => { - val iterationFactor = 1.0 * iteration / (p.iterationLimit) - val rgb = Rgb(rgbConfig) - var palletOffset = Math.max(0, palette.indexWhere(_._1 >= iterationFactor) - 1) - val palletPre = palette(palletOffset) - val palletPost = palette(palletOffset + 1) - val ratio = (iterationFactor - palletPre._1) / (palletPost._1 - palletPre._1) - - - rgb.r := ((palletPre._2.getRed * (1.0 - ratio) + palletPost._2.getRed * ratio) / 255 * ((1 << rgbConfig.rWidth) - 1)).toInt - rgb.g := ((palletPre._2.getGreen * (1.0 - ratio) + palletPost._2.getGreen * ratio) / 255 * ((1 << rgbConfig.gWidth) - 1)).toInt - rgb.b := ((palletPre._2.getBlue * (1.0 - ratio) + palletPost._2.getBlue * ratio) / 255 * ((1 << rgbConfig.bWidth) - 1)).toInt - - rgb - })) - - //Translate the pixelResult stream into a colorResult by using the rom - val colorResult = paletteRom.streamReadSync(core.io.pixelResult.translateWith(core.io.pixelResult.fragment.iteration), core.io.pixelResult.last) - - //Take mandelbrot pixelResults and translate them into simple memory access - val counter = Reg(UInt(memoryBusConfig.addressWidth bit)) init (0) - when(io.mandelbrotWriteCmd.fire) { - counter := counter + 1 - when(colorResult.linked) { - counter := 0 - } - } - io.mandelbrotWriteCmd.translateFrom(colorResult)((to, from) => { - to.address := counter - to.data := (B(from.value)).resized - }) - } - } - val vga = new ClockingArea(vgaClk) { - //Create VGA controller - val ctrl = new VgaCtrl(rgbConfig, 12) - ctrl.io.softReset := False - ctrl.io.timings.setAs_h640_v480_r60 //Static timing for 640*480 pixel at 60HZ - io.vga := ctrl.io.vga - - val newFrameEvent = ctrl.io.frameStart.genEvent - } - val vgaMemory = new ClockingArea(vgaMemoryClk) { - //Create the DMA for this VGA controller - val dma = new SblReadDma(memoryBusConfig) - - //Synchronise the frameStart event from the VGA to the current clock domain - val frameStart = StreamCCByToggle(vga.newFrameEvent, vgaClk, vgaMemoryClk) - //Translate it into a DMA command and send it into the DMA -// dma.io.cmd.translateFrom(frameStart)((to, from) => { -// to.offset := frameAddressOffset -// to.endAt := frameAddressOffset + p.screenResX * p.screenResY - 1 -// }) - - dma.io.cmd.arbitrationFrom(frameStart) - dma.io.cmd.offset := frameAddressOffset - dma.io.cmd.endAt := frameAddressOffset + p.screenResX * p.screenResY - 1 - - - //Count pendings command on the vgaRead bus - val pendingCmd = Reg(UInt(6 bit)) init (0) - when(io.vgaReadCmd.fire =/= io.vgaReadRet.fire) { - when(io.vgaReadCmd.fire) { - pendingCmd := pendingCmd + 1 - } otherwise { - pendingCmd := pendingCmd - 1 - } - } - - //Translate bus memory bus read Flow into a color read flow -// val colorFlow = Flow(rgbType).translateFrom(io.vgaReadRet)((to, from) => { -// to.assignFromBits(from.data) -// }) - - val colorFlow = Flow(Rgb(rgbConfig)) - colorFlow.valid := io.vgaReadRet.valid - colorFlow.payload.assignFromBits(io.vgaReadRet.payload.data) - - //Translate the color Flow ino a Stream and synchronise/bufferise to the VgaClk by using a cross clock fifo - val fifoSize = 512 - val (colorStream, colorStreamOccupancy) = colorFlow.toStream.queueWithPushOccupancy(fifoSize, vgaMemoryClk, vgaClk) - vga.ctrl.io.pixels << colorStream - - //Halt the vga read cmd stream if there is to mutch pending command or if the fifo is near than full - io.vgaReadCmd << dma.io.sblReadCmd.haltWhen(pendingCmd === pendingCmd.maxValue || RegNext(colorStreamOccupancy) > fifoSize - 128) - - } -} - - -object MandelbrotSblDemo { - def main(args: Array[String]) { - for(i <- 0 until 1){ - SpinalVhdl({ - val vgaClock = ClockDomain.external("vga") - val vgaMemoryClock = ClockDomain.external("vgaMemory") - val coreClock = ClockDomain.external("core",frequency=FixedFrequency(100 MHz)) - new MandelbrotSblDemo(0, new MandelbrotCoreParameters(256, 6, 640, 480, 7, 17 * 3), coreClock, vgaMemoryClock, vgaClock) - }) - } - } -} diff --git a/tester/src/test/scala/spinal/tester/CrossClockTester.scala b/tester/src/test/scala/spinal/tester/CrossClockTester.scala new file mode 100644 index 0000000000..c0bae4fad1 --- /dev/null +++ b/tester/src/test/scala/spinal/tester/CrossClockTester.scala @@ -0,0 +1,181 @@ +package spinal.tester + +import spinal.core._ + +import org.scalatest.funsuite.AnyFunSuite + +case class BBA(cd: ClockDomain) extends BlackBox { + val i = in port Bool() +} + +case class BBB(cd: ClockDomain) extends BlackBox { + val o = out port Bool() +} + +case class CrossClockA() extends Component { + val clkA = ClockDomain.external("clkA") + val clkB = ClockDomain.external("clkB") + + val reg = clkA(RegNext(in port Bool())) + + val bb = BBA(clkB) + bb.i := reg +} + +case class CrossClockB() extends Component { + val clkA = ClockDomain.external("clkA") + val clkB = ClockDomain.external("clkB") + + val reg = in port Bool() + + val bb = BBA(clkB) + bb.i := reg +} + +case class CrossClockC() extends Component { + val clkA = ClockDomain.external("clkA") + val clkB = ClockDomain.external("clkB") + + val reg = out port Bool() + + val bb = BBB(clkB) + bb.o <> reg +} + +class CrossClockCheckerTester extends AnyFunSuite { + test("a") { + GenerationShould pass CrossClockA() + } + + test("b") { + GenerationShould fail { + val c = CrossClockA() + c.bb.i.addTag(ClockDomainTag(c.clkB)) + c + } + } + + test("c") { + GenerationShould fail { + val c = CrossClockB() + c.reg.addTag(ClockDomainTag(c.clkA)) + c.bb.i.addTag(ClockDomainTag(c.clkB)) + c + } + } + + test("d") { + GenerationShould fail { + val c = CrossClockC() + c.reg.addTag(ClockDomainTag(c.clkA)) + c.bb.o.addTag(ClockDomainTag(c.clkB)) + c + } + } +} + +case class SyncronousA() extends Component { + val ck, rst = in port Bool() + val input = in port UInt(8 bits) + val output = out port UInt(8 bits) + + val cd = ClockDomain(ck, rst) + val logic = cd on new Area { + val a = RegNext(input) + val b = RegNext(a) + output := b + } +} + +case class SyncronousB() extends Component { + val ck1, rst = in port Bool() + val input = in port UInt(8 bits) + val output = out port UInt(8 bits) + + val ck2 = CombInit(ck1) + + val cd1 = ClockDomain(ck1, rst) + val cd2 = ClockDomain(ck2, rst) + + val logic1 = cd1 on new Area { + val a = RegNext(input) + val b = RegNext(a) + output := b + } + + val logic2 = cd2 on new Area { + val a = out port RegNext(logic1.a) + } +} + +case class SyncronousC(v: Int) extends Component { + val ck1, ck2, rst = in port Bool() + val input = in port UInt(8 bits) + val output = out port UInt(8 bits) + + val clk1Buf = List.fill(3)(Bool()).foldLeft(ck1) { (i, o) => o := i; o } + val clk2Buf = List.fill(3)(Bool()).foldLeft(ck2) { (i, o) => o := i; o } + + val cd1 = ClockDomain(clk1Buf, rst) + val cd2 = ClockDomain(clk2Buf, rst) + v match { + case 0 => + case 1 => cd1.setSyncWith(cd2) + case 2 => cd2.setSyncWith(cd1) + case 3 => ClockDomain(ck1).setSyncWith(cd2) + case 4 => ClockDomain(ck2).setSyncWith(cd1) + case 5 => ClockDomain(ck1).setSyncWith(ClockDomain(ck2)) + } + + val logic1 = cd1 on new Area { + val a = RegNext(input) + val b = RegNext(a) + output := b + } + + val logic2 = cd2 on new Area { + val a = out port RegNext(logic1.a) + } +} + +case class SyncronousCheckerTesterD(v: Int) extends Component { + val ck1, rst = in port Bool() + val input = in port UInt(8 bits) + val output = out port UInt(8 bits) + + val ck2 = ck1 && input === 0 + + val cd1 = ClockDomain(ck1, rst) + val cd2 = ClockDomain(ck2, rst) + + v match { + case 0 => + case 1 => cd1.setSyncWith(cd2) + case 2 => Clock.syncDrive(source = ck1, sink = ck2) + } + + val logic1 = cd1 on new Area { + val a = RegNext(input) + val b = RegNext(a) + output := b + } + + val logic2 = cd2 on new Area { + val a = out port RegNext(logic1.a) + } +} + +class SyncronousCheckerTester extends AnyFunSuite { + test("a") { GenerationShould pass SyncronousA() } + test("b") { GenerationShould pass SyncronousB() } + test("c0") { GenerationShould fail SyncronousC(0) } + test("c1") { GenerationShould pass SyncronousC(1) } + test("c2") { GenerationShould pass SyncronousC(2) } + test("c3") { GenerationShould pass SyncronousC(3) } + test("c4") { GenerationShould pass SyncronousC(4) } + test("c5") { GenerationShould pass SyncronousC(5) } + test("d0") { GenerationShould fail SyncronousCheckerTesterD(0) } + test("d1") { GenerationShould pass SyncronousCheckerTesterD(1) } + test("d2") { GenerationShould pass SyncronousCheckerTesterD(2) } +// test("d3") { GenerationShould fail (SyncronousCheckerTesterD(3)) } +} diff --git a/tester/src/test/scala/spinal/tester/GenerationShould.scala b/tester/src/test/scala/spinal/tester/GenerationShould.scala new file mode 100644 index 0000000000..c8490390df --- /dev/null +++ b/tester/src/test/scala/spinal/tester/GenerationShould.scala @@ -0,0 +1,487 @@ +package spinal.tester + +import org.scalatest.funsuite.AnyFunSuite + +import spinal.core._ + +class GenerationShouldTester extends AnyFunSuite { + test("BlackBoxInputUnconnected") { + GenerationShould fail (new Component { + class Sub extends BlackBox { + val input = in port Bool() + } + val sub = new Sub + }) + } + + test("literalWidth") { + val t = SpinalVhdl(new Component { + val a = out port B"32'h0" + }).toplevel + + assert(widthOf(t.a) == 32) + } + + test("componentNamedByIo") { + val t = SpinalVerilog(new Component { + val miaou = new Component { + val io = new Bundle { + val x = out port Bool() + } + assert(io.x.getName() == "io_x") + }.io + }.setDefinitionName("TopLevel")).toplevel + + assert(t.miaou.component.getName() == "miaou") + assert(t.miaou.getName() == "io") + } + + test("checkWidthAssignment") { + GenerationShould fail (new Component { + val output = out Bits (8 bits) + output := "00" + }) + } + + test("checkCombinatorialLoop") { + GenerationShould fail (new Component { + val input = in Bits (8 bits) + val cond = in Bool () + + val tempA = Bits(4 bits) + val output = out Bits (8 bits) + + tempA := input(7 downto 4) + val tempB = Bits(4 bits) + tempB := tempA + + when(cond) { + tempA(1) := tempB(0) + } + + output(3 downto 0) := input(3 downto 0) + output(7 downto 4) := tempB + }) + } + + test("checkNoPartialAssignment") { + GenerationShould pass (new Component { + val cond = in Bool () + val input = in Bits (8 bits) + val output = out Bits (8 bits) + when(cond) { + output(7 downto 1) := input.resized + when(cond) { + output(0) := cond + } otherwise { + output(0) := cond + } + } otherwise { + output := input + } + }) + + GenerationShould fail (new Component { + val cond = in port Bool() + val input = in port Bits(8 bits) + val output = out port Bits(8 bits) + when(cond) { + output(7 downto 1) := input.resized + when(cond) {} otherwise { + output(0) := cond + } + } otherwise { + output := input + } + }) + } + + test("checkNoMissingDefault") { + GenerationShould pass (new Component { + val cond = in port Bool() + val input = in port Bits(8 bits) + val output = out port Bits(8 bits) + when(cond) { + output := input + } otherwise { + when(cond) { + output := input + when(cond) { + output := input + } + } otherwise { + output := input + } + } + }) + + GenerationShould fail (new Component { + val cond = in port Bool() + val input = in port Bits(8 bits) + val output = out port Bits(8 bits) + when(cond) { + output := input + } otherwise { + when(cond) { + when(cond) { + output := input + } + } otherwise { + output := input + } + } + }) + } + + test("checkClockCrossing") { + GenerationShould fail (new Component { + val clockA = in port Bool() + val clockB = in port Bool() + + val areaA = new ClockingArea(ClockDomain(clockA)) { + val reg = Reg(Bool()) + reg := in port Bool() + } + + val areaB = new ClockingArea(ClockDomain(clockB)) { + val reg = Reg(Bool()) + reg := areaA.reg + val output = out port Bool() + output := reg + } + }) + } + + test("checkClockCrossingCheckingCheckSourcesPaths") { + GenerationShould pass (new Component { + val clock = in port Bool() + val clockA = Bool + val clockB = Bool + + clockA := clock + val sub = new Component { + val cIn = in port Bool() + val cOut = out port Bool() + + val tmp = Bool() + tmp := cIn + cOut := tmp + } + + sub.cIn := clock + clockB := sub.cOut + val areaA = new ClockingArea(ClockDomain(clockA)) { + val reg = Reg(Bool()) + reg := in port Bool() + } + + val areaB = new ClockingArea(ClockDomain(clockB)) { + val reg = Reg(Bool()) + reg := areaA.reg + val output = out port Bool() + output := reg + } + }) + } + + test("checkClockCrossingCheckingCheckSourcesPathsFalure") { + GenerationShould fail (new Component { + val clock1 = in port Bool() + val clock2 = in port Bool() + val clockA = Bool() + val clockB = Bool() + + clockA := clock1 + val sub = new Component { + val cIn = in port Bool() + val cOut = out port Bool() + + val tmp = Bool() + tmp := cIn + cOut := tmp + } + + sub.cIn := clock2 + clockB := sub.cOut + val areaA = new ClockingArea(ClockDomain(clockA)) { + val reg = Reg(Bool()) + reg := in port Bool() + } + + val areaB = new ClockingArea(ClockDomain(clockB)) { + val reg = Reg(Bool()) + reg := areaA.reg + val output = out port Bool() + output := reg + } + }) + } + + test("checkNoInputAssignment") { + GenerationShould fail (new Component { + val input = in port Bool() + val output = out port Bool() + output := input + input := False + }) + } + + test("checkNoSubOutputAssignment") { + GenerationShould fail (new Component { + val sub = new Component { + val output = out port True + } + sub.output := False + }) + } + + test("checkNoSubSignalAssignment") { + GenerationShould fail (new Component { + val sub = new Component { + val tmp = True + } + sub.tmp := False + }) + } + + test("checkNoOverrides") { + GenerationShould pass (new Component { + val a = out port Bool() + a := True + when(True === True) { + a := False + } + }) + + GenerationShould pass (new Component { + val a = out port Bool() + when(True === True) { + a := False + } otherwise { + a := True + } + }) + + GenerationShould fail (new Component { + val a = out port Bool() + a := True + a := False + }) + GenerationShould fail (new Component { + val a = out port Bool() + a := True + when(True === True) { + a := False + a := True + } + }) + + GenerationShould fail (new Component { + val a = out port Bool() + when(True === True) { + a := False + } + a := True + }) + + GenerationShould fail (new Component { + val sub = new Component { + val a = in port Bool() + val result = out port Bool() + result := a + } + + val result = out port Bool() + result := sub.result + }) + + GenerationShould fail (new Component { + val sub = new Component { + val result = out port Bool() + } + + val result = out port Bool() + result := sub.result + }) + + GenerationShould fail (new Component { + val sub = new Component { + val a = in port Bool() + val result = out port Bool() + result := a + } + + val result = out port Bool() + result := sub.result + when(True) { + sub.a := True + } + }) + } + + test("checkNoResetFail") { + GenerationShould fail (new Component { + ClockDomain(in port Bool()) { + val output = out port RegInit(False).setName("aaa") + } + }) + } + + test("checkOnlyIoInIoBundle") { + class CheckOnlyIoInBundle extends Component { + val io = new Bundle { + val x = Bool() + } + } + GenerationShould fail (new CheckOnlyIoInBundle) + } + + test("catchNegativeRangedAccess1") { + GenerationShould fail (new Component { + Bits(32 bits)(4 downto 7) + }) + } + + test("catchNegativeRangedAccess2") { + GenerationShould fail (new Component { + Bits(32 bits)(-1 downto -2) + }) + } + test("catchNegativeRangedAccess3") { + GenerationShould fail (new Component { + Bits(32 bits)(4 downto 7) := 0 + }) + } + + test("catchNegativeRangedAccess4") { + GenerationShould fail (new Component { + val input = in port Bits(8 bits) + val currState = Vec(Bits(64 bits), 25) + currState.assignFromBits(input, 0, 8) + }) + } + + test("catchShiftBig") { + GenerationShould fail (new Component { + val a = B(1) + val b = a << U(2, 30 bits) + }) + } + + test("litRange") { + def failBody(body: => Unit): Unit = { + GenerationShould fail (new Component { body }) + } + def passBody(body: => Unit): Unit = { + GenerationShould pass (new Component { body }) + } + + failBody(out(in(Bits(8 bits)) === B(256))) + failBody(out(in(Bits(8 bits)) =/= B(256))) + + failBody(out(in(SInt(8 bits)) === S(256))) + failBody(out(in(SInt(8 bits)) =/= S(256))) + failBody(out(in(SInt(8 bits)) < S(256))) + failBody(out(in(SInt(8 bits)) <= S(256))) + + failBody(out(in(SInt(9 bits)) === S(256))) + failBody(out(in(SInt(9 bits)) =/= S(256))) + failBody(out(in(SInt(9 bits)) < S(256))) + failBody(out(in(SInt(9 bits)) <= S(256))) + failBody(out(in(SInt(9 bits)) === S(-257))) + failBody(out(in(SInt(9 bits)) =/= S(-257))) + failBody(out(in(SInt(9 bits)) < S(-257))) + failBody(out(in(SInt(9 bits)) <= S(-257))) + + passBody(out(in(SInt(9 bits)) === S(255))) + passBody(out(in(SInt(9 bits)) =/= S(255))) + passBody(out(in(SInt(9 bits)) < S(255))) + passBody(out(in(SInt(9 bits)) <= S(255))) + passBody(out(in(SInt(9 bits)) === S(-256))) + passBody(out(in(SInt(9 bits)) =/= S(-256))) + passBody(out(in(SInt(9 bits)) < S(-256))) + passBody(out(in(SInt(9 bits)) <= S(-256))) + } + + test("scopeProperty") { + object FixedPointProperty extends ScopeProperty[Int] { + override def default = 42 + } + + def check(ref: Int): Unit = { + println(s"ref:$ref dut:${FixedPointProperty.get}") + assert(ref == FixedPointProperty.get) + } + class Sub extends Component { + check(666) + } + class Toplevel extends Component { + check(55) + val logic = FixedPointProperty(666) on new Area { + check(666) + val x = new Sub + check(666) + FixedPointProperty(1234) { + check(1234) + x.rework { + check(666) + } + check(1234) + } + check(666) +// throw new Exception("asd") + } + check(55) + } + + check(42) + FixedPointProperty(55) { + check(55) + val config = SpinalConfig() +// try { + config.generateVerilog(new Toplevel) +// } catch { +// case e : Exception => +// } + check(55) + } + check(42) +// assert(ScopeProperty.get.isEmpty) + } + +} + +class NameingTester extends AnyFunSuite { + test("reflectionNaming") { + val t = SpinalVhdl(new Component { + val a = new Area { + val aa = Bool() + val bb = new Area { + val aaa = Bool() + val bbb = Vec(Bool(), 4) + val ccc = Vec( + new Bundle { + val aaaa = Bool() + val bbbb = Vec(Bool(), 8) + val cccc = Vec(Vec(Vec(Bool(), 8), 8), 8) + val dddd = List.fill(4)(Bool) + val eeee = List.fill(4)(List.fill(4)(Bool)) + }, + 4 + ) + } + } + val b = Bool() + }).toplevel + + assert(t.b.getName() == "b") + assert(t.a.aa.getName() == "a_aa") + assert(t.a.bb.aaa.getName() == "a_bb_aaa") + assert(t.a.bb.bbb(2).getName() == "a_bb_bbb_2") + assert(t.a.bb.ccc(3).aaaa.getName() == "a_bb_ccc_3_aaaa") + assert(t.a.bb.ccc(3).bbbb(6).getName() == "a_bb_ccc_3_bbbb_6") + assert(t.a.bb.ccc(3).cccc(6)(5)(4).getName() == "a_bb_ccc_3_cccc_6_5_4") + assert(t.a.bb.ccc(3).dddd(3).getName() == "a_bb_ccc_3_dddd_3") + assert(t.a.bb.ccc(3).eeee(3)(2).getName() == "a_bb_ccc_3_eeee_3_2") + } +} diff --git a/tester/src/test/scala/spinal/tester/RepeatabilitySuite.scala b/tester/src/test/scala/spinal/tester/RepeatabilitySuite.scala new file mode 100644 index 0000000000..37f9a95fe1 --- /dev/null +++ b/tester/src/test/scala/spinal/tester/RepeatabilitySuite.scala @@ -0,0 +1,41 @@ +package spinal.tester + +import spinal.core._ +import spinal.core.sim._ +import spinal.core.internals.GraphUtils + +import spinal.lib.com.i2c._ +import spinal.lib.com.uart.{UartCtrl, UartCtrlGenerics} +import spinal.lib.soc.pinsec.{Pinsec, PinsecConfig} + +class RepeatabilityTester extends RepeatabilitySuite { + def configI2C = I2cSlaveMemoryMappedGenerics( + ctrlGenerics = I2cSlaveGenerics(), + addressFilterCount = 0, + masterGenerics = I2cMasterMemoryMappedGenerics(timerWidth = 32) + ) + + test("Apb3I2cCtrlGraph") { + val dut = SpinalConfig(defaultClockDomainFrequency = FixedFrequency(50 MHz)) + .generateVerilog(new Apb3I2cCtrl(configI2C)) + .toplevel + assert(GraphUtils.countNames(dut) == 221) + } + + test("UartGraph") { + val dut = SpinalVerilog(new UartCtrl(UartCtrlGenerics())).toplevel + assert(GraphUtils.countNames(dut) == 94) + } + + test("Apb3I2cCtrlVerilog") { + checkOutputHash(new Apb3I2cCtrl(configI2C)) + } + + test("UartVerilog") { + checkOutputHash(new UartCtrl(UartCtrlGenerics())) + } + + test("PinsecVerilog") { + checkOutputHash(new Pinsec(PinsecConfig.default)) + } +} diff --git a/tester/src/test/scala/spinal/tester/code/Play1.scala b/tester/src/test/scala/spinal/tester/code/Play1.scala index 0dbf230607..ab381e787e 100644 --- a/tester/src/test/scala/spinal/tester/code/Play1.scala +++ b/tester/src/test/scala/spinal/tester/code/Play1.scala @@ -5,7 +5,6 @@ import java.io.InputStream import java.util.concurrent.CyclicBarrier import spinal.core._ import spinal.core.fiber._ -import spinal.demo.mandelbrot.{MandelbrotCoreParameters, MandelbrotSblDemo} import spinal.lib._ import spinal.lib.bus.amba3.apb.{Apb3, Apb3Config, Apb3Gpio} import spinal.lib.bus.amba4.axi.{Axi4, Axi4SpecRenamer} @@ -1498,30 +1497,6 @@ object PlayLoop { } } - -// -//import org.scalameter.api._ -// -//object RangeBenchmark extends Bench.LocalTime { -//// val time = measure { -//// for (i <- 0 until 100000) yield i -//// } -//// println(s"Total time: $time") -//// MandelbrotSblDemo.main(null) -//// val sizes = Gen.range("size")(300000, 1500000, 300000) -//// -//// val ranges = for { -//// size <- sizes -//// } yield 0 until size -//// -//// performance of "Range" in { -//// measure method "map" in { -//// using(ranges) in { -//// r => r.map(_ + 1) -//// } -//// } -//// } -//} //object PlayBench { // // diff --git a/tester/src/test/scala/spinal/tester/code/Presentation.scala b/tester/src/test/scala/spinal/tester/code/Presentation.scala index 8720aa482f..35b8118f8f 100644 --- a/tester/src/test/scala/spinal/tester/code/Presentation.scala +++ b/tester/src/test/scala/spinal/tester/code/Presentation.scala @@ -2,7 +2,6 @@ package spinal.tester.code import spinal.core._ -import spinal.demo.mandelbrot._ import spinal.lib._ import spinal.lib.bus.amba3.apb.{Apb3SlaveFactory, Apb3, Apb3Config} import spinal.lib.bus.amba4.axi.{Axi4, Axi4Config} @@ -815,32 +814,6 @@ object t8_B2 { } - -object t9 { - - class FrameTaskSolver(p: MandelbrotCoreParameters) extends Component { - val io = new Bundle { - val frameTask = slave Stream FrameTask(p) - val pixelResult = master Stream Fragment(PixelResult(p)) - } - - val pixelTaskGenerator = new PixelTaskGenerator(p) - val pixelTaskDispatcher = new StreamDispatcherSequencial(Fragment(PixelTask(p)), p.pixelTaskSolverCount) - val pixelTaskSolver = for (i <- 0 until p.pixelTaskSolverCount) yield new PixelTaskSolver(p) - val pixelResultArbiter = StreamArbiterFactory.sequentialOrder.build(Fragment(PixelResult(p)), p.pixelTaskSolverCount) - - pixelTaskGenerator.io.frameTask << io.frameTask - pixelTaskDispatcher.io.input <-/< pixelTaskGenerator.io.pixelTask - for (solverId <- 0 until p.pixelTaskSolverCount) { - pixelTaskSolver(solverId).io.pixelTask <-/< pixelTaskDispatcher.io.outputs(solverId) - pixelResultArbiter.io.inputs(solverId) (0x000,0x400), - axiSlaves(1) -> (0x400,0x400), - axiSlaves(2) -> (0x800,0x400), - axiSlaves(3) -> (0xC00,0x400) - ) - .addConnections( - axiMasters(0) -> List(axiSlaves(1),axiSlaves(2),axiSlaves(3)), - axiMasters(1) -> List(axiSlaves(0),axiSlaves(2),axiSlaves(3)), - axiMasters(2) -> List(axiSlaves(0),axiSlaves(1),axiSlaves(3)) - ) - - val readCrossbar = crossbarFactory.build() - } -} - -class Axi4CrossbarTesterCocotbBoot extends SpinalTesterCocotbBase { - override def getName: String = "Axi4CrossbarTester" - override def pythonTestLocation: String = "tester/src/test/python/spinal/Axi4CrossbarTester" - override def createToplevel: Component = new Axi4CrossbarTester.Axi4CrossbarTester -} \ No newline at end of file diff --git a/tester/src/test/scala/spinal/tester/scalatest/ChecksTester.scala b/tester/src/test/scala/spinal/tester/scalatest/ChecksTester.scala deleted file mode 100644 index fe957dfd11..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/ChecksTester.scala +++ /dev/null @@ -1,595 +0,0 @@ -package spinal.tester.scalatest - -import java.io.File - -import org.apache.commons.io.FileUtils -import org.scalatest.funsuite.AnyFunSuite -import spinal.core._ -import spinal.core.internals.GraphUtils -import spinal.lib.com.i2c._ -import spinal.lib.com.uart.{UartCtrl, UartCtrlGenerics} -import spinal.lib.soc.pinsec.{Pinsec, PinsecConfig} -import spinal.lib.{Delay, StreamFifo} - -import scala.collection.mutable.ArrayBuffer -import scala.sys.process._ - -object CheckTester{ - def checkFailure(func : => Unit) : Boolean = { - try{func} catch { - case e: Throwable => { - print(e) - return true - } - } - return false - } - - def generationShouldFaild(gen : => Component): Unit ={ - println("[Warning] generationShouldFaild is deprecated! Use generationShouldFail") - generationShouldFail(gen) - } - - def generationShouldFail(gen : => Component): Unit ={ - assert(checkFailure{SpinalVhdl(gen)}) - assert(checkFailure{SpinalVerilog(gen)}) - } - - def generationShouldPass(gen : => Component): Unit ={ - assert(!checkFailure{SpinalVhdl(gen)}) - assert(!checkFailure{SpinalVerilog(gen)}) - } -} - -class ChecksTester extends AnyFunSuite { - import CheckTester._ - - - test("BlackBoxInputUnconnected"){ - generationShouldFail(new Component{ - class Sub extends BlackBox{ - val input = in Bool() - } - val sub = new Sub - }) - } - - test("literalWidth"){ - val t = SpinalVhdl(new Component{ - val a = out(B"32'h0") - }).toplevel - - assert(widthOf(t.a) == 32) - } - - - test("componentNamedByIo") { - val t = SpinalVerilog(new Component{ - val miaou = new Component{ - val io = new Bundle { - val x = out Bool() - } - assert(io.x.getName() == "io_x") - }.io - }.setDefinitionName("TopLevel")).toplevel - - assert(t.miaou.component.getName() == "miaou") - assert(t.miaou.getName() == "io") - } - - - - test("checkWidthAssignment") { - generationShouldFail(new Component{ - val output = out Bits(8 bits) - output := "00" - }) - } - - - test("checkCombinatorialLoop") { - generationShouldFail(new Component{ - val input = in Bits(8 bits) - val cond = in Bool() - - val tempA = Bits(4 bits) - val output = out Bits(8 bits) - - tempA := input(7 downto 4) - val tempB = Bits(4 bits) - tempB := tempA - - when(cond){ - tempA(1) := tempB(0) - } - - output(3 downto 0) := input (3 downto 0) - output(7 downto 4) := tempB - }) - } - - test("checkNoPartialAssignment") { - generationShouldPass(new Component{ - val cond = in Bool() - val input = in Bits(8 bits) - val output = out Bits(8 bits) - when(cond){ - output(7 downto 1) := input.resized - when(cond){ - output(0) := cond - } otherwise{ - output(0) := cond - } - }otherwise{ - output := input - } - }) - - generationShouldFail(new Component{ - val cond = in Bool() - val input = in Bits(8 bits) - val output = out Bits(8 bits) - when(cond){ - output(7 downto 1) := input.resized - when(cond){ - - } otherwise{ - output(0) := cond - } - }otherwise{ - output := input - } - }) - } - - test("checkNoMissingDefault") { - generationShouldPass(new Component{ - val cond = in Bool() - val input = in Bits(8 bits) - val output = out Bits(8 bits) - when(cond){ - output := input - }otherwise{ - when(cond) { - output := input - when(cond){ - output := input - } - } otherwise { - output := input - } - } - }) - - generationShouldFail(new Component{ - val cond = in Bool() - val input = in Bits(8 bits) - val output = out Bits(8 bits) - when(cond){ - output := input - }otherwise{ - when(cond) { - when(cond){ - output := input - } - } otherwise { - output := input - } - } - }) - } - - test("checkClockCrossing") { - generationShouldFail(new Component{ - val clockA = in Bool() - val clockB = in Bool() - - val areaA = new ClockingArea(ClockDomain(clockA)){ - val reg = Reg(Bool()) - reg := in(Bool) - } - - val areaB = new ClockingArea(ClockDomain(clockB)){ - val reg = Reg(Bool()) - reg := areaA.reg - val output = out Bool() - output := reg - } - }) - } - - test("checkClockCrossingCheckingCheckSourcesPaths") { - generationShouldPass(new Component{ - val clock = in Bool() - val clockA = Bool - val clockB = Bool - - clockA := clock - val sub = new Component{ - val cIn = in Bool() - val cOut = out Bool() - - val tmp = Bool() - tmp := cIn - cOut := tmp - } - - sub.cIn := clock - clockB := sub.cOut - val areaA = new ClockingArea(ClockDomain(clockA)){ - val reg = Reg(Bool()) - reg := in(Bool) - } - - val areaB = new ClockingArea(ClockDomain(clockB)){ - val reg = Reg(Bool()) - reg := areaA.reg - val output = out Bool() - output := reg - } - }) - } - - test("checkClockCrossingCheckingCheckSourcesPathsFalure") { - generationShouldFail(new Component{ - val clock1 = in Bool() - val clock2 = in Bool() - val clockA = Bool - val clockB = Bool - - clockA := clock1 - val sub = new Component{ - val cIn = in Bool() - val cOut = out Bool() - - val tmp = Bool() - tmp := cIn - cOut := tmp - } - - sub.cIn := clock2 - clockB := sub.cOut - val areaA = new ClockingArea(ClockDomain(clockA)){ - val reg = Reg(Bool()) - reg := in(Bool) - } - - val areaB = new ClockingArea(ClockDomain(clockB)){ - val reg = Reg(Bool()) - reg := areaA.reg - val output = out Bool() - output := reg - } - }) - } - - test("checkNoInputAssignment") { - generationShouldFail(new Component{ - val input = in Bool() - val output = out Bool() - output := input - input := False - }) - } - - test("checkNoSubOutputAssignment") { - generationShouldFail(new Component{ - val sub = new Component{ - val output = out(True) - } - sub.output := False - }) - } - - - - test("checkNoSubSignalAssignment") { - generationShouldFail(new Component{ - val sub = new Component{ - val tmp = True - } - sub.tmp := False - }) - } - - test("checkNoOverrides") { - generationShouldPass(new Component{ - val a = out Bool() - a := True - when(True === True) { - a := False - } - }) - - generationShouldPass(new Component{ - val a = out Bool() - when(True === True) { - a := False - } otherwise { - a := True - } - }) - - generationShouldFail(new Component{ - val a = out Bool() - a := True - a := False - }) - generationShouldFail(new Component{ - val a = out Bool() - a := True - when(True === True) { - a := False - a := True - } - }) - - generationShouldFail(new Component{ - val a = out Bool() - when(True === True) { - a := False - } - a := True - }) - - generationShouldFail(new Component{ - val sub = new Component{ - val a = in Bool() - val result = out Bool() - result := a - } - - val result = out Bool() - result := sub.result - }) - - generationShouldFail(new Component{ - val sub = new Component{ - val result = out Bool() - } - - val result = out Bool() - result := sub.result - }) - - generationShouldFail(new Component{ - val sub = new Component{ - val a = in Bool() - val result = out Bool() - result := a - } - - val result = out Bool() - result := sub.result - when(True){ - sub.a := True - } - }) - - - - } - - test("checkNoResetFail") { - generationShouldFail(new Component{ - ClockDomain(in Bool()) { - val output = out(RegInit(False)).setName("aaa") - } - }) - } - - test("checkOnlyIoInIoBundle") { - class CheckOnlyIoInBundle extends Component{ - val io = new Bundle{ - val x = Bool() - } - } - generationShouldFail(new CheckOnlyIoInBundle) - } - - - test("catchNegativeRangedAccess1") { - generationShouldFail(new Component { - Bits(32 bits)(4 downto 7) - }) - } - - test("catchNegativeRangedAccess2") { - generationShouldFail(new Component { - Bits(32 bits)(-1 downto -2) - }) - } - test("catchNegativeRangedAccess3") { - generationShouldFail(new Component { - Bits(32 bits)(4 downto 7) := 0 - }) - } - - test("catchNegativeRangedAccess4") { - generationShouldFail(new Component { - val input = in Bits(8 bits) - val currState = Vec(Bits(64 bits), 25) - currState.assignFromBits(input, 0, 8) - }) - } - - test("catchShiftBig"){ - generationShouldFail(new Component { - val a = B(1) - val b = a << U(2, 30 bits) - }) - } - - test("litRange"){ - def failBody(body : => Unit): Unit ={ - generationShouldFail(new Component {body}) - } - def passBody(body : => Unit): Unit ={ - generationShouldPass(new Component {body}) - } - - failBody(out(in(Bits(8 bits)) === B(256))) - failBody(out(in(Bits(8 bits)) =/= B(256))) - - failBody(out(in(SInt(8 bits)) === S(256))) - failBody(out(in(SInt(8 bits)) =/= S(256))) - failBody(out(in(SInt(8 bits)) < S(256))) - failBody(out(in(SInt(8 bits)) <= S(256))) - - failBody(out(in(SInt(9 bits)) === S(256))) - failBody(out(in(SInt(9 bits)) =/= S(256))) - failBody(out(in(SInt(9 bits)) < S(256))) - failBody(out(in(SInt(9 bits)) <= S(256))) - failBody(out(in(SInt(9 bits)) === S(-257))) - failBody(out(in(SInt(9 bits)) =/= S(-257))) - failBody(out(in(SInt(9 bits)) < S(-257))) - failBody(out(in(SInt(9 bits)) <= S(-257))) - - passBody(out(in(SInt(9 bits)) === S(255))) - passBody(out(in(SInt(9 bits)) =/= S(255))) - passBody(out(in(SInt(9 bits)) < S(255))) - passBody(out(in(SInt(9 bits)) <= S(255))) - passBody(out(in(SInt(9 bits)) === S(-256))) - passBody(out(in(SInt(9 bits)) =/= S(-256))) - passBody(out(in(SInt(9 bits)) < S(-256))) - passBody(out(in(SInt(9 bits)) <= S(-256))) - } - - - test("scopeProperty"){ - object FixedPointProperty extends ScopeProperty[Int]{ - override def default = 42 - } - - def check(ref : Int): Unit ={ - println(s"ref:$ref dut:${FixedPointProperty.get}") - assert(ref == FixedPointProperty.get) - } - class Sub extends Component{ - check(666) - } - class Toplevel extends Component{ - check(55) - val logic = FixedPointProperty(666) on new Area{ - check(666) - val x = new Sub - check(666) - FixedPointProperty(1234){ - check(1234) - x.rework{ - check(666) - } - check(1234) - } - check(666) -// throw new Exception("asd") - } - check(55) - } - - - check(42) - FixedPointProperty(55){ - check(55) - val config = SpinalConfig() -// try { - config.generateVerilog(new Toplevel) -// } catch { -// case e : Exception => -// } - check(55) - } - check(42) -// assert(ScopeProperty.get.isEmpty) - } - -} - -class RepeatabilityTester extends AnyFunSuite{ - var checkOutputHashCounter = 0 - def checkOutputHash(gen : => Component): Unit ={ - checkOutputHashCounter = checkOutputHashCounter + 1 - var ref = "" - for(i <- 0 until 8) { - val report = SpinalConfig(defaultClockDomainFrequency = FixedFrequency(50 MHz)).generateVerilog(gen.setDefinitionName(s"checkOutputHash_${checkOutputHashCounter}")) - FileUtils.copyFile(new File(report.generatedSourcesPaths.head),new File(report.generatedSourcesPaths.head + "_" + i + ".v")) - - import sys.process._ - val hash = s"md5sum ${report.generatedSourcesPaths.head}".!! - if(i == 0) ref = hash - else assert(ref == hash) - } - } - def configI2C = I2cSlaveMemoryMappedGenerics( - ctrlGenerics = I2cSlaveGenerics(), - addressFilterCount = 0, - masterGenerics = I2cMasterMemoryMappedGenerics(timerWidth = 32) - ) - - test("Apb3I2cCtrlGraph"){ - val dut = SpinalConfig(defaultClockDomainFrequency = FixedFrequency(50 MHz)).generateVerilog(new Apb3I2cCtrl(configI2C)).toplevel - assert(GraphUtils.countNames(dut) == 221) - } - - test("UartGraph"){ - val dut = SpinalVerilog(new UartCtrl(UartCtrlGenerics())).toplevel - assert(GraphUtils.countNames(dut) == 94) - } - - - - test("Apb3I2cCtrlVerilog"){ - checkOutputHash(new Apb3I2cCtrl(configI2C)) - } - - - test("UartVerilog"){ - checkOutputHash(new UartCtrl(UartCtrlGenerics())) - } - - test("PinsecVerilog"){ - checkOutputHash(new Pinsec(PinsecConfig.default)) - } - - test("BmbInterconnectVerilog"){ - checkOutputHash(SpinalSimBmbInterconnectGeneratorTester.f()) - } -} - -class NameingTester extends AnyFunSuite { - import CheckTester._ - - - test("reflectionNaming") { - val t = SpinalVhdl(new Component{ - val a = new Area{ - val aa = Bool() - val bb = new Area{ - val aaa = Bool() - val bbb = Vec(Bool(),4) - val ccc = Vec(new Bundle{ - val aaaa = Bool() - val bbbb = Vec(Bool(),8) - val cccc = Vec( Vec( Vec(Bool(),8),8),8) - val dddd = List.fill(4)(Bool) - val eeee = List.fill(4)(List.fill(4)(Bool)) - },4) - } - } - val b = Bool() - }).toplevel - - assert(t.b.getName() == "b") - assert(t.a.aa.getName() == "a_aa") - assert(t.a.bb.aaa.getName() == "a_bb_aaa") - assert(t.a.bb.bbb(2).getName() == "a_bb_bbb_2") - assert(t.a.bb.ccc(3).aaaa.getName() == "a_bb_ccc_3_aaaa") - assert(t.a.bb.ccc(3).bbbb(6).getName() == "a_bb_ccc_3_bbbb_6") - assert(t.a.bb.ccc(3).cccc(6)(5)(4).getName() == "a_bb_ccc_3_cccc_6_5_4") - assert(t.a.bb.ccc(3).dddd(3).getName() == "a_bb_ccc_3_dddd_3") - assert(t.a.bb.ccc(3).eeee(3)(2).getName() == "a_bb_ccc_3_eeee_3_2") - } -} - - - diff --git a/tester/src/test/scala/spinal/tester/scalatest/ClockDomainConfigTester.scala b/tester/src/test/scala/spinal/tester/scalatest/ClockDomainConfigTester.scala deleted file mode 100644 index b92a5d74fb..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/ClockDomainConfigTester.scala +++ /dev/null @@ -1,203 +0,0 @@ -package spinal.tester.scalatest - -import spinal.core._ -import spinal.tester.scalatest.ClockDomainConfigTester.ClockDomainConfigTester -import spinal.tester.scalatest.GrayCounterTester.GrayCounterTester -import language.postfixOps - -object ClockDomainConfigTester { - class ClockDomainConfigTester() extends Component { - val clk,syncReset,asyncReset,softReset,enable = in Bool() - val clkn,syncResetn,asyncResetn,softResetn,enablen = in Bool() - - class TestArea(cd : ClockDomain,withInit : Boolean = true) extends ClockingArea(cd){ - val regWithoutReset = out(Reg(UInt(8 bits)) randBoot()) - regWithoutReset := regWithoutReset + 1 - val regWithReset = if(withInit) { - val reg = out(Reg(UInt(8 bits)) init(42) randBoot()) - reg := reg + 1 - reg - } else null - } - - val test_clk = new TestArea(ClockDomain( - clock = clk, - config = ClockDomainConfig( - clockEdge = RISING, - resetKind = ASYNC, - resetActiveLevel = HIGH, - softResetActiveLevel = HIGH, - clockEnableActiveLevel= HIGH - ) - ),false) - - val test_clkn = new TestArea(ClockDomain( - clock = clkn, - config = ClockDomainConfig( - clockEdge = FALLING, - resetKind = ASYNC, - resetActiveLevel = HIGH, - softResetActiveLevel = HIGH, - clockEnableActiveLevel= HIGH - ) - ),false) - - - val test_clk_boot = new TestArea(ClockDomain( - clock = clk, - config = ClockDomainConfig( - clockEdge = RISING, - resetKind = BOOT, - resetActiveLevel = HIGH, - softResetActiveLevel = HIGH, - clockEnableActiveLevel= HIGH - ) - )) - - val test_async_reset = new TestArea(ClockDomain( - clock = clk, - reset = asyncReset, - config = ClockDomainConfig( - clockEdge = RISING, - resetKind = ASYNC, - resetActiveLevel = HIGH, - softResetActiveLevel = HIGH, - clockEnableActiveLevel= HIGH - ) - )) - - val test_async_resetn = new TestArea(ClockDomain( - clock = clk, - reset = asyncResetn, - config = ClockDomainConfig( - clockEdge = RISING, - resetKind = ASYNC, - resetActiveLevel = LOW, - softResetActiveLevel = HIGH, - clockEnableActiveLevel= HIGH - ) - )) - - val test_sync_reset = new TestArea(ClockDomain( - clock = clk, - reset = syncReset, - config = ClockDomainConfig( - clockEdge = RISING, - resetKind = SYNC, - resetActiveLevel = HIGH, - softResetActiveLevel = HIGH, - clockEnableActiveLevel= HIGH - ) - )) - - val test_sync_resetn = new TestArea(ClockDomain( - clock = clk, - reset = syncResetn, - config = ClockDomainConfig( - clockEdge = RISING, - resetKind = SYNC, - resetActiveLevel = LOW, - softResetActiveLevel = HIGH, - clockEnableActiveLevel= HIGH - ) - )) - - val test_enable = new TestArea(ClockDomain( - clock = clk, - clockEnable = enable, - config = ClockDomainConfig( - clockEdge = RISING, - resetKind = ASYNC, - resetActiveLevel = HIGH, - softResetActiveLevel = HIGH, - clockEnableActiveLevel= HIGH - ) - ),false) - - val test_enablen = new TestArea(ClockDomain( - clock = clk, - clockEnable = enablen, - config = ClockDomainConfig( - clockEdge = RISING, - resetKind = ASYNC, - resetActiveLevel = HIGH, - softResetActiveLevel = HIGH, - clockEnableActiveLevel= LOW - ) - ),false) - - val test_sync_reset_enable = new TestArea(ClockDomain( - clock = clk, - reset = syncReset, - clockEnable = enable, - config = ClockDomainConfig( - clockEdge = RISING, - resetKind = SYNC, - resetActiveLevel = HIGH, - softResetActiveLevel = HIGH, - clockEnableActiveLevel= HIGH - ) - )) - - val test_softReset = new TestArea(ClockDomain( - clock = clk, - softReset = softReset, - config = ClockDomainConfig( - clockEdge = RISING, - resetKind = ASYNC, - resetActiveLevel = HIGH, - softResetActiveLevel = HIGH, - clockEnableActiveLevel= HIGH - ) - )) - - val test_softResetn = new TestArea(ClockDomain( - clock = clk, - softReset = softResetn, - config = ClockDomainConfig( - clockEdge = RISING, - resetKind = ASYNC, - resetActiveLevel = HIGH, - softResetActiveLevel = LOW, - clockEnableActiveLevel= HIGH - ) - )) - - val test_async_reset_softReset = new TestArea(ClockDomain( - clock = clk, - reset = asyncReset, - softReset = softReset, - config = ClockDomainConfig( - clockEdge = RISING, - resetKind = ASYNC, - resetActiveLevel = HIGH, - softResetActiveLevel = HIGH, - clockEnableActiveLevel= HIGH - ) - )) - - val test_sync_reset_softReset = new TestArea(ClockDomain( - clock = clk, - reset = syncReset, - softReset = softReset, - config = ClockDomainConfig( - clockEdge = RISING, - resetKind = SYNC, - resetActiveLevel = HIGH, - softResetActiveLevel = HIGH, - clockEnableActiveLevel= HIGH - ) - )) - - - - } - -} - - -class ClockDomainConfigTesterCocotbBoot extends SpinalTesterCocotbBase { - override def getName: String = "ClockDomainConfigTester" - override def pythonTestLocation: String = "tester/src/test/python/spinal/ClockDomainConfigTester" - override def createToplevel: Component = new ClockDomainConfigTester() -} \ No newline at end of file diff --git a/tester/src/test/scala/spinal/tester/scalatest/CommonTester.scala b/tester/src/test/scala/spinal/tester/scalatest/CommonTester.scala deleted file mode 100644 index 8cead1b9f4..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/CommonTester.scala +++ /dev/null @@ -1,138 +0,0 @@ -package spinal.tester.scalatest - -import spinal.core._ -import spinal.lib._ - -object CommonTester { - - - class BundleA extends Bundle { - val bod = new Bundle { - val gggg = Bool() - val aosi = UInt(3 bit) - } - val ahe = Bool() - val zwg = Bool() - } - - class BundleAA extends BundleA { - val vsw = Bool() - val lwee = UInt(5 bit) - } - - class CommonTester extends Component { - val io = new Bundle { - val conds = in Vec(Bool(),8) - - val inUIntA = in UInt (8 bit) - val inUIntB = in UInt (8 bit) - val outUIntAdder = out UInt() - - val inAA = in(new BundleAA) - val inAABits = in Bits (new BundleAA().getBitsWidth bit) - val outAA = out(new BundleAA) - val outAABits = out Bits (new BundleAA().getBitsWidth bit) - - val complexLiteral = out UInt (16 bit) - - - val assign = new Bundle{ - val sel = in Vec(UInt(4 bit),4) - val bitDemux = out Bits(16 bit) - - - def doit: Unit ={ - bitDemux := B(0) - bitDemux(sel(0)) := conds(0) - when(conds(1)){ - bitDemux(sel(1)) := conds(2) - }elsewhen(conds(3)){ - bitDemux(sel(0)) := conds(4) - } - when(conds(5)){ - bitDemux(sel(1)) := conds(6) - } - bitDemux(5) := True - } - } - def doit: Unit ={ - assign.doit - } - } - - - io.doit - - val noData = NoData - - io.outAA.assignFromBits(io.inAABits) - io.outAABits := io.inAA.asBits - - io.complexLiteral(15 downto 4) := 0x70 - io.complexLiteral(15 downto 12) := (U(2) + U(1)).resized - io.complexLiteral(6) := True - io.complexLiteral(3) := True - io.complexLiteral(5) := True - io.complexLiteral(3 downto 0) := 2 - io.complexLiteral(13) := False - - def combAdderFunc(x : UInt,y : UInt) = { - val ret = UInt(Math.max(widthOf(x),widthOf(y)) bit) - val size = io.inUIntA.getWidth - var c = False - for (i <- 0 until size) { - val a = x(i) - val b = y(i) - ret(i) := a ^ b ^ c - c \= (a & b) | (a & c) | (b & c) - } - ret - } - - -// val combAdder = new Area { -// val size = io.inUIntA.getWidth -// val out = UInt(size bit) -// -// var c = False -// for (i <- 0 until size) { -// val a = io.inUIntA(i) -// val b = io.inUIntB(i) -// out(i) := a ^ b ^ c -// c = (a & b) | (a & c) | (b & c) -// } -// io.outUIntAdder := out -// } - io.outUIntAdder := combAdderFunc(io.inUIntA,io.inUIntB) - - - - //Clone test - case class MyBundle(paramBool : Bool,asd : Int) extends Bundle{ - val a = cloneOf(paramBool) - } - - class MyBundle2 extends Bundle{ - val a = Bool() - } - - cloneOf(new MyBundle(True,1)) - cloneOf(new MyBundle2) - - - - } - -} - -//class CommonTesterGhdlBoot extends SpinalTesterGhdlBase { -// override def getName: String = "CommonTester" -// -// override def createToplevel: Component = new CommonTester.CommonTester -//} - -class CommonTesterCocotbBoot extends SpinalTesterCocotbBase { - override def getName: String = "CommonTester" - override def createToplevel: Component = new CommonTester.CommonTester - override def pythonTestLocation: String = "tester/src/test/python/spinal/CommonTester" -} \ No newline at end of file diff --git a/tester/src/test/scala/spinal/tester/scalatest/CoreMiscTester.scala b/tester/src/test/scala/spinal/tester/scalatest/CoreMiscTester.scala deleted file mode 100644 index 72ede67614..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/CoreMiscTester.scala +++ /dev/null @@ -1,177 +0,0 @@ -package spinal.tester.scalatest - -import org.scalatest.funsuite.AnyFunSuite -import spinal.core._ -import spinal.core.sim._ -import spinal.lib._ -import scala.util.Random -class CoreMiscTester extends AnyFunSuite{ - test("SlowArea"){ - SimConfig.withConfig(SpinalConfig(defaultClockDomainFrequency = FixedFrequency(4000 Hz))).compile(new Component{ - val counter = out(RegInit(U"0000")) - counter := counter + 1 - assert(clockDomain.samplingRate.getValue.toInt == 4000) - - val slowArea = new SlowArea(4){ - val counter = out(RegInit(U"0000")) - counter := counter + 1 - assert(clockDomain.samplingRate.getValue.toInt == 1000) - } - - }).doSim{dut => - dut.clockDomain.forkStimulus(10) - - for(i <- 0 until 1000){ - dut.clockDomain.waitSampling() - assert(dut.counter.toInt == i % 16) - assert(dut.slowArea.counter.toInt == (i-1)/4 % 16) - } - } - } - - test("reg_nextValue"){ - SimConfig.compile(new Component{ - val conds = in(Vec.fill(8)(Bool())) - val a, b, c, d, e = out(Reg(UInt(8 bits)) init(0)) - - when(conds(0)){ - a := 1 - when(conds(1)){ - a := 2 - b := 11 - } otherwise { - a := 3 - c := 21 - } - } - when(conds(2)){ - a := 4 - b := 12 - c := 22 - d := 31 - } - - val x = out(a.getAheadValue) - val y = out(a.getAheadValue) - val z = out(b.getAheadValue) - - when(d.getAheadValue() === 0){ - e := 1 - } - }).doSim(seed = 42){dut => - var an,bn,cn,a,b,c = 0 - dut.conds.foreach(_ #= false) - dut.clockDomain.forkStimulus(10) - dut.clockDomain.waitSampling() - - for(i <- 0 until 1000){ - if(dut.conds(0).toBoolean){ - an = 1 - if(dut.conds(1).toBoolean){ - an = 2 - bn = 11 - } else { - an = 3 - cn = 21 - } - } - if(dut.conds(2).toBoolean){ - an = 4 - bn = 12 - cn = 22 - } - assert(dut.x.toInt == an) - assert(dut.y.toInt == an) - assert(dut.z.toInt == bn) - assert(dut.a.toInt == a) - assert(dut.b.toInt == b) - assert(dut.c.toInt == c) - a = an - b = bn - c = cn - dut.clockDomain.waitSampling() - dut.conds.foreach(_.randomize()) - } - } - } - - test("uint_wrap_comparison"){ - val width = 8 - SimConfig.compile(new Component{ - val smaller, bigger, eq_smaller, eq_bigger = out(Bool()) - val x, y = in(UInt(width bits)) - - smaller := x.wrap < y - bigger := x.wrap > y - eq_smaller := x.wrap <= y - eq_bigger := x.wrap >= y - }).doSim(seed = 42){dut => - val quarter = 1<<(width - 2) - for(i <- 0 until 2000){ - dut.x.randomize() - sleep(1) - var x = dut.x.toInt - var value = x + Random.nextInt(2*quarter) - quarter // ensure two datas' distance are not beyond a quarter. - value = if (value < 0) -value else value - value %= 4*quarter - dut.y #= value - sleep(1) - val y = dut.y.toInt - val needReverse = (x - y).abs > 3* quarter - - assert(dut.smaller.toBoolean == (if(needReverse) x > y else x < y)) - assert(dut.bigger.toBoolean == (if(needReverse) x < y else x > y)) - assert(dut.eq_smaller.toBoolean == (if(needReverse) x >= y else x <= y)) - assert(dut.eq_bigger.toBoolean == (if(needReverse) x <= y else x >= y)) - sleep(1) - } - } - } - - test("reverse_by_shuffle"){ - SimConfig.compile(new Component{ - val data = in(Bits(64 bits)) - val outData = out(UInt(64 bits)) - - val outSet = data.subdivideIn(8 bits) - outData := outSet.shuffle{ (i) => - outSet.length - 1 - i - }.asBits.asUInt - }).doSim(seed = 42){dut => - for(j <- 0 until 1000) { - dut.data.randomize() - sleep(1) - val data = dut.data.toBigInt - val outData = dut.outData.toBigInt - for ( i <- 0 until 8) { - val in = (data >> i * 8) & 0xFF - val out = (outData >> (7-i) *8) & 0xFF - assert(in == out) - } - } - } - } - - test("reverse_by_shuffle_with_size"){ - SimConfig.compile(new Component{ - val data = in(Bits(64 bits)) - val outData = out(UInt(64 bits)) - - outData := data.subdivideIn(8 bits).shuffleWithSize{ (total, i) => - total - 1 - i - }.asBits.asUInt - }).doSim(seed = 42){dut => - for(j <- 0 until 1000) { - dut.data.randomize() - sleep(1) - val data = dut.data.toBigInt - val outData = dut.outData.toBigInt - for ( i <- 0 until 8) { - val in = (data >> i * 8) & 0xFF - val out = (outData >> (7-i) *8) & 0xFF - assert(in == out) - } - } - } - } -} diff --git a/tester/src/test/scala/spinal/tester/scalatest/CrossClockCheckerTester.scala b/tester/src/test/scala/spinal/tester/scalatest/CrossClockCheckerTester.scala deleted file mode 100644 index 545f9ea035..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/CrossClockCheckerTester.scala +++ /dev/null @@ -1,192 +0,0 @@ -package spinal.tester.scalatest - -import org.scalatest.funsuite.AnyFunSuite -import spinal.core._ - - -class BBA(val cd : ClockDomain) extends BlackBox{ - val i = in(Bool) -} - -class BBB(val cd : ClockDomain) extends BlackBox{ - val o = out(Bool) -} - -class CrossClockCheckerTesterA extends Component{ - val clkA = ClockDomain.external("clkA") - val clkB = ClockDomain.external("clkB") - - val reg = clkA(RegNext(in Bool())) - - val bb = new BBA(clkB) - bb.i := reg -} - - -class CrossClockCheckerTesterB extends Component{ - val clkA = ClockDomain.external("clkA") - val clkB = ClockDomain.external("clkB") - - val reg = in Bool() - - val bb = new BBA(clkB) - bb.i := reg -} - -class CrossClockCheckerTesterC extends Component{ - val clkA = ClockDomain.external("clkA") - val clkB = ClockDomain.external("clkB") - - val reg = out Bool() - - val bb = new BBB(clkB) - bb.o <> reg -} - - -class CrossClockCheckerTester extends AnyFunSuite{ - import CheckTester._ - - test("a") { - generationShouldPass(new CrossClockCheckerTesterA) - } - - test("b") { - generationShouldFail({ - val c = new CrossClockCheckerTesterA - c.bb.i.addTag(ClockDomainTag(c.clkB)) - c - }) - } - - test("c") { - generationShouldFail({ - val c = new CrossClockCheckerTesterB - c.reg.addTag(ClockDomainTag(c.clkA)) - c.bb.i.addTag(ClockDomainTag(c.clkB)) - c - }) - } - - test("d") { - generationShouldFail({ - val c = new CrossClockCheckerTesterC - c.reg.addTag(ClockDomainTag(c.clkA)) - c.bb.o.addTag(ClockDomainTag(c.clkB)) - c - }) - } -} - - -class SyncronousCheckerTesterA extends Component{ - val clk,reset = in Bool() - val input = in UInt(8 bits) - val output = out UInt(8 bits) - - val cd = ClockDomain(clk, reset) - val logic = cd on new Area{ - val a = RegNext(input) - val b = RegNext(a) - output := b - } -} - -class SyncronousCheckerTesterB extends Component{ - val clk1,reset = in Bool() - val input = in UInt(8 bits) - val output = out UInt(8 bits) - - - val clk2 = CombInit(clk1) - - val cd1 = ClockDomain(clk1, reset) - val cd2 = ClockDomain(clk2, reset) - - val logic1 = cd1 on new Area{ - val a = RegNext(input) - val b = RegNext(a) - output := b - } - - val logic2 = cd2 on new Area{ - val a = out(RegNext(logic1.a)) - - } -} - -class SyncronousCheckerTesterC(v : Int) extends Component{ - val clk1, clk2, reset = in Bool() - val input = in UInt(8 bits) - val output = out UInt(8 bits) - - val clk1Buf = List.fill(3)(Bool).foldLeft(clk1){(i,o) => o := i; o} - val clk2Buf = List.fill(3)(Bool).foldLeft(clk2){(i,o) => o := i; o} - - val cd1 = ClockDomain(clk1Buf, reset) - val cd2 = ClockDomain(clk2Buf, reset) - v match{ - case 0 => - case 1 => cd1.setSyncWith(cd2) - case 2 => cd2.setSyncWith(cd1) - case 3 => ClockDomain(clk1).setSyncWith(cd2) - case 4 => ClockDomain(clk2).setSyncWith(cd1) - case 5 => ClockDomain(clk1).setSyncWith(ClockDomain(clk2)) - } - - val logic1 = cd1 on new Area{ - val a = RegNext(input) - val b = RegNext(a) - output := b - } - - val logic2 = cd2 on new Area{ - val a = out(RegNext(logic1.a)) - } -} - - -class SyncronousCheckerTesterD(v : Int) extends Component{ - val clk1,reset = in Bool() - val input = in UInt(8 bits) - val output = out UInt(8 bits) - - - val clk2 = clk1 && input === 0 - - val cd1 = ClockDomain(clk1, reset) - val cd2 = ClockDomain(clk2, reset) - - v match { - case 0 => - case 1 => cd1.setSyncWith(cd2) - case 2 => Clock.syncDrive(source = clk1, sink = clk2) - } - - val logic1 = cd1 on new Area{ - val a = RegNext(input) - val b = RegNext(a) - output := b - } - - val logic2 = cd2 on new Area{ - val a = out(RegNext(logic1.a)) - } -} - -class SyncronousCheckerTester extends AnyFunSuite{ - import CheckTester._ - - test("a") { generationShouldPass(new SyncronousCheckerTesterA) } - test("b") { generationShouldPass(new SyncronousCheckerTesterB) } - test("c0") { generationShouldFail(new SyncronousCheckerTesterC(0)) } - test("c1") { generationShouldPass(new SyncronousCheckerTesterC(1)) } - test("c2") { generationShouldPass(new SyncronousCheckerTesterC(2)) } - test("c3") { generationShouldPass(new SyncronousCheckerTesterC(3)) } - test("c4") { generationShouldPass(new SyncronousCheckerTesterC(4)) } - test("c5") { generationShouldPass(new SyncronousCheckerTesterC(5)) } - test("d0") { generationShouldFail(new SyncronousCheckerTesterD(0)) } - test("d1") { generationShouldPass(new SyncronousCheckerTesterD(1)) } - test("d2") { generationShouldPass(new SyncronousCheckerTesterD(2)) } -// test("d3") { generationShouldFail(new SyncronousCheckerTesterD(3)) } -} diff --git a/tester/src/test/scala/spinal/tester/scalatest/FixedPointTester.scala b/tester/src/test/scala/spinal/tester/scalatest/FixedPointTester.scala deleted file mode 100644 index 96ec150c44..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/FixedPointTester.scala +++ /dev/null @@ -1,53 +0,0 @@ -package spinal.tester.scalatest - -import spinal.core._ -import spinal.lib.com.uart._ -import spinal.tester.scalatest.FixedPointTester.FixedPointTester - -object FixedPointTester{ - - case class BundleA(width : Int) extends Bundle{ - val a = BundleAA(width) - } - case class BundleAA(width : Int) extends Bundle{ - val sfix = SFix(4 exp,width bit) - } - - class FixedPointTester extends Component { - val io = new Bundle { - val inSFix = in(Vec(Seq(SFix(4 exp,16 bit),SFix(2 exp,12 bit)))) - val outSFix = out(Vec(Seq(SFix(4 exp,16 bit),SFix(8 exp,24 bit)))) - - val inSFix2 = in SFix(0 exp, -8 exp) - val outSFix2 = out(SFix(2 exp, -8 exp)) - - val inBundleA = in(BundleA(8)) - val outBundleA = out(BundleA(6)) - } - io.outSFix(0) := (io.inSFix(0) + io.inSFix(1)) - //28 bit point at 28-6=22 target is at 24-8=16 - io.outSFix(1) := (io.inSFix(0) * io.inSFix(1)).truncated - - io.outSFix2 := ((io.inSFix2 <<|1) + io.inSFix2 ) <<|1 - //io.outSFix(0).raw := S(0,16 bit) - //io.outSFix(1).raw := S(0,24 bit) - //io.outBundleA.a.sfix.raw := S(0,6 bit) - io.inBundleA.a.sfix.addTag(tagTruncated) - io.outBundleA <> io.inBundleA - - - - } -} - -// -//class FixedPointTesterGhdlBoot extends SpinalTesterGhdlBase { -// override def getName: String = "FixedPointTester" -// override def createToplevel: Component = new FixedPointTester -//} - -class FixedPointTesterCocotbBoot extends SpinalTesterCocotbBase { - override def getName: String = "FixedPointTester" - override def pythonTestLocation: String = "tester/src/test/python/spinal/FixedPointTester" - override def createToplevel: Component = new FixedPointTester -} \ No newline at end of file diff --git a/tester/src/test/scala/spinal/tester/scalatest/FormalArbiterTester.scala b/tester/src/test/scala/spinal/tester/scalatest/FormalArbiterTester.scala deleted file mode 100644 index d34f9392c8..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/FormalArbiterTester.scala +++ /dev/null @@ -1,383 +0,0 @@ -package spinal.tester.scalatest - -import spinal.core._ -import spinal.core.formal._ -import spinal.lib._ -import spinal.lib.formal._ - -class FormalArbiterTester extends SpinalFormalFunSuite { - def usualVerify[T <: Data]( - inputs: Vec[Stream[T]], - output: Stream[T], - portCount: Int, - select: UInt, - selectOH: Bits, - reset: Bool, - withLock: Boolean, - locked: Bool - ) = new Area { - output.formalCovers(2) - when(reset || past(reset)) { - for (i <- 0 until portCount) { - assume(inputs(i).valid === False) - } - assert(select === 0) - if (withLock) assert(!locked) - } - - for (i <- 0 until portCount) { - inputs(i).formalAssumesSlave() - } - - assert(select < portCount) - assert(select === OHToUInt(selectOH)) - assert(selectOH === OHMasking.first(selectOH)) - assert(output.fire === inputs(select).fire) - assert(output.payload === inputs(select).payload) - } - - def prepareContext(withLock: Boolean) = new Area { - val portCount = 5 - val select = UInt(log2Up(portCount) bit) - val selectOH = Bits(portCount bit) - val dataType = Bits(8 bits) - val locked = Bool() - - val reset = ClockDomain.current.isResetActive - val notReset = !(reset || past(reset)) - cover(notReset) - assumeInitial(reset) - - val inputs = Vec(slave(Stream(dataType)), portCount) - val output = master(Stream(dataType)) - val usual = usualVerify(inputs, output, portCount, select, selectOH, reset, withLock, locked) - - val inputsValid = Vec(inputs.map(_.valid)) - val selStableCond = past(output.isStall) && notReset - val selectUnLockCond = !locked || past(output.fire) - } - - def prepareContextFragment(withLock: Boolean) = new Area { - val portCount = 5 - val select = UInt(log2Up(portCount) bit) - val selectOH = Bits(portCount bit) - val dataType = Fragment(Bits(8 bits)) - val locked = Bool() - - val reset = ClockDomain.current.isResetActive - val notReset = !(reset || past(reset)) - cover(notReset) - assumeInitial(reset) - - val inputs = Vec(slave(Stream(dataType)), portCount) - val output = master(Stream(dataType)) - val usual = usualVerify(inputs, output, portCount, select, selectOH, reset, withLock, locked) - - val inputsValid = Vec(inputs.map(_.valid)) - val selStableCond = !past((inputsValid.asBits === 0) || output.last || reset) - val selectUnLockCond = !locked || past(output.last && output.fire) - } - - def sequentialOrderVerify(select: UInt, portCount: Int) = new Area { - val d1 = anyconst(UInt(log2Up(portCount) bit)) - assume(d1 < portCount) - val d2 = UInt(log2Up(portCount) bit) - d2 := (d1 + 1) % portCount - - val cntSeqCheck = changed(select) && (select === d2) - cover(cntSeqCheck) - when(cntSeqCheck) { - assert(past(select) === d1) - } - } - - def lowFirstVerify( - selectOH: Bits, - inputsvalid: Vec[Bool], - unLockCond: Bool - ) = new Area { - val inputsLowerFirst = OHMasking.first(inputsvalid).asBits - cover(unLockCond) - when(unLockCond) { - assert(selectOH === inputsLowerFirst) - } - } - - def roundRobinVerify( - selectOH: Bits, - inputsValid: Vec[Bool], - portCount: Int, - maskLocked: Vec[Bool], - unLockCond: Bool - ) = new Area { - val requests = inputsValid.asBits.asUInt - val uGranted = selectOH.asUInt - val doubleRequests = requests @@ requests - val doubleGrant = doubleRequests & ~(doubleRequests - uGranted) - val masked = doubleGrant(portCount, portCount bits) | doubleGrant(0, portCount bits) - val inputsRoundRobinOH = masked.asBits - - cover(unLockCond) - when(unLockCond) { - assert(selectOH === inputsRoundRobinOH) - } - // used for Prove - assert(maskLocked === OHMasking.first(maskLocked)) - } - - def selStableVerify(selectOH: Bits, selStableCond: Bool, withLock: Boolean) = new Area { - if (withLock) { - cover(selStableCond) - when(selStableCond) { - assert(stable(selectOH)) - } - } - } - - def withAssertsVerify[T <: Data](outisStall: Bool, verifyCond: Vec[Bool], output: Stream[T], withLock: Boolean) = - new Area { - if (withLock) { - val stallStableSel = outisStall && stable(verifyCond) - cover(stallStableSel) - when(stallStableSel) { - output.formalAssertsMaster() - } - } - } - - test("Arbiter-sequentialOrder-verify") { - FormalConfig - .withBMC(20) - .withProve(20) - .withCover(20) - // .withDebug - .doVerify(new Component { - val withLock = true - val context = prepareContext(withLock) - val dut = FormalDut( - new StreamArbiter(context.dataType, context.portCount)( - StreamArbiter.Arbitration.sequentialOrder, - StreamArbiter.Lock.none - ) - ) - - context.select := dut.io.chosen - context.selectOH := dut.io.chosenOH - context.locked := dut.locked - context.output << dut.io.output - for (i <- 0 until context.portCount) { - context.inputs(i) >> dut.io.inputs(i) - } - - val withAssert = withAssertsVerify(context.output.isStall, context.inputsValid, context.output, withLock) - val selStable = selStableVerify(context.selectOH, context.selStableCond, withLock) - val sequentialOrder = sequentialOrderVerify(context.select, context.portCount) - }) - } - - test("Arbiter-lowerfirst-none-verify") { - FormalConfig - .withBMC(20) - .withProve(20) - .withCover(20) - // .withDebug - .doVerify(new Component { - val withLock = false - val context = prepareContext(withLock) - val dut = FormalDut( - new StreamArbiter(context.dataType, context.portCount)( - StreamArbiter.Arbitration.lowerFirst, - StreamArbiter.Lock.none - ) - ) - - context.select := dut.io.chosen - context.selectOH := dut.io.chosenOH - context.locked := dut.locked - context.output << dut.io.output - for (i <- 0 until context.portCount) { - context.inputs(i) >> dut.io.inputs(i) - } - - val withAssert = withAssertsVerify(context.output.isStall, context.inputsValid, context.output, withLock) - val selStable = selStableVerify(context.selectOH, context.selStableCond, withLock) - val lowFirst = lowFirstVerify(context.selectOH, context.inputsValid, context.selectUnLockCond) - }) - } - - test("Arbiter-lowerfirst-transactionLock-verify") { - FormalConfig - .withBMC(20) - .withProve(20) - .withCover(20) - // .withDebug - .doVerify(new Component { - - val withLock = true - val context = prepareContext(withLock) - val dut = FormalDut( - new StreamArbiter(context.dataType, context.portCount)( - StreamArbiter.Arbitration.lowerFirst, - StreamArbiter.Lock.transactionLock - ) - ) - - context.select := dut.io.chosen - context.selectOH := dut.io.chosenOH - context.locked := dut.locked - context.output << dut.io.output - for (i <- 0 until context.portCount) { - context.inputs(i) >> dut.io.inputs(i) - } - // used for Prove - when(context.notReset) { - assert(past(context.output.isStall) === dut.locked) - } - - val withAssert = withAssertsVerify(context.output.isStall, context.inputsValid, context.output, withLock) - val selStable = selStableVerify(context.selectOH, context.selStableCond, withLock) - val lowFirst = lowFirstVerify(context.selectOH, context.inputsValid, context.selectUnLockCond) - }) - } - - test("Arbiter-lowerfirst-fragment-verify") { - FormalConfig - .withBMC(20) - .withProve(20) - .withCover(20) - // .withDebug - .doVerify(new Component { - val withLock = true - val context = prepareContextFragment(withLock) - val dut = FormalDut( - new StreamArbiter(context.dataType, context.portCount)( - StreamArbiter.Arbitration.lowerFirst, - StreamArbiter.Lock.fragmentLock - ) - ) - - context.select := dut.io.chosen - context.selectOH := dut.io.chosenOH - context.locked := dut.locked - context.output << dut.io.output - for (i <- 0 until context.portCount) { - context.inputs(i) >> dut.io.inputs(i) - } - - val withAssert = withAssertsVerify(context.output.isStall, context.inputsValid, context.output, withLock) - val selStable = selStableVerify(context.selectOH, context.selStableCond, withLock) - val lowFirst = lowFirstVerify(context.selectOH, context.inputsValid, context.selectUnLockCond) - }) - } - - test("Arbiter-roundrobin-none-verify") { - FormalConfig - .withBMC(20) - .withProve(20) - .withCover(20) - // .withDebug - .doVerify(new Component { - val withLock = false - val context = prepareContext(withLock) - val dut = FormalDut( - new StreamArbiter(context.dataType, context.portCount)( - StreamArbiter.Arbitration.roundRobin, - StreamArbiter.Lock.none - ) - ) - - context.select := dut.io.chosen - context.selectOH := dut.io.chosenOH - context.locked := dut.locked - context.output << dut.io.output - for (i <- 0 until context.portCount) { - context.inputs(i) >> dut.io.inputs(i) - } - - val roundRobin = roundRobinVerify( - context.selectOH, - context.inputsValid, - context.portCount, - dut.maskLocked, - context.selectUnLockCond - ) - val withAssert = withAssertsVerify(context.output.isStall, roundRobin.masked.asBools, context.output, withLock) - val selStable = selStableVerify(context.selectOH, context.selStableCond, withLock) - }) - } - - test("Arbiter-roundrobin-transactionLock-verify") { - FormalConfig - .withBMC(20) - .withProve(20) - .withCover(20) - .withDebug - .doVerify(new Component { - val withLock = true - val context = prepareContext(withLock) - val dut = FormalDut( - new StreamArbiter(context.dataType, context.portCount)( - StreamArbiter.Arbitration.roundRobin, - StreamArbiter.Lock.transactionLock - ) - ) - - context.select := dut.io.chosen - context.selectOH := dut.io.chosenOH - context.locked := dut.locked - context.output << dut.io.output - for (i <- 0 until context.portCount) { - context.inputs(i) >> dut.io.inputs(i) - } - // used for Prove - when(context.notReset) { - assert(past(context.output.isStall) === dut.locked) - } - val roundRobin = roundRobinVerify( - context.selectOH, - context.inputsValid, - context.portCount, - dut.maskLocked, - context.selectUnLockCond - ) - val withAssert = withAssertsVerify(context.output.isStall, roundRobin.masked.asBools, context.output, withLock) - val selStable = selStableVerify(context.selectOH, context.selStableCond, withLock) - }) - } - - test("Arbiter-roundrobin-fragment-verify") { - FormalConfig - .withBMC(20) - .withProve(20) - .withCover(20) - // .withDebug - .doVerify(new Component { - val withLock = true - val context = prepareContextFragment(withLock) - val dut = FormalDut( - new StreamArbiter(context.dataType, context.portCount)( - StreamArbiter.Arbitration.roundRobin, - StreamArbiter.Lock.fragmentLock - ) - ) - - context.select := dut.io.chosen - context.selectOH := dut.io.chosenOH - context.locked := dut.locked - context.output << dut.io.output - for (i <- 0 until context.portCount) { - context.inputs(i) >> dut.io.inputs(i) - } - - val roundRobin = roundRobinVerify( - context.selectOH, - context.inputsValid, - context.portCount, - dut.maskLocked, - context.selectUnLockCond - ) - val withAssert = withAssertsVerify(context.output.isStall, roundRobin.masked.asBools, context.output, withLock) - val selStable = selStableVerify(context.selectOH, context.selStableCond, withLock) - }) - } -} diff --git a/tester/src/test/scala/spinal/tester/scalatest/FormalDeMuxTester.scala b/tester/src/test/scala/spinal/tester/scalatest/FormalDeMuxTester.scala deleted file mode 100644 index 4c2bdb10b1..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/FormalDeMuxTester.scala +++ /dev/null @@ -1,125 +0,0 @@ -package spinal.tester.scalatest - -import spinal.core._ -import spinal.core.formal._ -import spinal.lib._ -import spinal.lib.formal._ - -class FormalDeMuxTester extends SpinalFormalFunSuite { - def formaldemux(selWithCtrl: Boolean = false) = { - FormalConfig - .withBMC(20) - .withProve(20) - .withCover(20) - // .withDebug - .doVerify(new Component { - val portCount = 5 - val dataType = Bits(8 bits) - val dut = FormalDut(new StreamDemux(dataType, portCount)) - - val reset = ClockDomain.current.isResetActive - - assumeInitial(reset) - - val demuxSelect = anyseq(UInt(log2Up(portCount) bit)) - val demuxInput = slave(Stream(dataType)) - val demuxOutputs = Vec(master(Stream(dataType)), portCount) - - dut.io.select := demuxSelect - demuxInput >> dut.io.input - - when(reset || past(reset)) { - assume(demuxInput.valid === False) - } - - val selStableCond = if (selWithCtrl) past(demuxOutputs(demuxSelect).isStall) else null - if (selWithCtrl) { - cover(selStableCond) - when(selStableCond) { - assume(stable(demuxSelect)) - } - } - - assumeInitial(demuxSelect < portCount) - cover(demuxInput.fire) - demuxInput.formalAssumesSlave() - demuxInput.formalCovers(5) - - val inputFireStableSelChanged = past(demuxInput.fire) && demuxInput.fire && changed(demuxSelect) - cover(inputFireStableSelChanged) - - for (i <- 0 until portCount) { - demuxOutputs(i) << dut.io.outputs(i) - demuxOutputs(i).formalAssertsMaster() - demuxOutputs(i).formalCovers(5) - } - - for (i <- 0 until portCount) { - assert(demuxOutputs(i).payload === demuxInput.payload) - when(i =/= demuxSelect) { - assert(demuxOutputs(i).valid === False) - } - } - when(demuxSelect < portCount) { - assert(demuxOutputs(demuxSelect) === demuxInput) - } - }) - } - test("demux_sel_with_control") { - formaldemux(true) - } - test("demux_sel_without_control") { - shouldFail(formaldemux(false)) - } - - test("demux_with_selector") { - FormalConfig - .withProve(20) - .withCover(20) - .doVerify(new Component { - val portCount = 5 - val dataType = Bits(8 bits) - val dut = FormalDut(new StreamDemux(dataType, portCount)) - val selector = dut.io.createSelector() - - val reset = ClockDomain.current.isResetActive - assumeInitial(reset) - - val demuxSelector = slave(Stream(UInt(log2Up(portCount) bit))) - demuxSelector >> selector - val demuxInput = slave(Stream(dataType)) - demuxInput >> dut.io.input - val demuxOutputs = Vec(master(Stream(dataType)), portCount) - for (i <- 0 until portCount) { - demuxOutputs(i) << dut.io.outputs(i) - } - - when(reset || past(reset)) { - assume(demuxInput.valid === False) - assume(demuxSelector.valid === False) - } - - assumeInitial(demuxSelector.payload < portCount) - demuxSelector.formalAssumesSlave() - demuxInput.formalAssumesSlave() - demuxInput.formalCovers(5) - - val inputFireStableSelChanged = past(demuxInput.fire) && demuxInput.fire && changed(dut.io.select) - cover(inputFireStableSelChanged) - - for (i <- 0 until portCount) { - demuxOutputs(i).formalAssertsMaster() - demuxOutputs(i).formalCovers(5) - } - - for (i <- 0 until portCount) { - when(i =/= dut.io.select) { - assert(demuxOutputs(i).valid === False) - } - } - when(dut.io.select < portCount) { - assert(demuxOutputs(dut.io.select) === demuxInput) - } - }) - } -} diff --git a/tester/src/test/scala/spinal/tester/scalatest/FormalDispatcherSequencial.scala b/tester/src/test/scala/spinal/tester/scalatest/FormalDispatcherSequencial.scala deleted file mode 100644 index 839efb2722..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/FormalDispatcherSequencial.scala +++ /dev/null @@ -1,66 +0,0 @@ -package spinal.tester.scalatest - -import spinal.core._ -import spinal.core.formal._ -import spinal.lib._ -import spinal.lib.formal._ - -class FormalDispatcherSequencialTester extends SpinalFormalFunSuite { - test("DispatcherSequencial-verify") { - FormalConfig - .withBMC(20) - .withProve(20) - .withCover(40) - // .withDebug - .doVerify(new Component { - val portCount = 5 - val dataType = Bits(8 bits) - val reset = ClockDomain.current.isResetActive - val dut = FormalDut(new StreamDispatcherSequencial(dataType, portCount)) - - assumeInitial(reset) - - val muxInput = slave(Stream(dataType)) - val muxOutputs = Vec(master(Stream(dataType)), portCount) - - muxInput >> dut.io.input - for (i <- 0 until portCount) { - muxOutputs(i) << dut.io.outputs(i) - } - - when(reset || past(reset)) { - assume(muxInput.valid === False) - } - - cover(muxInput.fire) - - muxInput.formalAssumesSlave() - muxInput.formalCovers(3) - - for (i <- 0 until portCount) { - cover(dut.counter.value === i) - muxOutputs(i).formalAssertsMaster() - muxOutputs(i).formalCovers() - } - - for (i <- 0 until portCount) { - when(dut.counter.value =/= i) { - assert(muxOutputs(i).valid === False) - } otherwise { - assert(muxOutputs(i) === muxInput) - } - } - - val d1 = anyconst(UInt(log2Up(portCount) bit)) - assume(d1 < portCount) - val d2 = UInt(log2Up(portCount) bit) - d2 := (d1 + 1) % portCount - - val cntSeqCheck = changed(dut.counter.value) && (dut.counter.value === d2) - cover(cntSeqCheck) - when(cntSeqCheck) { - assert(past(dut.counter.value) === d1) - } - }) - } -} diff --git a/tester/src/test/scala/spinal/tester/scalatest/FormalFifoCCTester.scala b/tester/src/test/scala/spinal/tester/scalatest/FormalFifoCCTester.scala deleted file mode 100644 index fb460ccb3b..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/FormalFifoCCTester.scala +++ /dev/null @@ -1,192 +0,0 @@ -package spinal.tester.scalatest - -import spinal.core._ -import spinal.core.formal._ -import spinal.lib._ -import spinal.lib.formal._ - -class FormalFifoCCTester extends SpinalFormalFunSuite { - def formalContext(pushPeriod: Int, popPeriod: Int, seperateReset: Boolean = false) = new Area { - val back2backCycles = 2 - val fifoDepth = 4 - - val pushClock = ClockDomain.current - val reset = pushClock.isResetActive - val popClock = ClockDomain.external("pop") - val popReset = popClock.isResetActive - - val inValue = in(UInt(3 bits)) - val inValid = in(Bool()) - val outReady = in(Bool()) - val gclk = GlobalClock() - - assumeInitial(reset) - assumeInitial(popReset) - - gclk.assumeClockTiming(pushClock, pushPeriod) - gclk.assumeResetReleaseSync(pushClock) - if (!seperateReset) { - gclk.keepBoolLeastCycles(reset, popPeriod) - } - - gclk.assumeClockTiming(popClock, popPeriod) - if (seperateReset) { - gclk.assumeResetReleaseSync(popClock) - gclk.alignAsyncResetStart(pushClock, popClock) - } - - val dut = FormalDut(new StreamFifoCC(cloneOf(inValue), fifoDepth, pushClock, popClock, !seperateReset)) - gclk.assumeIOSync2Clock(pushClock, dut.io.push.valid) - gclk.assumeIOSync2Clock(pushClock, dut.io.push.payload) - gclk.assumeIOSync2Clock(popClock, dut.io.pop.ready) - - dut.io.push.payload := inValue - dut.io.push.valid := inValid - dut.io.pop.ready := outReady - - // assume no valid while reset and one clock later. - when(reset || past(reset)) { - assume(inValid === False) - } - - dut.formalAsserts(gclk.domain) - - val pushArea = new ClockingArea(pushClock) { - dut.io.push.formalAssumesSlave() - dut.io.push.formalCovers() - } - - // back to back transaction cover test. - val popCheckDomain = if (seperateReset) popClock else popClock.copy(reset = reset) - val popArea = new ClockingArea(popCheckDomain) { - dut.io.pop.formalCovers(back2backCycles) - dut.io.pop.formalAssertsMaster() - } - } - - def testMain(pushPeriod: Int, popPeriod: Int, seperateReset: Boolean = false) = { - val proveCycles = 8 - val coverCycles = 8 - val maxPeriod = Math.max(pushPeriod, popPeriod) - - FormalConfig - .withProve(maxPeriod * proveCycles) - .withCover(maxPeriod * coverCycles) - .withAsync - .doVerify(new Component { - val context = formalContext(pushPeriod, popPeriod, seperateReset) - }) - } - - test("fifo-verify fast pop") { - testMain(5, 3) - } - - test("fifo-verify fast push") { - testMain(3, 5) - } - -// test("fifo-verify ultra fast pop") { -// testMain(11, 2) -// } - -// test("fifo-verify ultra fast push") { -// testMain(2, 11) -// } - - test("fifo-verify fast pop reset seperately") { - testMain(5, 3, true) - } - - test("fifo-verify fast push reset seperately") { - testMain(3, 5, true) - } - -// test("fifo-verify ultra fast pop reset seperately") { -// testMain(11, 2, true) -// } - -// test("fifo-verify ultra fast push reset seperately") { -// testMain(2, 11, true) -// } - - def testNoLoss(pushPeriod: Int, popPeriod: Int, seperateReset: Boolean = false) = { - val proveCycles = 8 - val coverCycles = 8 - val maxPeriod = Math.max(pushPeriod, popPeriod) - - FormalConfig - .withCover(maxPeriod * coverCycles) - .withAsync - .withDebug - .doVerify(new Component { - val context = formalContext(pushPeriod, popPeriod, seperateReset) - - val d1 = anyconst(cloneOf(context.inValue)) - val d1_in = RegInit(False) - when(context.inValue === d1 & context.dut.io.push.fire) { - d1_in := True - } - when(d1_in) { assume(context.inValue =/= d1) } - - val popCheckArea = new ClockingArea(context.popCheckDomain) { - val d1_inCC = BufferCC(d1_in) - val cond = d1_inCC & context.dut.io.pop.fire - val hist = History(context.dut.io.pop.payload, context.fifoDepth, cond) - val counter = Counter(context.fifoDepth, inc = cond) - when(!d1_inCC) { counter.clear() } - cover(counter.willOverflow & !hist.sContains(d1)) - } - - val globalCheckArea = new ClockingArea(context.popCheckDomain) { - def checkValidData(cond: UInt => Bool): Seq[Bool] = context.dut.rework { - val maps = for (i <- 0 until context.fifoDepth) yield { - val index = context.dut.popCC.popPtr + i - val out = False - when(i < context.dut.pushCC.pushPtr - context.dut.popCC.popPtr) { - out := cond(context.dut.ram(index.resized)) - } - out - } - maps - } - val fits = checkValidData(_ === d1.pull()) - val containD1 = fits.reduce(_ || _) - when(!d1_in) { assume(!containD1) } - } - }) - } - - test("noloss fast pop") { - shouldFail(testNoLoss(5, 3)) - } - - test("noloss fast push") { - shouldFail(testNoLoss(3, 5)) - } - - // test("noloss ultra fast pop") { - // shouldFail(testNoLoss(11, 2)) - // } - - // test("noloss ultra fast push") { - // shouldFail(testNoLoss(2, 11)) - // } - - test("noloss fast pop reset seperately") { - shouldFail(testNoLoss(5, 3, true)) - } - - test("noloss fast push reset seperately") { - shouldFail(testNoLoss(3, 5, true)) - } - - // test("noloss ultra fast pop reset seperately") { - // shouldFail(testNoLoss(11, 2, true)) - // } - - // test("noloss ultra fast push reset seperately") { - // shouldFail(testNoLoss(2, 11, true)) - // } - -} diff --git a/tester/src/test/scala/spinal/tester/scalatest/FormalFifoTester.scala b/tester/src/test/scala/spinal/tester/scalatest/FormalFifoTester.scala deleted file mode 100644 index 7e5645e880..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/FormalFifoTester.scala +++ /dev/null @@ -1,72 +0,0 @@ -package spinal.tester.scalatest - -import spinal.core._ -import spinal.core.formal._ -import spinal.lib.{StreamFifo, History, OHToUInt} -import spinal.lib.formal._ - -class FormalFifoTester extends SpinalFormalFunSuite { - test("fifo-verify all") { - val initialCycles = 2 - val inOutDelay = 2 - val coverCycles = 10 - FormalConfig - .withBMC(10) - .withProve(10) - .withCover(coverCycles) - // .withDebug - .doVerify(new Component { - val depth = 4 - val dut = FormalDut(new StreamFifo(UInt(7 bits), depth)) - val reset = ClockDomain.current.isResetActive - - assumeInitial(reset) - - val inValue = anyseq(UInt(7 bits)) - val inValid = anyseq(Bool()) - val outReady = anyseq(Bool()) - dut.io.push.payload := inValue - dut.io.push.valid := inValid - dut.io.pop.ready := outReady - - // assume no valid while reset and one clock later. - when(reset || past(reset)) { - assume(inValid === False) - } - - dut.io.push.formalAssumesSlave() - dut.io.pop.formalAssertsMaster() - - dut.io.push.formalCovers() - // back to back transaction cover test. - dut.io.pop.formalCovers(coverCycles - initialCycles - inOutDelay - 1) - - val d1 = anyconst(UInt(7 bits)) - val d2 = anyconst(UInt(7 bits)) - - val (d1_in, d2_in) = dut.io.push.formalAssumesOrder(d1, d2) - val (d1_out, d2_out) = dut.io.pop.formalAssertsOrder(d1, d2) - - when(!d1_in) { assume(!dut.formalContains(d1)) } - when(d1_in && !d1_out) { assert(dut.formalCount(d1) === 1) } - - when(!d2_in) { assume(!dut.formalContains(d2)) } - when(d2_in && !d2_out) { assert(dut.formalCount(d2) === 1) } - - when(d1_in && d2_in && !d1_out) { assert(!d2_out) } - - def getCompId(x: UInt): UInt = { - val id = OHToUInt(dut.formalCheck(_ === x.pull()).asBits) - val extId = id +^ depth - val compId = CombInit(extId) - when(id >= dut.logic.popPtr) { - compId := id.resized - } - compId - } - when(d1_in && d2_in && !d1_out && !d2_out) { - assert(getCompId(d1) < getCompId(d2)) - } - }) - } -} diff --git a/tester/src/test/scala/spinal/tester/scalatest/FormalForkTester.scala b/tester/src/test/scala/spinal/tester/scalatest/FormalForkTester.scala deleted file mode 100644 index 179e513905..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/FormalForkTester.scala +++ /dev/null @@ -1,105 +0,0 @@ -package spinal.tester.scalatest - -import spinal.core._ -import spinal.core.formal._ -import spinal.lib._ -import spinal.lib.formal._ - -class FormalForkTester extends SpinalFormalFunSuite { - def formalfork (synchronous: Boolean = false, back2BackCheck: Boolean = false ) = { - FormalConfig - .withBMC(20) - .withProve(20) - .withCover(20) - // .withDebug - .doVerify(new Component { - val portCount = 2 - val dataType = Bits(8 bits) - val dut = FormalDut(new StreamFork(dataType, portCount, synchronous)) - - val reset = ClockDomain.current.isResetActive - - assumeInitial(reset) - - val input = slave(Stream(dataType)) - val outputs = Vec(master(Stream(dataType)), portCount) - - input >> dut.io.input - for (i <- 0 until portCount) { - outputs(i) << dut.io.outputs(i) - } - - when(reset || past(reset)) { - assume(input.valid === False) - } - - cover(input.fire) - - input.formalAssumesSlave() - if(back2BackCheck) input.formalCovers(3) - - for (i <- 0 until portCount) { - assert(outputs(i).payload === input.payload) - outputs(i).formalAssertsMaster() - if(back2BackCheck) outputs(i).formalCovers(3) - } - - val fired = if(!synchronous)Vec(RegInit(True), portCount) else null // store fire status, - val outputsFireAsync = if(!synchronous){fired(0) =/= fired(1)} else null - val out0FireFirst = if(!synchronous){fired(1) && !fired(0)} else null - val out1FireFirst = if(!synchronous){fired(0) && !fired(1)} else null - val out0FireLast = if(!synchronous){~(input.fire ^ outputs(0).fire)} else null - val out1FireLast = if(!synchronous){~(input.fire ^ outputs(1).fire)} else null - - if(synchronous){ - for (i <- 0 until portCount) { - assert(outputs(i).fire === input.fire) - - } - } - else{ - for(i <- 0 until portCount){ - cover(input.ready) - when(input.ready){ - fired(i) := True - } - cover(!input.ready && outputs(i).fire) - when(!input.ready && outputs(i).fire){ - fired(i) := False - } - - assert(fired(i) === dut.logic.linkEnable(i)) - } - - cover(out0FireFirst && !outputs(1).fire) - cover(out1FireFirst && !outputs(0).fire) - - when(outputsFireAsync) { - assert(!past(input.fire)) - } - - when(out0FireFirst) { - assert(out1FireLast) - assert(!outputs(0).valid) - } - - when(out1FireFirst) { - assert(out0FireLast) - assert(!outputs(1).valid) - } - } - }) - } - - test("fork-verify sync") { - formalfork(true,false) - } - - test("fork-verify sync back2Back fail") { - shouldFail(formalfork(true,true)) - } - - test("fork-verify async") { - formalfork(false,true) - } -} \ No newline at end of file diff --git a/tester/src/test/scala/spinal/tester/scalatest/FormalJoinTester.scala b/tester/src/test/scala/spinal/tester/scalatest/FormalJoinTester.scala deleted file mode 100644 index 9e2e819284..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/FormalJoinTester.scala +++ /dev/null @@ -1,69 +0,0 @@ -package spinal.tester.scalatest - -import spinal.core._ -import spinal.core.formal._ -import spinal.lib._ -import spinal.lib.formal._ - -class StreamJoin[T1 <: Data, T2 <: Data](dataType_0: T1, dataType_1: T2) extends Component { - val io = new Bundle { - val inputs_0 = slave(Stream (dataType_0)) - val inputs_1 = slave(Stream (dataType_1)) - val output = master(Stream(TupleBundle2( - dataType_0, - dataType_1 - ))) - } - val logic = StreamJoin(io.inputs_0,io.inputs_1) - io.output << logic -} - -class FormalJoinTester extends SpinalFormalFunSuite { - test("StreamJoinTester-verify") { - FormalConfig - .withBMC(20) - .withProve(20) - .withCover(20) - - // .withDebug - .doVerify(new Component { - val portCount = 5 - val dataType_0 = Bits(8 bits) - val dataType_1 = Bits(16 bits) - val dut = FormalDut(new StreamJoin(dataType_0, dataType_1)) - val reset = ClockDomain.current.isResetActive - - assumeInitial(reset) - - val inputs_0 = slave Stream (dataType_0) - val inputs_1 = slave Stream (dataType_1) - val output = master( - Stream( - TupleBundle2( - dataType_0, - dataType_1 - ) - ) - ) - - inputs_0 >> dut.io.inputs_0 - inputs_1 >> dut.io.inputs_1 - output << dut.io.output - - when(reset || past(reset)) { - assume(inputs_0.valid === False) - assume(inputs_1.valid === False) - } - - inputs_0.formalAssumesSlave() - inputs_1.formalAssumesSlave() - output.formalAssertsMaster() - output.formalCovers(3) - - assert(inputs_0.fire === inputs_1.fire) - assert(output.fire === inputs_0.fire) - assert(output.payload._1 === inputs_0.payload) - assert(output.payload._2 === inputs_1.payload) - }) - } -} diff --git a/tester/src/test/scala/spinal/tester/scalatest/FormalMuxTester.scala b/tester/src/test/scala/spinal/tester/scalatest/FormalMuxTester.scala deleted file mode 100644 index f13842fc24..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/FormalMuxTester.scala +++ /dev/null @@ -1,123 +0,0 @@ -package spinal.tester.scalatest - -import spinal.core._ -import spinal.core.formal._ -import spinal.lib._ -import spinal.lib.formal._ - -class FormalMuxTester extends SpinalFormalFunSuite { - def formalmux(selWithCtrl: Boolean = false) = { - FormalConfig - .withBMC(20) - .withProve(20) - .withCover(20) - // .withDebug - .doVerify(new Component { - val portCount = 5 - val dataType = Bits(8 bits) - val dut = FormalDut(new StreamMux(dataType, portCount)) - - val reset = ClockDomain.current.isResetActive - - assumeInitial(reset) - - val muxSelect = anyseq(UInt(log2Up(portCount) bit)) - val muxInputs = Vec(slave(Stream(dataType)), portCount) - val muxOutput = master(Stream(dataType)) - - dut.io.select := muxSelect - muxOutput << dut.io.output - - assumeInitial(muxSelect < portCount) - val selStableCond = if (selWithCtrl) past(muxOutput.isStall) else null - - when(reset || past(reset)) { - for (i <- 0 until portCount) { - assume(muxInputs(i).valid === False) - } - } - - if (selWithCtrl) { - cover(selStableCond) - when(selStableCond) { - assume(stable(muxSelect)) - } - } - muxOutput.formalAssertsMaster() - muxOutput.formalCovers(5) - - for (i <- 0 until portCount) { - muxInputs(i) >> dut.io.inputs(i) - muxInputs(i).formalAssumesSlave() - } - - cover(muxOutput.fire) - - for (i <- 0 until portCount) { - cover(dut.io.select === i) - muxInputs(i).formalAssumesSlave() - } - - when(muxSelect < portCount) { - assert(muxOutput === muxInputs(muxSelect)) - } - }) - } - test("mux_sel_with_control") { - formalmux(true) - } - test("mux_sel_without_control") { - shouldFail(formalmux(false)) - } - - test("mux_with_selector") { - FormalConfig - .withProve(20) - .withCover(20) - .doVerify(new Component { - val portCount = 5 - val dataType = Bits(8 bits) - val dut = FormalDut(new StreamMux(dataType, portCount)) - val selector = dut.io.createSelector() - - val reset = ClockDomain.current.isResetActive - assumeInitial(reset) - - val muxSelector = slave(cloneOf(selector)) - muxSelector >> selector - val muxInputs = Vec(slave(Stream(dataType)), portCount) - for (i <- 0 until portCount) { - muxInputs(i) >> dut.io.inputs(i) - } - val muxOutput = master(Stream(dataType)) - muxOutput << dut.io.output - - assumeInitial(muxSelector.payload < portCount) - muxSelector.formalAssumesSlave() - - when(reset || past(reset)) { - for (i <- 0 until portCount) { - assume(muxInputs(i).valid === False) - } - assume(muxSelector.valid === False) - } - - muxOutput.formalAssertsMaster() - muxOutput.formalCovers(5) - cover(dut.io.select =/= muxSelector.payload) - cover(changed(muxSelector.payload) & stable(muxSelector.valid) & muxSelector.valid) - val readyBits = muxInputs.map(_.ready).asBits() - assert((readyBits === 0) || (CountOne(readyBits) === 1)) - - for (i <- 0 until portCount) { - cover(dut.io.select === i) - muxInputs(i).formalAssumesSlave() - } - - when(dut.io.select < portCount) { - assert(muxOutput === muxInputs(dut.io.select)) - } - }) - - } -} diff --git a/tester/src/test/scala/spinal/tester/scalatest/FormalStreamExtender.scala b/tester/src/test/scala/spinal/tester/scalatest/FormalStreamExtender.scala deleted file mode 100644 index 02ee10eea1..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/FormalStreamExtender.scala +++ /dev/null @@ -1,205 +0,0 @@ -package spinal.tester.scalatest - -import spinal.core._ -import spinal.core.formal._ -import spinal.lib._ -import spinal.lib.formal._ - -class FormalStreamExtender extends SpinalFormalFunSuite { - def counterTester() { - FormalConfig - // .withBMC(10) - .withProve(10) - .withCover(10) - .doVerify(new Component { - val inStream = slave Stream (UInt(2 bits)) - val outStream = master Stream (UInt(2 bits)) - val count = in UInt (3 bits) - val dut = FormalDut(StreamTransactionCounter(inStream, outStream, count, false)) - - val inReady = in Bool () - inStream.ready := inReady - val outValid = in Bool () - outStream.valid := outValid - val outPayload = in UInt (2 bits) - outStream.payload := outPayload - - val reset = ClockDomain.current.isResetActive - assumeInitial(reset) - - val countHist = History(count, 2, inStream.fire, init = count.getZero) - when(!dut.io.available) { assume(inReady === False) } - - when(pastValid & past(!reset & inStream.fire)) { assert(dut.io.working) } - when(pastValid & past(dut.io.done & !inStream.fire)) { assert(!dut.io.working) } - - when(dut.io.done) { assert(dut.counter.value >= countHist(1)) } - when(dut.io.working) { - assert(countHist(1) === dut.expected) // key to sync verification logic and internal logic. - when(dut.counter.value === countHist(1) & outStream.fire) { assert(dut.io.done) } - when(!dut.io.done) { assert(!dut.io.available) } - .otherwise { assert(dut.io.available) } - } - .otherwise { assert(dut.io.available) } - val counterHelper = dut.formalAsserts() - - cover(inStream.fire & outStream.fire & dut.io.done) - cover(pastValid & past(dut.io.working) & !dut.io.working) - - inStream.formalAssumesSlave() - outStream.formalAssumesSlave() - - for(i <- 1 until 2) { - inStream.formalCovers(i) - outStream.formalCovers(i) - } - }) - } - - def counterNoDelayTester() { - FormalConfig - // .withBMC(10) - .withProve(10) - .withCover(10) - .doVerify(new Component { - val inStream = slave Stream (UInt(2 bits)) - val outStream = master Stream (UInt(2 bits)) - val count = in UInt (3 bits) - val dut = FormalDut(StreamTransactionCounter(inStream, outStream, count, true)) - - val inReady = in Bool () - inStream.ready := inReady - val outValid = in Bool () - outStream.valid := outValid - val outPayload = in UInt (2 bits) - outStream.payload := outPayload - - val reset = ClockDomain.current.isResetActive - assumeInitial(reset) - - val countHist = History(count, 2, inStream.fire, init = count.getZero) - val expected = countHist(1).getAheadValue() - when(!dut.io.available) { assume(inReady === False) } - - when(inStream.fire) { assert(dut.io.working) } - when(pastValid & past(dut.io.done) & !inStream.fire) { assert(!dut.io.working) } - - when(dut.io.done) { assert(dut.counter.value >= expected) } - when(dut.io.working) { - assert(expected === dut.expected) // key to sync verification logic and internal logic. - when(dut.counter.value === expected & outStream.fire) { assert(dut.io.done) } - when(!inStream.fire) { assert(!dut.io.available) } - .otherwise { assert(dut.io.available) } - } - .otherwise { assert(dut.io.available) } - cover(pastValid & past(dut.io.done) & inStream.fire) - cover(pastValid & past(dut.io.working) & !dut.io.working) - - inStream.formalAssumesSlave() - outStream.formalAssumesSlave() - - for(i <- 1 until 2) { - inStream.formalCovers(i) - outStream.formalCovers(i) - } - }) - } - - def extenderTester() { - FormalConfig - // .withBMC(10) - .withProve(10) - .withCover(10) - .doVerify(new Component { - val inStream = slave Stream (UInt(2 bits)) - val outStream = master Stream (UInt(2 bits)) - val count = in UInt (3 bits) - val dut = FormalDut(StreamTransactionExtender(inStream, outStream, count) { (_, p, _) => p }) - - val reset = ClockDomain.current.isResetActive - assumeInitial(reset) - - val countHist = History(count, 2, inStream.fire, init = count.getZero) - - when(pastValid & past(!reset & inStream.fire)) { assert(dut.io.working) } - when(pastValid & past(dut.io.done & !inStream.fire)) { assert(!dut.io.working) } - - when(dut.io.done) { assert(dut.counter.counter.value >= countHist(1)) } - when(dut.io.working) { - assert(countHist(1) === dut.counter.expected) // key to sync verification logic and internal logic. - when(dut.counter.counter.value === countHist(1) & outStream.fire) { assert(dut.io.done) } - when(!dut.io.done) { assert(!inStream.ready) } - } - cover(inStream.fire & outStream.fire & dut.io.done) - cover(pastValid & past(dut.io.working) & !dut.io.working) - - inStream.formalAssumesSlave() - outStream.formalAssertsMaster() - - for(i <- 1 until 2) { - inStream.formalCovers(i) - outStream.formalCovers(i) - } - }) - } - - - def extenderNoDelayTester() { - FormalConfig - // .withBMC(10) - .withProve(10) - .withCover(10) - .doVerify(new Component { - val inStream = slave Stream (UInt(2 bits)) - val outStream = master Stream (UInt(2 bits)) - val count = in UInt (3 bits) - val dut = FormalDut(StreamTransactionExtender(inStream, outStream, count, true) { (_, p, _) => p }) - - val reset = ClockDomain.current.isResetActive - assumeInitial(reset) - - val countHist = History(count, 2, inStream.fire, init = count.getZero) - val expected = countHist(1).getAheadValue() - - when(inStream.fire) { assert(dut.io.working) } - when(pastValid & past(dut.io.done) & !inStream.fire) { assert(!dut.io.working) } - - when(dut.io.done) { assert(dut.counter.counter.value >= expected) } - when(dut.io.working) { - assert(expected === dut.counter.expected) // key to sync verification logic and internal logic. - when(dut.counter.counter.value === expected & outStream.fire) { assert(dut.io.done) } - when(!inStream.fire) { assert(!dut.counter.io.available) } - .otherwise { assert(dut.counter.io.available) } - when(!dut.io.input.fire) { assert(!inStream.ready) } - when(dut.io.input.fire) { assert(dut.io.input.payload === dut.io.output.payload) } - .otherwise { assert(dut.io.output.payload === dut.payloadReg) } - } - cover(pastValid & past(dut.io.done) & inStream.fire) - cover(pastValid & past(dut.io.working) & !dut.io.working) - - inStream.formalAssumesSlave() - outStream.formalAssertsMaster() - - for(i <- 1 until 2) { - inStream.formalCovers(i) - outStream.formalCovers(i) - } - }) - } - - test("transaction counter") { - counterTester() - } - - test("transaction counter without delay") { - counterNoDelayTester() - } - - test("transaction extender") { - extenderTester() - } - - test("transaction extender without delay") { - extenderNoDelayTester() - } -} diff --git a/tester/src/test/scala/spinal/tester/scalatest/I2CIoMasterTester.scala b/tester/src/test/scala/spinal/tester/scalatest/I2CIoMasterTester.scala deleted file mode 100644 index 14d726a31e..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/I2CIoMasterTester.scala +++ /dev/null @@ -1,36 +0,0 @@ -///* -// * SpinalHDL -// * Copyright (c) Dolu, All rights reserved. -// * -// * This library is free software; you can redistribute it and/or -// * modify it under the terms of the GNU Lesser General Public -// * License as published by the Free Software Foundation; either -// * version 3.0 of the License, or (at your option) any later version. -// * -// * This library is distributed in the hope that it will be useful, -// * but WITHOUT ANY WARRANTY; without even the implied warranty of -// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// * Lesser General Public License for more details. -// * -// * You should have received a copy of the GNU Lesser General Public -// * License along with this library. -// */ -// -//package spinal.tester.scalatest -// -//import spinal.core._ -//import spinal.lib._ -//import spinal.lib.com.i2c._ -// -// -//class I2CIoMasterTester extends SpinalTesterCocotbBase { -// override def getName: String = "I2cIoMasterTester" -// override def pythonTestLocation: String = "tester/src/test/python/spinal/I2CTester2/IoMasterTester" -// override def createToplevel: Component = new I2cIoMaster(I2cIoMasterGenerics( -// samplingSize = 3, -// samplingClockDividerWidth = 10 bits, -// timerClockDividerWidth = 20 bits, -// timeoutBaudRatioLog2 = 5 -// )) -//} -// diff --git a/tester/src/test/scala/spinal/tester/scalatest/InternalClockTester.scala b/tester/src/test/scala/spinal/tester/scalatest/InternalClockTester.scala deleted file mode 100644 index fc5f998990..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/InternalClockTester.scala +++ /dev/null @@ -1,76 +0,0 @@ -package spinal.tester.scalatest - -import spinal.core._ -import spinal.lib._ - - -object InternalClockTester{ - class ClockGeneratorSub extends Component{ - val io = NoData - - val internalClock = CounterFreeRun(16)(0) - - val initCounter = RegInit(U(7)) - val srcReset = initCounter =/= U(0) - when(srcReset){ - initCounter := initCounter - U(1) - } - val internalClk = ClockDomain(internalClock) - val internalReset = Bool() - - val resetBuffer = new ClockingArea(internalClk){ - val internalReset = BufferCC(srcReset) - } - internalReset := resetBuffer.internalReset - - val internalClockDomain = ClockDomain(internalClock,internalReset) - } - - class ClockGenerator extends Component{ - val io = NoData - val sub = new ClockGeneratorSub - } - - class CounterComponentSub extends Component{ - val io = new Bundle{ - val counter = out UInt(8 bit) - } - val counter = Counter(256) - counter.increment() - io.counter := counter - } - - class CounterComponent extends Component{ - val io = new Bundle{ - val counter = out UInt(8 bit) - } - val sub = new CounterComponentSub - io <> sub.io - } -} - -import spinal.tester.scalatest.InternalClockTester._ -class InternalClockTester extends Component { - val io = new Bundle { - val internalClkCounter = out UInt(8 bit) - } - val clockGenerator = new ClockGenerator - - val internClockDomain = new ClockingArea(clockGenerator.sub.internalClockDomain){ - val counterComponent = new CounterComponent - io.internalClkCounter := counterComponent.io.counter - } -} - - - -//class InternalClockTesterGhdlBoot extends SpinalTesterGhdlBase { -// override def getName: String = "InternalClockTester" -// override def createToplevel: Component = new InternalClockTester -//} - -class InternalClockTesterCocotbBoot extends SpinalTesterCocotbBase { - override def getName: String = "InternalClockTester" - override def pythonTestLocation: String = "tester/src/test/python/spinal/InternalClockTester" - override def createToplevel: Component = new InternalClockTester -} \ No newline at end of file diff --git a/tester/src/test/scala/spinal/tester/scalatest/LibTester.scala b/tester/src/test/scala/spinal/tester/scalatest/LibTester.scala deleted file mode 100644 index efb8a08798..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/LibTester.scala +++ /dev/null @@ -1,38 +0,0 @@ -package spinal.tester.scalatest - -import org.scalatest.funsuite.AnyFunSuite -import spinal.core._ -import spinal.lib.{Delay, LatencyAnalysis} -import spinal.lib.com.uart._ -import spinal.lib.math.SIntMath -import spinal.tester.scalatest.FixedPointTester.FixedPointTester - -object LibTester{ - - - class LibTester extends Component { - val io = new Bundle { - val inSIntA = in SInt (16 bit) - val inSIntB = in SInt (16 bit) - val outSInt = out SInt (32 bit) - val outSIntRef = out SInt (32 bit) - } - io.outSInt := SIntMath.mul(io.inSIntA, io.inSIntB, 4, 0,1,(s,l) => RegNext(s)) - io.outSIntRef := Delay(io.inSIntA * io.inSIntB, LatencyAnalysis(io.inSIntA, io.outSInt)) - } - -} - - -class LibTesterCocotbBoot extends SpinalTesterCocotbBase { - override def getName: String = "LibTester" - override def pythonTestLocation: String = "tester/src/test/python/spinal/LibTester" - override def createToplevel: Component = new LibTester.LibTester - withWaveform = true -} - - -//class LibTesterGhdlBoot extends SpinalTesterGhdlBase { -// override def getName: String = "LibTester" -// override def createToplevel: Component = new LibTester.LibTester -//} diff --git a/tester/src/test/scala/spinal/tester/scalatest/MandelbrotTester.scala b/tester/src/test/scala/spinal/tester/scalatest/MandelbrotTester.scala deleted file mode 100644 index d974d317da..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/MandelbrotTester.scala +++ /dev/null @@ -1,35 +0,0 @@ -package spinal.tester.scalatest - -import spinal.core._ -import spinal.demo.mandelbrot._ - -class MandelbrotTester(p : MandelbrotCoreParameters ) extends MandelbrotCore(p){ - print("miaou") -} - - -//class MandelbrotTesterGhdlBoot extends SpinalTesterGhdlBase { -// override def getName: String = "MandelbrotTester" -// override def createToplevel: Component = new MandelbrotTester(MandelbrotCoreParameters(16, 8, 16, 16, 7, 34)) -// override def backendConfig(config: SpinalConfig) : SpinalConfig = { -// config.copy(defaultClockDomainFrequency=FixedFrequency(100 MHz)) -// } -// override def postTest: Unit = { -// super.postTest -// -// val out = scala.io.Source.fromFile("MandelbrotTester.out").getLines.reduceLeft(_+_) -// val ref = scala.io.Source.fromFile("tester/src/test/resources/MandelbrotTester.ref").getLines.reduceLeft(_+_) -// assert(out == ref,"Mandelbrot picture doesn't match with reference") -// -// } -//} - - -class MandelbrotTesterCocotbBoot extends SpinalTesterCocotbBase { - override def getName: String = "MandelbrotTester" - override def pythonTestLocation: String = "tester/src/test/python/spinal/MandelbrotTester" - override def createToplevel: Component = new MandelbrotTester(MandelbrotCoreParameters(16, 8, 16, 16, 7, 34)) - override def backendConfig(config: SpinalConfig) : SpinalConfig = { - config.copy(defaultClockDomainFrequency=FixedFrequency(100 MHz)) - } -} \ No newline at end of file diff --git a/tester/src/test/scala/spinal/tester/scalatest/MemTester.scala b/tester/src/test/scala/spinal/tester/scalatest/MemTester.scala deleted file mode 100644 index e277f3a485..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/MemTester.scala +++ /dev/null @@ -1,64 +0,0 @@ -package spinal.tester.scalatest - -import spinal.core._ -import spinal.lib._ -import spinal.lib.bus.amba3.ahblite._ - - - -object MemTester extends App{ - class MemTester extends Component { - val mem = Mem(Bits(32 bits), 16) - mem.initBigInt(List( - 0xbf6c8ffel, - 0x6f431025l, - 0xde894aeel, - 0xb007da48l, - 0xe39eca02l, - 0x1732378dl, - 0xd47822e3l, - 0xac711616l, - 0x0d45b17el, - 0xd863729dl, - 0x2210305el, - 0x73cf58e5l, - 0x80d3c954l, - 0xf56fb952l, - 0x9580e19cl, - 0xdd3b620dl - )) - - val readSync = slave(mem.readSyncPort) - val readAsync = new Bundle { - val address = in UInt(4 bits) - val data = out(mem.readAsync(address)) - } - val write = new Bundle { - val valid = in Bool() - val address = in UInt(4 bits) - val data = in Bits(32 bits) - val mask = in Bits(4 bits) - mem.write(address,data,valid,mask) - } - val readWrite = new Bundle { - val valid = in Bool() - val write = in Bool() - val address = in UInt(4 bits) - val writeData = in Bits(32 bits) - val mask = in Bits(4 bits) - val readData = out(mem.readWriteSync(address,writeData,valid,write,mask)) - - } - } - - SpinalVerilog(new MemTester) - SpinalVhdl(new MemTester) -} - -//class MemTesterCocotbBoot extends SpinalTesterCocotbBase { -// override def getName: String = "MemTester" -// override def pythonTestLocation: String = "tester/src/test/python/spinal/MemTester" -// override def createToplevel: Component = new MemTester.MemTester -// override def backendConfig(config: SpinalConfig): SpinalConfig = config.dumpWave() -// override def noVhdl = true -//} \ No newline at end of file diff --git a/tester/src/test/scala/spinal/tester/scalatest/MultiClockTester.scala b/tester/src/test/scala/spinal/tester/scalatest/MultiClockTester.scala deleted file mode 100644 index 5f3a9a6dfe..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/MultiClockTester.scala +++ /dev/null @@ -1,52 +0,0 @@ -package spinal.tester.scalatest - -import spinal.core._ -import spinal.lib._ - - -object MultiClockTester{ - class BundleA extends Bundle{ - val a = UInt(8 bit) - val b = Bool() - } -} - -import spinal.tester.scalatest.StreamTester._ - -class MultiClockTester extends Component { - import MultiClockTester._ - val io = new Bundle { - val clkA = in Bool() - val resetA = in Bool() - val clkB = in Bool() - val resetB = in Bool() - - val slave0 = slave Stream(new BundleA) - val master0 = master Stream(new BundleA) - val fifo0_pushOccupancy = out UInt() - val fifo0_popOccupancy = out UInt() - } - - val clockDomainA = ClockDomain(io.clkA,io.resetA) - val clockDomainB = ClockDomain(io.clkB,io.resetB) - - val fifo0 = new StreamFifoCC(new BundleA,16,clockDomainA,clockDomainB) - fifo0.io.push << io.slave0 - fifo0.io.pop >> io.master0 - io.fifo0_pushOccupancy := fifo0.io.pushOccupancy - io.fifo0_popOccupancy := fifo0.io.popOccupancy - -} - - - -//class MultiClockTesterGhdlBoot extends SpinalTesterGhdlBase { -// override def getName: String = "MultiClockTester" -// override def createToplevel: Component = new MultiClockTester -//} - -class MultiClockTesterCocotbBoot extends SpinalTesterCocotbBase { - override def getName: String = "MultiClockTester" - override def pythonTestLocation: String = "tester/src/test/python/spinal/MultiClockTester" - override def createToplevel: Component = new MultiClockTester -} \ No newline at end of file diff --git a/tester/src/test/scala/spinal/tester/scalatest/PinsecTester.scala b/tester/src/test/scala/spinal/tester/scalatest/PinsecTester.scala deleted file mode 100644 index 4b6d5f7c9d..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/PinsecTester.scala +++ /dev/null @@ -1,108 +0,0 @@ -package spinal.tester.scalatest - -import org.scalatest.{Stepwise, Sequential, Suites} -import spinal.core._ -import spinal.lib._ -import spinal.lib.com.jtag.Jtag -import spinal.lib.com.uart.Uart -import spinal.lib.io.TriStateArray -import spinal.lib.memory.sdram.sdr.IS42x320D -import spinal.lib.{master, slave} -import spinal.lib.soc.pinsec.{PinsecConfig, PinsecTimerCtrlExternal, Pinsec} - -/** - * Created by PIC32F_USER on 22/08/2016. -*/ - - - -//object PinsecTester{ -// case class SdramModel() extends BlackBox{ -// val Dq = in Bool() -// val Addr = in Bool() -// val Ba = in Bool() -// val Clk = in Bool() -// val Cke = in Bool() -// val Cs_n = in Bool() -// val Ras_n = in Bool() -// val Cas_n = in Bool() -// val We_n = in Bool() -// val Dqm = in Bool() -// } -// -// case class PinsecTester() extends Component{ -// val io = new Bundle{ -// val asyncReset = in Bool() -// val axiClk = in Bool() -// val jtag_tck = in Bool() -// val jtag = slave(Jtag()) -// val gpioA = master(TriStateArray(32 bits)) -// val gpioB = master(TriStateArray(32 bits)) -// val timerExternal = in(PinsecTimerCtrlExternal()) -// val uart = master(Uart()) -// } -// -// val pinsec = new Pinsec() -// io.asyncReset <> pinsec.io.asyncReset -// io.axiClk <> pinsec.io.axiClk -// io.jtag_tck <> pinsec.io.jtag_tck -// io.jtag <> pinsec.io.jtag -// io.gpioA <> pinsec.io.gpioA -// io.gpioB <> pinsec.io.gpioB -// io.timerExternal <> pinsec.io.timerExternal -// io.uart <> pinsec.io.uart -// } -//} - -class PinsecTesterCocotbBoot extends SpinalTesterCocotbBase { - override def getName: String = "PinsecTester" - override def pythonTests: Seq[(String,String)] = List( - "jtag" -> "tester/src/test/python/spinal/Pinsec/jtag", - "uart" -> "tester/src/test/python/spinal/Pinsec/uart" - ) - override def createToplevel: Component = { - val pinsec = new Pinsec(PinsecConfig.default.copy(axiFrequency = 133 MHz)) -// pinsec.axi.rom.ram.randBoot() - pinsec.axi.ram.ram.randBoot() - val sdramPowerupCounter = pinsec.axi.sdramCtrl.ctrl.powerup.counter - sdramPowerupCounter.component.rework( - sdramPowerupCounter init(sdramPowerupCounter.maxValue - 100) - ) - val miaou = pinsec.axi.ram.rework(new Area{ - import pinsec.axi.ram._ - - val port = ram.writePort - port.valid.setName("ram_port0_write") := False - port.address.setName("ram_port0_address") := 0 - port.data.setName("ram_port0_writeData") := 0 - - val a = Bool().setName("ram_port0_enable") - val b = Bits(4 bits).setName("ram_port0_mask") - a := False - b := 0 - }) - miaou.a.pull() - miaou.b.pull() - pinsec - } - override def backendConfig(config: SpinalConfig) = config.mode match { - case `Verilog` => config.copy(mergeAsyncProcess = false) // avoid iverilog bug - case _ => config - } - override def noVhdl = true - -// withWaveform = true -} - - -// -//class OrderedSuite extends Stepwise( -// new BundleTesterCocotbBoot, -// -// new FixedPointTesterCocotbBoot, -// new WhenTesterCocotbBoot, -// new StreamTesterCocotbBoot, -// new BlackboxTesterCocotbBoot -// , -// new ZeroWidthTesterCocotbBoot -//) \ No newline at end of file diff --git a/tester/src/test/scala/spinal/tester/scalatest/PllAAssertSDeassertTester.scala b/tester/src/test/scala/spinal/tester/scalatest/PllAAssertSDeassertTester.scala deleted file mode 100644 index 3743c4a2d5..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/PllAAssertSDeassertTester.scala +++ /dev/null @@ -1,51 +0,0 @@ -package spinal.tester.scalatest - -import spinal.core._ -import spinal.lib.{ResetCtrl, CounterFreeRun, Counter} -import spinal.lib.com.uart._ - - - -object PllAAssertSDeassertTester{ - class PLL extends BlackBox{ - val io = new Bundle{ - val clk_in = in Bool() - val clk_out = out Bool() - } - - noIoPrefix() - } - - class PllAAssertSDeassertTester extends Component{ - val aReset = in Bool() - val clk_100Mhz = in Bool() - - val pllBB = new PLL - pllBB.io.clk_in := clk_100Mhz - -// val coreClockDomain = ClockDomain( -// clock = pllBB.io.clk_out, -// reset = Bool.setName("coreReset") -// ) - val coreClockDomain = ClockDomain.internal("core") - coreClockDomain.clock := pllBB.io.clk_out - coreClockDomain.reset := ResetCtrl.asyncAssertSyncDeassert( - input = aReset, - clockDomain = coreClockDomain - ) - - val counter = out(coreClockDomain(CounterFreeRun(10).value)).setName("counter") - } -} - - - - -class PllAAssertSDeassertTesterBoot extends SpinalTesterCocotbBase { - override def getName: String = "PllAAssertSDeassertTester" - override def pythonTestLocation: String = "tester/src/test/python/spinal/PllAAssertSDeassertTester" - override def createToplevel: Component = new PllAAssertSDeassertTester.PllAAssertSDeassertTester - - override def backendConfig(config: SpinalConfig): SpinalConfig = config - .copy(defaultConfigForClockDomains = config.defaultConfigForClockDomains.copy(resetKind = SYNC)) -} \ No newline at end of file diff --git a/tester/src/test/scala/spinal/tester/scalatest/RomTester.scala b/tester/src/test/scala/spinal/tester/scalatest/RomTester.scala deleted file mode 100644 index bdb8d478ca..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/RomTester.scala +++ /dev/null @@ -1,192 +0,0 @@ - - -/* - * SpinalHDL - * Copyright (c) Dolu, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ - -package spinal.tester.scalatest - -import org.scalatest.funsuite.AnyFunSuite -import spinal.core._ -import spinal.tester.scalatest.RomTester.{RomTesterSymbols, RomTesterSymbolsSInt} -object RomTester { - - object MyEnum extends SpinalEnum{ - val a,b,c = newElement() - } - - class DataStruct extends Bundle{ - val bool = Bool() - val bits = Bits(9 bits) - val uint = UInt(10 bits) - val sint = SInt(11 bits) - val enumeration = MyEnum() - } - - class RomTester extends Component { - def lit(bool : Boolean,bits : Int,uint : Int,sint : Int,enumeration : MyEnum.E) = { - val data = new DataStruct - data.bool := Bool(bool) - data.bits := B(bits) - data.uint := U(uint) - data.sint := S(sint) - data.enumeration := enumeration - data - } - def initValues = List( - lit(false,0,0,0,MyEnum.a), - lit(true,0,0,0,MyEnum.a), - lit(false,0x1FF,0,0,MyEnum.a), - lit(false,0,0x3FF,0,MyEnum.a), - lit(false,0,0,-1,MyEnum.a), - lit(false,0,0,0,MyEnum.c), - lit(false,43,74,88,MyEnum.b) - ) - val rom = Mem(new DataStruct,initValues) - - val address = in UInt(3 bits) - val data = out(rom(address)) - } - - class RomTesterSymbols extends Component { - - val rom = Mem(Bits(32 bits),8) init(Seq( - BigInt(0x01234567l), - BigInt(0x12345670l), - BigInt(0x10293857l), - BigInt(0x0abcfe23l), - BigInt(0x02938571l), - BigInt(0xabcfe230l), - BigInt(0x717833aal), - BigInt(0x17833aa6l) - )) - rom.write(U"000",B(0, 32 bits),False,B"0000") - val address = in UInt(3 bits) - val data = out(rom(address)) - } - class RomTesterSymbolsSInt extends Component { - - val rom = Mem(SInt(32 bits),8) init(Seq( - S(0x01234567, 32 bits), - S(0x12345670, 32 bits), - S(0x10293857, 32 bits), - S(0x0abcfe23, 32 bits), - S(0x02938571, 32 bits), - S(0xabcfe230, 32 bits), - S(0x717833aa, 32 bits), - S(0x17833aa6, 32 bits) - )) - rom.write(U"000",S(0, 32 bits),False,B"0000") - val address = in UInt(3 bits) - val data = out(rom(address)) - } -} - - -class RomTesterGhdlBoot extends SpinalTesterGhdlBase { - override def getName: String = "RomTester" - override def createToplevel: Component = new RomTester.RomTester -} - -class RomTesterCocotbBoot extends SpinalTesterCocotbBase { - override def getName: String = "RomTester" - override def pythonTestLocation: String = "tester/src/test/python/spinal/RomTester" - override def createToplevel: Component = new RomTester.RomTester - override def noVhdl = true - override def backendConfig(config: SpinalConfig) = config.copy(inlineRom = true) -} - -class RomTesterCocotbBoot2 extends SpinalTesterCocotbBase { - override def getName: String = "RomTester2" - override def pythonTestLocation: String = "tester/src/test/python/spinal/RomTester2" - override def createToplevel: Component = new RomTester.RomTester().setDefinitionName("RomTester2") - override def noVhdl = true - override def backendConfig(config: SpinalConfig) = config.copy(inlineRom = false) - - override def genVerilog: Unit = { - super.genVerilog - import scala.sys.process._ - s"rm $pythonTestLocation/RomTester2.v_toplevel_rom.bin".! - s"cp RomTester2.v_toplevel_rom.bin $pythonTestLocation".! - } -} - -class RomTesterCocotbBoot3 extends SpinalTesterCocotbBase { - override def getName: String = "RomTester2" - override def pythonTestLocation: String = "tester/src/test/python/spinal/RomTester3" - override def createToplevel: Component = new RomTester.RomTesterSymbols().setDefinitionName("RomTester3") - override def noVhdl = true - override def backendConfig(config: SpinalConfig) = config.copy(inlineRom = false) - - override def genVerilog: Unit = { - super.genVerilog - import scala.sys.process._ - for(i <- 0 to 3) { - s"rm $pythonTestLocation/RomTester3.v_toplevel_rom_symbol$i.bin".! - s"cp RomTester3.v_toplevel_rom_symbol$i.bin $pythonTestLocation".! - } - } -} - -class SpinalSimRomTester extends AnyFunSuite { - test("test1"){ - import spinal.core.sim._ - import spinal.sim._ - SimConfig.compile(new RomTesterSymbols()).doSim{ dut => - val rom = Seq( - BigInt(0x01234567l), - BigInt(0x12345670l), - BigInt(0x10293857l), - BigInt(0x0abcfe23l), - BigInt(0x02938571l), - BigInt(0xabcfe230l), - BigInt(0x717833aal), - BigInt(0x17833aa6l) - ) - - for(repeat <- 0 until 100){ - dut.address.randomize() - sleep(1) - assert(dut.data.toBigInt == rom(dut.address.toInt)) - } - - } - } - test("testSInt"){ - import spinal.core.sim._ - import spinal.sim._ - SimConfig.compile(new RomTesterSymbolsSInt()).doSim{ dut => - val rom = Seq( - BigInt(0x01234567), - BigInt(0x12345670), - BigInt(0x10293857), - BigInt(0x0abcfe23), - BigInt(0x02938571), - BigInt(0xabcfe230), - BigInt(0x717833aa), - BigInt(0x17833aa6) - ) - - for(repeat <- 0 until 100){ - dut.address.randomize() - sleep(1) - assert(dut.data.toBigInt == rom(dut.address.toInt)) - } - - } - } -} \ No newline at end of file diff --git a/tester/src/test/scala/spinal/tester/scalatest/SdramXdrDdr3S7Cocotb.scala b/tester/src/test/scala/spinal/tester/scalatest/SdramXdrDdr3S7Cocotb.scala deleted file mode 100644 index 9c78343cec..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/SdramXdrDdr3S7Cocotb.scala +++ /dev/null @@ -1,145 +0,0 @@ -//package spinal.tester.scalatest -// -//import spinal.core._ -//import spinal.lib.bus.bmb._ -//import spinal.lib.memory.sdram.sdr.{MT41K128M16JT, MT48LC16M16A2} -//import spinal.lib.memory.sdram.xdr.{BmbPortParameter, CoreParameter, CtrlParameter, CtrlWithPhy, CtrlWithoutPhy, mt41k128m16jt_model, mt48lc16m16a2_model} -//import spinal.lib._ -//import spinal.lib.bus.amba3.apb.{Apb3, Apb3SlaveFactory} -//import spinal.lib.eda.bench.Rtl -//import spinal.lib.memory.sdram.xdr.phy.{SdrInferedPhy, XilinxS7Phy} -// -////CONFIGURE_OPTS="LDFLAGS=-m32 CFLAGS=-m32 --enable-shared" LD_LIBRARY_PATH=`pwd`/versions/2.7.13/lib:$LD_LIBRARY_PATH pyenv install 2.7.13 -vfk -// -//case class SdramXdrDdr3S7TesterCocotbTop() extends Component{ -// -// val clk0, clk90, rst0 = in Bool() -// val serdesClk0, serdesClk90 = in Bool() -// -// -// Clock.sync(clk0, clk90) -// Clock.sync(clk0, serdesClk0) -// Clock.sync(clk0, serdesClk90) -// -// -// val system = new ClockingArea(ClockDomain(clk0, rst0)) { -// // val dq = Analog(Bits(16 bits)) -// -// val sl = MT41K128M16JT.layout -// val cp = CtrlParameter( -// core = CoreParameter( -// portTockenMin = 4, -// portTockenMax = 8, -// timingWidth = 4, -// refWidth = 16, -// writeLatencies = List(3), -// readLatencies = List(5) -// ), -// ports = Seq( -// BmbPortParameter( -// bmb = BmbParameter( -// addressWidth = sl.byteAddressWidth, -// dataWidth = 64, -// lengthWidth = 4, -// sourceWidth = 3, -// contextWidth = 8 -// ), -// cmdBufferSize = 16, -// dataBufferSize = 16, -// rspBufferSize = 16, -// clockDomain = ClockDomain.current -// )/*, -// -// BmbPortParameter( -// bmb = BmbParameter( -// addressWidth = sl.byteAddressWidth, -// dataWidth = 16, -// lengthWidth = 4, -// sourceWidth = 5, -// contextWidth = 12 -// ), -// cmdBufferSize = 2, -// rspBufferSize = 5 -// ), -// -// BmbPortParameter( -// bmb = BmbParameter( -// addressWidth = sl.byteAddressWidth, -// dataWidth = 16, -// lengthWidth = 5, -// sourceWidth = 6, -// contextWidth = 16 -// ), -// cmdBufferSize = 8, -// rspBufferSize = 2 -// )*/ -// ) -// ) -// -// val io = new Bundle { -// val ctrlApb = slave(Apb3(12, 32)) -// val phyApb = slave(Apb3(12, 32)) -// val ports = Vec(cp.ports.map(p => slave(Bmb(p.bmb)))) -// } -// -// val phy = XilinxS7Phy(sl, clkRatio = 2, ClockDomain(clk90), ClockDomain(serdesClk0), ClockDomain(serdesClk90)) -// phy.driveFrom(Apb3SlaveFactory(io.phyApb)) -// -// phy.children.foreach { -// case bb: BlackBox => bb.clearBlackBox() -// case _ => -// } -// -// val ctrl = new CtrlWithoutPhy(cp, phy.pl) -// ctrl.io.bmb <> io.ports -// ctrl.io.apb <> io.ctrlApb -// ctrl.io.phy <> phy.io.ctrl -// -// -// val sdram = mt41k128m16jt_model() -// sdram.rst_n := phy.io.memory.RESETn -// sdram.ck := phy.io.memory.CK -// sdram.ck_n := phy.io.memory.CKn -// sdram.cke := phy.io.memory.CKE -// sdram.cs_n := phy.io.memory.CSn -// sdram.ras_n := phy.io.memory.RASn -// sdram.cas_n := phy.io.memory.CASn -// sdram.we_n := phy.io.memory.WEn -// sdram.odt := phy.io.memory.ODT -// sdram.ba := phy.io.memory.BA -// sdram.addr := phy.io.memory.ADDR -// -// val dq = Analog(Bits(16 bits)) -// val dqs = Analog(Bits(2 bits)) -// val dqs_n = Analog(Bits(2 bits)) -// val dm_tdqs = Analog(Bits(2 bits)) -// -// dq := sdram.dq -// dqs := sdram.dqs -// dqs_n := sdram.dqs_n -// dm_tdqs := sdram.dm_tdqs -// -// -// dq := phy.io.memory.DQ -// dqs := phy.io.memory.DQS -// dqs_n := phy.io.memory.DQSn -// -// // dq := B(0, widthOf(sdram.dq) bits) -// // dqs := B(0, widthOf(sdram.dqs) bits) -// // dqs_n := B(0, widthOf(sdram.dqs_n) bits) -// // dm_tdqs := B(0, widthOf(sdram.dm_tdqs) bits) -// -// } -// -//} -// -// -//class SdramXdrDdr3S7TesterCocotb extends SpinalTesterCocotbBase { -// override def getName: String = "SdramXdrDdr3S7TesterCocotbTop" -// override def pythonTestLocation: String = "tester/src/test/python/spinal/SdramXdr/Ddr3S7Tester" -// override def createToplevel: Component = { -// SdramXdrDdr3S7TesterCocotbTop().setDefinitionName(getName) -// } -// override def noVhdl = true -// withWaveform = true -//} diff --git a/tester/src/test/scala/spinal/tester/scalatest/SdramXdrSdrCocotb.scala b/tester/src/test/scala/spinal/tester/scalatest/SdramXdrSdrCocotb.scala deleted file mode 100644 index 1ea8e02661..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/SdramXdrSdrCocotb.scala +++ /dev/null @@ -1,204 +0,0 @@ -//package spinal.tester.scalatest -// -//import spinal.core._ -//import spinal.lib.bus.bmb._ -//import spinal.lib.memory.sdram.sdr.MT48LC16M16A2 -//import spinal.lib.memory.sdram.xdr.{BmbPortParameter, CoreParameter, CtrlWithPhy, CtrlParameter, mt48lc16m16a2_model} -//import spinal.lib._ -//import spinal.lib.bus.amba3.apb.Apb3 -//import spinal.lib.eda.bench.Rtl -//import spinal.lib.memory.sdram.xdr.phy.SdrInferedPhy -// -//case class SdramSdrTesterCocotbTop() extends Component{ -// val sl = MT48LC16M16A2.layout -// val cp = CtrlParameter( -// core = CoreParameter( -// portTockenMin = 4, -// portTockenMax = 8, -// timingWidth = 4, -// refWidth = 16, -// writeLatencies = List(0), -// readLatencies = List(2) -// ), -// ports = Seq( -// BmbPortParameter( -// bmb = BmbParameter( -// addressWidth = sl.byteAddressWidth, -// dataWidth = 16, -// lengthWidth = 3, -// sourceWidth = 3, -// contextWidth = 8 -// ), -// clockDomain = ClockDomain.current, -// cmdBufferSize = 4, -// dataBufferSize = 6, -// rspBufferSize = 4 -// ), -// -// BmbPortParameter( -// bmb = BmbParameter( -// addressWidth = sl.byteAddressWidth, -// dataWidth = 16, -// lengthWidth = 4, -// sourceWidth = 5, -// contextWidth = 12 -// ), -// clockDomain = ClockDomain.current, -// cmdBufferSize = 2, -// dataBufferSize = 2, -// rspBufferSize = 5 -// ), -// -// BmbPortParameter( -// bmb = BmbParameter( -// addressWidth = sl.byteAddressWidth, -// dataWidth = 16, -// lengthWidth = 5, -// sourceWidth = 6, -// contextWidth = 16 -// ), -// clockDomain = ClockDomain.current, -// cmdBufferSize = 8, -// dataBufferSize = 8, -// rspBufferSize = 2 -// ) -// ) -// ) -// -// val io = new Bundle { -// val apb = slave(Apb3(12, 32)) -// val ports = Vec(cp.ports.map(p => slave(Bmb(p.bmb)))) -// } -// -// val dq = Analog(Bits(16 bits)) -// -// val ctrl = new CtrlWithPhy(cp, SdrInferedPhy(sl)) -// io.ports <> ctrl.io.bmb -// io.apb <> ctrl.io.apb -// when(ctrl.io.memory.DQ.writeEnable) { -// dq := ctrl.io.memory.DQ.write -// } -// ctrl.io.memory.DQ.read := dq -// -// val sdram = mt48lc16m16a2_model() -// sdram.Addr := ctrl.io.memory.ADDR -// sdram.Ba := ctrl.io.memory.BA -// sdram.Clk := ClockDomain.current.readClockWire -// sdram.Cke := ctrl.io.memory.CKE -// sdram.Cs_n := ctrl.io.memory.CSn -// sdram.Ras_n := ctrl.io.memory.RASn -// sdram.Cas_n := ctrl.io.memory.CASn -// sdram.We_n := ctrl.io.memory.WEn -// sdram.Dqm := ctrl.io.memory.DQM -// dq := sdram.Dq -// -//} -// -// -////TODO REGRESSION -////class SdramSdrTesterCocotb extends SpinalTesterCocotbBase { -//// override def getName: String = "SdramSdrTesterCocotbTop" -//// override def pythonTestLocation: String = "tester/src/test/python/spinal/SdramXdr/SdrTester" -//// override def createToplevel: Component = { -//// SdramSdrTesterCocotbTop().setDefinitionName(getName) -//// } -//// override def noVhdl = true -//// withWaveform = true -////} -// -//import spinal.core._ -//import spinal.lib.eda.bench._ -// -////object SdramSdrSyntBench extends App{ -//// val sl = MT48LC16M16A2.layout.copy(bankWidth = 3) -//// val cp = CtrlParameter( -//// core = CoreParameter( -//// portTockenMin = 4, -//// portTockenMax = 8, -//// rspFifoSize = 4, -//// timingWidth = 4, -//// refWidth = 16, -//// writeLatencies = List(0), -//// readLatencies = List(2) -//// ), -//// ports = Seq( -//// BmbPortParameter( -//// bmb = BmbParameter( -//// addressWidth = sl.byteAddressWidth, -//// dataWidth = 16, -//// lengthWidth = 3, -//// sourceWidth = 0, -//// contextWidth = 0 -//// ), -//// clockDomain = ClockDomain.current, -//// cmdBufferSize = 4, -//// rspBufferSize = 4 -//// ), -//// -//// BmbPortParameter( -//// bmb = BmbParameter( -//// addressWidth = sl.byteAddressWidth, -//// dataWidth = 16, -//// lengthWidth = 4, -//// sourceWidth = 0, -//// contextWidth = 0 -//// ), -//// clockDomain = ClockDomain.current, -//// cmdBufferSize = 2, -//// rspBufferSize = 5 -//// )/*, -//// -//// BmbPortParameter( -//// bmb = BmbParameter( -//// addressWidth = sl.byteAddressWidth, -//// dataWidth = 16, -//// lengthWidth = 5, -//// sourceWidth = 0, -//// contextWidth = 0 -//// ), -//// clockDomain = ClockDomain.current, -//// cmdBufferSize = 8, -//// rspBufferSize = 2 -//// )*//*, -//// -//// BmbPortParameter( -//// bmb = BmbParameter( -//// addressWidth = sl.byteAddressWidth, -//// dataWidth = 16, -//// lengthWidth = 5, -//// sourceWidth = 0, -//// contextWidth = 0 -//// ), -//// clockDomain = ClockDomain.current, -//// cmdBufferSize = 8, -//// rspBufferSize = 2 -//// )*/ -//// ) -//// ) -//// -//// -//// val ports4 = new Rtl { -//// override def getName(): String = "Port4" -//// override def getRtlPath(): String = "Port4.v" -//// SpinalVerilog({ -//// val c = new CtrlWithPhy(cp, SdrInferedPhy(sl)).setDefinitionName(getRtlPath().split("\\.").head) -//// c -//// }) -//// } -//// -//// -//// val rtls = List(ports4) -//// -//// val targets = XilinxStdTargets( -//// vivadoArtix7Path = "/media/miaou/HD/linux/Xilinx/Vivado/2018.3/bin" -//// ) ++ AlteraStdTargets( -//// quartusCycloneIVPath = "/media/miaou/HD/linux/intelFPGA_lite/18.1/quartus/bin", -//// quartusCycloneVPath = "/media/miaou/HD/linux/intelFPGA_lite/18.1/quartus/bin" -//// ) -//// -//// Bench(rtls, targets, "/media/miaou/HD/linux/tmp") -//// -//// -//// -//// -////} \ No newline at end of file diff --git a/tester/src/test/scala/spinal/tester/scalatest/SimBigIntPimperTest.scala b/tester/src/test/scala/spinal/tester/scalatest/SimBigIntPimperTest.scala deleted file mode 100644 index 53f9d960af..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/SimBigIntPimperTest.scala +++ /dev/null @@ -1,43 +0,0 @@ -package spinal.tester.scalatest - -import org.scalatest.funsuite.AnyFunSuite -import spinal.core.sim._ -import spinal.core.{BIG, Endianness, LITTLE} - -class SimBigIntPimperTest extends AnyFunSuite { - def toBytes(bi: BigInt, bits: Int = -1, endian: Endianness = LITTLE) = - bi.toBytes(bits, endian).map(i => f"$i%02x").mkString(" ") - test("positive") { - // simple cases - assert(toBytes(0xff) == "ff") - assert(toBytes(0x80ff) == "ff 80") - // check result is prepended if necessary - assert(toBytes(0xff, 4*8) == "ff 00 00 00") - // check with BIG endian - assert(toBytes(0x80ff, endian=BIG) == "80 ff") - assert(toBytes(0x80ff, 4*8, endian=BIG) == "00 00 80 ff") - // check that bit length != n*8 works - assert(toBytes(0x3ff, 10) == "ff 03") - // also needs to work for BigInt bigger than Int - assert(toBytes(0x1122334455667788L) == "88 77 66 55 44 33 22 11") - // ... and longer than a Long - assert(toBytes(BigInt("112233445566778899aabbccddeeff", 16)) == "ff ee dd cc bb aa 99 88 77 66 55 44 33 22 11") - - // negative numbers are sign extended to full bytes by default - assert(toBytes(-1) == "ff") - // result must be prepended correctly if expanded - assert(toBytes(-1, 16) == "ff ff") - // sign extend is only up to given number of bytes - assert(toBytes(-1, 4) == "0f") - // negative numbers also need to be extended to big bitwidths - assert(toBytes(-1, 7*8) == "ff ff ff ff ff ff ff") - } - test("negative") { - // must throw if too little space is given - assertThrows[java.lang.AssertionError] { toBytes(0xffff, 8) } - // length must be checked precisely - assertThrows[java.lang.AssertionError] { toBytes(0x07, 2) } - // space for sign bit must be available - assertThrows[java.lang.AssertionError] { toBytes(-256, 8) } - } -} diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimAccessSubComponents.scala b/tester/src/test/scala/spinal/tester/scalatest/SpinalSimAccessSubComponents.scala deleted file mode 100644 index 43d3e10e1d..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimAccessSubComponents.scala +++ /dev/null @@ -1,85 +0,0 @@ -package spinal.tester.scalatest - -import org.scalatest.funsuite.AnyFunSuite -import spinal.core._ -import spinal.core.sim._ -import spinal.sim._ - -object SpinalSimAccessSubComponents { - class SubSub extends Component { - val io = new Bundle { - val a,b = in UInt(8 bits) - val result = out UInt(8 bits) - } - - io.result := io.a ^ io.b - val miaou = (io.a & io.b) - - val miaouVec = Vec(UInt(8 bits), 4) - miaouVec := Vec(io.a,io.b,io.result,miaou) - } - - class Sub extends Component { - val io = new Bundle { - val a,b = in UInt(8 bits) - val result = out UInt(8 bits) - } - val subSubInst = new SubSub - subSubInst.io.a <> io.a - subSubInst.io.b <> io.b - subSubInst.io.result <> io.result - } - - class Dut extends Component { - val io = new Bundle { - val a,b = in UInt(8 bits) - val result = out UInt(8 bits) - } - - val subInst = new Sub - subInst.io.a <> io.a - subInst.io.b <> io.b - subInst.io.result <> io.result - } - -} - -class SpinalSimAccessSubComponents extends AnyFunSuite { - SpinalSimTester { env => - import env._ - - var compiled: SimCompiled[SpinalSimAccessSubComponents.Dut] = null - test(prefix + "compile") { - compiled = SimConfig.compile { - val dut = new SpinalSimAccessSubComponents.Dut - dut.subInst.subSubInst.miaouVec.simPublic() - dut.subInst.subSubInst.io.a.simPublic() - dut.subInst.subSubInst.miaou.simPublic() - dut.subInst.subSubInst.miaou.pull() - dut.subInst.subSubInst.io.pull() - dut.subInst.subSubInst.miaouVec.pull() - dut.subInst.subSubInst.miaouVec.pull() - dut.subInst.subSubInst.miaouVec.pull() - dut.subInst.subSubInst.miaouVec.pull() - dut - } - } - - test(prefix + "simulate") { - compiled.doSim { dut => - for (repeat <- 0 until 1000) { - dut.io.a.randomize() - dut.io.b.randomize() - sleep(1) - assert(dut.io.result.toInt == (dut.io.a.toInt ^ dut.io.b.toInt)) - assert(dut.subInst.subSubInst.miaou.toInt == (dut.io.a.toInt & dut.io.b.toInt)) - assert(dut.subInst.subSubInst.io.a.toInt == (dut.io.a.toInt)) - assert(dut.subInst.subSubInst.miaouVec(0).toInt == (dut.io.a.toInt)) - assert(dut.subInst.subSubInst.miaouVec(1).toInt == (dut.io.b.toInt)) - assert(dut.subInst.subSubInst.miaouVec(2).toInt == (dut.io.a.toInt ^ dut.io.b.toInt)) - assert(dut.subInst.subSubInst.miaouVec(3).toInt == (dut.io.a.toInt & dut.io.b.toInt)) - } - } - } - } -} diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimBmbAlignerTester.scala b/tester/src/test/scala/spinal/tester/scalatest/SpinalSimBmbAlignerTester.scala deleted file mode 100644 index 155f279d3a..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimBmbAlignerTester.scala +++ /dev/null @@ -1,121 +0,0 @@ -package spinal.tester.scalatest - - -import org.scalatest.funsuite.AnyFunSuite -import spinal.core._ -import spinal.core.sim.SimConfig -import spinal.lib.bus.bmb.{BmbAligner, BmbDownSizerBridge, BmbParameter} -import spinal.lib.bus.bmb.sim.BmbBridgeTester - -class SpinalSimBmbAlignerTester extends AnyFunSuite { - for(w <- List(false, true); r <- List(false, true); if w || r) { - val header = "_" + (if(w) "w" else "") + (if(r) "r" else "") - test("BmbAligner_bypass" + header) { - SimConfig.compile { - val c = BmbAligner( - ip = BmbParameter( - addressWidth = 16, - dataWidth = 32, - lengthWidth = 6, - sourceWidth = 4, - contextWidth = 3, - canRead = r, - canWrite = w, - alignment = BmbParameter.BurstAlignement.WORD - ), - alignmentWidth = 2 - ) - c.rework { - RegNext(True) init (False) setName ("dummy") - } - c - }.doSimUntilVoid("test") { dut => - new BmbBridgeTester( - master = dut.io.input, - masterCd = dut.clockDomain, - slave = dut.io.output, - slaveCd = dut.clockDomain - ) - } - } - - test("BmbAligner_4" + header) { - SimConfig.compile { - BmbAligner( - ip = BmbParameter( - addressWidth = 16, - dataWidth = 32, - lengthWidth = 6, - sourceWidth = 4, - contextWidth = 3, - canRead = r, - canWrite = w, - alignment = BmbParameter.BurstAlignement.WORD - ), - alignmentWidth = 4 - ) - }.doSimUntilVoid("test") { dut => - new BmbBridgeTester( - master = dut.io.input, - masterCd = dut.clockDomain, - slave = dut.io.output, - slaveCd = dut.clockDomain - ) - } - } - - test("BmbAligner_3" + header) { - SimConfig.compile { - BmbAligner( - ip = BmbParameter( - addressWidth = 16, - dataWidth = 32, - lengthWidth = 6, - sourceWidth = 4, - contextWidth = 3, - canRead = r, - canWrite = w, - alignment = BmbParameter.BurstAlignement.WORD - ), - alignmentWidth = 3 - ) - }.doSimUntilVoid("test") { dut => - new BmbBridgeTester( - master = dut.io.input, - masterCd = dut.clockDomain, - slave = dut.io.output, - slaveCd = dut.clockDomain - ) - } - } - - test("BmbAligner_1" + header) { - SimConfig.compile { - val c = BmbAligner( - ip = BmbParameter( - addressWidth = 16, - dataWidth = 32, - lengthWidth = 6, - sourceWidth = 4, - contextWidth = 3, - canRead = r, - canWrite = w, - alignment = BmbParameter.BurstAlignement.WORD - ), - alignmentWidth = 1 - ) - c.rework { - RegNext(True) init (False) setName ("dummy") - } - c - }.doSimUntilVoid("test") { dut => - new BmbBridgeTester( - master = dut.io.input, - masterCd = dut.clockDomain, - slave = dut.io.output, - slaveCd = dut.clockDomain - ) - } - } - } -} diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimBmbLengthFixerTester.scala b/tester/src/test/scala/spinal/tester/scalatest/SpinalSimBmbLengthFixerTester.scala deleted file mode 100644 index b5dd6afb60..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimBmbLengthFixerTester.scala +++ /dev/null @@ -1,93 +0,0 @@ -package spinal.tester.scalatest - -import org.scalatest.funsuite.AnyFunSuite -import spinal.core._ -import spinal.lib.bus.bmb.sim.BmbBridgeTester -import spinal.lib.bus.bmb.{BmbAligner, BmbLengthFixer, BmbParameter} - -class SpinalSimBmbLengthFixerTester extends SpinalSimFunSuite { - test("bypass") { - SimConfig.compile { - val c = BmbLengthFixer( - ip = BmbParameter( - addressWidth = 16, - dataWidth = 32, - lengthWidth = 6, - sourceWidth = 4, - contextWidth = 3, - alignmentMin = 2, - canRead = true, - canWrite = true, - alignment = BmbParameter.BurstAlignement.WORD - ), - fixedWidth = 2 - ) - c - }.doSimUntilVoid("test") { dut => - new BmbBridgeTester( - master = dut.io.input, - masterCd = dut.clockDomain, - slave = dut.io.output, - slaveCd = dut.clockDomain, - alignmentMinWidth = dut.ip.access.alignmentMin - ) - } - } - - test("3") { - SimConfig.compile { - val c = BmbLengthFixer( - ip = BmbParameter( - addressWidth = 16, - dataWidth = 32, - lengthWidth = 6, - sourceWidth = 4, - contextWidth = 3, - alignmentMin = 3, - canRead = true, - canWrite = true, - alignment = BmbParameter.BurstAlignement.WORD - ), - fixedWidth = 3 - ) - c - }.doSimUntilVoid("test") { dut => - new BmbBridgeTester( - master = dut.io.input, - masterCd = dut.clockDomain, - slave = dut.io.output, - slaveCd = dut.clockDomain, - alignmentMinWidth = dut.ip.access.alignmentMin - ) - } - } - - test("4") { - SimConfig.compile { - val c = BmbLengthFixer( - ip = BmbParameter( - addressWidth = 16, - dataWidth = 32, - lengthWidth = 6, - sourceWidth = 4, - contextWidth = 3, - alignmentMin = 4, - canRead = true, - canWrite = true, - alignment = BmbParameter.BurstAlignement.WORD - ), - fixedWidth = 4 - ) - c - }.doSimUntilVoid("test") { dut => - new BmbBridgeTester( - master = dut.io.input, - masterCd = dut.clockDomain, - slave = dut.io.output, - slaveCd = dut.clockDomain, - alignmentMinWidth = dut.ip.access.alignmentMin - ) - } - } - -} diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimBmbLengthSpliterTester.scala b/tester/src/test/scala/spinal/tester/scalatest/SpinalSimBmbLengthSpliterTester.scala deleted file mode 100644 index 2653b12875..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimBmbLengthSpliterTester.scala +++ /dev/null @@ -1,95 +0,0 @@ -package spinal.tester.scalatest - -import org.scalatest.funsuite.AnyFunSuite -import spinal.core.sim.SimConfig -import spinal.lib.bus.bmb.sim.BmbBridgeTester -import spinal.lib.bus.bmb.{BmbAccessParameter, BmbAlignedSpliter, BmbParameter, BmbSourceParameter} - -class SpinalSimBmbLengthSpliterTester extends AnyFunSuite { - for(w <- List(false, true); r <- List(false, true); if w || r) { - val header = "_" + (if (w) "w" else "") + (if (r) "r" else "") - test("bypass" + header) { - SimConfig.compile { - val c = BmbAlignedSpliter( - ip = BmbAccessParameter( - addressWidth = 16, - dataWidth = 32 - ).addSources(16, BmbSourceParameter( - lengthWidth = 6, - contextWidth = 3, - alignmentMin = 0, - canRead = r, - canWrite = w, - alignment = BmbParameter.BurstAlignement.WORD - )).toBmbParameter(), - lengthMax = 4 - ) - c - }.doSimUntilVoid("test") { dut => - new BmbBridgeTester( - master = dut.io.input, - masterCd = dut.clockDomain, - slave = dut.io.output, - slaveCd = dut.clockDomain, - alignmentMinWidth = dut.ip.access.alignmentMin - ) - } - } - - test("8" + header) { - SimConfig.withWave.compile { - val c = BmbAlignedSpliter( - ip = BmbAccessParameter( - addressWidth = 16, - dataWidth = 32 - ).addSources(16, BmbSourceParameter( - lengthWidth = 6, - contextWidth = 8, - alignmentMin = 0, - canRead = r, - canWrite = w, - alignment = BmbParameter.BurstAlignement.WORD - )).toBmbParameter(), - lengthMax = 8 - ) - c - }.doSimUntilVoid("test", 42) { dut => - new BmbBridgeTester( - master = dut.io.input, - masterCd = dut.clockDomain, - slave = dut.io.output, - slaveCd = dut.clockDomain, - alignmentMinWidth = dut.ip.access.alignmentMin - ) - } - } - - test("16" + header) { - SimConfig.compile { - val c = BmbAlignedSpliter( - ip = BmbAccessParameter( - addressWidth = 16, - dataWidth = 32 - ).addSources(16, BmbSourceParameter( - lengthWidth = 6, - contextWidth = 8, - alignmentMin = 0, - canRead = r, - canWrite = w, - alignment = BmbParameter.BurstAlignement.WORD - )).toBmbParameter(), - lengthMax = 16 - ) - c - }.doSimUntilVoid("test") { dut => - new BmbBridgeTester( - master = dut.io.input, - masterCd = dut.clockDomain, - slave = dut.io.output, - slaveCd = dut.clockDomain, - alignmentMinWidth = dut.ip.access.alignmentMin - ) - } - } - } -} diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimClockDomainTest.scala b/tester/src/test/scala/spinal/tester/scalatest/SpinalSimClockDomainTest.scala deleted file mode 100644 index acd5104143..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimClockDomainTest.scala +++ /dev/null @@ -1,190 +0,0 @@ -package spinal.tester.scalatest - -import org.scalatest.funsuite.AnyFunSuite -import spinal.core._ -import spinal.sim._ -import spinal.core.sim._ -import spinal.tester.scalatest - -import scala.concurrent.{Await, Future} -import scala.util.Random - -object SpinalSimClockDomainTest{ - class SpinalSimClockDomainTest1 extends Component { - val io = new Bundle { - val mClk, mReset = in Bool() - val a, b, c = in UInt (8 bits) - val result = out UInt (8 bits) - } - - val tmpClk, tmpReset = Bool() - tmpClk := io.mClk - tmpReset := io.mReset - ClockDomain(tmpClk, tmpReset){ - io.result := RegNext(io.a + io.b - io.c) init(0) - } - } - - class SpinalSimClockDomainTest2 extends Component { - val io = new Bundle { - val mClk, mReset = in Bool() - val a, b, c = in UInt (8 bits) - val result = out UInt (8 bits) - } - - ClockDomain(io.mClk, io.mReset){ - io.result := RegNext(io.a + io.b - io.c) init(0) - } - } - class SpinalSimClockDomainTest3 extends Component { - val io = new Bundle { - val a, b, c = in UInt (8 bits) - val result = out UInt (8 bits) - } - - io.result := RegNext(io.a + io.b - io.c) init(0) - } - - class SpinalSimClockDomainTest4 extends Component { - val io = new Bundle { - val enable = in Bool() - val result = out UInt (8 bits) - } - - val reg = RegInit(U(42, 8 bits)) - when(io.enable){ - reg := reg + 1 - } - io.result := reg - } -} - -class SpinalSimClockDomainTest extends SpinalSimFunSuite { - val resetKinds = List(SYNC,ASYNC) - test("Test1") { - for (resetKind <- resetKinds) { - val compiled = SimConfig - .withConfig(SpinalConfig(defaultConfigForClockDomains = ClockDomainConfig(resetKind = resetKind))) - .compile(new scalatest.SpinalSimClockDomainTest.SpinalSimClockDomainTest1().setDefinitionName("SpinalSimClockDomainTest1" + resetKind.getClass.getSimpleName.toString.take(4))) - .doSim(resetKind.toString) { dut => - // dut.clockDomain.forkStimulus(period = 10) - val cd = ClockDomain(dut.io.mClk, dut.io.mReset) - cd.forkStimulus(period = 10) - - for (repeat2 <- 0 until 10000) { - val a, b, c = Random.nextInt(256) - dut.io.a #= a - dut.io.b #= b - dut.io.c #= c - cd.waitActiveEdge(); sleep(0) - if (cd.isResetDeasserted) assert(dut.io.result.toInt == ((a + b - c) & 0xFF)) - } - } - } - } - - test("TestDeltaCycle wake") { - for (resetKind <- resetKinds) { - val compiled = SimConfig - .withConfig(SpinalConfig(defaultConfigForClockDomains = ClockDomainConfig(resetKind = resetKind))) - .compile(new scalatest.SpinalSimClockDomainTest.SpinalSimClockDomainTest1().setDefinitionName("SpinalSimClockDomainTest1" + resetKind.getClass.getSimpleName.toString.take(4))) - .doSim(resetKind.toString) { dut => - // dut.clockDomain.forkStimulus(period = 10) - val cd = ClockDomain(dut.io.mClk, dut.io.mReset) - dut.io.a #= 0 - dut.io.b #= 0 - dut.io.c #= 0 - sleep(10) - cd.forkStimulus(period = 10) - cd.waitSampling() - cd.waitSampling() - dut.io.a #= 42 - cd.waitSampling() - assert(dut.io.result.toInt == 0) //Wakeup while rising edge, but before FF got the result out - sleep(0) - assert(dut.io.result.toInt == 42) - } - } - } - - - test("Test2") { - for (resetKind <- resetKinds) { - SimConfig - .withConfig(SpinalConfig(defaultConfigForClockDomains = ClockDomainConfig(resetKind = resetKind))) - .compile((new scalatest.SpinalSimClockDomainTest.SpinalSimClockDomainTest2().setDefinitionName("SpinalSimClockDomainTest2" + resetKind.getClass.getSimpleName.toString.take(4)))) - .doSim(resetKind.toString) { dut => - // dut.clockDomain.forkStimulus(period = 10) - val cd = ClockDomain(dut.io.mClk, dut.io.mReset) - cd.forkStimulus(period = 10) - - var counter = 0 - while (true) { - val a, b, c = Random.nextInt(256) - dut.io.a #= a - dut.io.b #= b - dut.io.c #= c - cd.waitActiveEdge(); - sleep(0) - if (cd.isResetDeasserted) assert(dut.io.result.toInt == ((a + b - c) & 0xFF)) - counter += 1 - if (counter == 10000) simSuccess() - } - } - } - } - - test("Test3") { - for (resetKind <- resetKinds) { - SimConfig - .withConfig(SpinalConfig(defaultConfigForClockDomains = ClockDomainConfig(resetKind = resetKind))) - .compile((new scalatest.SpinalSimClockDomainTest.SpinalSimClockDomainTest3().setDefinitionName("SpinalSimClockDomainTest3" + resetKind.getClass.getSimpleName.toString.take(4)))) - .doSim(resetKind.toString) { dut => - dut.clockDomain.forkStimulus(period = 10) - var model = BigInt(0) - for (repeat <- 0 until 10000) { - dut.io.a.randomize() - dut.io.b.randomize() - dut.io.c.randomize() - dut.clockDomain.waitActiveEdge() - if (dut.clockDomain.isResetDeasserted) { - assert(dut.io.result.toInt == model) - model = ((dut.io.a.toBigInt + dut.io.b.toLong - dut.io.c.toInt) & 0xFF) - } - } - } - } - } - - - test("Test4") { - SimConfig - .doSim(new SpinalSimClockDomainTest.SpinalSimClockDomainTest4) { dut => - dut.clockDomain.forkStimulus(period = 10) - var model = 42 - for (repeat <- 0 until 10000) { - dut.io.enable.randomize() - dut.clockDomain.waitActiveEdge(); sleep(0) - if (dut.io.enable.toBoolean) model = (model + 1) & 0xFF - assert(dut.io.result.toInt == model) - } - } - } - - test("Test5") { - SimConfig - .doSim(new SpinalSimClockDomainTest.SpinalSimClockDomainTest4) { dut => - dut.clockDomain.forkStimulus(period = 10) - var model = 42 - dut.io.enable #= false - dut.clockDomain.waitActiveEdge(1) - for (repeat <- 0 until 10000) { - dut.io.enable.randomize() - val waited = Random.nextInt(10) - dut.clockDomain.waitActiveEdge(waited); sleep(0) - if (dut.io.enable.toBoolean) model = (model + waited) & 0xFF - assert(dut.io.result.toInt == model) - } - } - } -} diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimLibTester.scala b/tester/src/test/scala/spinal/tester/scalatest/SpinalSimLibTester.scala deleted file mode 100644 index 253497cc20..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimLibTester.scala +++ /dev/null @@ -1,77 +0,0 @@ -import org.scalatest.funsuite.AnyFunSuite -import spinal.core._ -import spinal.core.sim._ -import spinal.lib._ -import spinal.lib.com.eth._ -import spinal.lib.sim.{FlowMonitor, StreamDriver, StreamMonitor, StreamReadyRandomizer} - -import scala.collection.mutable -import scala.util.Random - -class SpinalSimLibTester extends AnyFunSuite { - for (n <- 0 until 12) { - test("Vec (op) Vec on " + n + " elements") { - SimConfig.noOptimisation - .compile(new Component { - val a, b = in Vec (SInt(8 bits), n) - val xor = out(a ^ b) - val or = out(a | b) - val and = out(a & b) - val not = out(~a) - }) - .doSim(seed = 42) { dut => - for (_ <- 0 until 100) { - dut.a.randomize() - dut.b.randomize() - sleep(1) - for (i <- 0 until n) { - assert(dut.xor(i).toInt == (dut.a(i).toInt ^ dut.b(i).toInt)) - assert(dut.or(i).toInt == (dut.a(i).toInt | dut.b(i).toInt)) - assert(dut.and(i).toInt == (dut.a(i).toInt & dut.b(i).toInt)) - assert(dut.not(i).toInt == ~dut.a(i).toInt) - } - } - - def isEq(a: UInt, b: UInt): Boolean = a.toInt == b.toInt - } - } - } - - for (bitCount <- 0 until 12) { - test("CountOnes" + bitCount) { - LutInputs(Random.nextInt(5) + 2).on { - SimConfig.noOptimisation - .compile(new Component { - val input = in Bits (bitCount bits) - val output = out(CountOne(input)) - }) - .doSim(seed = 42) { dut => - for (_ <- 0 until 100 + (1 << bitCount) * 4) { - dut.input.randomize() - sleep(1) - assert(dut.output.toInt === dut.input.toBigInt.bitCount) - } - } - } - } - } - - for (bitCount <- 0 until 12) { - test("CountOneOnEach" + bitCount) { - SimConfig.noOptimisation - .compile(new Component { - val input = in Bits (bitCount bits) - val output = out Vec (CountOneOnEach(input)) - }) - .doSim(seed = 42) { dut => - for (_ <- 0 until 100 + (1 << bitCount) * 4) { - dut.input.randomize() - sleep(1) - val input = dut.input.toBigInt - for (i <- 0 until bitCount; mask = ((1 << i + 1) - 1)) - assert(dut.output(i).toInt === (input & mask).bitCount) - } - } - } - } -} diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimMultiThreadingTest.scala b/tester/src/test/scala/spinal/tester/scalatest/SpinalSimMultiThreadingTest.scala deleted file mode 100644 index 294d0389c8..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimMultiThreadingTest.scala +++ /dev/null @@ -1,72 +0,0 @@ -package spinal.tester.scalatest - -import org.scalatest.funsuite.AnyFunSuite -import spinal.sim._ -import spinal.core._ -import spinal.core.sim._ - -import scala.util.Random - - -class SpinalSimMultiThreadingDut(offset : Int) extends Component { - val io = new Bundle { - val a, b, c = in UInt (8 bits) - val result = out UInt (8 bits) - } - io.result := RegNext(io.a + io.b - io.c + offset) init (0) - // def rec(that : UInt, level : Int) : UInt = if(level != 0) - // rec(RegNext(that), level -1) - // else - // that - // io.result := rec(io.a + io.b - io.c, 1000) -} - -class SpinalSimMultiThreadingTest extends SpinalSimFunSuite { - test("Test1") { - var faild = false - val threads = for (t <- 0 to 3) yield { - new Thread { - override def run() = { - for (i <- 0 to 5) { - try { - SimConfig - .withConfig(SpinalConfig(defaultConfigForClockDomains = ClockDomainConfig(resetKind = SYNC))) - // .compile() - // .withWave - .doSim(new SpinalSimMultiThreadingDut(i + t).setDefinitionName(s"SpinalSimMultiThreadingDut_${t}_${i}")) { dut => - dut.clockDomain.forkStimulus(period = 10) - - for (repeat <- 0 until (100000*durationFactor).toInt) { - val a, b, c = Random.nextInt(256) - dut.io.a #= a - dut.io.b #= b - dut.io.c #= c - dut.clockDomain.waitSampling(); sleep(0) - if (dut.clockDomain.isResetDeasserted) assert(dut.io.result.toInt == ((a + b - c + i + t) & 0xFF)) - } - } - } catch { - case e: Throwable => { - faild = true - println(e) - println("FAILURE") - throw e - } - } - } - } - } - } - - for (thread <- threads) { - thread.start() - Thread.sleep(1000) - } - - for (thread <- threads) { - thread.join() - } - - assert(!faild) - } -} diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimOneEntryRamTester.scala b/tester/src/test/scala/spinal/tester/scalatest/SpinalSimOneEntryRamTester.scala deleted file mode 100644 index 17c429a138..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimOneEntryRamTester.scala +++ /dev/null @@ -1,187 +0,0 @@ -package spinal.tester.scalatest - -import org.scalatest.funsuite.AnyFunSuite -import spinal.core.sim._ -import spinal.core._ -import spinal.lib._ - -class SpinalSimOneEntryRamTester extends SpinalSimFunSuite{ - test("general") { - SimConfig.doSim(new Component { - val mem = Mem(Bits(8 bits), 1).randBoot() - val writePort = slave(mem.writePort) - val readSyncPort = slave(mem.readSyncPort) - val readAsyncPort = new Area { - val address = in(UInt(0 bits)) - val data = out(mem(address)) - } - }) { dut => - dut.clockDomain.forkStimulus(10) - - dut.writePort.valid #= true - dut.writePort.data #= 42 - dut.clockDomain.waitSampling() - dut.writePort.valid #= false - dut.readSyncPort.cmd.valid #= true - dut.clockDomain.waitSampling() - - var readSyncModel = 42 - var ramModel = 42 - for (repeat <- 0 to 100) { - dut.writePort.randomize() - dut.readSyncPort.cmd.randomize() - dut.readAsyncPort.address.randomize() - - dut.clockDomain.waitSampling() - assert(dut.readSyncPort.rsp.toInt == readSyncModel) - assert(dut.readAsyncPort.data.toInt == ramModel) - if (dut.readSyncPort.cmd.valid.toBoolean) { - readSyncModel = ramModel - } - if (dut.writePort.valid.toBoolean) { - ramModel = dut.writePort.data.toInt - } - sleep(1) - assert(dut.readAsyncPort.data.toInt == ramModel) - } - } - } - - test("rwPort") { - SimConfig.doSim(new Component { - val mem = Mem(Bits(8 bits), 1).randBoot() - val readWrite = new Area { - val address = U"" - val writeData = in Bits (8 bits) - val enable, write = in Bool() - val readData = out(mem.readWriteSync(address, writeData, enable, write)) - } - val readSyncPort = slave(mem.readSyncPort) - val readAsyncPort = new Area { - val address = in(UInt(0 bits)) - val data = out(mem(address)) - } - }) { dut => - dut.clockDomain.forkStimulus(10) - - dut.readWrite.enable #= true - dut.readWrite.write #= true - dut.readWrite.writeData #= 42 - dut.clockDomain.waitSampling() - dut.readWrite.write #= true - dut.readSyncPort.cmd.valid #= true - dut.clockDomain.waitSampling() - - var readWriteModel = 42 - var readSyncModel = 42 - var ramModel = 42 - for (repeat <- 0 until 100) { - dut.readWrite.enable.randomize() - dut.readWrite.write.randomize() - dut.readWrite.writeData.randomize() - dut.readSyncPort.cmd.randomize() - dut.readAsyncPort.address.randomize() - - dut.clockDomain.waitSampling() - assert(dut.readSyncPort.rsp.toInt == readSyncModel) - assert(dut.readAsyncPort.data.toInt == ramModel) - if (dut.readSyncPort.cmd.valid.toBoolean) { - readSyncModel = ramModel - } - if (dut.readWrite.enable.toBoolean && !dut.readWrite.write.toBoolean) { - readWriteModel = ramModel - } - if (dut.readWrite.enable.toBoolean && dut.readWrite.write.toBoolean) { - ramModel = dut.readWrite.writeData.toInt - } - sleep(1) - assert(dut.readAsyncPort.data.toInt == ramModel) - } - } - } - - test("rom") { - SimConfig.doSim(new Component { - val mem = Mem(Bits(8 bits), 1) init (Seq(B"xAA")) - val readSyncPort = slave(mem.readSyncPort) - val readAsyncPort = new Area { - val address = in(UInt(0 bits)) - val data = out(mem(address)) - } - }) { dut => - dut.clockDomain.forkStimulus(10) - - dut.clockDomain.waitSampling() - dut.readSyncPort.cmd.valid #= true - dut.clockDomain.waitSampling() - - var readSyncModel = 0xAA - var ramModel = 0xAA - for (repeat <- 0 until 100) { - dut.readSyncPort.cmd.randomize() - dut.readAsyncPort.address.randomize() - - dut.clockDomain.waitSampling() - assert(dut.readSyncPort.rsp.toInt == readSyncModel) - assert(dut.readAsyncPort.data.toInt == ramModel) - if (dut.readSyncPort.cmd.valid.toBoolean) { - readSyncModel = ramModel - } - sleep(1) - assert(dut.readAsyncPort.data.toInt == ramModel) - } - } - } -} - - -class SpinalSimRamTester extends AnyFunSuite { - test("general") { - SimConfig.withConfig(SpinalConfig(device = Device.XILINX)).compile(new Component { - val ram = Mem(Bits(32 bits), 256) - - val wrEnable = in Bool() - val wrAddress = in UInt(8 bits) - val wrData = in Bits(32 bits) - val wrMask = in Bits(4 bits) - - ram.write(wrAddress, wrData, wrEnable, wrMask) - - val rdAddress = in UInt(8 bits) - val rdData = out Bits(32 bits) - rdData := ram.readAsync(rdAddress) - }).doSim{dut => - dut.clockDomain.forkStimulus(10) - - - def wr(address : Int, data : Long, mask : Long): Unit ={ - dut.clockDomain.waitSampling() - dut.wrEnable #= true - dut.wrAddress #= address - dut.wrData #= data - dut.wrMask #= mask - dut.clockDomain.waitSampling() - } - - wr(42, 0x00112233l, 0x1) - wr(43, 0x44556677l, 0x3) - wr(44, 0x8899AABBl, 0xF) - wr(42, 0xFFFFFFFFl, 0xE) - wr(43, 0xFFFFFFFFl, 0xC) - wr(44, 0xFFFFFFFFl, 0x0) - - dut.clockDomain.waitSampling() - dut.clockDomain.waitSampling() - - def rdCheck(address : Int, data : Long, mask : Long): Unit ={ - dut.rdAddress #= address - sleep(1) - assert((dut.rdData.toLong & mask) == (data & mask)) - } - - rdCheck(42, 0x00112233l, 0x000000FF) - rdCheck(43, 0x44556677l, 0x0000FFFF) - rdCheck(44, 0x8899AABBl, 0xFFFFFFFF) - } - } -} diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimPerfTester.scala b/tester/src/test/scala/spinal/tester/scalatest/SpinalSimPerfTester.scala deleted file mode 100644 index a3a1b7baab..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimPerfTester.scala +++ /dev/null @@ -1,191 +0,0 @@ -package spinal.tester.scalatest - -import org.scalatest.funsuite.AnyFunSuite -import spinal.core._ -import spinal.sim._ -import spinal.core.sim._ -import spinal.tester.scalatest -import spinal.tester.scalatest.SpinalSimVerilatorIoTest.SpinalSimVerilatorIoTestTop - -import scala.concurrent.{Await, Future} -import scala.util.Random - -object SpinalSimPerfTester { - - class SpinalSimPerfTesterDut extends Component { - val io = new Bundle { - val a, b, c = in UInt (8 bits) - val result = out UInt (8 bits) - } - - io.result := RegNext(io.a + io.b - io.c) init (0) - } - -} - -class SpinalSimPerfTester extends AnyFunSuite { - SpinalSimTester { env => - import env._ - - var compiled: SimCompiled[SpinalSimPerfTester.SpinalSimPerfTesterDut] = null - - test(prefix + "compile") { - compiled = SimConfig - .allOptimisation - // .withGhdl - .compile(new SpinalSimPerfTester.SpinalSimPerfTesterDut()) - } - - - test(prefix + "TestStdSimIntThreadLess") { - compiled.doSim { dut => - dut.clockDomain.forkStimulus(period = 10) - dut.clockDomain.forkSimSpeedPrinter(0.2) - dut.io.a.randomize() - dut.io.b.randomize() - dut.io.c.randomize() - - var model = -1 - var times = 0 - dut.clockDomain.onSamplings { - assert(model == -1 || dut.io.result.toInt == model) - model = ((dut.io.a.toInt + dut.io.b.toInt - dut.io.c.toInt) & 0xFF) - dut.io.a #= Random.nextInt(256) - dut.io.b #= Random.nextInt(256) - dut.io.c #= Random.nextInt(256) - times += 1 - } - - for (repeat <- 0 until 4) { - val startAt = System.nanoTime - waitUntil(times == (2000000*durationFactor).toInt) - times = 0 - val endAt = System.nanoTime - System.out.println((endAt - startAt) * 1e-6 + " ms") - } - } - } - - - test(prefix + "TestStdSimInt") { - compiled.doSim { dut => - dut.clockDomain.forkStimulus(period = 10) - dut.clockDomain.forkSimSpeedPrinter(0.2) - - var model = 0 - for (repeat <- 0 until 4) { - val times = (2000000*durationFactor).toInt - val startAt = System.nanoTime - for (repeat2 <- 0 until times) { - dut.io.a #= Random.nextInt(256) - dut.io.b #= Random.nextInt(256) - dut.io.c #= Random.nextInt(256) - dut.clockDomain.waitActiveEdge() - if (dut.clockDomain.isResetDeasserted) { - assert(dut.io.result.toInt == model) - model = ((dut.io.a.toInt + dut.io.b.toInt - dut.io.c.toInt) & 0xFF) - } - } - val endAt = System.nanoTime - System.out.println((endAt - startAt) * 1e-6 + " ms") - } - } - } - - - test(prefix + "TestStdSimIntx2") { - compiled.doSim { dut => - dut.clockDomain.forkStimulus(period = 10) - - for (repeat <- 0 until 4) { - val times = (80000*durationFactor).toInt - val startAt = System.nanoTime - val t1, t2 = fork { - val rand = new Random(1) - for (repeat2 <- 0 until times) { - val a, b, c = rand.nextInt(256) - dut.io.a #= a - dut.io.b #= b - dut.io.c #= c - dut.clockDomain.waitActiveEdge() - sleep(0) - val dummy = if (dut.clockDomain.isResetDeasserted) - assert(dut.io.result.toInt == ((a + b - c) & 0xFF)) - } - } - t1.join(); t2.join() - val endAt = System.nanoTime - System.out.println((endAt - startAt) * 1e-6 + " ms") - } - } - } - - - test(prefix + "TestStdSimBigInt") { - compiled.doSim { dut => - dut.clockDomain.forkStimulus(period = 10) - - for (repeat <- 0 until 4) { - val times = (80000*durationFactor).toInt - val startAt = System.nanoTime - for (repeat2 <- 0 until times) { - val a, b, c = BigInt(Random.nextInt(256)) - dut.io.a #= a - dut.io.b #= b - dut.io.c #= c - dut.clockDomain.waitActiveEdge(); sleep(0) - if (dut.clockDomain.isResetDeasserted) assert(dut.io.result.toBigInt == ((a + b - c) & 0xFF)) - } - val endAt = System.nanoTime - System.out.println((endAt - startAt) * 1e-6 + " ms") - } - } - } - - test(prefix + "TestSleep0") { - compiled.doSim { dut => - dut.clockDomain.forkStimulus(period = 10) - - for (repeat <- 0 until 4) { - val times = (100000*durationFactor).toInt - val startAt = System.nanoTime - for (repeat2 <- 0 until times) { - sleep(0) - } - val endAt = System.nanoTime - System.out.println((endAt - startAt) * 1e-6 + " ms") - } - } - - } - - - test(prefix + "compilationSpeed") { - val stages = 100 - val states = (100*designFactor).toInt - val operands = 5 - SimConfig.withConfig(SpinalConfig(verbose = true)).allOptimisation.doSim(new Component { - val inputs = Vec(in UInt (8 bits), states) - val outputs = Vec(out UInt (8 bits), states) - var ptr = inputs - for (s <- 0 until stages) { - val result = Vec(Reg(UInt(8 bits)), states).setName("tmp_" + s) - for (elementId <- 0 until states) { - result(elementId) := (0 until operands).map(_ => ptr(Random.nextInt(states))).reduce(_ + _) - } - ptr = result - } - outputs := ptr - }) { dut => - - dut.clockDomain.forkStimulus(10) - for (r <- 0 until (10000*durationFactor).toInt) { - for (input <- dut.inputs) { - input.randomize() - } - dut.clockDomain.waitSampling() - } - } - } - } -} diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimRamAccessTester.scala b/tester/src/test/scala/spinal/tester/scalatest/SpinalSimRamAccessTester.scala deleted file mode 100644 index 60c9860f52..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimRamAccessTester.scala +++ /dev/null @@ -1,145 +0,0 @@ -package spinal.tester.scalatest - -import spinal.core._ -import spinal.lib._ -import spinal.core.sim._ - -import scala.util.Random - -class SpinalSimRamAccessTester extends SpinalSimFunSuite { - ghdlEnabled = false //TODO - - test("test1") { - SimConfig.compile(new Component{ - val mem = Mem(UInt(16 bits), 32).simPublic() - val write = slave(mem.writePort) - val read = new Area{ - val address = in(mem.addressType()) - val data = out(mem.readAsync(address)) - } - }).doSim{ dut => - val model = Array.fill(32)(Random.nextInt(1024*64)) - for ((v, i) <- model.zipWithIndex) dut.mem.setBigInt(i, v) - - def simWrite() { - val address = Random.nextInt(32) - val data = Random.nextInt(1024*64) - dut.mem.setBigInt(address, data) - model(address) = data - sleep(1) - } - def simCheck() = { - val address = Random.nextInt(32) - val readed = dut.mem.getBigInt(address) - assert(readed == model(address)) - } - - dut.write.valid #= false - def dutWrite() { - dut.clockDomain.waitSampling() - val address = Random.nextInt(32) - val data = Random.nextInt(1024*64) - dut.write.valid #= true - dut.write.address #= address - dut.write.data #= data - dut.clockDomain.waitSampling() - dut.write.valid #= false - dut.clockDomain.waitSampling() - model(address) = data - } - def dutCheck() = { - sleep(1) - val address = Random.nextInt(32) - dut.read.address #= address - sleep(1) - if(Random.nextBoolean()) sleep(1) else dut.clockDomain.waitSampling() - assert(dut.read.data.toInt == model(address)) - } - - - dut.clockDomain.forkStimulus(10) - dut.clockDomain.waitSampling(10) - for(i <- 0 until 1000) Random.nextInt(4) match { - case 0 => simWrite() - case 1 => simCheck() - case 2 => dutWrite() - case 3 => dutCheck() - } - println(simTime()) - } - } - - test("test2") { - SimConfig.compile(new Component{ - val mem = Mem(UInt(16 bits), 32).simPublic() - val write = new Area{ - val valid = in Bool() - val address = in(mem.addressType()) - val data = in(mem.wordType()) - val mask = in Bits(4 bits) - mem.write(address, data, enable = valid, mask = mask) - } - val read = new Area{ - val address = in(mem.addressType()) - val data = out(mem.readAsync(address)) - } - }).doSim{ dut => - val model = Array.fill(32)(Random.nextInt(1024*64)) - for ((v, i) <- model.zipWithIndex) dut.mem.setBigInt(i, v) - - def simWrite() { - val address = Random.nextInt(32) - val data = Random.nextInt(1024*64) - dut.mem.setBigInt(address, data) - model(address) = data - sleep(1) - } - def simCheck() = { - val address = Random.nextInt(32) - assert(dut.mem.getBigInt(address) == model(address)) - } - - dut.write.valid #= false - def dutWrite() { - dut.clockDomain.waitSampling() - val address = Random.nextInt(32) - val data = Random.nextInt(1024*64) - val mask = Random.nextInt(16) - dut.write.valid #= true - dut.write.address #= address - dut.write.data #= data - dut.write.mask #= mask - dut.clockDomain.waitSampling() - dut.write.valid #= false - dut.clockDomain.waitSampling() - var buffer = model(address) - for(i <- 0 until 4 if (mask & (1 << i)) != 0){ - val m = 0xF << 4*i - buffer = (buffer & ~m) | (data & m) - } - model(address) = buffer - } - def dutCheck() = { - sleep(1) - val address = Random.nextInt(32) - dut.read.address #= address - sleep(1) - if(Random.nextBoolean()) sleep(1) else dut.clockDomain.waitSampling() - assert(dut.read.data.toInt == model(address)) - } - - - dut.clockDomain.forkStimulus(10) - dut.clockDomain.waitSampling(10) - for(i <- 0 until 1000) Random.nextInt(4) match { - case 0 => simWrite() - case 1 => simCheck() - case 2 => dutWrite() - case 3 => dutCheck() - case _ => - } - println(simTime()) - } - } -} - diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimRandomizeTester.scala b/tester/src/test/scala/spinal/tester/scalatest/SpinalSimRandomizeTester.scala deleted file mode 100644 index bbd7912f55..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimRandomizeTester.scala +++ /dev/null @@ -1,60 +0,0 @@ -package spinal.tester.scalatest - -import org.scalatest.funsuite.AnyFunSuite -import spinal.core._ -import spinal.core.sim._ - -import scala.language.postfixOps - -object SomeEnum extends SpinalEnum { - val sIdle, sStart, sData, sParity, sStop = newElement() -} - -case class SimRandomizeTester() extends Component { - val io = new Bundle { - val b = in(Bool()) - val ui = in(UInt(4 bit)) - val uil = in(UInt(33 bit)) - val si = in(SInt(4 bit)) - val sil = in(UInt(33 bit)) - val e = in(SomeEnum()) - val uf = in(UFix(peak = 8 exp, resolution = -2 exp)) - val sf = in(SFix(peak = 8 exp, resolution = -2 exp)) - val af = in(AFix.UQ(2 bit, 2 bit)) - val af_out_of_range = in(AFix(8, -4, -2 exp)) - } -} - -class SpinalSimRandomizeTest extends AnyFunSuite { - val dut = SimConfig.compile { SimRandomizeTester() } - - test("randomize returns the value driven next") { - dut.doSim("randomize returns the value driven next") { dut => - for (_ <- 0 to 100) { - val b = dut.io.b.randomize() - val ui = dut.io.ui.randomize() - val uil = dut.io.uil.randomize() - val si = dut.io.si.randomize() - val sil = dut.io.sil.randomize() - val e = dut.io.e.randomize() - val uf = dut.io.uf.randomize() - val sf = dut.io.sf.randomize() - val af = dut.io.af.randomize() - val af_out_of_range = dut.io.af_out_of_range.randomize(inRange = false) - - sleep(10) - - assert(b == dut.io.b.toBoolean) - assert(ui == dut.io.ui.toBigInt) - assert(uil == dut.io.uil.toBigInt) - assert(si == dut.io.si.toBigInt) - assert(sil == dut.io.sil.toBigInt) - assert(e == dut.io.e.toEnum) - assert(uf == dut.io.uf.toBigDecimal) - assert(sf == dut.io.sf.toBigDecimal) - assert(af == dut.io.af.toBigDecimal) - assert(af_out_of_range == dut.io.af_out_of_range.toBigDecimal) - } - } - } -} diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimStreamExtenderTester.scala b/tester/src/test/scala/spinal/tester/scalatest/SpinalSimStreamExtenderTester.scala deleted file mode 100644 index 7e0f9f7ac8..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimStreamExtenderTester.scala +++ /dev/null @@ -1,161 +0,0 @@ -package spinal.tester.scalatest - -import scala.collection.mutable -import scala.util.Random -import org.scalatest.funsuite.AnyFunSuite - -import spinal.core._ -import spinal.lib._ -import spinal.lib.sim._ -import spinal.core.sim._ - -class SpinalSimStreamExtenderTester extends SpinalSimFunSuite { - def prepare( - dut: StreamTransactionExtender[UInt, UInt], - alwaysInput: Boolean = false, - alwaysOutput: Boolean = false, - inQueue: mutable.Queue[BigInt], - outQueue: mutable.Queue[BigInt], - countQueue: mutable.Queue[BigInt], - lastQueue: mutable.Queue[Boolean] - ) { - dut.clockDomain.forkStimulus(period = 10) - dut.io.input.valid #= false - - if (alwaysOutput) { - dut.io.output.ready #= true - } else { - val randomReady = StreamReadyRandomizer(dut.io.output, dut.clockDomain) - } - - val driver = StreamDriver(dut.io.input, dut.clockDomain) { payload => - if (inQueue.nonEmpty) { - payload #= inQueue.dequeue() - dut.io.count #= countQueue.dequeue() - true - } else { - false - } - } - driver.transactionDelay = () => { - if (!alwaysInput) { - val x = Random.nextDouble() - (x * x * 10).toInt - } else { - 0 - } - } - - val monitor = StreamMonitor(dut.io.output, dut.clockDomain) { payload => - { - val address = outQueue.dequeue() - val last = lastQueue.dequeue() - // println("##pop out queue:" + address.toString(16)) - val data = payload.toBigInt - assert((data >> 1) == address) - assert(((data & 1) == 1) == last) - } - } - - for (j <- 0 until 10000) { - val count = Random.nextInt(20) - val address = Random.nextInt(0xffffff) - - inQueue.enqueue(address) - countQueue.enqueue(count) - - for (i <- 0 to count) { - outQueue.enqueue(address) - lastQueue.enqueue(i == count) - } - } - } - - test("testRandomInOut") { - val lastQueue = mutable.Queue[Boolean]() - val compiled = SimConfig.allOptimisation.compile { - val dut = new StreamTransactionExtender( - UInt(32 bits), - UInt(33 bits), - 12, - false, - (id, payload: UInt, last) => payload @@ last - ) - dut - } - compiled.doSimUntilVoid { dut => - val inQueue = mutable.Queue[BigInt]() - val outQueue = mutable.Queue[BigInt]() - val countQueue = mutable.Queue[BigInt]() - prepare(dut, false, false, inQueue, outQueue, countQueue, lastQueue) - dut.clockDomain.waitSampling((1 KiB).toInt) - simSuccess() - } - } - - test("testRandomIn") { - val lastQueue = mutable.Queue[Boolean]() - val compiled = SimConfig.allOptimisation.compile { - val dut = new StreamTransactionExtender( - UInt(32 bits), - UInt(33 bits), - 12, - false, - (id, payload: UInt, last) => payload @@ last - ) - dut - } - compiled.doSimUntilVoid { dut => - val inQueue = mutable.Queue[BigInt]() - val outQueue = mutable.Queue[BigInt]() - val countQueue = mutable.Queue[BigInt]() - prepare(dut, false, true, inQueue, outQueue, countQueue, lastQueue) - dut.clockDomain.waitSampling((1 KiB).toInt) - simSuccess() - } - } - - test("testRandomOut") { - val lastQueue = mutable.Queue[Boolean]() - val compiled = SimConfig.allOptimisation.compile { - val dut = new StreamTransactionExtender( - UInt(32 bits), - UInt(33 bits), - 12, - false, - (id, payload: UInt, last) => payload @@ last - ) - dut - } - compiled.doSimUntilVoid { dut => - val inQueue = mutable.Queue[BigInt]() - val outQueue = mutable.Queue[BigInt]() - val countQueue = mutable.Queue[BigInt]() - prepare(dut, true, false, inQueue, outQueue, countQueue, lastQueue) - dut.clockDomain.waitSampling((1 KiB).toInt) - simSuccess() - } - } - - test("testFullPipeline") { - val lastQueue = mutable.Queue[Boolean]() - val compiled = SimConfig.allOptimisation.compile { - val dut = new StreamTransactionExtender( - UInt(32 bits), - UInt(33 bits), - 12, - false, - (id, payload: UInt, last) => payload @@ last - ) - dut - } - compiled.doSimUntilVoid { dut => - val inQueue = mutable.Queue[BigInt]() - val outQueue = mutable.Queue[BigInt]() - val countQueue = mutable.Queue[BigInt]() - prepare(dut, true, true, inQueue, outQueue, countQueue, lastQueue) - dut.clockDomain.waitSampling((1 KiB).toInt) - simSuccess() - } - } -} diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimStreamFifoCCTester.scala b/tester/src/test/scala/spinal/tester/scalatest/SpinalSimStreamFifoCCTester.scala deleted file mode 100644 index 1d5c311fca..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimStreamFifoCCTester.scala +++ /dev/null @@ -1,261 +0,0 @@ -package spinal.tester.scalatest - -import org.scalatest.funsuite.AnyFunSuite -import spinal.core._ -import spinal.sim._ -import spinal.core.sim._ -import spinal.lib.StreamFifoCC -import spinal.tester - -import scala.collection.mutable -import scala.util.Random - -class SpinalSimStreamFifoCCTester extends SpinalSimFunSuite { - -// onlyVerilator() - - def testbench(dut : StreamFifoCC[Bits]): Unit ={ - val queueModel = mutable.Queue[Long]() - - //Push data randomly and fill the queueModel with pushed transactions - val pushThread = fork{ - while(true){ - dut.io.push.valid.randomize() - dut.io.push.payload.randomize() - dut.pushClock.waitSampling() - if(dut.io.push.valid.toBoolean && dut.io.push.ready.toBoolean){ - queueModel.enqueue(dut.io.push.payload.toLong) - } - } - } - - //Pop data randomly and check that it match with the queueModel - val popThread = fork{ - dut.io.pop.ready #= false - dut.pushClock.waitSampling() - dut.popClock.waitSampling() - for(repeat <- 0 until 10000){ - dut.io.pop.ready.randomize() - dut.popClock.waitSampling() - if(dut.io.pop.valid.toBoolean && dut.io.pop.ready.toBoolean){ - assert(dut.io.pop.payload.toLong == queueModel.dequeue()) - } - } - simSuccess() - } - } - - for(pushResetLevel <- List(LOW, HIGH); - popResetLevel <- List(LOW, HIGH); - popResetEnable <- List(false, true)) { - val postfix = s"${pushResetLevel}_${popResetLevel}_${popResetEnable}" - test("testAsyncReset_" + postfix) { - //Compile the simulator - val compiled = SimConfig.allOptimisation.compile( - rtl = new StreamFifoCC( - dataType = Bits(32 bits), - depth = 32, - pushClock = ClockDomain.external("clkA", config = ClockDomainConfig(resetActiveLevel = pushResetLevel)), - popClock = ClockDomain.external("clkB", withReset = popResetEnable, config = ClockDomainConfig(resetActiveLevel = popResetLevel)), - withPopBufferedReset = !popResetEnable - ) - ) - - //Run the simulation - compiled.doSimUntilVoid { dut => - fork { - //Clear clock domains signals, to be sure the simulation capture their first edge. - dut.pushClock.fallingEdge() - dut.popClock.fallingEdge() - dut.pushClock.deassertReset() - if(popResetEnable) dut.popClock.deassertReset() - sleep(0) - - //Do the resets - dut.pushClock.assertReset() - if(popResetEnable)dut.popClock.assertReset() - sleep(10) - dut.pushClock.deassertReset() - if(popResetEnable)dut.popClock.deassertReset() - sleep(1) - - //Forever, randomly toggle one of the clocks (will create asynchronous clocks without fixed frequencies) - while (true) { - if (Random.nextBoolean()) { - dut.pushClock.clockToggle() - } else { - dut.popClock.clockToggle() - } - sleep(1) - } - } - testbench(dut) - } - } - - test("testSyncReset_" + postfix) { - //Compile the simulator - val compiled = SimConfig.withConfig(SpinalConfig(defaultConfigForClockDomains = ClockDomainConfig(resetKind = SYNC))).allOptimisation.compile( - rtl = new StreamFifoCC( - dataType = Bits(32 bits), - depth = 32, - pushClock = ClockDomain.external("clkA", config = ClockDomainConfig(resetActiveLevel = pushResetLevel)), - popClock = ClockDomain.external("clkB", withReset = popResetEnable, config = ClockDomainConfig(resetActiveLevel = popResetLevel)), - withPopBufferedReset = !popResetEnable - ) - ) - - //Run the simulation - compiled.doSimUntilVoid { dut => - dut.pushClock.fallingEdge() - dut.popClock.fallingEdge() - dut.pushClock.deassertReset() - if(popResetEnable) dut.popClock.deassertReset() - fork { - //Clear clock domains signals, to be sure the simulation capture their first edge. - sleep(0) - - //Do the resets - dut.pushClock.assertReset() - if(popResetEnable) dut.popClock.assertReset() - sleep(10) - dut.pushClock.deassertReset() - if(popResetEnable) dut.popClock.deassertReset() - sleep(1) - } - - fork { - sleep(1) - for (i <- 0 until 5) { - dut.pushClock.clockToggle() - dut.popClock.clockToggle() - sleep(1) - } - //Forever, randomly toggle one of the clocks (will create asynchronous clocks without fixed frequencies) - while (true) { - if (Random.nextBoolean()) { - dut.pushClock.clockToggle() - } else { - dut.popClock.clockToggle() - } - sleep(1) - } - } - testbench(dut) - } - } - } - - test("testBootReset") { - //Compile the simulator - val compiled = SimConfig.withConfig(SpinalConfig(defaultConfigForClockDomains = ClockDomainConfig(resetKind = BOOT))).allOptimisation.compile( - rtl = new StreamFifoCC( - dataType = Bits(32 bits), - depth = 32, - pushClock = ClockDomain.external("clkA"), - popClock = ClockDomain.external("clkB", withReset = false) - ) - ) - - //Run the simulation - compiled.doSimUntilVoid { dut => - fork { - dut.pushClock.fallingEdge() - dut.popClock.fallingEdge() - sleep(1) - //Forever, randomly toggle one of the clocks (will create asynchronous clocks without fixed frequencies) - while (true) { - if (Random.nextBoolean()) { - dut.pushClock.clockToggle() - } else { - dut.popClock.clockToggle() - } - sleep(1) - } - } - testbench(dut) - } - } -} - - -object TesterBugPlay extends App{ - - def testbench(dut : StreamFifoCC[Bits]): Unit ={ - val queueModel = mutable.Queue[Long]() - - //Push data randomly and fill the queueModel with pushed transactions - val pushThread = fork{ - while(true){ - dut.io.push.valid.randomize() - dut.io.push.payload.randomize() - dut.pushClock.waitSampling() - if(dut.io.push.valid.toBoolean && dut.io.push.ready.toBoolean){ - queueModel.enqueue(dut.io.push.payload.toLong) - } - } - } - - //Pop data randomly and check that it match with the queueModel - val popThread = fork{ - for(repeat <- 0 until 10000){ - dut.io.pop.ready.randomize() - dut.popClock.waitSampling() - if(dut.io.pop.valid.toBoolean && dut.io.pop.ready.toBoolean){ - assert(dut.io.pop.payload.toLong == queueModel.dequeue()) - } - } - simSuccess() - } - } - val compiled = SimConfig.withIVerilog.withConfig(SpinalConfig(defaultConfigForClockDomains = ClockDomainConfig(resetKind = SYNC))).allOptimisation.compile( - rtl = new StreamFifoCC( - dataType = Bits(32 bits), - depth = 32, - pushClock = ClockDomain.external("clkA"), - popClock = ClockDomain.external("clkB", withReset = false) - ) - ) - - for(i <- 132 until 1000) { - - //Run the simulation - compiled.doSimUntilVoid(seed = i) { dut => - dut.pushClock.fallingEdge() - dut.popClock.fallingEdge() - dut.pushClock.deassertReset() -// dut.popClock.deassertReset() - fork { - //Clear clock domains signals, to be sure the simulation capture their first edge. - sleep(0) - - //Do the resets - dut.pushClock.assertReset() -// dut.popClock.assertReset() - sleep(10) - dut.pushClock.deassertReset() -// dut.popClock.deassertReset() - sleep(1) - } - - fork { - sleep(1) - for(i <- 0 until 5) { - dut.pushClock.clockToggle() - dut.popClock.clockToggle() - sleep(1) - } - //Forever, randomly toggle one of the clocks (will create asynchronous clocks without fixed frequencies) - while (true) { - if (Random.nextBoolean()) { - dut.pushClock.clockToggle() - } else { - dut.popClock.clockToggle() - } - sleep(1) - } - } - testbench(dut) - } - } -} \ No newline at end of file diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimStreamFifoMultiChannelSharedSpaceTester.scala b/tester/src/test/scala/spinal/tester/scalatest/SpinalSimStreamFifoMultiChannelSharedSpaceTester.scala deleted file mode 100644 index a45e572126..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimStreamFifoMultiChannelSharedSpaceTester.scala +++ /dev/null @@ -1,46 +0,0 @@ -package spinal.tester.scalatest - -import org.scalatest.funsuite.AnyFunSuite -import spinal.core._ -import spinal.sim._ -import spinal.core.sim._ -import spinal.lib.{StreamFifoCC, StreamFifoMultiChannelSharedSpace} -import spinal.tester - -import scala.collection.mutable -import scala.collection.mutable.ArrayBuffer -import scala.util.Random - -class SpinalSimStreamFifoMultiChannelSharedSpaceTester extends AnyFunSuite { - test("t1") { - SimConfig.compile(new StreamFifoMultiChannelSharedSpace(Bits(32 bits), 4, 16)).doSimUntilVoid(seed = 42) { dut => - val queueModel = ArrayBuffer.fill(4)(mutable.Queue[Long]()) - - SimTimeout(1000000) - dut.clockDomain.forkStimulus(2) - //Push data randomly and fill the queueModel with pushed transactions - dut.io.push.stream.valid #= false - dut.io.pop.stream.ready #= true - - val successCount = Array.fill(4)(0) - dut.clockDomain.onSamplings { - assert(!(dut.io.push.full.toBoolean && (dut.io.availability.toInt > 1))) - - if (dut.io.push.stream.valid.toBoolean && dut.io.push.stream.ready.toBoolean) { - queueModel(log2Up(dut.io.push.channel.toInt)).enqueue(dut.io.push.stream.payload.toLong) - } - if (dut.io.pop.stream.valid.toBoolean && dut.io.pop.stream.ready.toBoolean) { - val channel = log2Up(dut.io.pop.channel.toInt) - assert(dut.io.pop.stream.payload.toLong == queueModel(channel).dequeue()) - successCount(channel) += 1 - if (successCount.forall(_ > 20000)) simSuccess() - } - dut.io.push.stream.valid.randomize() - dut.io.push.stream.payload.randomize() - dut.io.push.channel #= (1 << Random.nextInt(dut.channelCount)) - dut.io.pop.stream.ready.randomize() - dut.io.pop.channel #= (1 << Random.nextInt(dut.channelCount)) - } - } - } -} diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimStreamFifoTester.scala b/tester/src/test/scala/spinal/tester/scalatest/SpinalSimStreamFifoTester.scala deleted file mode 100644 index 6811ff91ed..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimStreamFifoTester.scala +++ /dev/null @@ -1,271 +0,0 @@ -package spinal.tester.scalatest - -import org.scalatest.funsuite.AnyFunSuite -import spinal.core._ -import spinal.sim._ -import spinal.core.sim._ -import spinal.lib.{StreamFifo, StreamFifoLowLatency} -import spinal.lib.graphic.Rgb -import spinal.lib.sim._ -import spinal.tester - -import scala.collection.mutable -import scala.util.Random - -class SpinalSimStreamFifoTester extends SpinalSimFunSuite { - test("testBits") { - //Compile the simulator - val compiled = SimConfig.allOptimisation.compile( - rtl = new StreamFifo( - dataType = Bits(32 bits), - depth = 32 - ) - ) - - //Run the simulation - compiled.doSimUntilVoid { dut => - val queueModel = mutable.Queue[Long]() - - SimTimeout(1000000 * 8) - dut.clockDomain.forkStimulus(2) - - dut.io.flush #= false - - //Push data randomly and fill the queueModel with pushed transactions - dut.io.push.valid #= false - dut.clockDomain.onSamplings { - if (dut.io.push.valid.toBoolean && dut.io.push.ready.toBoolean) { - queueModel.enqueue(dut.io.push.payload.toLong) - } - dut.io.push.valid.randomize() - dut.io.push.payload.randomize() - } - - //Pop data randomly and check that it match with the queueModel - val popThread = fork { - dut.io.pop.ready #= true - for (repeat <- 0 until 10000) { - dut.io.pop.ready.randomize() - dut.clockDomain.waitSampling() - if (dut.io.pop.valid.toBoolean && dut.io.pop.ready.toBoolean) { - assert(dut.io.pop.payload.toLong == queueModel.dequeue()) - } - } - simSuccess() - } - } - } - - - test("testOne") { - //Compile the simulator - val compiled = SimConfig.allOptimisation.compile( - rtl = new StreamFifo( - dataType = Bits(32 bits), - depth = 1 - ) - ) - - //Run the simulation - compiled.doSimUntilVoid { dut => - val queueModel = mutable.Queue[Long]() - - SimTimeout(1000000 * 8) - dut.clockDomain.forkStimulus(2) - - dut.io.flush #= false - - //Push data randomly and fill the queueModel with pushed transactions - dut.io.push.valid #= false - dut.clockDomain.onSamplings { - if (dut.io.push.valid.toBoolean && dut.io.push.ready.toBoolean) { - queueModel.enqueue(dut.io.push.payload.toLong) - } - dut.io.push.valid.randomize() - dut.io.push.payload.randomize() - } - - //Pop data randomly and check that it match with the queueModel - val popThread = fork { - dut.io.pop.ready #= true - for (repeat <- 0 until 10000) { - dut.io.pop.ready.randomize() - dut.clockDomain.waitSampling() - if (dut.io.pop.valid.toBoolean && dut.io.pop.ready.toBoolean) { - assert(dut.io.pop.payload.toLong == queueModel.dequeue()) - } - } - simSuccess() - } - } - } - - - test("testBundle") { - //Bundle used as fifo payload - case class Transaction() extends Bundle { - val flag = Bool() - val data = Bits(8 bits) - val color = Rgb(5, 6, 5) - - override def clone = Transaction() - } - - val compiled = SimConfig.allOptimisation.compile( - rtl = new StreamFifo( - dataType = Transaction(), - depth = 32 - ) - ) - - //Run the simulation - compiled.doSim { dut => - //Inits - SimTimeout(1000000 * 8) - dut.clockDomain.forkStimulus(2) - dut.clockDomain.forkSimSpeedPrinter() - dut.io.flush #= false - - val scoreboard = ScoreboardInOrder[SimData]() - - //Drivers - StreamDriver(dut.io.push, dut.clockDomain) { payload => - payload.randomize() - true - } - StreamReadyRandomizer(dut.io.pop, dut.clockDomain) - - //Monitors - StreamMonitor(dut.io.push, dut.clockDomain) { payload => - scoreboard.pushRef(payload) - } - StreamMonitor(dut.io.pop, dut.clockDomain) { payload => - scoreboard.pushDut(payload) - } - - waitUntil(scoreboard.matches == 10000) - } - } - - test("testTwoDepth") { - //Bundle used as fifo payload - case class Transaction() extends Bundle { - val flag = Bool() - val data = Bits(8 bits) - val color = Rgb(5, 6, 5) - } - - val compiled = SimConfig.allOptimisation.compile( - rtl = new StreamFifo( - dataType = Transaction(), - depth = 2 - ) - ) - - //Run the simulation - compiled.doSim { dut => - //Inits - SimTimeout(1000000 * 8) - dut.clockDomain.forkStimulus(2) - dut.clockDomain.forkSimSpeedPrinter() - dut.io.flush #= false - - val scoreboard = ScoreboardInOrder[SimData]() - - //Drivers - StreamDriver(dut.io.push, dut.clockDomain) { payload => - payload.randomize() - true - } - StreamReadyRandomizer(dut.io.pop, dut.clockDomain) - - //Monitors - StreamMonitor(dut.io.push, dut.clockDomain) { payload => - scoreboard.pushRef(payload) - } - StreamMonitor(dut.io.pop, dut.clockDomain) { payload => - scoreboard.pushDut(payload) - } - - waitUntil(scoreboard.matches == 10000) - } - } - - - test("lowLatency_0") { - //Bundle used as fifo payload - case class Transaction() extends Bundle { - val flag = Bool() - val data = Bits(8 bits) - val color = Rgb(5, 6, 5) - } - - val compiled = SimConfig.allOptimisation.compile( - rtl = new StreamFifoLowLatency( - dataType = Transaction(), - depth = 2, - latency = 0 - ) - ) - - //Run the simulation - compiled.doSim { dut => - //Inits - SimTimeout(1000000 * 8) - dut.clockDomain.forkStimulus(2) - dut.clockDomain.forkSimSpeedPrinter() - dut.io.flush #= false - - val scoreboard = ScoreboardInOrder[SimData]() - - //Drivers - StreamDriver(dut.io.push, dut.clockDomain) { payload => payload.randomize(); true } - StreamReadyRandomizer(dut.io.pop, dut.clockDomain) - - //Monitors - StreamMonitor(dut.io.push, dut.clockDomain) { payload => scoreboard.pushRef(payload) } - StreamMonitor(dut.io.pop, dut.clockDomain) { payload => scoreboard.pushDut(payload) } - - waitUntil(scoreboard.matches == 10000) - } - } - - - test("lowLatency_1") { - //Bundle used as fifo payload - case class Transaction() extends Bundle { - val flag = Bool() - val data = Bits(8 bits) - val color = Rgb(5, 6, 5) - } - - val compiled = SimConfig.allOptimisation.compile( - rtl = new StreamFifoLowLatency( - dataType = Transaction(), - depth = 4, - latency = 1 - ) - ) - - //Run the simulation - compiled.doSim { dut => - //Inits - SimTimeout(1000000 * 8) - dut.clockDomain.forkStimulus(2) - dut.clockDomain.forkSimSpeedPrinter() - dut.io.flush #= false - - val scoreboard = ScoreboardInOrder[SimData]() - - //Drivers - StreamDriver(dut.io.push, dut.clockDomain) { payload => payload.randomize(); true } - StreamReadyRandomizer(dut.io.pop, dut.clockDomain) - - //Monitors - StreamMonitor(dut.io.push, dut.clockDomain) { payload => scoreboard.pushRef(payload) } - StreamMonitor(dut.io.pop, dut.clockDomain) { payload => scoreboard.pushDut(payload) } - - waitUntil(scoreboard.matches == 10000) - } - } -} diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimStreamWidthAdapterTester.scala b/tester/src/test/scala/spinal/tester/scalatest/SpinalSimStreamWidthAdapterTester.scala deleted file mode 100644 index ae5f50e448..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimStreamWidthAdapterTester.scala +++ /dev/null @@ -1,476 +0,0 @@ -package spinal.tester.scalatest - -import org.scalatest.funsuite.AnyFunSuite -import spinal.core._ -import spinal.lib._ -import spinal.sim._ -import spinal.core.sim._ -import spinal.lib.StreamWidthAdapter -import spinal.lib.sim._ -import spinal.tester - -import scala.collection.mutable -import scala.util.Random - -class SpinalSimStreamWidthAdapterTester extends SpinalSimFunSuite { - test("test2xOut") { - //Compile the simulator - val baseWidth = 32 - val compiled = SimConfig.allOptimisation.compile(rtl = new Component{ - val input = slave Stream(UInt(baseWidth bits)) - val output = master Stream(UInt(baseWidth*2 bits)) - val rtl = StreamWidthAdapter(input, output) - } - ) - - //Run the simulation - compiled.doSimUntilVoid { dut => - val queueModel = mutable.Queue[BigInt]() - - SimTimeout(1000000 * 8) - dut.clockDomain.forkStimulus(2) - - val driver = StreamDriver(dut.input, dut.clockDomain) { _ => - true - } - val inMonitor = StreamMonitor(dut.input, dut.clockDomain) { p => - queueModel.enqueue(p.toBigInt) - } - - val ready = StreamReadyRandomizer(dut.output, dut.clockDomain) - val outMonitor = StreamMonitor(dut.output, dut.clockDomain) { p => - assert(queueModel.nonEmpty) - val low = queueModel.dequeue() - assert(queueModel.nonEmpty) - val high = queueModel.dequeue() - val value = (high << baseWidth) + low - assert(p.toBigInt == value) - } - - dut.clockDomain.waitSampling(10000) - simSuccess() - } - } - - test("test2xIn") { - //Compile the simulator - val baseWidth = 32 - val compiled = SimConfig.allOptimisation.compile(rtl = new Component{ - val input = slave Stream(UInt(baseWidth*2 bits)) - val output = master Stream(UInt(baseWidth bits)) - val rtl = StreamWidthAdapter(input, output) - } - ) - - //Run the simulation - compiled.doSimUntilVoid { dut => - val inQueue = mutable.Queue[BigInt]() - val lowQueue = mutable.Queue[BigInt]() - val highQueue = mutable.Queue[BigInt]() - - SimTimeout(1000000 * 8) - dut.clockDomain.forkStimulus(2) - def check(){ - if(inQueue.nonEmpty && lowQueue.nonEmpty && highQueue.nonEmpty){ - val low = lowQueue.dequeue() - val high = highQueue.dequeue() - val value = (high << baseWidth) + low - assert(inQueue.dequeue() == value) - } - } - - val driver = StreamDriver(dut.input, dut.clockDomain) { p => - true - } - val inMonitor = StreamMonitor(dut.input, dut.clockDomain) { p => - inQueue.enqueue(p.toBigInt) - check() - } - - val ready = StreamReadyRandomizer(dut.output, dut.clockDomain) - val outMonitor = StreamMonitor(dut.output, dut.clockDomain) { p => - if (lowQueue.length <= highQueue.length){ - lowQueue.enqueue(p.toBigInt) - } else { - highQueue.enqueue(p.toBigInt) - } - check() - } - - dut.clockDomain.waitSampling(10000) - simSuccess() - } - } - - test("test2xOutHighFirst") { - //Compile the simulator - val baseWidth = 32 - val compiled = SimConfig.allOptimisation.compile(rtl = new Component{ - val input = slave Stream(UInt(baseWidth bits)) - val output = master Stream(UInt(baseWidth*2 bits)) - val rtl = StreamWidthAdapter(input, output, order = HIGHER_FIRST) - } - ) - - //Run the simulation - compiled.doSimUntilVoid { dut => - val queueModel = mutable.Queue[BigInt]() - - SimTimeout(1000000 * 8) - dut.clockDomain.forkStimulus(2) - - val driver = StreamDriver(dut.input, dut.clockDomain) { _ => - true - } - val inMonitor = StreamMonitor(dut.input, dut.clockDomain) { p => - queueModel.enqueue(p.toBigInt) - } - - val ready = StreamReadyRandomizer(dut.output, dut.clockDomain) - val outMonitor = StreamMonitor(dut.output, dut.clockDomain) { p => - assert(queueModel.nonEmpty) - val high = queueModel.dequeue() - assert(queueModel.nonEmpty) - val low = queueModel.dequeue() - val value = (high << baseWidth) + low - assert(p.toBigInt == value) - } - - dut.clockDomain.waitSampling(10000) - simSuccess() - } - } - - test("test2xInHighFirst") { - //Compile the simulator - val baseWidth = 32 - val compiled = SimConfig.allOptimisation.compile(rtl = new Component{ - val input = slave Stream(UInt(baseWidth*2 bits)) - val output = master Stream(UInt(baseWidth bits)) - val rtl = StreamWidthAdapter(input, output, order = HIGHER_FIRST) - } - ) - - //Run the simulation - compiled.doSimUntilVoid { dut => - val inQueue = mutable.Queue[BigInt]() - val lowQueue = mutable.Queue[BigInt]() - val highQueue = mutable.Queue[BigInt]() - - SimTimeout(1000000 * 8) - dut.clockDomain.forkStimulus(2) - def check(){ - if(inQueue.nonEmpty && lowQueue.nonEmpty && highQueue.nonEmpty){ - val low = lowQueue.dequeue() - val high = highQueue.dequeue() - val value = (high << baseWidth) + low - assert(inQueue.dequeue() == value) - } - } - - val driver = StreamDriver(dut.input, dut.clockDomain) { p => - true - } - val inMonitor = StreamMonitor(dut.input, dut.clockDomain) { p => - inQueue.enqueue(p.toBigInt) - check() - } - - val ready = StreamReadyRandomizer(dut.output, dut.clockDomain) - val outMonitor = StreamMonitor(dut.output, dut.clockDomain) { p => - if (lowQueue.length > highQueue.length){ - lowQueue.enqueue(p.toBigInt) - } else { - highQueue.enqueue(p.toBigInt) - } - check() - } - - dut.clockDomain.waitSampling(10000) - simSuccess() - } - } - - test("test2xOutWithNegPadding") { - //Compile the simulator - val baseWidth = 16 - val extraWidth = -2 - val compiled = SimConfig.allOptimisation.compile(rtl = new Component{ - val input = slave Stream(UInt(baseWidth bits)) - val output = master Stream(UInt(baseWidth*2+extraWidth bits)) - val rtl = StreamWidthAdapter(input, output, padding=true) - } - ) - - //Run the simulation - compiled.doSimUntilVoid { dut => - val queueModel = mutable.Queue[BigInt]() - - SimTimeout(1000000 * 8) - dut.clockDomain.forkStimulus(2) - - val driver = StreamDriver(dut.input, dut.clockDomain) { _ => - true - } - val inMonitor = StreamMonitor(dut.input, dut.clockDomain) { p => - queueModel.enqueue(p.toBigInt) - } - - val ready = StreamReadyRandomizer(dut.output, dut.clockDomain) - val outMonitor = StreamMonitor(dut.output, dut.clockDomain) { p => - assert(queueModel.nonEmpty) - val low = queueModel.dequeue() - assert(queueModel.nonEmpty) - val high = queueModel.dequeue() - val mask = ((BigInt(1) << dut.output.payload.getBitsWidth) - 1) - val value = ((high << baseWidth) + low) & mask - assert(p.toBigInt == value) - } - - dut.clockDomain.waitSampling(10000) - simSuccess() - } - } - - test("test2xInWithNegPadding") { - //Compile the simulator - val baseWidth = 16 - val extraWidth = -2 - val compiled = SimConfig.allOptimisation.compile(rtl = new Component{ - val input = slave Stream(UInt(baseWidth*2+extraWidth bits)) - val output = master Stream(UInt(baseWidth bits)) - val rtl = StreamWidthAdapter(input, output, padding=true) - } - ) - - //Run the simulation - compiled.doSimUntilVoid { dut => - val inQueue = mutable.Queue[BigInt]() - val lowQueue = mutable.Queue[BigInt]() - val highQueue = mutable.Queue[BigInt]() - - SimTimeout(1000000 * 8) - dut.clockDomain.forkStimulus(2) - def check(){ - if(inQueue.nonEmpty && lowQueue.nonEmpty && highQueue.nonEmpty){ - val low = lowQueue.dequeue() - val high = highQueue.dequeue() - val value = (high << baseWidth) + low - assert(inQueue.dequeue() == value) - } - } - - val driver = StreamDriver(dut.input, dut.clockDomain) { p => - true - } - val inMonitor = StreamMonitor(dut.input, dut.clockDomain) { p => - inQueue.enqueue(p.toBigInt) - check() - } - - val ready = StreamReadyRandomizer(dut.output, dut.clockDomain) - val outMonitor = StreamMonitor(dut.output, dut.clockDomain) { p => - if (lowQueue.length <= highQueue.length){ - lowQueue.enqueue(p.toBigInt) - } else { - highQueue.enqueue(p.toBigInt) - } - check() - } - - dut.clockDomain.waitSampling(10000) - simSuccess() - } - } - - test("test2xInWithPosPadding") { - //Compile the simulator - val baseWidth = 16 - val extraWidth = 2 - val compiled = SimConfig.allOptimisation.compile(rtl = new Component{ - val input = slave Stream(UInt(baseWidth*2+extraWidth bits)) - val output = master Stream(UInt(baseWidth bits)) - val rtl = StreamWidthAdapter(input, output, padding=true) - } - ) - - //Run the simulation - compiled.doSimUntilVoid { dut => - val inQueue = mutable.Queue[BigInt]() - val lowQueue = mutable.Queue[BigInt]() - val midQueue = mutable.Queue[BigInt]() - val highQueue = mutable.Queue[BigInt]() - - SimTimeout(1000000 * 8) - dut.clockDomain.forkStimulus(2) - def check(){ - if(inQueue.nonEmpty && lowQueue.nonEmpty && midQueue.nonEmpty && highQueue.nonEmpty){ - val low = lowQueue.dequeue() - val mid = midQueue.dequeue() - val high = highQueue.dequeue() - val value = (high << baseWidth*2) + (mid << baseWidth) + low - assert(inQueue.dequeue() == value) - } - } - - val driver = StreamDriver(dut.input, dut.clockDomain) { p => - true - } - val inMonitor = StreamMonitor(dut.input, dut.clockDomain) { p => - inQueue.enqueue(p.toBigInt) - check() - } - - val ready = StreamReadyRandomizer(dut.output, dut.clockDomain) - val outMonitor = StreamMonitor(dut.output, dut.clockDomain) { p => - if (lowQueue.isEmpty || lowQueue.length < midQueue.length){ - lowQueue.enqueue(p.toBigInt) - } else if (midQueue.isEmpty || midQueue.length < highQueue.length){ - midQueue.enqueue(p.toBigInt) - } else { - highQueue.enqueue(p.toBigInt) - } - check() - } - - dut.clockDomain.waitSampling(10000) - simSuccess() - } - } - - test("test2xOutWithPosPadding") { - //Compile the simulator - val baseWidth = 16 - val extraWidth = 2 - val compiled = SimConfig.allOptimisation.compile(rtl = new Component{ - val input = slave Stream(UInt(baseWidth bits)) - val output = master Stream(UInt(baseWidth*2+extraWidth bits)) - val rtl = StreamWidthAdapter(input, output, padding=true) - } - ) - - //Run the simulation - compiled.doSimUntilVoid { dut => - val queueModel = mutable.Queue[BigInt]() - - SimTimeout(1000000 * 8) - dut.clockDomain.forkStimulus(2) - - val driver = StreamDriver(dut.input, dut.clockDomain) { _ => - true - } - val inMonitor = StreamMonitor(dut.input, dut.clockDomain) { p => - queueModel.enqueue(p.toBigInt) - } - - val ready = StreamReadyRandomizer(dut.output, dut.clockDomain) - val outMonitor = StreamMonitor(dut.output, dut.clockDomain) { p => - assert(queueModel.nonEmpty) - val low = queueModel.dequeue() - assert(queueModel.nonEmpty) - val mid = queueModel.dequeue() - assert(queueModel.nonEmpty) - val high = queueModel.dequeue() - val mask = ((BigInt(1) << dut.output.payload.getBitsWidth) - 1) - val value = ((high << baseWidth*2) + (mid << baseWidth) + low) & mask - assert(p.toBigInt == value) - } - - dut.clockDomain.waitSampling(10000) - simSuccess() - } - } - - test("test2xOutHighFirstPadding") { - //Compile the simulator - val baseWidth = 32 - val extraWidth = -2 - val compiled = SimConfig.allOptimisation.compile(rtl = new Component{ - val input = slave Stream(UInt(baseWidth bits)) - val output = master Stream(UInt(baseWidth*2+extraWidth bits)) - val rtl = StreamWidthAdapter(input, output, order = HIGHER_FIRST, padding=true) - } - ) - - //Run the simulation - compiled.doSimUntilVoid { dut => - val queueModel = mutable.Queue[BigInt]() - - SimTimeout(1000000 * 8) - dut.clockDomain.forkStimulus(2) - - val driver = StreamDriver(dut.input, dut.clockDomain) { _ => - true - } - val inMonitor = StreamMonitor(dut.input, dut.clockDomain) { p => - queueModel.enqueue(p.toBigInt) - } - - val ready = StreamReadyRandomizer(dut.output, dut.clockDomain) - val outMonitor = StreamMonitor(dut.output, dut.clockDomain) { p => - assert(queueModel.nonEmpty) - val high = queueModel.dequeue() - assert(queueModel.nonEmpty) - val low = queueModel.dequeue() - val mask = ((BigInt(1) << dut.output.payload.getBitsWidth) - 1) - val value = ((high << baseWidth) + low) & mask - assert(p.toBigInt == value) - } - - dut.clockDomain.waitSampling(10000) - simSuccess() - } - } - - test("test2xInHighFirstPadding") { - //Compile the simulator - val baseWidth = 32 - val extraWidth = -2 - val compiled = SimConfig.allOptimisation.compile(rtl = new Component{ - val input = slave Stream(UInt(baseWidth*2+extraWidth bits)) - val output = master Stream(UInt(baseWidth bits)) - val rtl = StreamWidthAdapter(input, output, order = HIGHER_FIRST, padding=true) - } - ) - - //Run the simulation - compiled.doSimUntilVoid { dut => - val inQueue = mutable.Queue[BigInt]() - val lowQueue = mutable.Queue[BigInt]() - val highQueue = mutable.Queue[BigInt]() - - SimTimeout(1000000 * 8) - dut.clockDomain.forkStimulus(2) - def check(){ - if(inQueue.nonEmpty && lowQueue.nonEmpty && highQueue.nonEmpty){ - val low = lowQueue.dequeue() - val high = highQueue.dequeue() - val mask = ((BigInt(1) << dut.output.payload.getBitsWidth) - 1) - val value = ((high << baseWidth) + low) & mask - assert(inQueue.dequeue() == value) - } - } - - val driver = StreamDriver(dut.input, dut.clockDomain) { p => - true - } - val inMonitor = StreamMonitor(dut.input, dut.clockDomain) { p => - inQueue.enqueue(p.toBigInt) - check() - } - - val ready = StreamReadyRandomizer(dut.output, dut.clockDomain) - val outMonitor = StreamMonitor(dut.output, dut.clockDomain) { p => - if (lowQueue.length > highQueue.length){ - lowQueue.enqueue(p.toBigInt) - } else { - highQueue.enqueue(p.toBigInt) - } - check() - } - - dut.clockDomain.waitSampling(10000) - simSuccess() - } - } -} diff --git a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimUsbTester.scala b/tester/src/test/scala/spinal/tester/scalatest/SpinalSimUsbTester.scala deleted file mode 100644 index 702e444ae0..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/SpinalSimUsbTester.scala +++ /dev/null @@ -1,64 +0,0 @@ -package spinal.tester.scalatest - -import org.scalatest.funsuite.AnyFunSuite -import spinal.core._ -import spinal.core.sim._ -import spinal.lib._ -import spinal.lib.com.eth._ -import spinal.lib.com.usb.phy.{UsbHubLsFs, UsbLsFsPhy} -import spinal.lib.sim.{StreamDriver, StreamMonitor, StreamReadyRandomizer} - -import scala.collection.mutable -import scala.util.Random - -class SpinalSimUsbTester extends AnyFunSuite{ -// implicit class UsbLsFsCtrlPimper(self : UsbHubLsFs.Ctrl)(implicit cd : ClockDomain){ -// def init(): Unit = { -// self.tx.kind #= UsbHubLsFs.TxKind.NONE -// cd.waitSampling(10) -// } -// -// def issue(cmd : UsbHubLsFs.TxKind.E): Unit ={ -// self.tx.kind #= cmd -// cd.waitSamplingWhere(self.tx.ready.toBoolean) -// self.tx.kind #= UsbHubLsFs.TxKind.NONE -// } -// -// def reset(): Unit ={ -// issue(UsbHubLsFs.TxKind.RESET) -// } -// def suspend(): Unit ={ -// issue(UsbHubLsFs.TxKind.SUSPEND) -// } -// def resume(): Unit ={ -// issue(UsbHubLsFs.TxKind.RESUME) -// } -// def packet(bytes : Seq[Int]): Unit ={ -// for((byte, i) <- bytes.zipWithIndex) { -// self.tx.data #= byte -// self.tx.last #= i == bytes.length-1 -// issue(UsbHubLsFs.TxKind.PACKET) -// } -// } -// -// } - -// test("UsbLsFsPhy"){ -// SimConfig.withFstWave.compile(UsbLsFsPhy(4)).doSim{dut => -// implicit val cd = dut.clockDomain -// cd.forkStimulus(20833) -// -// dut.io.ctrl.fullSpeed #= true -// dut.io.ctrl.init() -// dut.io.ctrl.reset() -// cd.waitSampling(100) -// dut.io.ctrl.suspend() -// cd.waitSampling(100) -// dut.io.ctrl.resume() -// cd.waitSampling(100) -// dut.io.ctrl.packet(List(0x00, 0xAA, 0xAA, 0x55, 0x55, 0x00, 0xFF, 0xFF)) -// dut.io.ctrl.packet(List(0x00, 0xAA, 0xAA, 0x55, 0x55, 0x00, 0xFF, 0xFF)) -// cd.waitSampling(100) -// } -// } -} diff --git a/tester/src/test/scala/spinal/tester/scalatest/StreamTester.scala b/tester/src/test/scala/spinal/tester/scalatest/StreamTester.scala deleted file mode 100644 index 115fec4dae..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/StreamTester.scala +++ /dev/null @@ -1,90 +0,0 @@ -package spinal.tester.scalatest - -import spinal.core._ -import spinal.lib._ - - -object StreamTester{ - case class BundleA(aaa : Int) extends Bundle{ - val a = UInt(8 bit) - val b = Bool() - } -} - -import spinal.tester.scalatest.StreamTester._ - -class StreamTester extends Component { - val io = new Bundle { - val slave0 = slave Stream new BundleA(8) - val master0 = master Stream new BundleA(8) - val fifo0_occupancy = out UInt() - } - - val fifo0 = new StreamFifo(new BundleA(8),16) - fifo0.io.push << io.slave0 - fifo0.io.pop >/-> io.master0 - io.fifo0_occupancy := fifo0.io.occupancy - - assert(3 == LatencyAnalysis(io.slave0.a,io.master0.a)) - assert(2 == LatencyAnalysis(io.master0.ready,io.slave0.ready)) - - - - val forkInput = slave Stream(Bits(8 bits)) - val forkOutputs = Vec(master Stream(Bits(8 bits)),3) - (forkOutputs , StreamFork(forkInput,3)).zipped.foreach(_ << _) - - val dispatcherInOrderInput = slave Stream(Bits(8 bits)) - val dispatcherInOrderOutputs = Vec(master Stream(Bits(8 bits)),3) - (dispatcherInOrderOutputs , StreamDispatcherSequencial(dispatcherInOrderInput,3)).zipped.foreach(_ << _) - - val streamFlowArbiterInputStream = slave Stream(Bits(8 bits)) - val streamFlowArbiterInputFlow = slave Flow(Bits(8 bits)) - val streamFlowArbiterOutput = master Flow(Bits(8 bits)) - streamFlowArbiterOutput << StreamFlowArbiter(streamFlowArbiterInputStream,streamFlowArbiterInputFlow) - - val arbiterInOrderInputs = Vec(slave Stream(Bits(8 bits)),3) - val arbiterInOrderOutput = master Stream(Bits(8 bits)) - arbiterInOrderOutput << StreamArbiterFactory.sequentialOrder.on(arbiterInOrderInputs) - - val arbiterLowIdPortFirstInputs = Vec(slave Stream(Bits(8 bits)),3) - val arbiterLowIdPortFirstOutput = master Stream(Bits(8 bits)) - arbiterLowIdPortFirstOutput << StreamArbiterFactory.lowerFirst.on(arbiterLowIdPortFirstInputs) - - val arbiterRoundRobinInputs = Vec(slave Stream(Bits(8 bits)),3) - val arbiterRoundRobinOutput = master Stream(Bits(8 bits)) - arbiterRoundRobinOutput << StreamArbiterFactory.roundRobin.on(arbiterRoundRobinInputs) - - - val arbiterLowIdPortFirstNoLockInputs = Vec(slave Stream(Bits(8 bits)),3) - val arbiterLowIdPortFirstNoLockOutput = master Stream(Bits(8 bits)) - arbiterLowIdPortFirstNoLockOutput << StreamArbiterFactory.lowerFirst.noLock.on(arbiterLowIdPortFirstNoLockInputs) - - val arbiterLowIdPortFirstFragmentLockInputs = Vec(slave Stream(Fragment(Bits(8 bits))),3) - val arbiterLowIdPortFirstFragmentLockOutput = master Stream(Fragment(Bits(8 bits))) - arbiterLowIdPortFirstFragmentLockOutput << StreamArbiterFactory.lowerFirst.fragmentLock.on(arbiterLowIdPortFirstFragmentLockInputs) - - - // val muxSelect = in UInt(2 bits) -// val muxInputs = Vec(slave Stream(Bits(8 bits)),3) -// val muxOutput = master Stream(Bits(8 bits)) -// muxOutput << StreamMux(muxSelect,muxInputs) - -// val joinInputs = Vec(slave Stream(Bits(8 bits)),3) -// val joinOutput = master.Event -// joinOutput << StreamJoin(joinInputs) -} - - - -class StreamTesterGhdlBoot extends SpinalTesterGhdlBase { - override def getName: String = "StreamTester" - override def createToplevel: Component = new StreamTester -} - -class StreamTesterCocotbBoot extends SpinalTesterCocotbBase { - override def getName: String = "StreamTester" - override def pythonTestLocation: String = "tester/src/test/python/spinal/StreamTester" - override def createToplevel: Component = new StreamTester - override def noVhdl = true -} \ No newline at end of file diff --git a/tester/src/test/scala/spinal/tester/scalatest/StreamTester2.scala b/tester/src/test/scala/spinal/tester/scalatest/StreamTester2.scala deleted file mode 100644 index 27ed578d61..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/StreamTester2.scala +++ /dev/null @@ -1,42 +0,0 @@ -package spinal.tester.scalatest - -import spinal.core._ -import spinal.lib._ - - -object StreamTester2 { - case class BundleA() extends Bundle{ - val a = UInt(8 bit) - val b = Bool() - } - - class StreamTester2 extends Component{ - val fifoA = new StreamFifo(BundleA(),16) - val fifoAPush = slave(cloneOf(fifoA.io.push)) - val fifoAPop = master(cloneOf(fifoA.io.pop)) - val fifoAOccupancy = out(cloneOf(fifoA.io.occupancy)) - fifoA.io.push << fifoAPush - fifoA.io.pop >> fifoAPop - fifoA.io.occupancy <> fifoAOccupancy - assert(2 == LatencyAnalysis(fifoAPush.a,fifoAPop.a)) - assert(1 == LatencyAnalysis(fifoAPop.ready,fifoAPush.ready)) - - - val fifoB = new StreamFifoLowLatency(BundleA(),16) - val fifoBPush = slave(cloneOf(fifoB.io.push)) - val fifoBPop = master(cloneOf(fifoB.io.pop)) - val fifoBOccupancy = out(cloneOf(fifoB.io.occupancy)) - fifoB.io.push << fifoBPush - fifoB.io.pop >> fifoBPop - fifoB.io.occupancy <> fifoBOccupancy - assert(0 == LatencyAnalysis(fifoBPush.a,fifoBPop.a)) - assert(1 == LatencyAnalysis(fifoBPop.ready,fifoBPush.ready)) - } -} - -class StreamTester2CocotbBoot extends SpinalTesterCocotbBase { - override def getName: String = "StreamTester2" - override def pythonTestLocation: String = "tester/src/test/python/spinal/StreamTester2" - override def createToplevel: Component = new StreamTester2.StreamTester2 - override def backendConfig(config: SpinalConfig): SpinalConfig = config -} \ No newline at end of file diff --git a/tester/src/test/scala/spinal/tester/scalatest/VerilatorCacheTester.scala b/tester/src/test/scala/spinal/tester/scalatest/VerilatorCacheTester.scala deleted file mode 100644 index 3fe59413d8..0000000000 --- a/tester/src/test/scala/spinal/tester/scalatest/VerilatorCacheTester.scala +++ /dev/null @@ -1,198 +0,0 @@ -package spinal.tester.scalatest - -import org.scalatest.funsuite.AnyFunSuite -import spinal.core._ -import spinal.core.sim._ - -import java.io.File -import org.apache.commons.io.FileUtils -import spinal.lib.Delay - -import java.io.PrintStream - - -object VerilatorCacheTester { - case class ComponentA(n: Int, x: BigInt) extends Component { - val io = new Bundle { - val x = out Bits(n bits) - val something = in Bits(n bits) - val dummy = out Bits(n bits) - } - - io.x := x - - io.dummy := Delay(io.something, 4000) - } - - - class VerilatorCacheUsedChecker(out: PrintStream) extends PrintStream(out) { - var verilatorCompilationRunning = false - var verilatorCompilationDone = false - var verilatorCacheUsed = false - - def reset(): Unit = { - verilatorCompilationRunning = false - verilatorCompilationDone = false - verilatorCacheUsed = false - } - - def test(shouldUseCache: Boolean): Unit = { - assert(verilatorCompilationRunning == false, "Verilator compilation should not be running now") - assert(verilatorCompilationDone == true, "Verilator compilation should be done now") - - if (shouldUseCache) { - assert(verilatorCacheUsed == true, "Verilator cache not used but it should be used") - } else { - assert(verilatorCacheUsed == false, "Verilator cache used but it should not be used") - } - } - - override def println(x: Any): Unit = { - if (x.isInstanceOf[String]) { - val str = x.asInstanceOf[String] - - if (str == "[Progress] Verilator compilation started") { - verilatorCompilationRunning = true - verilatorCompilationDone = false - verilatorCacheUsed = false - } else if (str.startsWith("[Progress] Verilator compilation done in ")) { - verilatorCompilationRunning = false - verilatorCompilationDone = true - } - - if (verilatorCompilationRunning) { - if (str == "[info] Found cached verilator binaries") { - verilatorCacheUsed = true - } - } - - super.println(x) - } else { - super.println(x) - } - } - } -} - -class VerilatorCacheTester extends AnyFunSuite { - import VerilatorCacheTester._ - - val cacheDir = new File(SimConfig._workspacePath + "/.cache_cachetest") - - def deleteCache(): Unit = { - if (cacheDir.exists()) { - FileUtils.forceDelete(cacheDir) - } - } - - def testComponentA(verilatorCacheUsedChecker: VerilatorCacheUsedChecker, n: Int, x: BigInt, shouldUseCache: Boolean, disableCache: Boolean = false, maxCacheEntries: Int = -1, waveDepth: Int = -1): Long = { - var cfg = SimConfig.cachePath(cacheDir.getAbsolutePath()) - if (disableCache) cfg = cfg.disableCache - if (maxCacheEntries >= 0) cfg = cfg.maxCacheEntries(maxCacheEntries) - if (waveDepth >= 0) cfg = cfg.withWave(waveDepth) - - verilatorCacheUsedChecker.reset() - - val tStart = System.nanoTime() - cfg.compile(ComponentA(n, x)).doSim(dut => assert(dut.io.x.toBigInt == x)) - val duration = System.nanoTime()-tStart - - verilatorCacheUsedChecker.test(shouldUseCache) - - duration - } - - test("verilator cache") { - deleteCache() - - var durationWithoutCacheTotal: Double = 0 - var durationWithoutCacheCount = 0 - - var durationWithCacheTotal: Double = 0 - var durationWithCacheCount = 0 - - val verilatorCacheUsedChecker = new VerilatorCacheUsedChecker(Console.out) - Console.withOut(verilatorCacheUsedChecker) { - // first compilation with cache disabled - durationWithoutCacheTotal += testComponentA(verilatorCacheUsedChecker, n=3, x=0, shouldUseCache=false, disableCache=true) - durationWithoutCacheCount += 1 - - // first compilation with cache enabled - durationWithoutCacheTotal += testComponentA(verilatorCacheUsedChecker, n=3, x=0, shouldUseCache=false) - durationWithoutCacheCount += 1 - - // now cache should be used - durationWithCacheTotal += testComponentA(verilatorCacheUsedChecker, n=3, x=0, shouldUseCache=true) - durationWithCacheCount += 1 - - // nothing changed, cache should be used again - durationWithCacheTotal += testComponentA(verilatorCacheUsedChecker, n=3, x=0, shouldUseCache=true) - durationWithCacheCount += 1 - - // change component, should not use cache - durationWithoutCacheTotal += testComponentA(verilatorCacheUsedChecker, n=3, x=1, shouldUseCache=false) - durationWithoutCacheCount += 1 - - // now the cache should be used again - durationWithCacheTotal += testComponentA(verilatorCacheUsedChecker, n=3, x=1, shouldUseCache=true) - durationWithCacheCount += 1 - - // nothing changed, cache should be used again - durationWithCacheTotal += testComponentA(verilatorCacheUsedChecker, n=3, x=1, shouldUseCache=true) - durationWithCacheCount += 1 - - // cache disabled, cache should not be used - durationWithoutCacheTotal += testComponentA(verilatorCacheUsedChecker, n=3, x=1, shouldUseCache=false, disableCache=true) - durationWithoutCacheCount += 1 - - // cache reenabled, cache should be used - durationWithCacheTotal += testComponentA(verilatorCacheUsedChecker, n=3, x=1, shouldUseCache=true) - durationWithCacheCount += 1 - - // restore previous component configuration, should use cache - durationWithCacheTotal += testComponentA(verilatorCacheUsedChecker, n=3, x=0, shouldUseCache=true) - durationWithCacheCount += 1 - - // 2 cache entries used till now, should not use cache and generate 2 new cache entries - durationWithoutCacheTotal += testComponentA(verilatorCacheUsedChecker, n=4, x=0, shouldUseCache=false, maxCacheEntries=4) - durationWithoutCacheTotal += testComponentA(verilatorCacheUsedChecker, n=4, x=1, shouldUseCache=false, maxCacheEntries=4) - durationWithoutCacheCount += 2 - - // 4 (=max) cache entries used, should use cache - durationWithCacheTotal += testComponentA(verilatorCacheUsedChecker, n=3, x=0, shouldUseCache=true, maxCacheEntries=4) - Thread.sleep(1100) // ensure different timestamps - durationWithCacheTotal += testComponentA(verilatorCacheUsedChecker, n=3, x=1, shouldUseCache=true, maxCacheEntries=4) - Thread.sleep(1100) // ensure different timestamps - durationWithCacheTotal += testComponentA(verilatorCacheUsedChecker, n=4, x=0, shouldUseCache=true, maxCacheEntries=4) - Thread.sleep(1100) // ensure different timestamps - durationWithCacheTotal += testComponentA(verilatorCacheUsedChecker, n=4, x=1, shouldUseCache=true, maxCacheEntries=4) - Thread.sleep(1100) // ensure different timestamps - durationWithCacheCount += 4 - - // 4 (=max) cache entries used, new configuration, should not use cache - durationWithoutCacheTotal += testComponentA(verilatorCacheUsedChecker, n=4, x=2, shouldUseCache=false, maxCacheEntries=4) - durationWithoutCacheCount += 1 - - // cache entry deleted in previous test, should not use cache - durationWithoutCacheTotal += testComponentA(verilatorCacheUsedChecker, n=3, x=0, shouldUseCache=false, maxCacheEntries=5) - durationWithoutCacheCount += 1 - - // other cache entries (+ new cache entry) should not have been deleted, should use cache - durationWithCacheTotal += testComponentA(verilatorCacheUsedChecker, n=3, x=1, shouldUseCache=true, maxCacheEntries=5) - durationWithCacheTotal += testComponentA(verilatorCacheUsedChecker, n=4, x=0, shouldUseCache=true, maxCacheEntries=5) - durationWithCacheTotal += testComponentA(verilatorCacheUsedChecker, n=4, x=1, shouldUseCache=true, maxCacheEntries=5) - durationWithCacheTotal += testComponentA(verilatorCacheUsedChecker, n=4, x=2, shouldUseCache=true, maxCacheEntries=5) - durationWithCacheCount += 4 - - // change sim config, should not use cache - durationWithoutCacheTotal += testComponentA(verilatorCacheUsedChecker, n=4, x=2, shouldUseCache=false, waveDepth=1) - durationWithoutCacheCount += 1 - } - - val durationWithoutCacheAvg = durationWithoutCacheTotal / durationWithoutCacheCount - val durationWithCacheAvg = durationWithCacheTotal / durationWithCacheCount - - assert(durationWithCacheAvg < durationWithoutCacheAvg, "Verilator compilation needs more time when using the cache") - } -} -