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