xref: /XiangShan/src/main/scala/xiangshan/backend/issue/NewAgeDetector.scala (revision 4243aa09225ffb7b71ce68fd9a01299dce92729c)
15db4956bSzhanglyGit/***************************************************************************************
25db4956bSzhanglyGit * Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
35db4956bSzhanglyGit * Copyright (c) 2020-2021 Peng Cheng Laboratory
45db4956bSzhanglyGit *
55db4956bSzhanglyGit * XiangShan is licensed under Mulan PSL v2.
65db4956bSzhanglyGit * You can use this software according to the terms and conditions of the Mulan PSL v2.
75db4956bSzhanglyGit * You may obtain a copy of Mulan PSL v2 at:
85db4956bSzhanglyGit *          http://license.coscl.org.cn/MulanPSL2
95db4956bSzhanglyGit *
105db4956bSzhanglyGit * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
115db4956bSzhanglyGit * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
125db4956bSzhanglyGit * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
135db4956bSzhanglyGit *
145db4956bSzhanglyGit * See the Mulan PSL v2 for more details.
155db4956bSzhanglyGit ***************************************************************************************/
165db4956bSzhanglyGit
175db4956bSzhanglyGitpackage xiangshan.backend.issue
185db4956bSzhanglyGit
1983ba63b3SXuan Huimport org.chipsalliance.cde.config.Parameters
205db4956bSzhanglyGitimport chisel3._
215db4956bSzhanglyGitimport chisel3.util._
225db4956bSzhanglyGitimport xiangshan._
235db4956bSzhanglyGitimport utils._
245db4956bSzhanglyGitimport utility._
255db4956bSzhanglyGit
26527eefbdSsinsanctionclass NewAgeDetector(numEntries: Int, numEnq: Int, numDeq: Int)(implicit p: Parameters) extends XSModule {
275db4956bSzhanglyGit  val io = IO(new Bundle {
285db4956bSzhanglyGit    val enq = Vec(numEnq, Input(Bool()))
29527eefbdSsinsanction    val canIssue = Vec(numDeq, Input(UInt(numEntries.W)))
30527eefbdSsinsanction    val out = Vec(numDeq, Output(UInt(numEntries.W)))
315db4956bSzhanglyGit  })
325db4956bSzhanglyGit
335db4956bSzhanglyGit  // age(i)(j): entry i enters queue before entry j
345db4956bSzhanglyGit  val age = Seq.fill(numEntries)(Seq.fill(numEntries)(RegInit(false.B)))
355db4956bSzhanglyGit  val nextAge = Seq.fill(numEntries)(Seq.fill(numEntries)(Wire(Bool())))
365db4956bSzhanglyGit
375db4956bSzhanglyGit  // to reduce reg usage, only use upper matrix
38291e39d9Ssinsanction  def get_age(row: Int, col: Int): Bool = {
39291e39d9Ssinsanction    if (row < col)
40291e39d9Ssinsanction      age(row)(col)
41291e39d9Ssinsanction    else if (row == col)
42291e39d9Ssinsanction      true.B
43291e39d9Ssinsanction    else
44291e39d9Ssinsanction      !age(col)(row)
45291e39d9Ssinsanction  }
465db4956bSzhanglyGit  def get_next_age(row: Int, col: Int): Bool = if (row <= col) nextAge(row)(col) else !nextAge(col)(row)
475db4956bSzhanglyGit
485db4956bSzhanglyGit  //only for row <= col
495db4956bSzhanglyGit  for((row, i) <- nextAge.zipWithIndex) {
505db4956bSzhanglyGit    for((elem, j) <- row.zipWithIndex) {
51cf4a131aSsinsanction      if (i == j) {
52cf4a131aSsinsanction        // an entry is always older than itself
53cf4a131aSsinsanction        elem := true.B
54cf4a131aSsinsanction      }
55cf4a131aSsinsanction      else if (i < j) {
56cf4a131aSsinsanction        when (io.enq(j)) {
57527eefbdSsinsanction          // (1) when entry j enqueues from port k,
58527eefbdSsinsanction          // (1.1) if entry i (<j) enqueues from previous ports, it is older than entry j
59527eefbdSsinsanction          // (1.2) if entry i does not enqueue, set col(j) older than entry j
60cf4a131aSsinsanction          elem := true.B
61cf4a131aSsinsanction        }.elsewhen (io.enq(i)) {
62cf4a131aSsinsanction          // (2) when entry i enqueues, set row(i) to false
635db4956bSzhanglyGit          elem := false.B
645db4956bSzhanglyGit        }.otherwise {
65cf4a131aSsinsanction          // default: unchanged
66cf4a131aSsinsanction          elem := get_age(i, j)
675db4956bSzhanglyGit        }
68cf4a131aSsinsanction      }
69cf4a131aSsinsanction      else {
705db4956bSzhanglyGit        elem := !nextAge(j)(i)
715db4956bSzhanglyGit      }
72*4243aa09SsinceforYy      age(i)(j) := Mux(io.enq(i) | io.enq(j), elem, age(i)(j))
735db4956bSzhanglyGit    }
745db4956bSzhanglyGit  }
755db4956bSzhanglyGit
76cf4a131aSsinsanction  def getOldestCanIssue(get: (Int, Int) => Bool, canIssue: UInt): UInt = {
775db4956bSzhanglyGit    VecInit((0 until numEntries).map(i => {
78cf4a131aSsinsanction      (VecInit((0 until numEntries).map(j => get(i, j))).asUInt | ~canIssue).andR & canIssue(i)
795db4956bSzhanglyGit    })).asUInt
805db4956bSzhanglyGit  }
815db4956bSzhanglyGit
82527eefbdSsinsanction  io.out.zip(io.canIssue).foreach { case (out, canIssue) =>
83527eefbdSsinsanction    out := getOldestCanIssue(get_age, canIssue)
84527eefbdSsinsanction  }
855db4956bSzhanglyGit}
865db4956bSzhanglyGit
875db4956bSzhanglyGitobject NewAgeDetector {
88527eefbdSsinsanction  def apply(numEntries: Int, enq: Vec[Bool], canIssue: Vec[UInt])(implicit p: Parameters): Vec[Valid[UInt]] = {
89527eefbdSsinsanction    val age = Module(new NewAgeDetector(numEntries, enq.length, canIssue.length))
905db4956bSzhanglyGit    age.io.enq := enq
91cf4a131aSsinsanction    age.io.canIssue := canIssue
92527eefbdSsinsanction    val outVec = Wire(Vec(canIssue.length, Valid(UInt(numEntries.W))))
93527eefbdSsinsanction    outVec.zipWithIndex.foreach { case (out, i) =>
94527eefbdSsinsanction      out.valid := canIssue(i).orR
95527eefbdSsinsanction      out.bits := age.io.out(i)
96cf4a131aSsinsanction      when (out.valid) {
97527eefbdSsinsanction        assert(PopCount(out.bits) === 1.U, s"out ($i) is not ont-hot when there is at least one entry can be issued\n")
98cf4a131aSsinsanction      }
99527eefbdSsinsanction    }
100527eefbdSsinsanction    outVec
1015db4956bSzhanglyGit  }
1025db4956bSzhanglyGit}