xref: /XiangShan/src/main/scala/utils/ArbiterHelper.scala (revision 8891a219bbc84f568e1d134854d8d5ed86d6d560)
1/***************************************************************************************
2* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
3* Copyright (c) 2020-2021 Peng Cheng Laboratory
4*
5* XiangShan is licensed under Mulan PSL v2.
6* You can use this software according to the terms and conditions of the Mulan PSL v2.
7* You may obtain a copy of Mulan PSL v2 at:
8*          http://license.coscl.org.cn/MulanPSL2
9*
10* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13*
14* See the Mulan PSL v2 for more details.
15***************************************************************************************/
16
17package utils
18
19import org.chipsalliance.cde.config.Parameters
20import chisel3._
21import chisel3.util._
22import xiangshan.cache._
23
24object ArbiterCtrl {
25  def apply(request: Seq[Bool]): Seq[Bool] = request.length match {
26    case 0 => Seq()
27    case 1 => Seq(true.B)
28    case _ => true.B +: request.tail.init.scanLeft(request.head)(_ || _).map(!_)
29  }
30}
31
32/** Hardware module that is used to sequence n producers into 1 consumer.
33  * Priority is given to lower producer.
34  * if any producer's cache block addr matches the one of chosen producer, the producer will be served
35  *
36  * @param gen data type, must have addr which indicates physical address
37  * @param n number of inputs
38  * @param offset_width cache line offset width
39  * @param paddr_bits how many bits in paddr
40  *
41  * @example {{{
42  * val arb = Module(new Arbiter(UInt(), 2))
43  * arb.io.in(0) <> producer0.io.out
44  * arb.io.in(1) <> producer1.io.out
45  * consumer.io.in <> arb.io.out
46  * }}}
47  */
48class ArbiterFilterByCacheLineAddr[T <: MissReqWoStoreData](val gen: T, val n: Int, val offset_width: Int, val paddr_bits: Int) extends Module{
49  val io = IO(new ArbiterIO(gen, n))
50
51  io.chosen := (n - 1).asUInt
52  io.out.bits := io.in(n - 1).bits
53  for (i <- n - 2 to 0 by -1) {
54    when(io.in(i).valid) {
55      io.chosen := i.asUInt
56      io.out.bits := io.in(i).bits
57    }
58  }
59
60  val grant = ArbiterCtrl(io.in.map(_.valid))
61  for ((in, g) <- io.in.zip(grant))
62    in.ready := (g || (in.bits.addr(paddr_bits - 1, offset_width) === io.out.bits.addr(paddr_bits - 1, offset_width))) && io.out.ready
63  io.out.valid := !grant.last || io.in.last.valid
64}
65