xref: /XiangShan/src/main/scala/xiangshan/backend/issue/AgeDetector.scala (revision 4243aa09225ffb7b71ce68fd9a01299dce92729c)
1124bf66aSXuan Hu/***************************************************************************************
2124bf66aSXuan Hu* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
3124bf66aSXuan Hu* Copyright (c) 2020-2021 Peng Cheng Laboratory
4124bf66aSXuan Hu*
5124bf66aSXuan Hu* XiangShan is licensed under Mulan PSL v2.
6124bf66aSXuan Hu* You can use this software according to the terms and conditions of the Mulan PSL v2.
7124bf66aSXuan Hu* You may obtain a copy of Mulan PSL v2 at:
8124bf66aSXuan Hu*          http://license.coscl.org.cn/MulanPSL2
9124bf66aSXuan Hu*
10124bf66aSXuan Hu* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11124bf66aSXuan Hu* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12124bf66aSXuan Hu* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13124bf66aSXuan Hu*
14124bf66aSXuan Hu* See the Mulan PSL v2 for more details.
15124bf66aSXuan Hu***************************************************************************************/
16124bf66aSXuan Hu
17124bf66aSXuan Hupackage xiangshan.backend.issue
18124bf66aSXuan Hu
194b0d80d8SXuan Huimport org.chipsalliance.cde.config.Parameters
20124bf66aSXuan Huimport chisel3._
21124bf66aSXuan Huimport chisel3.util._
22124bf66aSXuan Huimport xiangshan._
23124bf66aSXuan Huimport utils._
24124bf66aSXuan Huimport utility._
25124bf66aSXuan Hu
26527eefbdSsinsanctionclass AgeDetector(numEntries: Int, numEnq: Int, numDeq: Int)(implicit p: Parameters) extends XSModule {
27124bf66aSXuan Hu  val io = IO(new Bundle {
28cf4a131aSsinsanction    // NOTE: now we do not consider deq.
29cf4a131aSsinsanction    //       keeping these old invalid entries
30cf4a131aSsinsanction    //       does not affect the selection of the oldest entry that can be issued.
31124bf66aSXuan Hu    val enq = Vec(numEnq, Input(UInt(numEntries.W)))
32527eefbdSsinsanction    val canIssue = Vec(numDeq, Input(UInt(numEntries.W)))
33527eefbdSsinsanction    val out = Vec(numDeq, Output(UInt(numEntries.W)))
34124bf66aSXuan Hu  })
35124bf66aSXuan Hu
36124bf66aSXuan Hu  // age(i)(j): entry i enters queue before entry j
37124bf66aSXuan Hu  val age = Seq.fill(numEntries)(Seq.fill(numEntries)(RegInit(false.B)))
38124bf66aSXuan Hu  val nextAge = Seq.fill(numEntries)(Seq.fill(numEntries)(Wire(Bool())))
39124bf66aSXuan Hu
40124bf66aSXuan Hu  // to reduce reg usage, only use upper matrix
41291e39d9Ssinsanction  def get_age(row: Int, col: Int): Bool = {
42291e39d9Ssinsanction    if (row < col)
43291e39d9Ssinsanction      age(row)(col)
44291e39d9Ssinsanction    else if (row == col)
45291e39d9Ssinsanction      true.B
46291e39d9Ssinsanction    else
47291e39d9Ssinsanction      !age(col)(row)
48291e39d9Ssinsanction  }
49124bf66aSXuan Hu  def get_next_age(row: Int, col: Int): Bool = if (row <= col) nextAge(row)(col) else !nextAge(col)(row)
50cf4a131aSsinsanction  def isEnq(i: Int): Bool = {
51cf4a131aSsinsanction    VecInit(io.enq.map(_(i))).asUInt.orR
52cf4a131aSsinsanction  }
53cf4a131aSsinsanction  def isEnqNport(i: Int, numPorts: Int = 0): Bool = {
54cf4a131aSsinsanction    numPorts match {
55124bf66aSXuan Hu      case 0 => false.B
56cf4a131aSsinsanction      case n => VecInit(io.enq.take(n).map(_(i))).asUInt.orR
57124bf66aSXuan Hu    }
58124bf66aSXuan Hu  }
59124bf66aSXuan Hu
60124bf66aSXuan Hu  for ((row, i) <- nextAge.zipWithIndex) {
61124bf66aSXuan Hu    for ((elem, j) <- row.zipWithIndex) {
62cf4a131aSsinsanction      if (i == j) {
63cf4a131aSsinsanction        // an entry is always older than itself
64cf4a131aSsinsanction        elem := true.B
65cf4a131aSsinsanction      }
66cf4a131aSsinsanction      else if (i < j) {
67cf4a131aSsinsanction        when (isEnq(i) && isEnq(j)) {
68cf4a131aSsinsanction          // (1) when entry i enqueues from port k,
69cf4a131aSsinsanction          // (1.1) if entry j enqueues from previous ports, set to false
70cf4a131aSsinsanction          // (1.2) otherwise, set to true
71124bf66aSXuan Hu          val sel = io.enq.map(_(i))
72cf4a131aSsinsanction          val result = (0 until numEnq).map(k => isEnqNport(j, k))
73cf4a131aSsinsanction          elem := !ParallelMux(sel, result)
74cf4a131aSsinsanction        }.elsewhen (isEnq(i)) {
75cf4a131aSsinsanction          // (2) when entry i enqueues, set row(i) to false
76cf4a131aSsinsanction          elem := false.B
77cf4a131aSsinsanction        }.elsewhen (isEnq(j)) {
78cf4a131aSsinsanction          // (3) when entry j enqueues, set col(j) to true
79cf4a131aSsinsanction          elem := true.B
80124bf66aSXuan Hu        }.otherwise {
81124bf66aSXuan Hu          // default: unchanged
82124bf66aSXuan Hu          elem := get_age(i, j)
83124bf66aSXuan Hu        }
84cf4a131aSsinsanction      }
85cf4a131aSsinsanction      else {
86cf4a131aSsinsanction        elem := !nextAge(j)(i)
87cf4a131aSsinsanction      }
88*4243aa09SsinceforYy      age(i)(j) := Mux(isEnq(i) | isEnq(j), elem, age(i)(j))
89124bf66aSXuan Hu    }
90124bf66aSXuan Hu  }
91124bf66aSXuan Hu
92cf4a131aSsinsanction  def getOldestCanIssue(get: (Int, Int) => Bool, canIssue: UInt): UInt = {
93124bf66aSXuan Hu    VecInit((0 until numEntries).map(i => {
94cf4a131aSsinsanction      (VecInit((0 until numEntries).map(j => get(i, j))).asUInt | ~canIssue).andR & canIssue(i)
95124bf66aSXuan Hu    })).asUInt
96124bf66aSXuan Hu  }
97124bf66aSXuan Hu
98527eefbdSsinsanction  io.out.zip(io.canIssue).foreach { case (out, canIssue) =>
99527eefbdSsinsanction    out := getOldestCanIssue(get_age, canIssue)
100527eefbdSsinsanction  }
101124bf66aSXuan Hu
102cf4a131aSsinsanction  for (i <- 0 until numEnq) {
103cf4a131aSsinsanction    assert(PopCount(io.enq(i)) <= 1.U, s"enq port ($i) is not ont-hot\n")
104cf4a131aSsinsanction  }
105124bf66aSXuan Hu}
106124bf66aSXuan Hu
107124bf66aSXuan Huobject AgeDetector {
108527eefbdSsinsanction  def apply(numEntries: Int, enq: Vec[UInt], canIssue: Vec[UInt])(implicit p: Parameters): Vec[Valid[UInt]] = {
109527eefbdSsinsanction    val age = Module(new AgeDetector(numEntries, enq.length, canIssue.length))
110124bf66aSXuan Hu    age.io.enq := enq
111cf4a131aSsinsanction    age.io.canIssue := canIssue
112527eefbdSsinsanction    val outVec = Wire(Vec(canIssue.length, Valid(UInt(numEntries.W))))
113527eefbdSsinsanction    outVec.zipWithIndex.foreach { case (out, i) =>
114527eefbdSsinsanction      out.valid := canIssue(i).orR
115527eefbdSsinsanction      out.bits := age.io.out(i)
116527eefbdSsinsanction      when (out.valid) {
117527eefbdSsinsanction        assert(PopCount(out.bits) === 1.U, s"out ($i) is not ont-hot when there is at least one entry can be issued\n")
118527eefbdSsinsanction      }
119527eefbdSsinsanction    }
120527eefbdSsinsanction    outVec
121527eefbdSsinsanction  }
122527eefbdSsinsanction  def apply(numEntries: Int, enq: Vec[UInt], canIssue: UInt)(implicit p: Parameters): Valid[UInt] = {
123527eefbdSsinsanction    val age = Module(new AgeDetector(numEntries, enq.length, 1))
124527eefbdSsinsanction    age.io.enq := enq
125527eefbdSsinsanction    age.io.canIssue(0) := canIssue
126cf4a131aSsinsanction    val out = Wire(Valid(UInt(numEntries.W)))
127cf4a131aSsinsanction    out.valid := canIssue.orR
128527eefbdSsinsanction    out.bits := age.io.out(0)
129cf4a131aSsinsanction    when (out.valid) {
130cf4a131aSsinsanction      assert(PopCount(out.bits) === 1.U, "out is not ont-hot when there is at least one entry can be issued\n")
131cf4a131aSsinsanction    }
132124bf66aSXuan Hu    out
133124bf66aSXuan Hu  }
134124bf66aSXuan Hu}
135