未验证 提交 9412fdbd 编写于 作者: L ljw 提交者: GitHub

Merge pull request #218 from RISCVERS/sbuffer-test

Update LRU algorithm
......@@ -70,7 +70,7 @@ jobs:
echo $AM_HOME
echo $NEMU_HOME
echo $NOOP_HOME
make -C $AM_HOME/apps/microbench ARCH=riscv64-noop AM_HOME=$AM_HOME NEMU_HOME=$NEMU_HOME NOOP_HOME=$NOOP_HOME mainargs=test run 2> /dev/null
make -C $AM_HOME/apps/microbench ARCH=riscv64-noop AM_HOME=$AM_HOME NEMU_HOME=$NEMU_HOME NOOP_HOME=$NOOP_HOME mainargs=test run
riscv-tests:
runs-on: self-hosted
......@@ -87,5 +87,5 @@ jobs:
echo $NEMU_HOME
echo $NOOP_HOME
echo $RVTEST_HOME
make -C $RVTEST_HOME/isa/ SUITES+=rv64ui SUITES+=rv64um SUITES+=rv64ua NEMU_HOME=$NEMU_HOME NOOP_HOME=$NOOP_HOME noop_run 2> /dev/null
make -C $RVTEST_HOME/isa/ SUITES+=rv64ui SUITES+=rv64um SUITES+=rv64ua NEMU_HOME=$NEMU_HOME NOOP_HOME=$NOOP_HOME noop_run
......@@ -37,4 +37,16 @@ object ParallelLookUp {
def apply[T<:Data](key: UInt, mapping:Seq[(UInt,T)]): T = {
ParallelMux(mapping.map(m => (m._1===key) -> m._2))
}
}
object ParallelMax {
def apply[T <: Data](xs: Seq[T]): T = {
ParallelOperation(xs, (a: T, b:T) => Mux(a.asUInt() > b.asUInt(),a, b).asTypeOf(xs.head))
}
}
object ParallelMin {
def apply[T <: Data](xs: Seq[T]): T = {
ParallelOperation(xs, (a: T, b:T) => Mux(a.asUInt() < b.asUInt(),a, b).asTypeOf(xs.head))
}
}
\ No newline at end of file
......@@ -76,6 +76,7 @@ class TrueLRU(n_ways: Int) {
nextState.zipWithIndex.tail.foldLeft((nextState.head.apply(n_ways-1,1),0)) { case ((pe,pi),(ce,ci)) => (Cat(ce.apply(n_ways-1,ci+1), pe), ci) }._1
}
def get_next_state(state: UInt, touch_ways: Seq[Valid[UInt]]): UInt = {
touch_ways.foldLeft(state)((prev, touch_way) => Mux(touch_way.valid, get_next_state(prev, touch_way.bits), prev))
}
......@@ -162,3 +163,66 @@ class SeqPLRU(n_sets: Int, n_ways: Int) extends SeqReplacementPolicy {
def way = plru_way
}
class SbufferLRU(n_ways: Int) {
def nBits = n_ways * n_ways
private val state_reg = RegInit(0.U(nBits.W))
def state_read = WireDefault(state_reg)
def get_next_state(state: UInt, touch_way: UInt): UInt = {
val nextState = Wire(Vec(n_ways, UInt(n_ways.W)))
val moreRecentVec = state.asTypeOf(Vec(n_ways, UInt(n_ways.W)))
val wayDec = UIntToOH(touch_way, n_ways)
val wayUpd = (~wayDec).asUInt()
nextState.zipWithIndex.foreach { case (e, i) =>
e := Mux(i.U === touch_way,
wayUpd,
moreRecentVec(i) & wayUpd
)
}
nextState.asUInt()
}
def get_next_state(state: UInt, touch_ways: Seq[Valid[UInt]]): UInt = {
touch_ways.foldLeft(state)((prev, touch_way) => Mux(touch_way.valid, get_next_state(prev, touch_way.bits), prev))
}
def access(touch_way: UInt) {
state_reg := get_next_state(state_reg, touch_way)
}
def access(touch_ways: Seq[Valid[UInt]]) {
when (ParallelOR(touch_ways.map(_.valid))) {
state_reg := get_next_state(state_reg, touch_ways)
}
}
def get_min_value(xs: Seq[(UInt,UInt)]): (UInt,UInt)= {
xs match {
case Seq(a) => a
case Seq(a, b) => (Mux(a._1<b._1,a._1,b._1),Mux(a._1<b._1,a._2,b._2))
case _ =>
get_min_value(Seq(get_min_value(xs take xs.size/2), get_min_value(xs drop xs.size/2)))
}
}
def get_replace_way(state: UInt, sbufferState:Seq[Bool]): UInt = {
val moreRecentVec = state.asTypeOf(Vec(n_ways, UInt(n_ways.W)))
val count = Wire(Vec(n_ways, UInt(log2Up(n_ways).W)))
for(i <- 0 until n_ways){
count(i) := Mux(sbufferState(i), PopCount(moreRecentVec(i)), ((1<<n_ways)-1).U)
}
count.zip((0 until n_ways).map(_.U))
get_min_value(count.zip((0 until n_ways).map(_.U)))._2
}
def way(sbufferState:Seq[Bool]) = get_replace_way(state_reg,sbufferState)
//def miss = access(way)
def hit = {}
def flush() = { state_reg := 0.U(nBits.W) }
//@deprecated("replace 'replace' with 'way' from abstract class ReplacementPolicy","Rocket Chip 2020.05")
//def replace: UInt = way
}
\ No newline at end of file
......@@ -70,7 +70,8 @@ class NewSbuffer extends XSModule with HasSbufferCst {
val buffer = Mem(StoreBufferSize, new SbufferLine)
val stateVec = RegInit(VecInit(Seq.fill(StoreBufferSize)(s_invalid)))
val lru = new TrueLRU(StoreBufferSize)
//val lru = new SbufferLRU(StoreBufferSize)
val lru = new SbufferLRU(StoreBufferSize)
// 2 * enq + 1 * deq
val lruAccessWays = Wire(Vec(io.in.getWidth+1, new Valid(UInt(SbufferIndexWidth.W))))
for(w <- lruAccessWays){
......@@ -217,7 +218,7 @@ class NewSbuffer extends XSModule with HasSbufferCst {
val do_eviction = Wire(Bool())
val empty = Cat(stateVec.map(s => s===s_invalid)).andR() && !Cat(io.in.map(_.valid)).orR()
val replaceIdx = lru.way
val replaceIdx = lru.way(stateVec.map(s => s===s_valid))
val firstValidEntry = PriorityEncoder(stateVec.map(s => s===s_valid))
val evictor = Module(new NaiveEvictor(StoreBufferSize-4))
......@@ -248,6 +249,8 @@ class NewSbuffer extends XSModule with HasSbufferCst {
}
XSDebug(p"sbuffer state:${sbuffer_state} do eviction:${do_eviction} empty:${empty}\n")
//XSDebug(p"replaceIdx:${replaceIdx}\n")
//val evictionIdxWire = replaceIdx
val evictionIdxWire = Mux(stateVec(replaceIdx)===s_valid, replaceIdx, firstValidEntry)
val evictionIdxEnqReq = Wire(DecoupledIO(UInt(SbufferIndexWidth.W)))
val evictionIdxQueue = Module(new Queue(UInt(SbufferIndexWidth.W), StoreBufferSize, pipe = true, flow = false))
......
package xiangshan.memend
import org.scalatest._
import chiseltest._
import chisel3._
import chisel3.experimental.BundleLiterals._
import chisel3.util._
import xiangshan._
import xiangshan.cache.{DCacheLineIO, DCacheWordReq}
import xiangshan.mem.{LoadForwardQueryIO, NewSbuffer}
import xiangshan.testutils._
import scala.util.Random
class SbufferWapper extends XSModule {
val io = IO(new Bundle() {
val in = Vec(StorePipelineWidth, Flipped(Decoupled(new DCacheWordReq)))
val dcache = new DCacheLineIO
val forward = Vec(LoadPipelineWidth, Flipped(new LoadForwardQueryIO))
val flush = new Bundle {
val valid = Input(Bool())
val empty = Output(Bool())
} // sbuffer flush
})
val sbuffer = Module(new NewSbuffer)
io <> sbuffer.io
// fake dcache
sbuffer.io.dcache.req.ready := true.B
sbuffer.io.dcache.resp.valid := RegNext(RegNext(RegNext(RegNext(sbuffer.io.dcache.req.valid))))
sbuffer.io.dcache.resp.bits.meta.id := RegNext(RegNext(RegNext(RegNext(sbuffer.io.dcache.req.bits.meta.id))))
}
class SbufferTest extends FlatSpec
with ChiselScalatestTester
with Matchers
with HasXSParameter
with ParallelTestExecution
with HasPartialDecoupledDriver {
top.Parameters.set(top.Parameters.debugParameters)
it should "random req" in {
test(new SbufferWapper{AddSinks()}){ c =>
def store_enq(addr: Seq[UInt], data: Seq[UInt], mask: Seq[UInt]) ={
(0 until StorePipelineWidth).map { i =>
c.io.in(i).valid.poke(true.B)
c.io.in(i).bits.pokePartial(chiselTypeOf(c.io.in(i).bits).Lit(
_.mask -> mask(i),
_.addr -> addr(i),
_.data -> data(i)
))
}
c.clock.step(1)
for (in <- c.io.in){ in.valid.poke(false.B)}
}
def forward_req_and_resp(addr: Seq[UInt], data: Seq[UInt], mask:Seq[UInt]) = {
(0 until LoadPipelineWidth).map{ i =>
c.io.forward(i).paddr.poke(addr(i))
c.io.forward(i).mask.poke(mask(i))
if(c.io.in(i).ready.peek() == true.B) {
(0 until 8).map { j =>
c.io.forward(i).forwardData(j).expect(data(i)(j * 8 + 7, j * 8))
}
}
}
}
val TEST_SIZE = 100
for(i <- 0 until TEST_SIZE) {
val addr = Seq.fill(StorePipelineWidth)((Random.nextLong() & 0x7ffffffff8L).U)// align to block size
val data = Seq.fill(StorePipelineWidth)((Random.nextLong() & 0x7fffffffffffffffL).U)
val mask = Seq.fill(StorePipelineWidth)(0xff.U)
store_enq(addr, data, mask)
forward_req_and_resp(addr, data, mask)
}
}
}
it should "sequence req" in {
test(new SbufferWapper{AddSinks()}){ c =>
def store_enq(addr: Seq[UInt], data: Seq[UInt], mask: Seq[UInt]) = {
(0 until StorePipelineWidth).map { i =>
c.io.in(i).valid.poke(true.B)
c.io.in(i).bits.pokePartial(chiselTypeOf(c.io.in(i).bits).Lit(
_.mask -> mask(i),
_.addr -> addr(i),
_.data -> data(i)
))
}
c.clock.step(1)
for (in <- c.io.in){ in.valid.poke(false.B)}
}
def forward_req_and_resp(addr: Seq[UInt], data: Seq[UInt], mask:Seq[UInt]) = {
(0 until LoadPipelineWidth).map{ i =>
c.io.forward(i).paddr.poke(addr(i))
c.io.forward(i).mask.poke(mask(i))
if(c.io.in(i).ready.peek() == true.B) {
(0 until 8).map { j =>
c.io.forward(i).forwardData(j).expect(data(i)(j * 8 + 7, j * 8))
}
}
}
}
val TEST_SIZE = 100
val start_addr = Random.nextLong() & 0x7ffffffff8L
for(i <- 0 until TEST_SIZE) {
val addr = Seq(((i<<4) + start_addr).U,((i<<4)+8+start_addr).U)
val data = Seq.fill(StorePipelineWidth)((Random.nextLong() & 0x7fffffffffffffffL).U)
val mask = Seq.fill(StorePipelineWidth)(0xff.U)
store_enq(addr, data, mask)
forward_req_and_resp(addr, data, mask)
}
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册