Ejemplo n.º 1
0
    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()
Ejemplo n.º 2
0
    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
Ejemplo n.º 3
0
    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
Ejemplo n.º 4
0
 def tagbits(self):
     wordbits = log2_int(32 // 8)
     addressbits = log2_int(self.limit - self.base)
     return addressbits - (wordbits + self.offsetbits + self.linebits)
Ejemplo n.º 5
0
 def linebits(self):
     return log2_int(self.nb_lines) - self.offsetbits
Ejemplo n.º 6
0
 def offsetbits(self):
     return log2_int(self.nb_words)