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 org.chipsalliance.cde.config.Parameters 20import chisel3._ 21import chisel3.util._ 22import xiangshan._ 23import utils._ 24import utility._ 25 26class NewAgeDetector(numEntries: Int, numEnq: Int, numDeq: Int)(implicit p: Parameters) extends XSModule { 27 val io = IO(new Bundle { 28 val enq = Vec(numEnq, Input(Bool())) 29 val canIssue = Vec(numDeq, Input(UInt(numEntries.W))) 30 val out = Vec(numDeq, 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 = { 39 if (row < col) 40 age(row)(col) 41 else if (row == col) 42 true.B 43 else 44 !age(col)(row) 45 } 46 def get_next_age(row: Int, col: Int): Bool = if (row <= col) nextAge(row)(col) else !nextAge(col)(row) 47 48 //only for row <= col 49 for((row, i) <- nextAge.zipWithIndex) { 50 for((elem, j) <- row.zipWithIndex) { 51 if (i == j) { 52 // an entry is always older than itself 53 elem := true.B 54 } 55 else if (i < j) { 56 when (io.enq(j)) { 57 // (1) when entry j enqueues from port k, 58 // (1.1) if entry i (<j) enqueues from previous ports, it is older than entry j 59 // (1.2) if entry i does not enqueue, set col(j) older than entry j 60 elem := true.B 61 }.elsewhen (io.enq(i)) { 62 // (2) when entry i enqueues, set row(i) to false 63 elem := false.B 64 }.otherwise { 65 // default: unchanged 66 elem := get_age(i, j) 67 } 68 } 69 else { 70 elem := !nextAge(j)(i) 71 } 72 age(i)(j) := Mux(io.enq(i) | io.enq(j), elem, age(i)(j)) 73 } 74 } 75 76 def getOldestCanIssue(get: (Int, Int) => Bool, canIssue: UInt): UInt = { 77 VecInit((0 until numEntries).map(i => { 78 (VecInit((0 until numEntries).map(j => get(i, j))).asUInt | ~canIssue).andR & canIssue(i) 79 })).asUInt 80 } 81 82 io.out.zip(io.canIssue).foreach { case (out, canIssue) => 83 out := getOldestCanIssue(get_age, canIssue) 84 } 85} 86 87object NewAgeDetector { 88 def apply(numEntries: Int, enq: Vec[Bool], canIssue: Vec[UInt])(implicit p: Parameters): Vec[Valid[UInt]] = { 89 val age = Module(new NewAgeDetector(numEntries, enq.length, canIssue.length)) 90 age.io.enq := enq 91 age.io.canIssue := canIssue 92 val outVec = Wire(Vec(canIssue.length, Valid(UInt(numEntries.W)))) 93 outVec.zipWithIndex.foreach { case (out, i) => 94 out.valid := canIssue(i).orR 95 out.bits := age.io.out(i) 96 when (out.valid) { 97 assert(PopCount(out.bits) === 1.U, s"out ($i) is not ont-hot when there is at least one entry can be issued\n") 98 } 99 } 100 outVec 101 } 102}