Получение исключения SimpleHellaCacheIF при двух доступах к памяти из одной и той же инструкции - PullRequest
1 голос
/ 31 октября 2019

Я пытаюсь изменить пример генератора аккумулятора, чтобы загрузить два доступа одновременно, например, чтобы загрузить два индекса из одного массива. Я изменил только то, что когда приходит первый ответ памяти, я увеличиваю счетчик и отправляю другой. Но я получаю исключение кеша. Мой код для ускорителя ниже. В нем только несколько изменений по сравнению с аккумулятором.

Меня также смущает то, что первый доступ работает, и я получаю данные, и на данный момент я использую тот же адрес со вторым доступом. Так почему бы это не сработало?

val regfile = Mem(4, UInt(width = 16.W))
val busy = Reg(init = Vec.fill(4){Bool(false)})

val cmd = Queue(io.cmd)
val funct = cmd.bits.inst.funct
val addr = cmd.bits.rs2(log2Up(4)-1,0)
val doLoad = funct === UInt(0)
val doRead = funct === UInt(1)
val doWrite = funct === UInt(2)
val doAccum = funct === UInt(3)
val memRespTag = io.mem.resp.bits.tag

// datapath
val addend = cmd.bits.rs1
val accum = regfile(addr)
val wdata = Mux(doWrite, addend, accum + addend)

val counter = RegInit(0.U)

when (cmd.fire() && (doWrite || doAccum)) {
  regfile(addr) := wdata
}

when (io.mem.resp.valid) {
regfile(memRespTag) := io.mem.resp.bits.data
busy(memRespTag) := Bool(false)
when(counter === 0.U) {
  counter := 1.U
}
}

// control
when (io.mem.req.fire()) {
busy(counter) := Bool(true)
}

val doResp = cmd.bits.inst.xd
val stallReg = busy(counter)
val stallLoad = doLoad && !io.mem.req.ready
val stallResp = doResp && !io.resp.ready

cmd.ready := !stallReg && !stallLoad && !stallResp // command resolved if no stalls AND not issuing a load that will need a request

// PROC RESPONSE INTERFACE
io.resp.valid := cmd.valid && doResp && !stallReg && !stallLoad
// valid response if valid command, need a response, and no stalls
io.resp.bits.rd := cmd.bits.inst.rd
// Must respond with the appropriate tag or undefined behavior
io.resp.bits.data := accum
// Semantics is to always send out prior accumulator register value

io.busy := cmd.valid || busy.reduce(_||_)
// Be busy when have pending memory requests or committed possibility of pending requests
io.interrupt := Bool(false)
// Set this true to trigger an interrupt on the processor (please refer to supervisor documentation)

io.mem.req.valid := ((cmd.valid && doLoad) || counter === 1.U ) && !stallReg && !stallResp
io.mem.req.bits.addr := addend
io.mem.req.bits.tag := addr
io.mem.req.bits.cmd := M_XRD // perform a load (M_XWR for stores)
io.mem.req.bits.size := log2Ceil(8).U
io.mem.req.bits.signed := Bool(false)
io.mem.req.bits.data := Bits(0) // we're not performing any stores...
io.mem.req.bits.phys := Bool(false)
...