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