Exemple #1
0
    def connect_update_port(self, update: AxiCacheTagArrayUpdateIntf,
                            tag_mem_port_w: BramPort_withoutClk):
        update_tmp = self._reg("update_tmp",
                               HStruct(
                                   (update.addr._dtype, "addr"),
                                   (BIT, "delete"),
                                   (update.way_en._dtype, "way_en"),
                                   (BIT, "vld"),
                               ),
                               def_val={"vld": 0})
        update_tmp(update)
        tag, index, _ = self.parse_addr(update.addr)

        tag_mem_port_w.en(update.vld)
        tag_mem_port_w.addr(index)

        # construct the byte enable mask for various tag enable configurations
        # prepare write tag in every way but byte enable only requested ways
        tag_record = self.tag_record_t.from_py({
            "tag": tag,
            "valid": ~update.delete,
        })
        tag_record = tag_record._reinterpret_cast(
            Bits(self.tag_record_t.bit_length()))
        tag_mem_port_w.din(Concat(*(tag_record for _ in range(self.WAY_CNT))))
        tag_be_t = Bits(self.tag_record_t.bit_length() // 8)
        tag_en = tag_be_t.from_py(tag_be_t.all_mask())
        tag_not_en = tag_be_t.from_py(0)
        tag_mem_port_w.we(
            Concat(*reversed(
                [en._ternary(tag_en, tag_not_en) for en in update.way_en])))
        return update_tmp
Exemple #2
0
    def _mkFieldInterface(self, structIntf: StructIntf, field: HStructField):
        """
        Instantiate field interface for fields in structure template of this endpoint

        :return: interface for specified field
        """
        t = field.dtype
        path = structIntf._field_path / field.name
        shouldEnter, shouldUse = self.shouldEnterFn(self.STRUCT_TEMPLATE, path)

        if shouldUse:
            if isinstance(t, Bits):
                p = BusEndpoint.intf_for_Bits(t)
            elif isinstance(t, HArray):
                p = BramPort_withoutClk()
                assert isinstance(t.element_t, Bits), t.element_t
                p.DATA_WIDTH = t.element_t.bit_length()
                p.ADDR_WIDTH = log2ceil(t.size - 1)
            else:
                raise NotImplementedError(t)

        elif shouldEnter:
            if isinstance(t, HArray):
                e_t = t.element_t
                if isinstance(e_t, Bits):
                    p = HObjList()
                    for i_i in range(int(t.size)):
                        i = BusEndpoint.intf_for_Bits(e_t)
                        structIntf._fieldsToInterfaces[path / i_i] = i
                        p.append(i)
                elif isinstance(e_t, HStruct):
                    p = HObjList(
                        StructIntf(t.element_t,
                                   path / i,
                                   instantiateFieldFn=self._mkFieldInterface)
                        for i in range(int(t.size)))
                    for i in p:
                        i._fieldsToInterfaces = structIntf._fieldsToInterfaces
                else:
                    raise NotImplementedError()
            elif isinstance(t, HStruct):
                p = StructIntf(t,
                               path,
                               instantiateFieldFn=self._mkFieldInterface)
                p._fieldsToInterfaces = structIntf._fieldsToInterfaces
            else:
                raise TypeError(t)

        return p
Exemple #3
0
 def connectPort(self, port: BramPort_withoutClk, mem: RtlSignal):
     If(self.clk._onRisingEdge() & port.en,
        If(port.we,
           mem[port.addr](port.din)
        ),
        port.dout(mem[port.addr])
     )
Exemple #4
0
    def _mkFieldInterface(self, structIntf: HStruct, field: HStructField):
        t = field.dtype

        if isinstance(t, Bits):
            p = RegCntrl()
            dw = t.bit_length()
        elif isinstance(t, HArray):
            field_path = structIntf._field_path / field.name
            if self.shouldEnterFn(field_path)[0]:
                if isinstance(t.element_t, Bits):
                    p = HObjList(RegCntrl() for _ in range(int(t.size)))
                    dw = t.element_t.bit_length()
                else:
                    p = HObjList([StructIntf(
                        t.element_t,
                        field_path,
                        instantiateFieldFn=self._mkFieldInterface)
                        for _ in range(int(t.size))])
                    return p
            else:
                p = BramPort_withoutClk()
                dw = t.element_t.bit_length()
                p.ADDR_WIDTH = log2ceil(int(t.size) - 1)
        else:
            raise NotImplementedError(t)

        p.DATA_WIDTH = dw

        return p
    def _mkFieldInterface(self, structIntf, field):
        t = field.dtype

        if isinstance(t, Bits):
            p = RegCntrl()
            dw = t.bit_length()
        elif isinstance(t, HArray):
            if self.shouldEnterFn(field):
                if isinstance(t.elmType, Bits):
                    p = HObjList(RegCntrl() for _ in range(int(t.size)))
                    dw = t.elmType.bit_length()
                else:
                    p = HObjList([
                        StructIntf(t.elmType,
                                   instantiateFieldFn=self._mkFieldInterface)
                        for _ in range(int(t.size))
                    ])
                    return p
            else:
                p = BramPort_withoutClk()
                dw = t.elmType.bit_length()
                p.ADDR_WIDTH.set(log2ceil(int(t.size) - 1))
        else:
            raise NotImplementedError(t)

        p.DATA_WIDTH.set(dw)

        return p
Exemple #6
0
    def _declr(self):
        PORTS = int(self.PORT_CNT)

        self.clk = Clk()
        with self._paramsShared():
            # to let IDEs resolve type of port
            self.a = BramPort_withoutClk()

            for i in range(PORTS - 1):
                self._sportPort(i + 1)
Exemple #7
0
    def _declr(self):
        PORT_CNT = self.PORT_CNT

        with self._paramsShared():
            self.clk = Clk()

            # to let IDEs resolve type of port
            self.firstA = BramPort_withoutClk()
            self.secondA = BramPort_withoutClk()

            if PORT_CNT == 2:
                self.firstB = BramPort_withoutClk()
                self.secondB = BramPort_withoutClk()
            elif PORT_CNT > 2:
                raise NotImplementedError()

            self.select_sig = Signal()

            self.ram0 = RamSingleClock()
            self.ram1 = RamSingleClock()
Exemple #8
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()
Exemple #9
0
    def _mkFieldInterface(self, structIntf, field):
        """
        Instantiate field interface for fields in structure template of this endpoint

        :return: interface for specified field
        """
        t = field.dtype
        DW = int(self.DATA_WIDTH)

        shouldEnter, shouldUse = self.shouldEnterFn(field)
        if shouldUse:
            if isinstance(t, Bits):
                p = RegCntrl()
                dw = t.bit_length()
            elif isinstance(t, HArray):
                p = BramPort_withoutClk()
                assert isinstance(t.elmType, Bits), t.elmType
                dw = t.elmType.bit_length()
                p.ADDR_WIDTH.set(log2ceil(t.size - 1))
            else:
                raise NotImplementedError(t)

        elif shouldEnter:
            if isinstance(t, HArray):
                if isinstance(t.elmType, Bits):
                    p = HObjList(RegCntrl() for _ in range(int(t.size)))
                    dw = t.elmType.bit_length()
                else:
                    return HObjList(
                        StructIntf(t.elmType,
                                   instantiateFieldFn=self._mkFieldInterface)
                        for _ in range(int(t.size)))
            elif isinstance(t, HStruct):
                return StructIntf(t, instantiateFieldFn=self._mkFieldInterface)
            else:
                raise TypeError(t)

        if isinstance(p, HObjList):
            _p = p
        else:
            _p = [p]

        if dw == DW:
            # use param instead of value to improve readability
            DW = self.DATA_WIDTH
            if isinstance(DW, Param):
                for i in _p:
                    i._replaceParam(i.DATA_WIDTH, DW)
        else:
            for i in _p:
                i.DATA_WIDTH.set(dw)

        return p
Exemple #10
0
 def connect_port(clk: RtlSignal, port: BramPort_withoutClk, mem: RtlSignal):
     if port.HAS_R and port.HAS_W:
         If(clk._onRisingEdge(),
             If(port.en,
                 *RamSingleClock.mem_write(mem, port),
                 port.dout(mem[port.addr])
             )
         )
     elif port.HAS_R:
         If(clk._onRisingEdge(),
             If(port.en,
                 port.dout(mem[port.addr])
             )
         )
     elif port.HAS_W:
         If(clk._onRisingEdge(),
             If(port.en,
                *RamSingleClock.mem_write(mem, port),
             )
         )
     else:
         raise AssertionError("Bram port has to have at least write or read part")
Exemple #11
0
    def _declr(self):
        self.PAGE_OFFSET_WIDTH = log2ceil(self.PAGE_SIZE).val
        self.LVL1_PAGE_TABLE_INDX_WIDTH = log2ceil(
            self.LVL1_PAGE_TABLE_ITEMS).val
        self.LVL2_PAGE_TABLE_INDX_WIDTH = int(self.ADDR_WIDTH -
                                              self.LVL1_PAGE_TABLE_INDX_WIDTH -
                                              self.PAGE_OFFSET_WIDTH)
        self.LVL2_PAGE_TABLE_ITEMS = 2**int(self.LVL2_PAGE_TABLE_INDX_WIDTH)
        assert self.LVL1_PAGE_TABLE_INDX_WIDTH > 0, self.LVL1_PAGE_TABLE_INDX_WIDTH
        assert self.LVL2_PAGE_TABLE_INDX_WIDTH > 0, self.LVL2_PAGE_TABLE_INDX_WIDTH
        assert self.LVL2_PAGE_TABLE_ITEMS > 1, self.LVL2_PAGE_TABLE_ITEMS

        # public interfaces
        addClkRstn(self)
        with self._paramsShared():
            self.rDatapump = AxiRDatapumpIntf()._m()
            self.rDatapump.MAX_LEN.set(1)

        i = self.virtIn = Handshaked()
        i._replaceParam(i.DATA_WIDTH, self.VIRT_ADDR_WIDTH)

        i = self.physOut = Handshaked()._m()
        i._replaceParam(i.DATA_WIDTH, self.ADDR_WIDTH)
        self.segfault = Signal()._m()

        self.lvl1Table = BramPort_withoutClk()

        # internal components
        self.lvl1Storage = RamSingleClock()
        self.lvl1Storage.PORT_CNT.set(1)
        self.lvl1Converter = RamAsHs()
        for u in [self.lvl1Table, self.lvl1Converter, self.lvl1Storage]:
            u.DATA_WIDTH.set(self.ADDR_WIDTH)
            u.ADDR_WIDTH.set(self.LVL1_PAGE_TABLE_INDX_WIDTH)

        with self._paramsShared():
            self.lvl2get = ArrayItemGetter()
        self.lvl2get.ITEM_WIDTH.set(self.ADDR_WIDTH)
        self.lvl2get.ITEMS.set(self.LVL2_PAGE_TABLE_ITEMS)

        self.lvl2indxFifo = HandshakedFifo(Handshaked)
        self.lvl2indxFifo.DEPTH.set(self.MAX_OVERLAP // 2)
        self.lvl2indxFifo.DATA_WIDTH.set(self.LVL2_PAGE_TABLE_INDX_WIDTH)

        self.pageOffsetFifo = HandshakedFifo(Handshaked)
        self.pageOffsetFifo.DEPTH.set(self.MAX_OVERLAP)
        self.pageOffsetFifo.DATA_WIDTH.set(self.PAGE_OFFSET_WIDTH)
Exemple #12
0
    def _declr(self):
        addClkRstn(self)
        with self._paramsShared():
            self.bus = Axi4Lite()

            self.signalLoop = SigLoop()
            self.signalIn = VectSignal(self.DATA_WIDTH)

            self.regCntrlLoop = Loop(RegCntrl)
            self.regCntrlOut = RegCntrl()._m()

            self.vldSyncedLoop = Loop(VldSynced)
            self.vldSyncedOut = VldSynced()._m()

        with self._paramsShared(exclude=({"ADDR_WIDTH"}, set())):
            self.bramLoop = Loop(BramPort_withoutClk)
            self.bramLoop.ADDR_WIDTH = 2

            self.bramOut = BramPort_withoutClk()._m()
            self.bramOut.ADDR_WIDTH = 2
Exemple #13
0
 def connectPort(self, port: BramPort_withoutClk, mem: RtlSignal):
     If(self.clk._onRisingEdge() & port.en,
        If(port.we, mem[port.addr](port.din)), port.dout(mem[port.addr]))
Exemple #14
0
 def _declr(self):
     addClkRst(self)
     self.din = BramPort_withoutClk()
     self.dout = BramPort_withoutClk()._m()
Exemple #15
0
 def _config(self):
     BramPort_withoutClk._config(self)
Exemple #16
0
 def _sportPort(self, index) -> None:
     name = self.genPortName(index)
     setattr(self, name, BramPort_withoutClk())
Exemple #17
0
    def connect_lookup_port(self, lookup: AddrHs,
                            tag_mem_port_r: BramPort_withoutClk,
                            lookupRes: AxiCacheTagArrayLookupResIntf,
                            update_tmp: StructIntf):
        lookup_tmp = self._reg(
            "lookup_tmp",
            HStruct(*([(lookup.id._dtype, "id")] if lookup.ID_WIDTH else ()),
                    (lookup.addr._dtype, "addr"), (BIT, "vld")),
            def_val={"vld": 0})

        pa = self.parse_addr
        just_updated = rename_signal(
            self,
            # updated on same index (using "update" port) = the result which is currently on output
            # of the ram may be invalid
            update_tmp.vld
            & pa(lookup_tmp.addr)[1]._eq(pa(update_tmp.addr)[1]),
            "just_updated")

        # tag comparator
        tag, _, _ = self.parse_addr(lookup_tmp.addr)
        tags = tag_mem_port_r.dout._reinterpret_cast(
            self.tag_record_t[self.WAY_CNT])
        found = [
            # is matching and just this tag was not updated
            (t.valid & t.tag._eq(tag) &
             (~just_updated | (update_tmp.vld & ~update_tmp.way_en[i]))) | (
                 # or was updated to the matching tag
                 just_updated & update_tmp.way_en[i] & ~update_tmp.delete
                 & pa(lookup_tmp.addr)[0]._eq(pa(update_tmp.addr)[0]))
            for i, t in enumerate(tags)
        ]

        # if the data which is currently on output of the ram was
        # just updated it means that the data is invalid and the update
        # data will be lost in next clock cycle, if the consumer of lookupRes
        # can not consume the data just know, we need to perform lookup in tag_array
        # once again
        lookup.rd(~lookup_tmp.vld | lookupRes.rd)
        If(
            lookup.rd,
            lookup_tmp.id(lookup.id) if lookup.ID_WIDTH else [],
            lookup_tmp.addr(lookup.addr),
        )
        lookup_tmp.vld(lookup.vld | (lookup_tmp.vld & ~lookupRes.rd))

        tag_mem_port_r.addr((lookup_tmp.vld & ~lookupRes.rd)._ternary(
            self.parse_addr(lookup_tmp.addr)
            [1],  # lookup previous address and look for a change
            self.parse_addr(lookup.addr)[1],  # lookup a new address
        ))
        tag_mem_port_r.en(lookup.vld | (lookup_tmp.vld & ~lookupRes.rd))

        if lookupRes.ID_WIDTH:
            lookupRes.id(lookup_tmp.id)
        lookupRes.addr(lookup_tmp.addr)
        lookupRes.way(oneHotToBin(self, found))
        lookupRes.found(Or(*found))
        lookupRes.tags(tags)

        lookupRes.vld(lookup_tmp.vld)
Exemple #18
0
 def _declr(self):
     addClkRstn(self)
     with self._paramsShared():
         self.r = RamHsR()
         self.w = AddrDataHs()
         self.ram = BramPort_withoutClk()._m()