def __init__(self, nways, nlines, nwords, base, limit): if not nlines or nlines & nlines-1: raise ValueError("nlines must be a power of 2, not {!r}".format(nlines)) if nwords not in {4, 8, 16}: raise ValueError("nwords must be 4, 8 or 16, not {!r}".format(nwords)) if nways not in {1, 2}: raise ValueError("nways must be 1 or 2, not {!r}".format(nways)) self.nways = nways self.nlines = nlines self.nwords = nwords self.base = base self.limit = limit offsetbits = log2_int(nwords) linebits = log2_int(nlines) tagbits = log2_int(limit-base) - log2_int(nlines) - log2_int(nwords) - 2 self.s1_addr = Record([("offset", offsetbits), ("line", linebits), ("tag", tagbits)]) self.s1_flush = Signal() self.s1_stall = Signal() self.s1_valid = Signal() self.s2_addr = Record.like(self.s1_addr) self.s2_re = Signal() self.s2_evict = Signal() self.s2_valid = Signal() self.bus_valid = Signal() self.bus_error = Signal() self.bus_rdata = Signal(32) self.s2_miss = Signal() self.s2_rdata = Signal(32) self.bus_re = Signal() self.bus_addr = Record.like(self.s1_addr) self.bus_last = Signal()
def elaborate(self, platform): m = Module() dcache = m.submodules.dcache = L1Cache(*self.dcache_args) x_dcache_select = Signal() m_dcache_select = Signal() m.d.comb += x_dcache_select.eq((self.x_addr >= dcache.base) & (self.x_addr < dcache.limit)) with m.If(~self.x_stall): m.d.sync += m_dcache_select.eq(x_dcache_select) m.d.comb += [ dcache.s1_addr.eq(self.x_addr[2:]), dcache.s1_flush.eq(self.x_flush), dcache.s1_stall.eq(self.x_stall), dcache.s1_valid.eq(self.x_valid & x_dcache_select), dcache.s2_addr.eq(self.m_addr[2:]), dcache.s2_re.eq(self.m_load), dcache.s2_evict.eq(self.m_store), dcache.s2_valid.eq(self.m_valid & m_dcache_select) ] wrbuf_din = Record([("addr", 30), ("mask", 4), ("data", 32)]) wrbuf_dout = Record.like(wrbuf_din) wrbuf = m.submodules.wrbuf = SyncFIFO(width=len(wrbuf_din), depth=dcache.nwords) m.d.comb += [ wrbuf.din.eq(wrbuf_din), wrbuf_din.addr.eq(self.x_addr[2:]), wrbuf_din.mask.eq(self.x_mask), wrbuf_din.data.eq(self.x_store_data), wrbuf.we.eq(self.x_store & self.x_valid & x_dcache_select & ~self.x_stall), wrbuf_dout.eq(wrbuf.dout), ] dbus_arbiter = m.submodules.dbus_arbiter = WishboneArbiter() m.d.comb += dbus_arbiter.bus.connect(self.dbus) wrbuf_port = dbus_arbiter.port(priority=0) with m.If(wrbuf_port.cyc): with m.If(wrbuf_port.ack | wrbuf_port.err): m.d.sync += [ wrbuf_port.cyc.eq(0), wrbuf_port.stb.eq(0) ] m.d.comb += wrbuf.re.eq(1) with m.Elif(wrbuf.readable): m.d.sync += [ wrbuf_port.cyc.eq(1), wrbuf_port.stb.eq(1), wrbuf_port.adr.eq(wrbuf_dout.addr), wrbuf_port.sel.eq(wrbuf_dout.mask), wrbuf_port.dat_w.eq(wrbuf_dout.data) ] m.d.comb += wrbuf_port.we.eq(Const(1)) dcache_port = dbus_arbiter.port(priority=1) m.d.comb += [ dcache_port.cyc.eq(dcache.bus_re), dcache_port.stb.eq(dcache.bus_re), dcache_port.adr.eq(dcache.bus_addr), dcache_port.cti.eq(Mux(dcache.bus_last, Cycle.END, Cycle.INCREMENT)), dcache_port.bte.eq(Const(log2_int(dcache.nwords) - 1)), dcache.bus_valid.eq(dcache_port.ack), dcache.bus_error.eq(dcache_port.err), dcache.bus_rdata.eq(dcache_port.dat_r) ] bare_port = dbus_arbiter.port(priority=2) bare_rdata = Signal.like(bare_port.dat_r) with m.If(bare_port.cyc): with m.If(bare_port.ack | bare_port.err | ~self.m_valid): m.d.sync += [ bare_port.cyc.eq(0), bare_port.stb.eq(0), bare_rdata.eq(bare_port.dat_r) ] with m.Elif((self.x_load | self.x_store) & ~x_dcache_select & self.x_valid & ~self.x_stall): m.d.sync += [ bare_port.cyc.eq(1), bare_port.stb.eq(1), bare_port.adr.eq(self.x_addr[2:]), bare_port.sel.eq(self.x_mask), bare_port.we.eq(self.x_store), bare_port.dat_w.eq(self.x_store_data) ] with m.If(self.dbus.cyc & self.dbus.err): m.d.sync += [ self.m_load_error.eq(~self.dbus.we), self.m_store_error.eq(self.dbus.we), self.m_badaddr.eq(self.dbus.adr) ] with m.Elif(~self.m_stall): m.d.sync += [ self.m_load_error.eq(0), self.m_store_error.eq(0) ] with m.If(self.x_fence_i): m.d.comb += self.x_busy.eq(wrbuf.readable) with m.Elif(x_dcache_select): m.d.comb += self.x_busy.eq(self.x_store & ~wrbuf.writable) with m.Else(): m.d.comb += self.x_busy.eq(bare_port.cyc) with m.If(self.m_load_error | self.m_store_error): m.d.comb += [ self.m_busy.eq(0), self.m_load_data.eq(0) ] with m.Elif(m_dcache_select): m.d.comb += [ self.m_busy.eq(dcache.s2_re & dcache.s2_miss), self.m_load_data.eq(dcache.s2_rdata) ] with m.Else(): m.d.comb += [ self.m_busy.eq(bare_port.cyc), self.m_load_data.eq(bare_rdata) ] return m
def elaborate(self, platform): m = Module() icache = m.submodules.icache = L1Cache(*self.icache_args) a_icache_select = Signal() f_icache_select = Signal() m.d.comb += a_icache_select.eq((self.a_pc >= icache.base) & (self.a_pc < icache.limit)) with m.If(~self.a_stall): m.d.sync += f_icache_select.eq(a_icache_select) m.d.comb += [ icache.s1_addr.eq(self.a_pc[2:]), icache.s1_flush.eq(self.a_flush), icache.s1_stall.eq(self.a_stall), icache.s1_valid.eq(self.a_valid & a_icache_select), icache.s2_addr.eq(self.f_pc[2:]), icache.s2_re.eq(Const(1)), icache.s2_evict.eq(Const(0)), icache.s2_valid.eq(self.f_valid & f_icache_select) ] ibus_arbiter = m.submodules.ibus_arbiter = WishboneArbiter() m.d.comb += ibus_arbiter.bus.connect(self.ibus) icache_port = ibus_arbiter.port(priority=0) m.d.comb += [ icache_port.cyc.eq(icache.bus_re), icache_port.stb.eq(icache.bus_re), icache_port.adr.eq(icache.bus_addr), icache_port.cti.eq(Mux(icache.bus_last, Cycle.END, Cycle.INCREMENT)), icache_port.bte.eq(Const(log2_int(icache.nwords) - 1)), icache.bus_valid.eq(icache_port.ack), icache.bus_error.eq(icache_port.err), icache.bus_rdata.eq(icache_port.dat_r) ] bare_port = ibus_arbiter.port(priority=1) bare_rdata = Signal.like(bare_port.dat_r) with m.If(bare_port.cyc): with m.If(bare_port.ack | bare_port.err | ~self.f_valid): m.d.sync += [ bare_port.cyc.eq(0), bare_port.stb.eq(0), bare_rdata.eq(bare_port.dat_r) ] with m.Elif(~a_icache_select & self.a_valid & ~self.a_stall): m.d.sync += [ bare_port.cyc.eq(1), bare_port.stb.eq(1), bare_port.adr.eq(self.a_pc[2:]) ] with m.If(self.ibus.cyc & self.ibus.err): m.d.sync += [ self.f_fetch_error.eq(1), self.f_badaddr.eq(self.ibus.adr) ] with m.Elif(~self.f_stall): m.d.sync += self.f_fetch_error.eq(0) with m.If(a_icache_select): m.d.comb += self.a_busy.eq(0) with m.Else(): m.d.comb += self.a_busy.eq(bare_port.cyc) with m.If(self.f_fetch_error): m.d.comb += [ self.f_busy.eq(0), self.f_instruction.eq(0x00000013) # nop (addi x0, x0, 0) ] with m.Elif(f_icache_select): m.d.comb += [ self.f_busy.eq(icache.s2_re & icache.s2_miss), self.f_instruction.eq(icache.s2_rdata) ] with m.Else(): m.d.comb += [ self.f_busy.eq(bare_port.cyc), self.f_instruction.eq(bare_rdata) ] return m
def tagbits(self): wordbits = log2_int(32 // 8) addressbits = log2_int(self.limit - self.base) return addressbits - (wordbits + self.offsetbits + self.linebits)
def linebits(self): return log2_int(self.nb_lines) - self.offsetbits
def offsetbits(self): return log2_int(self.nb_words)