WrBypass.scala 3.9 KB
Newer Older
L
Lingrui98 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/***************************************************************************************
* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
* Copyright (c) 2020-2021 Peng Cheng Laboratory
*
* XiangShan is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*          http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*
* See the Mulan PSL v2 for more details.
***************************************************************************************/
package xiangshan.frontend

import chipsalliance.rocketchip.config.Parameters
import chisel3._
import chisel3.util._
import xiangshan._
import utils._
import chisel3.experimental.chiselName
24
import xiangshan.cache.mmu.CAMTemplate
L
Lingrui98 已提交
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47

class WrBypass[T <: Data](gen: T, val numEntries: Int, val idxWidth: Int,
  val numWays: Int = 1, val tagWidth: Int = 0)(implicit p: Parameters) extends XSModule {
  require(numEntries >= 0)
  require(idxWidth > 0)
  require(numWays >= 1)
  require(tagWidth >= 0)
  def hasTag = tagWidth > 0
  def multipleWays = numWays > 1
  val io = IO(new Bundle {
    val wen = Input(Bool())
    val write_idx = Input(UInt(idxWidth.W))
    val write_tag = if (hasTag) Some(Input(UInt(tagWidth.W))) else None
    val write_data = Input(Vec(numWays, gen))
    val write_way_mask = if (multipleWays) Some(Input(Vec(numWays, Bool()))) else None

    val hit = Output(Bool())
    val hit_data = Vec(numWays, Valid(gen))
  })

  class WrBypassPtr extends CircularQueuePtr[WrBypassPtr](numEntries){
  }

48 49 50 51 52 53 54 55 56 57
  class Idx_Tag extends Bundle {
    val idx = UInt(idxWidth.W)
    val tag = if (hasTag) Some(UInt(tagWidth.W)) else None
    def apply(idx: UInt, tag: UInt) = {
      this.idx := idx
      this.tag.map(_ := tag)
    }
  }
  val idx_tag_cam = Module(new CAMTemplate(new Idx_Tag, numEntries, 1))
  val data_mem = Mem(numEntries, Vec(numWays, gen))
L
Lingrui98 已提交
58 59 60 61 62 63

  val valids = RegInit(0.U.asTypeOf(Vec(numEntries, Vec(numWays, Bool()))))

  val enq_ptr = RegInit(0.U.asTypeOf(new WrBypassPtr))
  val enq_idx = enq_ptr.value

64 65 66 67
  idx_tag_cam.io.r.req(0)(io.write_idx, io.write_tag.getOrElse(0.U))
  val hits_oh = idx_tag_cam.io.r.resp(0)
  val hit_idx = OHToUInt(hits_oh)
  val hit = hits_oh.reduce(_||_)
L
Lingrui98 已提交
68 69 70

  io.hit := hit
  for (i <- 0 until numWays) {
71 72
    io.hit_data(i).valid := Mux1H(hits_oh, valids)(i)
    io.hit_data(i).bits  := data_mem.read(hit_idx)(i)
L
Lingrui98 已提交
73 74
  }

75 76 77 78 79 80 81 82 83 84
  val full_mask = Fill(numWays, 1.U(1.W)).asTypeOf(Vec(numWays, Bool()))
  val update_way_mask = io.write_way_mask.getOrElse(full_mask)

  // write data on every request
  when (io.wen) {
    val data_write_idx = Mux(hit, hit_idx, enq_idx)
    data_mem.write(data_write_idx, io.write_data, update_way_mask)
  }

  // update valids
L
Lingrui98 已提交
85 86 87
  for (i <- 0 until numWays) {
    when (io.wen) {
      when (hit) {
88
        when (update_way_mask(i)) {
L
Lingrui98 已提交
89 90 91 92
          valids(hit_idx)(i) := true.B
        }
      }.otherwise {
        valids(enq_idx)(i) := false.B
93
        when (update_way_mask(i)) {
L
Lingrui98 已提交
94 95 96 97 98 99
          valids(enq_idx)(i) := true.B
        }
      }
    }
  }

100 101 102 103 104
  val enq_en = io.wen && !hit
  idx_tag_cam.io.w.valid := enq_en
  idx_tag_cam.io.w.bits.index := enq_idx
  idx_tag_cam.io.w.bits.data(io.write_idx, io.write_tag.getOrElse(0.U))
  enq_ptr := enq_ptr + enq_en
L
Lingrui98 已提交
105 106 107 108 109 110 111 112

  XSPerfAccumulate("wrbypass_hit",  io.wen &&  hit)
  XSPerfAccumulate("wrbypass_miss", io.wen && !hit)

  XSDebug(io.wen && hit,  p"wrbypass hit entry #${hit_idx}, idx ${io.write_idx}" +
    p"tag ${io.write_tag.getOrElse(0.U)}data ${io.write_data}\n")
  XSDebug(io.wen && !hit, p"wrbypass enq entry #${enq_idx}, idx ${io.write_idx}" +
    p"tag ${io.write_tag.getOrElse(0.U)}data ${io.write_data}\n")
L
LinJiawei 已提交
113
}