xref: /XiangShan/src/main/scala/xiangshan/backend/issue/NewAgeDetector.scala (revision 5db4956b8ea14332169fca361912b6eefd5d475f)
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 xiangshan.backend.issue
18
19import chipsalliance.rocketchip.config.Parameters
20import chisel3._
21import chisel3.util._
22import xiangshan._
23import utils._
24import utility._
25
26class NewAgeDetector(numEntries: Int, numEnq: Int, regOut: Boolean = true)(implicit p: Parameters) extends XSModule {
27  val io = IO(new Bundle {
28    val enq = Vec(numEnq, Input(Bool()))
29    val clear = Input(UInt(numEntries.W))
30    val out = Output(UInt(numEntries.W))
31  })
32
33  // age(i)(j): entry i enters queue before entry j
34  val age = Seq.fill(numEntries)(Seq.fill(numEntries)(RegInit(false.B)))
35  val nextAge = Seq.fill(numEntries)(Seq.fill(numEntries)(Wire(Bool())))
36
37  // to reduce reg usage, only use upper matrix
38  def get_age(row: Int, col: Int): Bool = if (row <= col) age(row)(col) else !age(col)(row)
39  def get_next_age(row: Int, col: Int): Bool = if (row <= col) nextAge(row)(col) else !nextAge(col)(row)
40  def isFlushed(i: Int): Bool = io.clear(i)
41
42  //only for row <= col
43  for((row, i) <- nextAge.zipWithIndex) {
44    for((elem, j) <- row.zipWithIndex) {
45      if (i <= j) {
46        when(io.enq(i)){
47          elem := io.enq(j) || isFlushed(j) || !get_age(j, j)
48        }.elsewhen(isFlushed(i)) {
49          elem := false.B
50        }.otherwise {
51          elem := (!io.enq(j) && !isFlushed(j) && get_age(i, j)) || (!io.enq(j) && isFlushed(j)) || (io.enq(j) && get_age(i, i))
52        }
53      } else {
54        elem := !nextAge(j)(i)
55      }
56      age(i)(j) := elem
57    }
58  }
59
60  def getOldest(get: (Int, Int) => Bool): UInt = {
61    VecInit((0 until numEntries).map(i => {
62      VecInit((0 until numEntries).map(j => get(i, j))).asUInt.andR
63    })).asUInt
64  }
65
66  val best = getOldest(get_age)
67  val nextBest = getOldest(get_next_age)
68
69  io.out := (if (regOut) best else nextBest)
70
71  val ageMatrix = VecInit(age.map(v => VecInit(v).asUInt.andR)).asUInt
72  val symmetricAge = RegNext(nextBest)
73  XSError(ageMatrix =/= symmetricAge, p"age error between ${Hexadecimal(ageMatrix)} and ${Hexadecimal(symmetricAge)}\n")
74}
75
76object NewAgeDetector {
77  def apply(numEntries: Int, enq: Vec[Bool], clear: Vec[Bool], canIssue: UInt)(implicit p: Parameters): Valid[UInt] = {
78    val age = Module(new NewAgeDetector(numEntries, enq.length, regOut = true))
79    age.io.enq := enq
80    age.io.clear := clear.asUInt
81    val out = Wire(Valid(UInt(clear.getWidth.W)))
82    out.valid := (canIssue & age.io.out).orR
83    out.bits := age.io.out
84    out
85  }
86}