1
0
rocket-chip/rocket/src/main/scala/rocc.scala

131 lines
3.9 KiB
Scala
Raw Normal View History

2014-09-13 03:06:41 +02:00
// See LICENSE for license details.
package rocket
import Chisel._
2013-09-15 07:34:53 +02:00
import uncore._
2014-05-15 01:17:39 +02:00
import Util._
2015-10-22 03:18:32 +02:00
import cde.{Parameters, Field}
case object RoccMaxTaggedMemXacts extends Field[Int]
case object RoccNMemChannels extends Field[Int]
2013-09-15 00:31:50 +02:00
class RoCCInstruction extends Bundle
{
val funct = Bits(width = 7)
val rs2 = Bits(width = 5)
val rs1 = Bits(width = 5)
2013-09-15 00:31:50 +02:00
val xd = Bool()
val xs1 = Bool()
val xs2 = Bool()
val rd = Bits(width = 5)
2013-09-15 00:31:50 +02:00
val opcode = Bits(width = 7)
}
2015-10-06 06:48:05 +02:00
class RoCCCommand(implicit p: Parameters) extends CoreBundle()(p) {
2013-09-15 00:31:50 +02:00
val inst = new RoCCInstruction
val rs1 = Bits(width = xLen)
val rs2 = Bits(width = xLen)
2013-09-15 00:31:50 +02:00
}
2015-10-06 06:48:05 +02:00
class RoCCResponse(implicit p: Parameters) extends CoreBundle()(p) {
2013-09-15 00:31:50 +02:00
val rd = Bits(width = 5)
val data = Bits(width = xLen)
2013-09-15 00:31:50 +02:00
}
2015-10-06 06:48:05 +02:00
class RoCCInterface(implicit p: Parameters) extends Bundle {
2013-09-15 00:31:50 +02:00
val cmd = Decoupled(new RoCCCommand).flip
val resp = Decoupled(new RoCCResponse)
2015-10-06 06:48:05 +02:00
val mem = new HellaCacheIO()(p.alterPartial({ case CacheName => "L1D" }))
2014-01-29 07:13:16 +01:00
val busy = Bool(OUTPUT)
2014-02-06 09:09:42 +01:00
val s = Bool(INPUT)
2014-01-29 07:13:16 +01:00
val interrupt = Bool(OUTPUT)
// These should be handled differently, eventually
val imem = new ClientUncachedTileLinkIO
val dmem = Vec(p(RoccNMemChannels), new ClientUncachedTileLinkIO)
2013-11-06 02:12:09 +01:00
val iptw = new TLBPTWIO
val dptw = new TLBPTWIO
val pptw = new TLBPTWIO
2014-01-29 07:13:16 +01:00
val exception = Bool(INPUT)
2013-09-15 00:31:50 +02:00
}
2015-10-06 06:48:05 +02:00
abstract class RoCC(implicit p: Parameters) extends CoreModule()(p) {
val io = new RoCCInterface
io.mem.req.bits.phys := Bool(true) // don't perform address translation
2013-09-15 00:31:50 +02:00
}
2015-10-06 06:48:05 +02:00
class AccumulatorExample(n: Int = 4)(implicit p: Parameters) extends RoCC()(p) {
val regfile = Mem(n, UInt(width = xLen))
val busy = Reg(init = Vec.fill(n){Bool(false)})
2013-09-15 00:31:50 +02:00
2013-09-15 07:34:53 +02:00
val cmd = Queue(io.cmd)
val funct = cmd.bits.inst.funct
val addr = cmd.bits.rs2(log2Up(n)-1,0)
2013-09-15 07:34:53 +02:00
val doWrite = funct === UInt(0)
val doRead = funct === UInt(1)
val doLoad = funct === UInt(2)
val doAccum = funct === UInt(3)
val memRespTag = io.mem.resp.bits.tag(log2Up(n)-1,0)
// datapath
val addend = cmd.bits.rs1
2013-09-15 00:31:50 +02:00
val accum = regfile(addr)
2013-09-15 07:34:53 +02:00
val wdata = Mux(doWrite, addend, accum + addend)
2013-09-15 00:31:50 +02:00
2013-09-15 07:34:53 +02:00
when (cmd.fire() && (doWrite || doAccum)) {
2013-09-15 00:31:50 +02:00
regfile(addr) := wdata
}
2013-09-15 07:34:53 +02:00
when (io.mem.resp.valid) {
regfile(memRespTag) := io.mem.resp.bits.data
}
// control
when (io.mem.req.fire()) {
busy(addr) := Bool(true)
}
when (io.mem.resp.valid) {
busy(memRespTag) := Bool(false)
}
val doResp = cmd.bits.inst.xd
val stallReg = busy(addr)
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
2013-09-15 07:34:53 +02:00
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
2013-09-15 07:34:53 +02:00
io.busy := cmd.valid || busy.reduce(_||_)
// Be busy when have pending memory requests or committed possibility of pending requests
2013-09-15 00:31:50 +02:00
io.interrupt := Bool(false)
// Set this true to trigger an interrupt on the processor (please refer to supervisor documentation)
2013-09-15 07:34:53 +02:00
// MEMORY REQUEST INTERFACE
io.mem.req.valid := cmd.valid && doLoad && !stallReg && !stallResp
2013-09-15 07:34:53 +02:00
io.mem.req.bits.addr := addend
io.mem.req.bits.tag := addr
2013-09-15 07:34:53 +02:00
io.mem.req.bits.cmd := M_XRD // perform a load (M_XWR for stores)
io.mem.req.bits.typ := MT_D // D = 8 bytes, W = 4, H = 2, B = 1
io.mem.req.bits.data := Bits(0) // we're not performing any stores...
io.mem.invalidate_lr := false
2014-05-15 01:17:39 +02:00
io.imem.acquire.valid := false
io.imem.grant.ready := false
io.dmem.head.acquire.valid := false
io.dmem.head.grant.ready := false
2014-05-15 01:17:39 +02:00
io.iptw.req.valid := false
io.dptw.req.valid := false
io.pptw.req.valid := false
2013-09-15 00:31:50 +02:00
}