risc-v中文社区

 找回密码
 立即注册
查看: 1142|回复: 1

[原创] 仲裁器Arbiter(2)

[复制链接]

347

主题

564

帖子

2237

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
2237
发表于 2021-9-10 21:24:01 | 显示全部楼层 |阅读模式
//仲裁器的IO Bundle 用Vec(n,Decoupled(gen)表示有多个producer,Decoupled(gen)表示只有一个consummer,还有一个chosen选择指示索引
class ArbiterIO[T <: Data](private val gen: T, val n: Int) extends Bundle {
  // See github.com/freechipsproject/chisel3/issues/765 for why gen is a private val and proposed replacement APIs.

  val in  = Flipped(Vec(n, Decoupled(gen)))
  val out = Decoupled(gen)
  val chosen = Output(UInt(log2Ceil(n).W))
}
//检测哪一个producer被访问
private object ArbiterCtrl {
  def apply(request: Seq[Bool]): Seq[Bool] = request.length match {
    case 0 => Seq() //空
    case 1 => Seq(true.B) //元素个数是1则始终是true.B
    case _ => true.B +: request.tail.init.scanLeft(request.head)(_ || _).map(!_) //从head开始一直扫描到倒数第二个(最后一个不包括在内),在结果的最前面再加一个true.B,也就是说数量不变
        //head是true.B,则scalLeft(head)(_ || _)生成的Seq每个元素都是true.B,再map(!_)则全都是false.B,最终只有加进来的true.B才是true值
        //head是false.B,则scalLeft(head)(_ || _)生成的Seq第一个是false.B,第二个是第二个的值,第三个是前一个与本项的||,总结来说,从哪一个索引项的值为true开始,后面生成的Seq的所有项都是true
        //      当然,再map(!_)之后,从这项开始后面全都是false.B了
        //case _=>这句总结:第一项是true.B,Seq的最后一项不包括在内,Seq中从哪一个项的值为true.B开始(包括它在内),后面所有的项的值在最终生成的Seq中的值都是false.B
  }
}
class Arbiter[T <: Data](gen: T, n: Int) extends Module {
  val io = IO(new ArbiterIO(gen, n))

  io.chosen := (n-1).asUInt //默认选择n-1通道
  io.out.bits := io.in(n-1).bits //默认数据为n-1通道的数据
  for (i <- n-2 to 0 by -1) { //从n-2,n-3,n-4,...,2,1,0,从大到小
    when (io.in(i).valid) { //只要哪个producer的valid是true.B
      io.chosen := i.asUInt //io.chosen就选择这个索引,如果有多个,则最小序号的有效(因为多次:=,只有最后一个有效)
      io.out.bits := io.in(i).bits //本仲裁器模块的输出数据连到这个序号的producer的数据线(多个producer的valid有效时,最小序号的有效)
    }
  }

  private val grant = ArbiterCtrl(io.in.map(_.valid))//多个producer,其实也是Seq[T]类型,所以有map处理每个元素(每个元素的类型是DecoupledIO[T]即有valid,ready,bits),
  //_.valid 表示每个DecoupledIO[T]的valid信号。所以本句代码的作用是:调用ArbiterCtrl的apply方法,参数是仲裁器的多个producer的DecoupledIO[T]的valid信号值组成的Seq[Bool]
  for ((in, g) <- io.in zip grant) //所有的producer即Vec[DecoupledIO[T]] zip grant
    in.ready := g && io.out.ready //producer的ready信号 := 这个producer的valid && 下游发过来的ready信号(表示数据接收已准备好) 造成有可能没仲裁到它但在处理其它producer很长时间???
  io.out.valid := !grant.last || io.in.last.valid //模块输出valid := 所有producer的valid组成的Seq[Bool]的最小序号的值取反 || 各个producer组成的Vec的最小序号producer的valid
  //也就是说如果最小序号producer的valid是无效的,模块输出的valid就指数据输出有效
  //如果序号最小的producer的valid有效则模块输出的valid也指示有效
}

回复

使用道具 举报

347

主题

564

帖子

2237

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
2237
 楼主| 发表于 2021-9-10 21:26:04 | 显示全部楼层
测试代码:
class MyArbiterTester(m:MyArbiter[UInt]) extends PeekPokeTester(m) {
  poke(m.io.enq(0).valid,false)
  poke(m.io.enq(1).valid,false)
  poke(m.io.deq.ready,false)
  println(s"启动:")
  println(s"\tenq(0).ready=${peek(m.io.enq(0).ready)}, enq(1).ready=${peek(m.io.enq(1).ready)}")
  println(s"\tenq(0).valid=${peek(m.io.enq(0).valid)}, enq(1).ready=${peek(m.io.enq(1).valid)}")
  poke(m.io.enq(0).bits,18) //producer0的数据先输入在此,不变动
  poke(m.io.enq(1).valid,true) //producer1的valid有效
  poke(m.io.enq(1).bits,17)
  poke(m.io.deq.ready,true)  //下游发出ready
  println(s"producer1有效:")
  println(s"\tenq(0).ready=${peek(m.io.enq(0).ready)}, enq(1).ready=${peek(m.io.enq(1).ready)}")
  println(s"deq.valid=${peek(m.io.deq.valid)},deq.bits=${peek(m.io.deq.bits)}")
  poke(m.io.enq(0).valid,true)

  println(s"producer1和2都有效:")
  println(s"\tenq(0).ready=${peek(m.io.enq(0).ready)}, enq(1).ready=${peek(m.io.enq(1).ready)}")
  println(s"deq.valid=${peek(m.io.deq.valid)},deq.bits=${peek(m.io.deq.bits)}")
  poke(m.io.enq(1).valid,false)
  println(s"producer0有效:")
  println(s"\tenq(0).ready=${peek(m.io.enq(0).ready)}, enq(1).ready=${peek(m.io.enq(1).ready)}")
  println(s"deq.valid=${peek(m.io.deq.valid)},deq.bits=${peek(m.io.deq.bits)}")

}
class DownTickerSpec extends ChiselFlatSpec {
  "MyArbiter" should "pass" in {
    iotesters.Driver(()=>new MyArbiter(UInt(8.W),2))(t => new MyArbiterTester(t))
  }
}
显示如下:
[info] [0.003] 启动:
[info] [0.005]         enq(0).ready=0, enq(1).ready=0
[info] [0.005]         enq(0).valid=0, enq(1).ready=0
[info] [0.006] producer1有效:
[info] [0.007]         enq(0).ready=1, enq(1).ready=1
[info] [0.007] deq.valid=1,deq.bits=17
[info] [0.007] producer1和2都有效:
[info] [0.008]         enq(0).ready=1, enq(1).ready=0
[info] [0.009] deq.valid=1,deq.bits=18
[info] [0.009] producer0有效:
[info] [0.010]         enq(0).ready=1, enq(1).ready=0
[info] [0.011] deq.valid=1,deq.bits=18
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



Archiver|手机版|小黑屋|risc-v中文社区

GMT+8, 2024-5-3 09:44 , Processed in 0.017533 second(s), 17 queries .

risc-v中文社区论坛 官方网站

Copyright © 2018-2021, risc-v open source

快速回复 返回顶部 返回列表