Beispiel #1
0
    def _declr(self):
        self._compute_constants()
        addClkRstn(self)
        # used to initialize the LRU data (in the case of cache reset)
        # while set port is active all other ports are blocked
        s = self.set = AddrDataHs()
        s.ADDR_WIDTH = self.INDEX_W
        s.DATA_WIDTH = self.LRU_WIDTH

        # used to increment the LRU data in the case of hit
        self.incr = HObjList(IndexWayHs() for _ in range(self.INCR_PORT_CNT))
        for i in self.incr:
            i.INDEX_WIDTH = self.INDEX_W
            i.WAY_CNT = self.WAY_CNT

        # get a victim for a selected cacheline index
        # The cacheline returned as a victim is also marked as used just now
        vr = self.victim_req = AddrHs()
        vr.ADDR_WIDTH = self.INDEX_W
        vr.ID_WIDTH = 0
        vd = self.victim_data = Handshaked()._m()
        vd.DATA_WIDTH = log2ceil(self.WAY_CNT - 1)

        m = self.lru_mem = RamXorSingleClock()
        m.ADDR_WIDTH = self.INDEX_W
        m.DATA_WIDTH = self.LRU_WIDTH
        m.PORT_CNT = (
            # victim_req preload, victim_req write back or set,
            READ, WRITE,
            #  incr preload, incr write back...
            *flatten((READ, WRITE) for _ in range(self.INCR_PORT_CNT))
        )
Beispiel #2
0
    def _declr(self):
        assert self.HAS_R or self.HAS_W
        addClkRstn(self)
        with self._paramsShared():
            if self.HAS_R:
                self.r = RamHsR()
            if self.HAS_W:
                self.w = AddrDataHs()
                self.w.HAS_MASK = self.HAS_BE

            self.ram = BramPort_withoutClk()._m()
Beispiel #3
0
    def _declr(self):
        addClkRstn(self)
        self._declr_match_io()

        # address is index of CAM cell, data is key to store
        if self.USE_VLD_BIT:
            w = AddrDataVldHs()
        else:
            w = AddrDataHs()
        w.DATA_WIDTH = self.KEY_WIDTH
        w.ADDR_WIDTH = log2ceil(self.ITEMS - 1)
        self.write = w
Beispiel #4
0
    def _declr(self):
        addClkRstn(self)
        with self._paramsShared(prefix="S_"):
            if self.HAS_R:
                self.s_r = RamHsR()
            if self.HAS_W:
                self.s_w = AddrDataHs()

        with self._paramsShared():
            self.m = self.intfCls()._m()

        self.in_axi_t, self.data_words_in_axi_word = self.generate_in_axi_type(
        )
Beispiel #5
0
    def _declr(self):
        addClkRstn(self)

        with self._paramsShared():
            if self.HAS_R:
                self.r = RamHsR()
            if self.HAS_W:
                self.w = AddrDataHs()

            self.conv = RamAsHs()
            r = self.ram = RamSingleClock()
            if not self.HAS_W:
                assert self.INIT_DATA is not None
                assert self.HAS_R
                r.PORT_CNT = (READ,)
            elif not self.HAS_R:
                assert self.HAS_W
                r.PORT_CNT = (WRITE,)
Beispiel #6
0
    def flush_or_read_node(
            self,
            d_arr_r: RamHsR,
            d_arr_w: AddrDataHs,
            st2_out: HsStructIntf,
            data_arr_read: Axi4_r,
            tag_update: AxiCacheTagArrayUpdateIntf,  # out
    ):
        ########################## st1 - post (victim flushing, read forwarding) ######################
        in_w = AxiSBuilder(self, self.s.w)\
            .buff(self.tag_array.LOOKUP_LATENCY + 4)\
            .end

        st2 = st2_out.data
        d_arr_w.addr(
            self.addr_in_data_array(st2.victim_way,
                                    self.parse_addr(st2.replacement_addr)[1]))
        data_arr_read_data = d_arr_r.data  # HsBuilder(self, d_arr_r.data).buff(1, latency=(1, 2)).end
        d_arr_w.data(in_w.data)
        d_arr_w.mask(in_w.strb)

        self.s.b.id(st2.write_id)
        self.s.b.resp(RESP_OKAY)

        data_arr_read.id(st2.read_id)
        data_arr_read.data(data_arr_read_data.data)
        data_arr_read.resp(RESP_OKAY)
        data_arr_read.last(1)

        m = self.m
        m.aw.addr(st2.victim_addr)
        m.aw.id(st2.write_id)
        m.aw.len(0)
        self.axiAddrDefaults(m.aw)

        m.w.data(data_arr_read_data.data)
        m.w.strb(mask(m.w.data._dtype.bit_length() // 8))
        m.w.last(1)

        # flushing needs to have higher priority then read in order
        # to prevent deadlock
        # write replacement after victim load with higher priority
        # else if found just write the data to data array
        is_flush = st2.data_array_op._eq(data_trans_t.write_and_flush)
        contains_write = rename_signal(
            self,
            In(st2.data_array_op, [
                data_trans_t.write, data_trans_t.write_and_flush,
                data_trans_t.read_and_write
            ]), "contains_write")
        contains_read = rename_signal(
            self,
            In(st2.data_array_op, [
                data_trans_t.read, data_trans_t.write_and_flush,
                data_trans_t.read_and_write
            ]), "contains_read")
        contains_read_data = rename_signal(
            self,
            In(st2.data_array_op,
               [data_trans_t.read, data_trans_t.read_and_write]),
            "contains_read_data")

        flush_or_read_node = StreamNode(
            [st2_out, data_arr_read_data, in_w
             ],  # collect read data from data array, collect write data
            [data_arr_read, m.aw, m.w, d_arr_w, self.s.b
             ],  # to read block or to slave connected on "m" interface
            # write data to data array and send write acknowledge
            extraConds={
                data_arr_read_data: contains_read,
                in_w: contains_write,
                data_arr_read: contains_read_data,
                m.aw: is_flush,
                m.w: is_flush,
                d_arr_w: contains_write,
                self.s.b: contains_write,
            },
            skipWhen={
                data_arr_read_data: ~contains_read,
                in_w: ~contains_write,
                data_arr_read: ~contains_read_data,
                m.aw: ~is_flush,
                m.w: ~is_flush,
                d_arr_w: ~contains_write,
                self.s.b: ~contains_write,
            })
        flush_or_read_node.sync()
        m.b.ready(1)

        tag_update.vld(st2_out.vld & contains_write)
        tag_update.delete(0)
        tag_update.way_en(binToOneHot(st2.victim_way))
        tag_update.addr(st2.replacement_addr)
        # [TODO] initial clean
        lru_array_set = self.lru_array.set
        lru_array_set.addr(None)
        lru_array_set.data(None)
        lru_array_set.vld(0)