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 chipsalliance.rocketchip.config.Parameters 20import chisel3._ 21import chisel3.util._ 22import xiangshan._ 23import utils._ 24import utility._ 25 26class NewAgeDetector(numEntries: Int, numEnq: Int, regOut: Boolean = true)(implicit p: Parameters) extends XSModule { 27 val io = IO(new Bundle { 28 val enq = Vec(numEnq, Input(Bool())) 29 val clear = Input(UInt(numEntries.W)) 30 val out = 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 = if (row <= col) age(row)(col) else !age(col)(row) 39 def get_next_age(row: Int, col: Int): Bool = if (row <= col) nextAge(row)(col) else !nextAge(col)(row) 40 def isFlushed(i: Int): Bool = io.clear(i) 41 42 //only for row <= col 43 for((row, i) <- nextAge.zipWithIndex) { 44 for((elem, j) <- row.zipWithIndex) { 45 if (i <= j) { 46 when(io.enq(i)){ 47 elem := io.enq(j) || isFlushed(j) || !get_age(j, j) 48 }.elsewhen(isFlushed(i)) { 49 elem := false.B 50 }.otherwise { 51 elem := (!io.enq(j) && !isFlushed(j) && get_age(i, j)) || (!io.enq(j) && isFlushed(j)) || (io.enq(j) && get_age(i, i)) 52 } 53 } else { 54 elem := !nextAge(j)(i) 55 } 56 age(i)(j) := elem 57 } 58 } 59 60 def getOldest(get: (Int, Int) => Bool): UInt = { 61 VecInit((0 until numEntries).map(i => { 62 VecInit((0 until numEntries).map(j => get(i, j))).asUInt.andR 63 })).asUInt 64 } 65 66 val best = getOldest(get_age) 67 val nextBest = getOldest(get_next_age) 68 69 io.out := (if (regOut) best else nextBest) 70 71 val ageMatrix = VecInit(age.map(v => VecInit(v).asUInt.andR)).asUInt 72 val symmetricAge = RegNext(nextBest) 73 XSError(ageMatrix =/= symmetricAge, p"age error between ${Hexadecimal(ageMatrix)} and ${Hexadecimal(symmetricAge)}\n") 74} 75 76object NewAgeDetector { 77 def apply(numEntries: Int, enq: Vec[Bool], clear: Vec[Bool], canIssue: UInt)(implicit p: Parameters): Valid[UInt] = { 78 val age = Module(new NewAgeDetector(numEntries, enq.length, regOut = true)) 79 age.io.enq := enq 80 age.io.clear := clear.asUInt 81 val out = Wire(Valid(UInt(clear.getWidth.W))) 82 out.valid := (canIssue & age.io.out).orR 83 out.bits := age.io.out 84 out 85 } 86}