2014-09-13 00:31:38 +02:00
|
|
|
// See LICENSE for license details.
|
|
|
|
|
2013-11-08 00:42:10 +01:00
|
|
|
package uncore
|
2013-11-07 22:19:04 +01:00
|
|
|
|
|
|
|
import Chisel._
|
2015-07-23 23:58:46 +02:00
|
|
|
import Chisel.ImplicitConversions._
|
2015-09-01 23:47:18 +02:00
|
|
|
import junctions.SMIIO
|
2013-11-07 22:19:04 +01:00
|
|
|
|
2014-08-08 21:21:57 +02:00
|
|
|
case object HTIFWidth extends Field[Int]
|
|
|
|
case object HTIFNSCR extends Field[Int]
|
|
|
|
case object HTIFOffsetBits extends Field[Int]
|
|
|
|
case object HTIFNCores extends Field[Int]
|
2015-09-25 21:07:03 +02:00
|
|
|
case object HTIFSCRDataBits extends Field[Int]
|
2014-08-08 21:21:57 +02:00
|
|
|
|
2014-08-25 04:27:58 +02:00
|
|
|
abstract trait HTIFParameters extends UsesParameters {
|
|
|
|
val dataBits = params(TLDataBits)
|
2014-12-07 12:02:20 +01:00
|
|
|
val dataBeats = params(TLDataBeats)
|
2014-08-25 04:27:58 +02:00
|
|
|
val w = params(HTIFWidth)
|
|
|
|
val nSCR = params(HTIFNSCR)
|
2015-09-01 23:47:18 +02:00
|
|
|
val scrAddrBits = log2Up(nSCR)
|
2015-09-25 21:07:03 +02:00
|
|
|
val scrDataBits = params(HTIFSCRDataBits)
|
|
|
|
val scrDataBytes = scrDataBits / 8
|
2014-08-25 04:27:58 +02:00
|
|
|
val offsetBits = params(HTIFOffsetBits)
|
|
|
|
val nCores = params(HTIFNCores)
|
|
|
|
}
|
|
|
|
|
|
|
|
abstract class HTIFBundle extends Bundle with HTIFParameters
|
|
|
|
|
|
|
|
class HostIO extends HTIFBundle
|
2013-11-07 22:19:04 +01:00
|
|
|
{
|
|
|
|
val clk = Bool(OUTPUT)
|
|
|
|
val clk_edge = Bool(OUTPUT)
|
|
|
|
val in = Decoupled(Bits(width = w)).flip
|
|
|
|
val out = Decoupled(Bits(width = w))
|
|
|
|
val debug_stats_pcr = Bool(OUTPUT)
|
|
|
|
}
|
|
|
|
|
2014-08-25 04:27:58 +02:00
|
|
|
class HTIFIO extends HTIFBundle {
|
2013-11-07 22:19:04 +01:00
|
|
|
val reset = Bool(INPUT)
|
2014-08-25 04:27:58 +02:00
|
|
|
val id = UInt(INPUT, log2Up(nCores))
|
2015-09-25 21:07:03 +02:00
|
|
|
val pcr = new SMIIO(scrDataBits, 12).flip
|
2014-08-25 04:27:58 +02:00
|
|
|
val ipi_req = Decoupled(Bits(width = log2Up(nCores)))
|
2013-11-07 22:19:04 +01:00
|
|
|
val ipi_rep = Decoupled(Bool()).flip
|
|
|
|
val debug_stats_pcr = Bool(OUTPUT)
|
|
|
|
// wired directly to stats register
|
|
|
|
// expected to be used to quickly indicate to testbench to do logging b/c in 'interesting' work
|
|
|
|
}
|
|
|
|
|
2015-09-11 02:53:42 +02:00
|
|
|
class HTIF(pcr_RESET: Int) extends Module with HTIFParameters {
|
|
|
|
val io = new Bundle {
|
2014-08-25 04:27:58 +02:00
|
|
|
val host = new HostIO
|
2015-08-27 18:47:02 +02:00
|
|
|
val cpu = Vec(new HTIFIO, nCores).flip
|
2015-04-18 01:55:20 +02:00
|
|
|
val mem = new ClientUncachedTileLinkIO
|
2015-09-25 21:07:03 +02:00
|
|
|
val scr = new SMIIO(scrDataBits, scrAddrBits)
|
2015-09-11 02:53:42 +02:00
|
|
|
}
|
2014-08-08 21:21:57 +02:00
|
|
|
|
2013-11-07 22:19:04 +01:00
|
|
|
io.host.debug_stats_pcr := io.cpu.map(_.debug_stats_pcr).reduce(_||_)
|
|
|
|
// system is 'interesting' if any tile is 'interesting'
|
|
|
|
|
|
|
|
val short_request_bits = 64
|
2014-12-07 12:02:20 +01:00
|
|
|
val long_request_bits = short_request_bits + dataBits*dataBeats
|
2013-11-07 22:19:04 +01:00
|
|
|
require(short_request_bits % w == 0)
|
|
|
|
|
|
|
|
val rx_count_w = 13 + log2Up(64) - log2Up(w) // data size field is 12 bits
|
|
|
|
val rx_count = Reg(init=UInt(0,rx_count_w))
|
|
|
|
val rx_shifter = Reg(Bits(width = short_request_bits))
|
|
|
|
val rx_shifter_in = Cat(io.host.in.bits, rx_shifter(short_request_bits-1,w))
|
|
|
|
val next_cmd = rx_shifter_in(3,0)
|
|
|
|
val cmd = Reg(Bits())
|
|
|
|
val size = Reg(Bits())
|
|
|
|
val pos = Reg(Bits())
|
|
|
|
val seqno = Reg(Bits())
|
|
|
|
val addr = Reg(Bits())
|
|
|
|
when (io.host.in.valid && io.host.in.ready) {
|
|
|
|
rx_shifter := rx_shifter_in
|
|
|
|
rx_count := rx_count + UInt(1)
|
|
|
|
when (rx_count === UInt(short_request_bits/w-1)) {
|
|
|
|
cmd := next_cmd
|
|
|
|
size := rx_shifter_in(15,4)
|
2014-04-02 02:14:45 +02:00
|
|
|
pos := rx_shifter_in(15,4+offsetBits-3)
|
2013-11-07 22:19:04 +01:00
|
|
|
seqno := rx_shifter_in(23,16)
|
|
|
|
addr := rx_shifter_in(63,24)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-08-04 22:15:17 +02:00
|
|
|
val rx_word_count = (rx_count >> log2Up(short_request_bits/w))
|
2013-11-07 22:19:04 +01:00
|
|
|
val rx_word_done = io.host.in.valid && rx_count(log2Up(short_request_bits/w)-1,0).andR
|
|
|
|
val packet_ram_depth = long_request_bits/short_request_bits-1
|
2014-05-19 04:26:35 +02:00
|
|
|
val packet_ram = Mem(Bits(width = short_request_bits), packet_ram_depth)
|
2013-11-07 22:19:04 +01:00
|
|
|
when (rx_word_done && io.host.in.ready) {
|
|
|
|
packet_ram(rx_word_count(log2Up(packet_ram_depth)-1,0) - UInt(1)) := rx_shifter_in
|
|
|
|
}
|
|
|
|
|
|
|
|
val cmd_readmem :: cmd_writemem :: cmd_readcr :: cmd_writecr :: cmd_ack :: cmd_nack :: Nil = Enum(UInt(), 6)
|
|
|
|
|
2015-08-13 06:23:17 +02:00
|
|
|
val pcr_addr = addr(io.cpu(0).pcr.req.bits.addr.getWidth-1, 0)
|
2014-08-08 21:21:57 +02:00
|
|
|
val pcr_coreid = addr(log2Up(nCores)-1+20+1,20)
|
2013-11-07 22:19:04 +01:00
|
|
|
val pcr_wdata = packet_ram(0)
|
|
|
|
|
2014-04-02 02:14:45 +02:00
|
|
|
val bad_mem_packet = size(offsetBits-1-3,0).orR || addr(offsetBits-1-3,0).orR
|
2013-11-07 22:19:04 +01:00
|
|
|
val nack = Mux(cmd === cmd_readmem || cmd === cmd_writemem, bad_mem_packet,
|
|
|
|
Mux(cmd === cmd_readcr || cmd === cmd_writecr, size != UInt(1),
|
|
|
|
Bool(true)))
|
|
|
|
|
|
|
|
val tx_count = Reg(init=UInt(0, rx_count_w))
|
|
|
|
val tx_subword_count = tx_count(log2Up(short_request_bits/w)-1,0)
|
|
|
|
val tx_word_count = tx_count(rx_count_w-1, log2Up(short_request_bits/w))
|
|
|
|
val packet_ram_raddr = tx_word_count(log2Up(packet_ram_depth)-1,0) - UInt(1)
|
|
|
|
when (io.host.out.valid && io.host.out.ready) {
|
|
|
|
tx_count := tx_count + UInt(1)
|
|
|
|
}
|
|
|
|
|
|
|
|
val rx_done = rx_word_done && Mux(rx_word_count === UInt(0), next_cmd != cmd_writemem && next_cmd != cmd_writecr, rx_word_count === size || rx_word_count(log2Up(packet_ram_depth)-1,0) === UInt(0))
|
|
|
|
val tx_size = Mux(!nack && (cmd === cmd_readmem || cmd === cmd_readcr || cmd === cmd_writecr), size, UInt(0))
|
|
|
|
val tx_done = io.host.out.ready && tx_subword_count.andR && (tx_word_count === tx_size || tx_word_count > UInt(0) && packet_ram_raddr.andR)
|
|
|
|
|
2015-03-24 10:06:53 +01:00
|
|
|
val state_rx :: state_pcr_req :: state_pcr_resp :: state_mem_rreq :: state_mem_wreq :: state_mem_rresp :: state_mem_wresp :: state_tx :: Nil = Enum(UInt(), 8)
|
2013-11-07 22:19:04 +01:00
|
|
|
val state = Reg(init=state_rx)
|
|
|
|
|
2015-03-24 10:06:53 +01:00
|
|
|
val (cnt, cnt_done) = Counter((state === state_mem_wreq && io.mem.acquire.ready) ||
|
|
|
|
(state === state_mem_rresp && io.mem.grant.valid), dataBeats)
|
2013-11-07 22:19:04 +01:00
|
|
|
val rx_cmd = Mux(rx_word_count === UInt(0), next_cmd, cmd)
|
|
|
|
when (state === state_rx && rx_done) {
|
2014-03-29 18:53:49 +01:00
|
|
|
state := Mux(rx_cmd === cmd_readmem, state_mem_rreq,
|
|
|
|
Mux(rx_cmd === cmd_writemem, state_mem_wreq,
|
2013-11-07 22:19:04 +01:00
|
|
|
Mux(rx_cmd === cmd_readcr || rx_cmd === cmd_writecr, state_pcr_req,
|
2014-03-29 18:53:49 +01:00
|
|
|
state_tx)))
|
2013-11-07 22:19:04 +01:00
|
|
|
}
|
2014-12-07 12:02:20 +01:00
|
|
|
when (state === state_mem_wreq) {
|
|
|
|
when (cnt_done) { state := state_mem_wresp }
|
2013-11-07 22:19:04 +01:00
|
|
|
}
|
2014-12-07 12:02:20 +01:00
|
|
|
when (state === state_mem_rreq) {
|
|
|
|
when(io.mem.acquire.ready) { state := state_mem_rresp }
|
2013-11-07 22:19:04 +01:00
|
|
|
}
|
2015-03-24 10:06:53 +01:00
|
|
|
when (state === state_mem_wresp && io.mem.grant.valid) {
|
|
|
|
state := Mux(cmd === cmd_readmem || pos === UInt(1), state_tx, state_rx)
|
|
|
|
pos := pos - UInt(1)
|
|
|
|
addr := addr + UInt(1 << offsetBits-3)
|
2013-11-07 22:19:04 +01:00
|
|
|
}
|
2015-03-24 10:06:53 +01:00
|
|
|
when (state === state_mem_rresp && cnt_done) {
|
2013-11-07 22:19:04 +01:00
|
|
|
state := Mux(cmd === cmd_readmem || pos === UInt(1), state_tx, state_rx)
|
|
|
|
pos := pos - UInt(1)
|
2014-04-02 02:14:45 +02:00
|
|
|
addr := addr + UInt(1 << offsetBits-3)
|
2013-11-07 22:19:04 +01:00
|
|
|
}
|
|
|
|
when (state === state_tx && tx_done) {
|
|
|
|
when (tx_word_count === tx_size) {
|
|
|
|
rx_count := UInt(0)
|
|
|
|
tx_count := UInt(0)
|
|
|
|
}
|
2014-03-29 18:53:49 +01:00
|
|
|
state := Mux(cmd === cmd_readmem && pos != UInt(0), state_mem_rreq, state_rx)
|
2013-11-07 22:19:04 +01:00
|
|
|
}
|
|
|
|
|
2015-02-02 04:57:53 +01:00
|
|
|
val n = dataBits/short_request_bits
|
|
|
|
val mem_req_data = (0 until n).map { i =>
|
|
|
|
val ui = UInt(i, log2Up(n))
|
2014-03-29 18:53:49 +01:00
|
|
|
when (state === state_mem_rresp && io.mem.grant.valid) {
|
2015-03-24 10:06:53 +01:00
|
|
|
packet_ram(Cat(io.mem.grant.bits.addr_beat, ui)) :=
|
|
|
|
io.mem.grant.bits.data((i+1)*short_request_bits-1, i*short_request_bits)
|
2013-11-07 22:19:04 +01:00
|
|
|
}
|
2015-02-02 04:57:53 +01:00
|
|
|
packet_ram(Cat(cnt, ui))
|
|
|
|
}.reverse.reduce(_##_)
|
|
|
|
|
2015-08-04 22:15:17 +02:00
|
|
|
val init_addr = addr.toUInt >> (offsetBits-3)
|
2014-12-07 12:02:20 +01:00
|
|
|
io.mem.acquire.valid := state === state_mem_rreq || state === state_mem_wreq
|
2015-03-10 00:34:59 +01:00
|
|
|
io.mem.acquire.bits := Mux(cmd === cmd_writemem,
|
2015-03-01 02:02:13 +01:00
|
|
|
PutBlock(
|
2015-02-02 04:57:53 +01:00
|
|
|
addr_block = init_addr,
|
|
|
|
addr_beat = cnt,
|
|
|
|
client_xact_id = UInt(0),
|
2015-05-14 21:37:35 +02:00
|
|
|
data = mem_req_data),
|
2015-03-01 02:02:13 +01:00
|
|
|
GetBlock(addr_block = init_addr))
|
2015-03-24 10:06:53 +01:00
|
|
|
io.mem.grant.ready := Bool(true)
|
2013-11-07 22:19:04 +01:00
|
|
|
|
2015-08-13 06:23:17 +02:00
|
|
|
val pcrReadData = Reg(Bits(width = io.cpu(0).pcr.resp.bits.getWidth))
|
2014-08-08 21:21:57 +02:00
|
|
|
for (i <- 0 until nCores) {
|
2013-11-07 22:19:04 +01:00
|
|
|
val my_reset = Reg(init=Bool(true))
|
|
|
|
val my_ipi = Reg(init=Bool(false))
|
|
|
|
|
|
|
|
val cpu = io.cpu(i)
|
|
|
|
val me = pcr_coreid === UInt(i)
|
2015-08-13 06:23:17 +02:00
|
|
|
cpu.pcr.req.valid := state === state_pcr_req && me && pcr_addr != UInt(pcr_RESET)
|
|
|
|
cpu.pcr.req.bits.rw := cmd === cmd_writecr
|
|
|
|
cpu.pcr.req.bits.addr := pcr_addr
|
|
|
|
cpu.pcr.req.bits.data := pcr_wdata
|
2013-11-07 22:19:04 +01:00
|
|
|
cpu.reset := my_reset
|
|
|
|
|
|
|
|
when (cpu.ipi_rep.ready) {
|
|
|
|
my_ipi := Bool(false)
|
|
|
|
}
|
|
|
|
cpu.ipi_rep.valid := my_ipi
|
|
|
|
cpu.ipi_req.ready := Bool(true)
|
2014-08-08 21:21:57 +02:00
|
|
|
for (j <- 0 until nCores) {
|
2013-11-07 22:19:04 +01:00
|
|
|
when (io.cpu(j).ipi_req.valid && io.cpu(j).ipi_req.bits === UInt(i)) {
|
|
|
|
my_ipi := Bool(true)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-01 23:47:18 +02:00
|
|
|
when (cpu.pcr.req.fire()) { state := state_pcr_resp }
|
|
|
|
|
2015-03-14 10:15:24 +01:00
|
|
|
when (state === state_pcr_req && me && pcr_addr === UInt(pcr_RESET)) {
|
2013-11-07 22:19:04 +01:00
|
|
|
when (cmd === cmd_writecr) {
|
|
|
|
my_reset := pcr_wdata(0)
|
|
|
|
}
|
|
|
|
pcrReadData := my_reset.toBits
|
|
|
|
state := state_tx
|
|
|
|
}
|
|
|
|
|
2015-08-13 06:23:17 +02:00
|
|
|
cpu.pcr.resp.ready := Bool(true)
|
|
|
|
when (state === state_pcr_resp && cpu.pcr.resp.valid) {
|
|
|
|
pcrReadData := cpu.pcr.resp.bits
|
2013-11-07 22:19:04 +01:00
|
|
|
state := state_tx
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-01 23:47:18 +02:00
|
|
|
io.scr.req.valid := (state === state_pcr_req && pcr_coreid.andR)
|
|
|
|
io.scr.req.bits.addr := addr(scrAddrBits - 1, 0).toUInt
|
|
|
|
io.scr.req.bits.data := pcr_wdata
|
|
|
|
io.scr.req.bits.rw := (cmd === cmd_writecr)
|
|
|
|
io.scr.resp.ready := Bool(true)
|
|
|
|
|
|
|
|
when (io.scr.req.fire()) { state := state_pcr_resp }
|
|
|
|
when (state === state_pcr_resp && io.scr.resp.valid) {
|
|
|
|
pcrReadData := io.scr.resp.bits
|
2013-11-07 22:19:04 +01:00
|
|
|
state := state_tx
|
|
|
|
}
|
|
|
|
|
|
|
|
val tx_cmd = Mux(nack, cmd_nack, cmd_ack)
|
|
|
|
val tx_cmd_ext = Cat(Bits(0, 4-tx_cmd.getWidth), tx_cmd)
|
|
|
|
val tx_header = Cat(addr, seqno, tx_size, tx_cmd_ext)
|
|
|
|
val tx_data = Mux(tx_word_count === UInt(0), tx_header,
|
|
|
|
Mux(cmd === cmd_readcr || cmd === cmd_writecr, pcrReadData,
|
|
|
|
packet_ram(packet_ram_raddr)))
|
|
|
|
|
|
|
|
io.host.in.ready := state === state_rx
|
|
|
|
io.host.out.valid := state === state_tx
|
|
|
|
io.host.out.bits := tx_data >> Cat(tx_count(log2Up(short_request_bits/w)-1,0), Bits(0, log2Up(w)))
|
|
|
|
}
|