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}