-
Notifications
You must be signed in to change notification settings - Fork 616
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into cat-sourcelocators
- Loading branch information
Showing
2 changed files
with
130 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package chiselTests | ||
|
||
import chisel3._ | ||
import chisel3.util._ | ||
import chisel3.testers.BasicTester | ||
|
||
class Arbiter[T <: Data: Manifest](n: Int, private val gen: T) extends Module { | ||
val io = IO(new Bundle { | ||
val in = Flipped(Vec(n, new DecoupledIO(gen))) | ||
val out = new DecoupledIO(gen) | ||
}) | ||
|
||
def arbitrateTwo(a: DecoupledIO[T], b: DecoupledIO[T]) = { | ||
|
||
val idleA :: idleB :: hasA :: hasB :: Nil = Enum(4) | ||
val regData = Reg(gen) | ||
val regState = RegInit(idleA) | ||
val out = Wire(new DecoupledIO(gen)) | ||
|
||
a.ready := regState === idleA | ||
b.ready := regState === idleB | ||
out.valid := (regState === hasA || regState === hasB) | ||
|
||
switch(regState) { | ||
is(idleA) { | ||
when(a.valid) { | ||
regData := a.bits | ||
regState := hasA | ||
}.otherwise { | ||
regState := idleB | ||
} | ||
} | ||
is(idleB) { | ||
when(b.valid) { | ||
regData := b.bits | ||
regState := hasB | ||
}.otherwise { | ||
regState := idleA | ||
} | ||
} | ||
is(hasA) { | ||
when(out.ready) { | ||
regState := idleB | ||
} | ||
} | ||
is(hasB) { | ||
when(out.ready) { | ||
regState := idleA | ||
} | ||
} | ||
} | ||
|
||
out.bits := regData.asUInt + 1.U | ||
out | ||
} | ||
|
||
io.out <> io.in.reduceTree(arbitrateTwo) | ||
} | ||
|
||
class ReduceTreeBalancedTester(nodes: Int) extends BasicTester { | ||
|
||
val cnt = RegInit(0.U(8.W)) | ||
val min = RegInit(99.U(8.W)) | ||
val max = RegInit(0.U(8.W)) | ||
|
||
val dut = Module(new Arbiter(nodes, UInt(16.W))) | ||
for (i <- 0 until nodes) { | ||
dut.io.in(i).valid := true.B | ||
dut.io.in(i).bits := 0.U | ||
} | ||
dut.io.out.ready := true.B | ||
|
||
when(dut.io.out.valid) { | ||
val hops = dut.io.out.bits | ||
when(hops < min) { | ||
min := hops | ||
} | ||
when(hops > max) { | ||
max := hops | ||
} | ||
} | ||
|
||
when(!(max === 0.U || min === 99.U)) { | ||
assert(max - min <= 1.U) | ||
} | ||
|
||
cnt := cnt + 1.U | ||
when(cnt === 10.U) { | ||
stop() | ||
} | ||
} | ||
|
||
class ReduceTreeBalancedSpec extends ChiselPropSpec { | ||
property("Tree shall be fair and shall have a maximum difference of one hop for each node") { | ||
|
||
// This test will fail for 5 nodes due to an unbalanced tree. | ||
// A fix is on the way. | ||
for (n <- 1 to 5) { | ||
assertTesterPasses { | ||
new ReduceTreeBalancedTester(n) | ||
} | ||
} | ||
} | ||
} |