2013-09-13 07:34:38 +02:00
|
|
|
package rocket
|
|
|
|
|
|
|
|
import Chisel._
|
|
|
|
import Node._
|
2013-09-15 07:34:53 +02:00
|
|
|
import uncore._
|
2013-09-13 07:34:38 +02:00
|
|
|
|
2013-09-15 00:31:50 +02:00
|
|
|
class RoCCInstruction extends Bundle
|
|
|
|
{
|
|
|
|
val funct = Bits(width = 7)
|
2013-09-22 12:18:06 +02:00
|
|
|
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()
|
2013-09-22 12:18:06 +02:00
|
|
|
val rd = Bits(width = 5)
|
2013-09-15 00:31:50 +02:00
|
|
|
val opcode = Bits(width = 7)
|
|
|
|
}
|
|
|
|
|
2014-05-10 04:30:05 +02:00
|
|
|
class RoCCCommand(implicit val conf: RocketConfiguration) extends BundleWithConf
|
2013-09-15 00:31:50 +02:00
|
|
|
{
|
|
|
|
val inst = new RoCCInstruction
|
|
|
|
val rs1 = Bits(width = conf.xprlen)
|
|
|
|
val rs2 = Bits(width = conf.xprlen)
|
|
|
|
}
|
|
|
|
|
2014-05-10 04:30:05 +02:00
|
|
|
class RoCCResponse(implicit val conf: RocketConfiguration) extends BundleWithConf
|
2013-09-15 00:31:50 +02:00
|
|
|
{
|
|
|
|
val rd = Bits(width = 5)
|
|
|
|
val data = Bits(width = conf.xprlen)
|
|
|
|
}
|
|
|
|
|
2014-05-10 04:30:05 +02:00
|
|
|
class RoCCInterface(implicit val conf: RocketConfiguration) extends BundleWithConf
|
2013-09-15 00:31:50 +02:00
|
|
|
{
|
2014-04-02 02:15:46 +02:00
|
|
|
implicit val as = conf.as
|
2013-09-15 00:31:50 +02:00
|
|
|
val cmd = Decoupled(new RoCCCommand).flip
|
|
|
|
val resp = Decoupled(new RoCCResponse)
|
2013-09-15 07:34:53 +02:00
|
|
|
val mem = new HellaCacheIO()(conf.dcache)
|
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
|
2013-11-06 02:12:09 +01:00
|
|
|
val imem = new UncachedTileLinkIO()(conf.tl)
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2013-09-15 07:34:53 +02:00
|
|
|
abstract class RoCC(conf: RocketConfiguration) extends Module
|
2013-09-15 00:31:50 +02:00
|
|
|
{
|
2013-09-15 07:34:53 +02:00
|
|
|
val io = new RoCCInterface()(conf)
|
2013-09-24 22:53:49 +02:00
|
|
|
|
|
|
|
io.mem.req.bits.phys := Bool(true) // don't perform address translation
|
2013-09-15 00:31:50 +02:00
|
|
|
}
|
|
|
|
|
2013-09-15 07:34:53 +02:00
|
|
|
class AccumulatorExample(conf: RocketConfiguration) extends RoCC(conf)
|
2013-09-15 00:31:50 +02:00
|
|
|
{
|
2013-09-15 07:34:53 +02:00
|
|
|
val n = 4
|
|
|
|
val regfile = Mem(UInt(width = conf.xprlen), n)
|
|
|
|
val busy = Vec.fill(n){Reg(init=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.inst.rs2(log2Up(n)-1,0)
|
|
|
|
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
|
|
|
|
|
2013-09-24 19:54:09 +02:00
|
|
|
cmd.ready := !stallReg && !stallLoad && !stallResp
|
2013-09-23 09:21:43 +02:00
|
|
|
// command resolved if no stalls AND not issuing a load that will need a request
|
|
|
|
|
2013-09-25 01:32:49 +02:00
|
|
|
// PROC RESPONSE INTERFACE
|
2013-09-24 19:54:09 +02:00
|
|
|
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
|
2013-09-25 01:32:49 +02:00
|
|
|
// 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
|
|
|
|
2013-09-25 01:32:49 +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)
|
2013-09-25 01:32:49 +02:00
|
|
|
// Set this true to trigger an interrupt on the processor (please refer to supervisor documentation)
|
2013-09-15 07:34:53 +02:00
|
|
|
|
2013-09-25 01:32:49 +02:00
|
|
|
// MEMORY REQUEST INTERFACE
|
2013-09-24 19:54:09 +02:00
|
|
|
io.mem.req.valid := cmd.valid && doLoad && !stallReg && !stallResp
|
2013-09-15 07:34:53 +02:00
|
|
|
io.mem.req.bits.addr := addend
|
2013-09-24 19:54:09 +02:00
|
|
|
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...
|
2013-09-15 00:31:50 +02:00
|
|
|
}
|