Diplomacyを使ってOCPバスを作成している。OCP SRAMの動作を確認しつつ、OCPのDelayerを実装しようと思う。DelayerというのはバスのReady信号を遅らせて、信号を遅らせてバスの問題を検出するための機能だ。
TileLinkのDelayerはすでに実装されている。これはLFSRを使ってReady信号を遅らせる機構となっている。
chisel-hw/src/main/scala/ocp/Delayer.scala
def feed[T <: Data](sink: DecoupledIO[T], source: DecoupledIO[T], noise: T) { val allow = UInt((q * 65535.0).toInt) <= LFSRNoiseMaker(16, source.valid) sink.valid := source.valid && allow source.ready := sink.ready && allow sink.bits := source.bits when (!sink.valid) { sink.bits := noise } }
このfeed
関数を使ってOCPの3つのチャネルを接続する。Valid信号が立ち上がっていないときは、Noise信号を挿入してバスをわざと乱すことでデバッグを行う。
(node.in zip node.out) foreach { case ((in, _), (out, _)) => val cmd_noise = Wire(in.cmd.bits) cmd_noise.mcmd := LFSRNoiseMaker(3) cmd_noise.tagId := LFSRNoiseMaker(cmd_noise.params.tagidBits) cmd_noise.address := LFSRNoiseMaker(cmd_noise.params.addressBits) val data_noise = Wire(in.data.bits) data_noise.tagId := LFSRNoiseMaker(data_noise.params.tagidBits) data_noise.data := LFSRNoiseMaker(data_noise.params.dataBits) val resp_noise = Wire(out.resp.bits) resp_noise.tagId := LFSRNoiseMaker(resp_noise.params.tagidBits) resp_noise.data := LFSRNoiseMaker(resp_noise.params.dataBits) feed(out.cmd, in.cmd, cmd_noise) feed(out.data, in.data, data_noise) feed(in.resp, out.resp, resp_noise) }
これを使ってテストコードを作ってみよう。これまで通りMasterとSlaveの間にDelayerを挿入して、シミュレーションを実行してみる。
val pusher = LazyModule(new OCPPatternPusher("pat1", Seq( new WriteReqPattern(0x100, 0x2), new WriteDataPattern(0x012345678L), new WriteReqPattern(0x104, 0x2), new WriteDataPattern(0x0abcdef01L), new WriteReqPattern(0x108, 0x2), new WriteDataPattern(0x0deadbeefL), new WriteReqPattern(0x10c, 0x2), new WriteDataPattern(0x087654321L), new ReadExpectPattern(0x100, 0x2, 0x012345678L), new ReadExpectPattern(0x104, 0x2, 0x0abcdef01L), new ReadExpectPattern(0x108, 0x2, 0x0deadbeefL), new ReadExpectPattern(0x10c, 0x2, 0x087654321L) ))) val ram = LazyModule(new OCPRAM(AddressSet(0x0, 0x3ff))) ram.node := OCPDelayer(0.01) := pusher.node
シミュレーションを実行して波形を表示してみた。上手く動作しているようだ。
make tilelink CONFIG=OCPUnitDelayerTestConfig
./tilelink Started UnitTest OCPUnitDelayerTest Count = 1000 Resp Fired : same as expected. 12345678 Resp Fired : same as expected. abcdef01 Count = 2000 Resp Fired : same as expected. deadbeef Resp Fired : same as expected. 87654321