unify cache backend interfaces; generify arbiter
This commit is contained in:
parent
7034c9be65
commit
6135615104
@ -18,74 +18,48 @@ class ioMem() extends Bundle
|
|||||||
val resp_data = Bits(MEM_DATA_BITS, INPUT);
|
val resp_data = Bits(MEM_DATA_BITS, INPUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
class ioMemArbiter extends Bundle() {
|
class ioMemArbiter(n: Int) extends Bundle() {
|
||||||
val mem = new ioMem();
|
val mem = new ioMem();
|
||||||
val dcache = new ioDCache();
|
val requestor = Vec(n) { new ioDCache() }
|
||||||
// val icache = new ioICache();
|
|
||||||
val icache = new ioIPrefetcherMem().flip();
|
|
||||||
val vicache = new ioICache();
|
|
||||||
val htif = new ioDCache();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class rocketMemArbiter extends Component {
|
class rocketMemArbiter(n: Int) extends Component {
|
||||||
val io = new ioMemArbiter();
|
val io = new ioMemArbiter(n);
|
||||||
|
require(io.mem.req_tag.getWidth >= log2up(n) + io.requestor(0).req_tag.getWidth)
|
||||||
|
|
||||||
// *****************************
|
var req_val = Bool(false)
|
||||||
// Interface to memory
|
var req_rdy = io.mem.req_rdy
|
||||||
// *****************************
|
for (i <- 0 until n)
|
||||||
|
{
|
||||||
|
io.requestor(i).req_rdy := req_rdy
|
||||||
|
req_val = req_val || io.requestor(i).req_val
|
||||||
|
req_rdy = req_rdy && !io.requestor(i).req_val
|
||||||
|
}
|
||||||
|
|
||||||
// Memory request is valid if either icache or dcache have a valid request
|
var req_rw = io.requestor(n-1).req_rw
|
||||||
io.mem.req_val := io.icache.req_val || io.vicache.req_val || io.dcache.req_val || io.htif.req_val
|
var req_addr = io.requestor(n-1).req_addr
|
||||||
|
var req_wdata = io.requestor(n-1).req_wdata
|
||||||
|
var req_tag = Cat(io.requestor(n-1).req_tag, UFix(n-1, log2up(n)))
|
||||||
|
for (i <- n-1 to 0 by -1)
|
||||||
|
{
|
||||||
|
req_rw = Mux(io.requestor(i).req_val, io.requestor(i).req_rw, req_rw)
|
||||||
|
req_addr = Mux(io.requestor(i).req_val, io.requestor(i).req_addr, req_addr)
|
||||||
|
req_wdata = Mux(io.requestor(i).req_val, io.requestor(i).req_wdata, req_wdata)
|
||||||
|
req_tag = Mux(io.requestor(i).req_val, Cat(io.requestor(i).req_tag, UFix(i, log2up(n))), req_tag)
|
||||||
|
}
|
||||||
|
|
||||||
// Set read/write bit. I$ always reads
|
io.mem.req_val := req_val
|
||||||
io.mem.req_rw :=
|
io.mem.req_rw := req_rw
|
||||||
Mux(io.dcache.req_val, io.dcache.req_rw,
|
io.mem.req_addr := req_addr
|
||||||
Mux(io.icache.req_val, Bool(false),
|
io.mem.req_wdata := req_wdata
|
||||||
Mux(io.vicache.req_val, Bool(false),
|
io.mem.req_tag := req_tag
|
||||||
io.htif.req_rw)))
|
|
||||||
|
|
||||||
// Give priority to D$
|
for (i <- 0 until n)
|
||||||
io.mem.req_addr :=
|
{
|
||||||
Mux(io.dcache.req_val, io.dcache.req_addr,
|
io.requestor(i).resp_val := io.mem.resp_val && io.mem.resp_tag(log2up(n)-1,0) === UFix(i)
|
||||||
Mux(io.icache.req_val, io.icache.req_addr,
|
io.requestor(i).resp_data := io.mem.resp_data
|
||||||
Mux(io.vicache.req_val, io.vicache.req_addr,
|
io.requestor(i).resp_tag := io.mem.resp_tag >> UFix(log2up(n))
|
||||||
io.htif.req_addr)))
|
}
|
||||||
|
|
||||||
io.mem.req_wdata := Mux(io.dcache.req_val, io.dcache.req_wdata, io.htif.req_wdata)
|
|
||||||
|
|
||||||
// low bit of tag to indicate D$, I$, and VI$
|
|
||||||
val t_dcache :: t_icache :: t_vicache :: t_htif :: Nil = Enum(4){ UFix() }
|
|
||||||
io.mem.req_tag :=
|
|
||||||
Mux(io.dcache.req_val, Cat(io.dcache.req_tag, t_dcache),
|
|
||||||
Mux(io.icache.req_val, Cat(io.icache.req_tag, t_icache),
|
|
||||||
Mux(io.vicache.req_val, t_vicache,
|
|
||||||
t_htif)))
|
|
||||||
|
|
||||||
// *****************************
|
|
||||||
// Interface to caches
|
|
||||||
// *****************************
|
|
||||||
|
|
||||||
// Read for request from cache if the memory is ready. Give priority to D$.
|
|
||||||
// This way, writebacks will never be interrupted by I$ refills.
|
|
||||||
io.dcache.req_rdy := io.mem.req_rdy;
|
|
||||||
io.icache.req_rdy := io.mem.req_rdy && !io.dcache.req_val;
|
|
||||||
io.vicache.req_rdy := io.mem.req_rdy && !io.dcache.req_val && !io.icache.req_val
|
|
||||||
io.htif.req_rdy := io.mem.req_rdy && !io.dcache.req_val && !io.icache.req_val && !io.vicache.req_val
|
|
||||||
|
|
||||||
// Response will only be valid for D$ or I$ not both because of tag bits
|
|
||||||
io.dcache.resp_val := io.mem.resp_val && (io.mem.resp_tag(1,0) === t_dcache)
|
|
||||||
io.icache.resp_val := io.mem.resp_val && (io.mem.resp_tag(1,0) === t_icache)
|
|
||||||
io.vicache.resp_val := io.mem.resp_val && (io.mem.resp_tag(1,0) === t_vicache)
|
|
||||||
io.htif.resp_val := io.mem.resp_val && (io.mem.resp_tag(1,0) === t_htif)
|
|
||||||
|
|
||||||
// Feed through data to both
|
|
||||||
io.dcache.resp_data := io.mem.resp_data;
|
|
||||||
io.icache.resp_data := io.mem.resp_data;
|
|
||||||
io.vicache.resp_data := io.mem.resp_data
|
|
||||||
io.htif.resp_data := io.mem.resp_data
|
|
||||||
|
|
||||||
io.dcache.resp_tag := io.mem.resp_tag >> UFix(2)
|
|
||||||
io.icache.resp_tag := io.mem.resp_tag >> UFix(2)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,20 +17,10 @@ class ioImem(view: List[String] = null) extends Bundle (view)
|
|||||||
val resp_val = Bool(OUTPUT);
|
val resp_val = Bool(OUTPUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
// interface between I$ and memory (128 bits wide)
|
|
||||||
class ioICache(view: List[String] = null) extends Bundle (view)
|
|
||||||
{
|
|
||||||
val req_addr = UFix(PADDR_BITS - OFFSET_BITS, INPUT);
|
|
||||||
val req_val = Bool(INPUT);
|
|
||||||
val req_rdy = Bool(OUTPUT);
|
|
||||||
val resp_data = Bits(MEM_DATA_BITS, OUTPUT);
|
|
||||||
val resp_val = Bool(OUTPUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
class ioRocketICache extends Bundle()
|
class ioRocketICache extends Bundle()
|
||||||
{
|
{
|
||||||
val cpu = new ioImem();
|
val cpu = new ioImem();
|
||||||
val mem = new ioICache().flip();
|
val mem = new ioDCache().flip()
|
||||||
}
|
}
|
||||||
|
|
||||||
// basic direct mapped instruction cache
|
// basic direct mapped instruction cache
|
||||||
@ -139,6 +129,7 @@ class rocketICache(sets: Int, assoc: Int) extends Component {
|
|||||||
rdy := !io.cpu.itlb_miss && (state === s_ready) && (!r_cpu_req_val || tag_hit);
|
rdy := !io.cpu.itlb_miss && (state === s_ready) && (!r_cpu_req_val || tag_hit);
|
||||||
io.cpu.resp_data := data_mux.io.out
|
io.cpu.resp_data := data_mux.io.out
|
||||||
io.mem.req_val := (state === s_request);
|
io.mem.req_val := (state === s_request);
|
||||||
|
io.mem.req_rw := Bool(false)
|
||||||
io.mem.req_addr := r_cpu_miss_addr(tagmsb,indexlsb).toUFix
|
io.mem.req_addr := r_cpu_miss_addr(tagmsb,indexlsb).toUFix
|
||||||
|
|
||||||
// control state machine
|
// control state machine
|
||||||
|
@ -5,20 +5,9 @@ import Node._;
|
|||||||
import Constants._;
|
import Constants._;
|
||||||
import scala.math._;
|
import scala.math._;
|
||||||
|
|
||||||
class ioIPrefetcherMem(view: List[String] = null) extends Bundle (view)
|
|
||||||
{
|
|
||||||
val req_addr = UFix(PADDR_BITS - OFFSET_BITS, OUTPUT);
|
|
||||||
val req_val = Bool(OUTPUT);
|
|
||||||
val req_rdy = Bool(INPUT);
|
|
||||||
val req_tag = Bits(IMEM_TAG_BITS, OUTPUT);
|
|
||||||
val resp_data = Bits(MEM_DATA_BITS, INPUT);
|
|
||||||
val resp_val = Bool(INPUT);
|
|
||||||
val resp_tag = Bits(IMEM_TAG_BITS, INPUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
class ioIPrefetcher extends Bundle() {
|
class ioIPrefetcher extends Bundle() {
|
||||||
val icache = new ioICache();
|
val icache = new ioDCache();
|
||||||
val mem = new ioIPrefetcherMem();
|
val mem = new ioDCache().flip()
|
||||||
val invalidate = Bool(INPUT)
|
val invalidate = Bool(INPUT)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,7 +30,8 @@ class rocketIPrefetcher extends Component() {
|
|||||||
val ip_mem_resp_val = io.mem.resp_val && io.mem.resp_tag(0).toBool;
|
val ip_mem_resp_val = io.mem.resp_val && io.mem.resp_tag(0).toBool;
|
||||||
|
|
||||||
io.mem.req_val := io.icache.req_val & ~hit | (state === s_req_wait);
|
io.mem.req_val := io.icache.req_val & ~hit | (state === s_req_wait);
|
||||||
io.mem.req_tag := !(io.icache.req_val && !hit);
|
io.mem.req_rw := Bool(false)
|
||||||
|
io.mem.req_tag := Mux(io.icache.req_val && !hit, UFix(0), UFix(1))
|
||||||
io.mem.req_addr := Mux(io.mem.req_tag(0).toBool, prefetch_addr, io.icache.req_addr);
|
io.mem.req_addr := Mux(io.mem.req_tag(0).toBool, prefetch_addr, io.icache.req_addr);
|
||||||
|
|
||||||
val fill_cnt = Reg(resetVal = UFix(0, ceil(log(REFILL_CYCLES)/log(2)).toInt));
|
val fill_cnt = Reg(resetVal = UFix(0, ceil(log(REFILL_CYCLES)/log(2)).toInt));
|
||||||
|
@ -21,13 +21,13 @@ class Top() extends Component {
|
|||||||
val icache_pf = new rocketIPrefetcher();
|
val icache_pf = new rocketIPrefetcher();
|
||||||
val vicache = new rocketICache(128, 2); // 128 sets x 2 ways
|
val vicache = new rocketICache(128, 2); // 128 sets x 2 ways
|
||||||
val dcache = new HellaCacheUniproc();
|
val dcache = new HellaCacheUniproc();
|
||||||
val arbiter = new rocketMemArbiter();
|
|
||||||
|
|
||||||
arbiter.io.mem <> io.mem;
|
val arbiter = new rocketMemArbiter(4);
|
||||||
arbiter.io.dcache <> dcache.io.mem;
|
arbiter.io.requestor(0) <> dcache.io.mem
|
||||||
arbiter.io.icache <> icache_pf.io.mem;
|
arbiter.io.requestor(1) <> icache_pf.io.mem
|
||||||
arbiter.io.vicache <> vicache.io.mem
|
arbiter.io.requestor(2) <> vicache.io.mem
|
||||||
arbiter.io.htif <> htif.io.mem
|
arbiter.io.requestor(3) <> htif.io.mem
|
||||||
|
arbiter.io.mem <> io.mem
|
||||||
|
|
||||||
htif.io.host <> io.host
|
htif.io.host <> io.host
|
||||||
cpu.io.host <> htif.io.cpu(0);
|
cpu.io.host <> htif.io.cpu(0);
|
||||||
|
Loading…
Reference in New Issue
Block a user