Rocket-Chipは、主にTileLinkとAXIバスによって記述されており、TileLinkがRocketChipに近い方、AXIが外部バスに出ていく方として記述されているのだけれども、AXI4のバスもChiselで書かれているようだ。 とりあえず見てみたが、正直なんだか良く分からない。Scala苦手だ。。。
こういうのを購入しないとダメかしら。
- 作者: Martin Odersky,Lex Spoon,Bill Venners,羽生田栄一,水島宏太,長尾高弘
- 出版社/メーカー: インプレス
- 発売日: 2016/09/20
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (1件) を見る
ChiselでのAXIバスの定義
GenericParameterizedBundle
というクラスを継承する形で定義されている。
abstract class GenericParameterizedBundle[+T <: Object](val params: T) extends Bundle { ...
例えば、AXIのAチャネルは以下のように定義されている。
abstract class AXI4BundleA(params: AXI4BundleParameters) extends AXI4BundleBase(params) { val id = UInt(width = params.idBits) val addr = UInt(width = params.addrBits) val len = UInt(width = params.lenBits) // number of beats - 1 val size = UInt(width = params.sizeBits) // bytes in beat = 2^size val burst = UInt(width = params.burstBits) val lock = UInt(width = params.lockBits) val cache = UInt(width = params.cacheBits) val prot = UInt(width = params.protBits) val qos = UInt(width = params.qosBits) // 0=no QoS, bigger = higher priority val user = if (params.userBits > 0) Some(UInt(width = params.userBits)) else None // val region = UInt(width = 4) // optional // Number of bytes-1 in this operation def bytes1(x:Int=0) = { val maxShift = 1 << params.sizeBits val tail = UInt((BigInt(1) << maxShift) - 1) (Cat(len, tail) << size) >> maxShift } }
次に、RegisterRouterというレジスタスライスの定義を見てみる。 regmapという定義がされており、どうやらこれが信号がレジスタそのものになっているようだ。
def regmap(mapping: RegField.Map*) = { val ar = bundleIn(0).ar val aw = bundleIn(0).aw val w = bundleIn(0).w val r = bundleIn(0).r val b = bundleIn(0).b val params = RegMapperParams(log2Up((address.mask+1)/beatBytes), beatBytes, ar.bits.params.idBits + ar.bits.params.userBits) val in = Wire(Decoupled(new RegMapperInput(params))) // Prefer to execute reads first in.valid := ar.valid || (aw.valid && w.valid) ar.ready := in.ready aw.ready := in.ready && !ar.valid && w .valid w .ready := in.ready && !ar.valid && aw.valid val ar_extra = Cat(Seq(ar.bits.id) ++ ar.bits.user.toList) val aw_extra = Cat(Seq(aw.bits.id) ++ aw.bits.user.toList) val in_extra = Mux(ar.valid, ar_extra, aw_extra) val addr = Mux(ar.valid, ar.bits.addr, aw.bits.addr) val mask = MaskGen(ar.bits.addr, ar.bits.size, beatBytes) in.bits.read := ar.valid in.bits.index := addr >> log2Ceil(beatBytes) in.bits.data := w.bits.data in.bits.mask := Mux(ar.valid, mask, w.bits.strb) in.bits.extra := in_extra // Invoke the register map builder and make it Irrevocable val out = Queue.irrevocable( RegMapper(beatBytes, concurrency, undefZero, in, mapping:_*), entries = 2) // No flow control needed out.ready := Mux(out.bits.read, r.ready, b.ready) r.valid := out.valid && out.bits.read b.valid := out.valid && !out.bits.read val out_id = if (r.bits.params.idBits == 0) UInt(0) else (out.bits.extra >> ar.bits.params.userBits) r.bits.id := out_id r.bits.data := out.bits.data r.bits.last := Bool(true) r.bits.resp := AXI4Parameters.RESP_OKAY r.bits.user.foreach { _ := out.bits.extra } b.bits.id := out_id b.bits.resp := AXI4Parameters.RESP_OKAY b.bits.user.foreach { _ := out.bits.extra } }