1

我正在尝试修改累加器生成器示例以一次加载两个访问,例如从一个数组加载两个索引。我所做的只是当第一个内存响应进来时,我增加一个计数器并发送另一个。但我得到一个缓存异常。我的加速器代码如下。它与累加器只有一些变化。

我也感到困惑的是,第一次访问有效并且我得到了数据,而现在,我使用与第二次访问相同的地址。那么为什么这行不通呢?

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)
4

1 回答 1

1

我设法从 io.mem 界面读取了多个位置,但仍在为多次写入而苦苦挣扎。最初,我也遇到了同样的异常,因为在触发 io.mem 请求时我提供了无效的内存地址(该地址不存在内存)。在这里,在您的情况下,在将计数器从 0 切换为值 1 之后。它仍然很高。所以没有来自 cmd.valid 的控制。在这种情况下 cmd.valid 很重要,因为分配给 io.mem.req.bits.addr 信号的值(加数)仅在 cmd.valid 为高时才有效。您可以使界面独立于 cmd.valid。您必须相应地修改界面。

因此,结论是,io.mem.req 接口的示例有效地址。根据我的经验,您可以使用单个自定义命令读取任意数量的位置。

谢谢和问候, Sanket,

于 2020-01-22T10:37:52.903 回答