1c6d43980SLemover/*************************************************************************************** 2c6d43980SLemover* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3f320e0f0SYinan Xu* Copyright (c) 2020-2021 Peng Cheng Laboratory 4c6d43980SLemover* 5c6d43980SLemover* XiangShan is licensed under Mulan PSL v2. 6c6d43980SLemover* You can use this software according to the terms and conditions of the Mulan PSL v2. 7c6d43980SLemover* You may obtain a copy of Mulan PSL v2 at: 8c6d43980SLemover* http://license.coscl.org.cn/MulanPSL2 9c6d43980SLemover* 10c6d43980SLemover* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 11c6d43980SLemover* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 12c6d43980SLemover* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 13c6d43980SLemover* 14c6d43980SLemover* See the Mulan PSL v2 for more details. 15c6d43980SLemover***************************************************************************************/ 16c6d43980SLemover 17b034d3b9SLinJiaweipackage xiangshan.backend.rename 18b034d3b9SLinJiawei 19*8891a219SYinan Xuimport org.chipsalliance.cde.config.Parameters 20b034d3b9SLinJiaweiimport chisel3._ 21b034d3b9SLinJiaweiimport chisel3.util._ 22fa7f2c26STang Haojinimport utility.HasCircularQueuePtrHelper 233c02ee8fSwakafaimport utility.ParallelPriorityMux 243c02ee8fSwakafaimport utils.XSError 25b034d3b9SLinJiaweiimport xiangshan._ 26fa7f2c26STang Haojinimport xiangshan.backend.SnapshotGenerator 27b034d3b9SLinJiawei 282225d46eSJiawei Linclass RatReadPort(implicit p: Parameters) extends XSBundle { 297fa2c198SYinan Xu val hold = Input(Bool()) 30b034d3b9SLinJiawei val addr = Input(UInt(5.W)) 317fa2c198SYinan Xu val data = Output(UInt(PhyRegIdxWidth.W)) 32b034d3b9SLinJiawei} 33b034d3b9SLinJiawei 342225d46eSJiawei Linclass RatWritePort(implicit p: Parameters) extends XSBundle { 357fa2c198SYinan Xu val wen = Bool() 367fa2c198SYinan Xu val addr = UInt(5.W) 377fa2c198SYinan Xu val data = UInt(PhyRegIdxWidth.W) 38b034d3b9SLinJiawei} 39b034d3b9SLinJiawei 40fa7f2c26STang Haojinclass RenameTable(float: Boolean)(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelper { 4166b2c4a4SYinan Xu val io = IO(new Bundle { 42ccfddc82SHaojin Tang val redirect = Input(Bool()) 43b034d3b9SLinJiawei val readPorts = Vec({if(float) 4 else 3} * RenameWidth, new RatReadPort) 447fa2c198SYinan Xu val specWritePorts = Vec(CommitWidth, Input(new RatWritePort)) 457fa2c198SYinan Xu val archWritePorts = Vec(CommitWidth, Input(new RatWritePort)) 46dcf3a679STang Haojin val old_pdest = Vec(CommitWidth, Output(UInt(PhyRegIdxWidth.W))) 47dcf3a679STang Haojin val need_free = Vec(CommitWidth, Output(Bool())) 48fa7f2c26STang Haojin val snpt = Input(new SnapshotPort) 492225d46eSJiawei Lin val debug_rdata = Vec(32, Output(UInt(PhyRegIdxWidth.W))) 50b034d3b9SLinJiawei }) 51b034d3b9SLinJiawei 52b034d3b9SLinJiawei // speculative rename table 5366b2c4a4SYinan Xu val rename_table_init = VecInit.tabulate(32)(i => (if (float) i else 0).U(PhyRegIdxWidth.W)) 5466b2c4a4SYinan Xu val spec_table = RegInit(rename_table_init) 557fa2c198SYinan Xu val spec_table_next = WireInit(spec_table) 56b034d3b9SLinJiawei // arch state rename table 5766b2c4a4SYinan Xu val arch_table = RegInit(rename_table_init) 58ccfddc82SHaojin Tang val arch_table_next = WireDefault(arch_table) 59dcf3a679STang Haojin // old_pdest 60dcf3a679STang Haojin val old_pdest = RegInit(VecInit.fill(CommitWidth)(0.U(PhyRegIdxWidth.W))) 61dcf3a679STang Haojin val need_free = RegInit(VecInit.fill(CommitWidth)(false.B)) 62b034d3b9SLinJiawei 637fa2c198SYinan Xu // For better timing, we optimize reading and writing to RenameTable as follows: 647fa2c198SYinan Xu // (1) Writing at T0 will be actually processed at T1. 657fa2c198SYinan Xu // (2) Reading is synchronous now. 667fa2c198SYinan Xu // (3) RAddr at T0 will be used to access the table and get data at T0. 677fa2c198SYinan Xu // (4) WData at T0 is bypassed to RData at T1. 68ccfddc82SHaojin Tang val t1_redirect = RegNext(io.redirect, false.B) 697fa2c198SYinan Xu val t1_rdata = io.readPorts.map(p => RegNext(Mux(p.hold, p.data, spec_table_next(p.addr)))) 707fa2c198SYinan Xu val t1_raddr = io.readPorts.map(p => RegEnable(p.addr, !p.hold)) 71ccfddc82SHaojin Tang val t1_wSpec = RegNext(Mux(io.redirect, 0.U.asTypeOf(io.specWritePorts), io.specWritePorts)) 72b034d3b9SLinJiawei 73fa7f2c26STang Haojin val t1_snpt = RegNext(io.snpt, 0.U.asTypeOf(io.snpt)) 74fa7f2c26STang Haojin 75fa7f2c26STang Haojin val snapshots = SnapshotGenerator(spec_table, t1_snpt.snptEnq, t1_snpt.snptDeq, t1_redirect) 76fa7f2c26STang Haojin 777fa2c198SYinan Xu // WRITE: when instruction commits or walking 787fa2c198SYinan Xu val t1_wSpec_addr = t1_wSpec.map(w => Mux(w.wen, UIntToOH(w.addr), 0.U)) 797fa2c198SYinan Xu for ((next, i) <- spec_table_next.zipWithIndex) { 807fa2c198SYinan Xu val matchVec = t1_wSpec_addr.map(w => w(i)) 817fa2c198SYinan Xu val wMatch = ParallelPriorityMux(matchVec.reverse, t1_wSpec.map(_.data).reverse) 827fa2c198SYinan Xu // When there's a flush, we use arch_table to update spec_table. 83fa7f2c26STang Haojin next := Mux( 84fa7f2c26STang Haojin t1_redirect, 85fa7f2c26STang Haojin Mux(t1_snpt.useSnpt, snapshots(t1_snpt.snptSelect)(i), arch_table(i)), 86fa7f2c26STang Haojin Mux(VecInit(matchVec).asUInt.orR, wMatch, spec_table(i)) 87fa7f2c26STang Haojin ) 887fa2c198SYinan Xu } 897fa2c198SYinan Xu spec_table := spec_table_next 907fa2c198SYinan Xu 917fa2c198SYinan Xu // READ: decode-rename stage 92b034d3b9SLinJiawei for ((r, i) <- io.readPorts.zipWithIndex) { 937fa2c198SYinan Xu // We use two comparisons here because r.hold has bad timing but addrs have better timing. 947fa2c198SYinan Xu val t0_bypass = io.specWritePorts.map(w => w.wen && Mux(r.hold, w.addr === t1_raddr(i), w.addr === r.addr)) 95ccfddc82SHaojin Tang val t1_bypass = RegNext(Mux(io.redirect, 0.U.asTypeOf(VecInit(t0_bypass)), VecInit(t0_bypass))) 967fa2c198SYinan Xu val bypass_data = ParallelPriorityMux(t1_bypass.reverse, t1_wSpec.map(_.data).reverse) 977fa2c198SYinan Xu r.data := Mux(t1_bypass.asUInt.orR, bypass_data, t1_rdata(i)) 98b034d3b9SLinJiawei } 99b034d3b9SLinJiawei 100dcf3a679STang Haojin for ((w, i) <- io.archWritePorts.zipWithIndex) { 1017fa2c198SYinan Xu when (w.wen) { 102ccfddc82SHaojin Tang arch_table_next(w.addr) := w.data 103ce4949a0SYinan Xu } 104dcf3a679STang Haojin val arch_mask = VecInit.fill(PhyRegIdxWidth)(w.wen).asUInt 105dcf3a679STang Haojin old_pdest(i) := 106dcf3a679STang Haojin MuxCase(arch_table(w.addr) & arch_mask, 107dcf3a679STang Haojin io.archWritePorts.take(i).reverse.map(x => (x.wen && x.addr === w.addr, x.data & arch_mask))) 108b034d3b9SLinJiawei } 109ccfddc82SHaojin Tang arch_table := arch_table_next 110b034d3b9SLinJiawei 111dcf3a679STang Haojin for (((old, free), i) <- (old_pdest zip need_free).zipWithIndex) { 112dcf3a679STang Haojin val hasDuplicate = old_pdest.take(i).map(_ === old) 113dcf3a679STang Haojin val blockedByDup = if (i == 0) false.B else VecInit(hasDuplicate).asUInt.orR 114dcf3a679STang Haojin free := VecInit(arch_table.map(_ =/= old)).asUInt.andR && !blockedByDup 115dcf3a679STang Haojin } 116dcf3a679STang Haojin 117dcf3a679STang Haojin io.old_pdest := old_pdest 118dcf3a679STang Haojin io.need_free := need_free 1192225d46eSJiawei Lin io.debug_rdata := arch_table 12044dead2fSZhangZifei} 1217fa2c198SYinan Xu 1227fa2c198SYinan Xuclass RenameTableWrapper(implicit p: Parameters) extends XSModule { 1237fa2c198SYinan Xu val io = IO(new Bundle() { 124ccfddc82SHaojin Tang val redirect = Input(Bool()) 125ccfddc82SHaojin Tang val robCommits = Input(new RobCommitIO) 1267fa2c198SYinan Xu val intReadPorts = Vec(RenameWidth, Vec(3, new RatReadPort)) 1277fa2c198SYinan Xu val intRenamePorts = Vec(RenameWidth, Input(new RatWritePort)) 1287fa2c198SYinan Xu val fpReadPorts = Vec(RenameWidth, Vec(4, new RatReadPort)) 1297fa2c198SYinan Xu val fpRenamePorts = Vec(RenameWidth, Input(new RatWritePort)) 130dcf3a679STang Haojin val int_old_pdest = Vec(CommitWidth, Output(UInt(PhyRegIdxWidth.W))) 131dcf3a679STang Haojin val fp_old_pdest = Vec(CommitWidth, Output(UInt(PhyRegIdxWidth.W))) 132dcf3a679STang Haojin val int_need_free = Vec(CommitWidth, Output(Bool())) 133fa7f2c26STang Haojin val snpt = Input(new SnapshotPort) 1347fa2c198SYinan Xu // for debug printing 1357fa2c198SYinan Xu val debug_int_rat = Vec(32, Output(UInt(PhyRegIdxWidth.W))) 1367fa2c198SYinan Xu val debug_fp_rat = Vec(32, Output(UInt(PhyRegIdxWidth.W))) 1377fa2c198SYinan Xu }) 1387fa2c198SYinan Xu 1397fa2c198SYinan Xu val intRat = Module(new RenameTable(float = false)) 1407fa2c198SYinan Xu val fpRat = Module(new RenameTable(float = true)) 1417fa2c198SYinan Xu 1427fa2c198SYinan Xu intRat.io.debug_rdata <> io.debug_int_rat 1437fa2c198SYinan Xu intRat.io.readPorts <> io.intReadPorts.flatten 144ccfddc82SHaojin Tang intRat.io.redirect := io.redirect 145ccfddc82SHaojin Tang fpRat.io.redirect := io.redirect 146fa7f2c26STang Haojin intRat.io.snpt := io.snpt 147fa7f2c26STang Haojin fpRat.io.snpt := io.snpt 148dcf3a679STang Haojin io.int_old_pdest := intRat.io.old_pdest 149dcf3a679STang Haojin io.fp_old_pdest := fpRat.io.old_pdest 150dcf3a679STang Haojin io.int_need_free := intRat.io.need_free 151c3abb8b6SYinan Xu val intDestValid = io.robCommits.info.map(_.rfWen) 1527fa2c198SYinan Xu for ((arch, i) <- intRat.io.archWritePorts.zipWithIndex) { 1536474c47fSYinan Xu arch.wen := io.robCommits.isCommit && io.robCommits.commitValid(i) && intDestValid(i) 1547fa2c198SYinan Xu arch.addr := io.robCommits.info(i).ldest 1557fa2c198SYinan Xu arch.data := io.robCommits.info(i).pdest 156c3abb8b6SYinan Xu XSError(arch.wen && arch.addr === 0.U && arch.data =/= 0.U, "pdest for $0 should be 0\n") 1577fa2c198SYinan Xu } 1587fa2c198SYinan Xu for ((spec, i) <- intRat.io.specWritePorts.zipWithIndex) { 1596474c47fSYinan Xu spec.wen := io.robCommits.isWalk && io.robCommits.walkValid(i) && intDestValid(i) 1607fa2c198SYinan Xu spec.addr := io.robCommits.info(i).ldest 161ccfddc82SHaojin Tang spec.data := io.robCommits.info(i).pdest 162c3abb8b6SYinan Xu XSError(spec.wen && spec.addr === 0.U && spec.data =/= 0.U, "pdest for $0 should be 0\n") 1637fa2c198SYinan Xu } 1647fa2c198SYinan Xu for ((spec, rename) <- intRat.io.specWritePorts.zip(io.intRenamePorts)) { 1657fa2c198SYinan Xu when (rename.wen) { 1667fa2c198SYinan Xu spec.wen := true.B 1677fa2c198SYinan Xu spec.addr := rename.addr 1687fa2c198SYinan Xu spec.data := rename.data 1697fa2c198SYinan Xu } 1707fa2c198SYinan Xu } 1717fa2c198SYinan Xu 1727fa2c198SYinan Xu // debug read ports for difftest 1737fa2c198SYinan Xu fpRat.io.debug_rdata <> io.debug_fp_rat 1747fa2c198SYinan Xu fpRat.io.readPorts <> io.fpReadPorts.flatten 1757fa2c198SYinan Xu for ((arch, i) <- fpRat.io.archWritePorts.zipWithIndex) { 1766474c47fSYinan Xu arch.wen := io.robCommits.isCommit && io.robCommits.commitValid(i) && io.robCommits.info(i).fpWen 1777fa2c198SYinan Xu arch.addr := io.robCommits.info(i).ldest 1787fa2c198SYinan Xu arch.data := io.robCommits.info(i).pdest 1797fa2c198SYinan Xu } 1807fa2c198SYinan Xu for ((spec, i) <- fpRat.io.specWritePorts.zipWithIndex) { 1816474c47fSYinan Xu spec.wen := io.robCommits.isWalk && io.robCommits.walkValid(i) && io.robCommits.info(i).fpWen 1827fa2c198SYinan Xu spec.addr := io.robCommits.info(i).ldest 183ccfddc82SHaojin Tang spec.data := io.robCommits.info(i).pdest 1847fa2c198SYinan Xu } 1857fa2c198SYinan Xu for ((spec, rename) <- fpRat.io.specWritePorts.zip(io.fpRenamePorts)) { 1867fa2c198SYinan Xu when (rename.wen) { 1877fa2c198SYinan Xu spec.wen := true.B 1887fa2c198SYinan Xu spec.addr := rename.addr 1897fa2c198SYinan Xu spec.data := rename.data 1907fa2c198SYinan Xu } 1917fa2c198SYinan Xu } 1927fa2c198SYinan Xu 1937fa2c198SYinan Xu} 194