Esempio n. 1
0
class FlipRam(Unit):
    """
    Switchable RAM, there are two memories and two sets of ports,
    Each set of ports is every time connected to opposite ram.
    By select you can choose between RAMs.

    This component is meant to be form of synchronization.
    Example first RAM is connected to first set of ports, writer performs actualizations on first RAM
    and reader reads data from second ram by second set of ports.

    Then select is set and access is flipped. Reader now has access to RAM 0 and writer to RAM 1.
    
    .. hwt-schematic::
    """
    def _config(self):
        RamSingleClock._config(self)

    def _declr(self):
        PORT_CNT = int(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()

    def _impl(self):
        propagateClk(self)
        PORT_CNT = int(self.PORT_CNT)

        fa = self.firstA
        sa = self.secondA

        If(self.select_sig, self.ram0.a(fa),
           self.ram1.a(sa)).Else(self.ram0.a(sa), self.ram1.a(fa))
        if PORT_CNT == 2:
            fb = self.firstB
            sb = self.secondB
            If(
                self.select_sig,
                self.ram0.b(fb),
                self.ram1.b(sb),
            ).Else(self.ram0.b(sb), self.ram1.b(fb))
        elif PORT_CNT > 2:
            raise NotImplementedError()
Esempio n. 2
0
class RamWithHs(RamAsHs):
    def _declr(self):
        addClkRstn(self)

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

            self.conv = RamAsHs()
            self.ram = RamSingleClock()

    def _impl(self):
        propagateClkRstn(self)
        self.conv.r(self.r)
        self.conv.w(self.w)
        self.ram.a(self.conv.ram)
Esempio n. 3
0
class RamWithHs(RamAsHs):

    def _declr(self):
        addClkRstn(self)

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

            self.conv = RamAsHs()
            self.ram = RamSingleClock()

    def _impl(self):
        propagateClkRstn(self)
        self.conv.r(self.r)
        self.conv.w(self.w)
        self.ram.a(self.conv.ram)
Esempio n. 4
0
class MMU_2pageLvl(Unit):
    """
    MMU where parent page table is stored in ram this unit
    and only items from leaf page tables are download on each request
    over rDatapump interface

    :attention: if item in pagetable is BAD_PHYS_ADDR output signal segfault becomes 1
                and unit will stop working
    :attention: rootPageTable has to be initialized before first request
               over virtIn interface
    :attention: rootPageTable has write only access
    :attention: use value -1 to mark that page is not mapped, it will result in segfault signal asserted high
                when this address is accessed
    
    .. hwt-schematic::
    """
    def _config(self):
        # width of id signal for bus
        self.ID_WIDTH = Param(1)
        self.ADDR_WIDTH = Param(32)
        self.DATA_WIDTH = Param(64)

        self.VIRT_ADDR_WIDTH = Param(32)
        self.LVL1_PAGE_TABLE_ITEMS = Param(512)
        self.PAGE_SIZE = Param(int(2**12))

        self.MAX_OVERLAP = Param(16)

    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)

    def connectLvl1PageTable(self):
        rpgt = self.lvl1Table
        rootW = self.lvl1Converter.w
        rpgt.dout(None)
        rootW.addr(rpgt.addr)
        wEn = rpgt.en & rpgt.we
        rootW.vld(wEn)
        rootW.data(rpgt.din)

        self.lvl1Storage.a(self.lvl1Converter.ram)

        lvl1read = self.lvl1Converter.r
        return lvl1read

    def connectL1Load(self, lvl1readAddr):
        virtIn = self.virtIn
        lvl2indx = self.lvl2indxFifo.dataIn
        pageOffset = self.pageOffsetFifo

        lvl2indx.data(
            virtIn.data[(self.LVL2_PAGE_TABLE_INDX_WIDTH +
                         self.PAGE_OFFSET_WIDTH):self.PAGE_OFFSET_WIDTH])
        connect(virtIn.data, pageOffset.dataIn.data, fit=True)
        lvl1readAddr.data(virtIn.data[:(self.LVL2_PAGE_TABLE_INDX_WIDTH +
                                        self.PAGE_OFFSET_WIDTH)])
        StreamNode(masters=[virtIn],
                   slaves=[lvl2indx, lvl1readAddr, pageOffset.dataIn]).sync()

    def connectL2Load(self, lvl2base, segfaultFlag):
        lvl2get = self.lvl2get
        lvl2indx = self.lvl2indxFifo.dataOut

        self.rDatapump(lvl2get.rDatapump)

        lvl2get.base(lvl2base.data)
        lvl2get.index.data(lvl2indx.data)
        StreamNode(masters=[lvl2base, lvl2indx],
                   slaves=[lvl2get.index],
                   extraConds={
                       lvl2get.index: ~segfaultFlag
                   }).sync()

    def connectPhyout(self, segfaultFlag):
        phyAddrBase = self.lvl2get.item
        pageOffset = self.pageOffsetFifo.dataOut

        segfault = segfaultFlag | phyAddrBase.data[0]._eq(FLAG_INVALID)
        StreamNode(masters=[phyAddrBase, pageOffset],
                   slaves=[self.physOut],
                   extraConds={
                       self.physOut: ~segfault
                   }).sync()

        self.physOut.data(
            Concat(phyAddrBase.data[:self.PAGE_OFFSET_WIDTH], pageOffset.data))

    def segfaultChecker(self):
        lvl1item = self.lvl1Converter.r.data
        lvl2item = self.lvl2get.item
        segfaultFlag = self._reg("segfaultFlag", defVal=False)

        def errVal(intf):
            return intf.vld & intf.data[0]._eq(FLAG_INVALID)

        If(errVal(lvl1item) | errVal(lvl2item), segfaultFlag(1))

        return segfaultFlag

    def _impl(self):
        propagateClkRstn(self)

        segfaultFlag = self.segfaultChecker()

        lvl1read = self.connectLvl1PageTable()
        self.connectL1Load(lvl1read.addr)
        self.connectL2Load(lvl1read.data, segfaultFlag)
        self.connectPhyout(segfaultFlag)

        self.segfault(segfaultFlag)
Esempio n. 5
0
class MMU_2pageLvl(Unit):
    """
    MMU where parent page table is stored in ram this unit
    and only items from leaf page tables are download on each request
    over rDatapump interface

    :attention: if item in pagetable is BAD_PHYS_ADDR output signal segfault becomes 1
                and unit will stop working
    :attention: rootPageTable has to be initialized before first request
               over virtIn interface
    :attention: rootPageTable has write only access
    :attention: use value -1 to mark that page is not mapped, it will result in segfault signal asserted high
                when this address is accessed
    
    .. hwt-schematic::
    """
    def _config(self):
        # width of id signal for bus
        self.ID_WIDTH = Param(1)
        self.ADDR_WIDTH = Param(32)
        self.DATA_WIDTH = Param(64)

        self.VIRT_ADDR_WIDTH = Param(32)
        self.LVL1_PAGE_TABLE_ITEMS = Param(512)
        self.PAGE_SIZE = Param(int(2 ** 12))

        self.MAX_OVERLAP = Param(16)

    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)

    def connectLvl1PageTable(self):
        rpgt = self.lvl1Table
        rootW = self.lvl1Converter.w
        rpgt.dout(None)
        rootW.addr(rpgt.addr)
        wEn = rpgt.en & rpgt.we
        rootW.vld(wEn)
        rootW.data(rpgt.din)

        self.lvl1Storage.a(self.lvl1Converter.ram)

        lvl1read = self.lvl1Converter.r
        return lvl1read

    def connectL1Load(self, lvl1readAddr):
        virtIn = self.virtIn
        lvl2indx = self.lvl2indxFifo.dataIn
        pageOffset = self.pageOffsetFifo

        lvl2indx.data(virtIn.data[(self.LVL2_PAGE_TABLE_INDX_WIDTH 
                                   + self.PAGE_OFFSET_WIDTH):self.PAGE_OFFSET_WIDTH])
        connect(virtIn.data, pageOffset.dataIn.data, fit=True)
        lvl1readAddr.data(virtIn.data[:(self.LVL2_PAGE_TABLE_INDX_WIDTH 
                                           + self.PAGE_OFFSET_WIDTH)])
        StreamNode(masters=[virtIn],
                   slaves=[lvl2indx, lvl1readAddr, pageOffset.dataIn]).sync()

    def connectL2Load(self, lvl2base, segfaultFlag):
        lvl2get = self.lvl2get
        lvl2indx = self.lvl2indxFifo.dataOut

        self.rDatapump(lvl2get.rDatapump)

        lvl2get.base(lvl2base.data)
        lvl2get.index.data(lvl2indx.data)
        StreamNode(masters=[lvl2base, lvl2indx],
                   slaves=[lvl2get.index],
                   extraConds={
                               lvl2get.index:~segfaultFlag
                              }).sync()

    def connectPhyout(self, segfaultFlag):
        phyAddrBase = self.lvl2get.item
        pageOffset = self.pageOffsetFifo.dataOut

        segfault = segfaultFlag | phyAddrBase.data[0]._eq(FLAG_INVALID)
        StreamNode(masters=[phyAddrBase, pageOffset],
                   slaves=[self.physOut],
                   extraConds={self.physOut:~segfault}).sync()

        self.physOut.data(Concat(phyAddrBase.data[:self.PAGE_OFFSET_WIDTH],
                                 pageOffset.data))

    def segfaultChecker(self):
        lvl1item = self.lvl1Converter.r.data
        lvl2item = self.lvl2get.item
        segfaultFlag = self._reg("segfaultFlag", defVal=False)

        def errVal(intf):
            return intf.vld & intf.data[0]._eq(FLAG_INVALID)

        If(errVal(lvl1item) | errVal(lvl2item),
           segfaultFlag(1)
        )

        return segfaultFlag

    def _impl(self):
        propagateClkRstn(self)

        segfaultFlag = self.segfaultChecker()

        lvl1read = self.connectLvl1PageTable()
        self.connectL1Load(lvl1read.addr)
        self.connectL2Load(lvl1read.data, segfaultFlag)
        self.connectPhyout(segfaultFlag)

        self.segfault(segfaultFlag)
Esempio n. 6
0
class FlipRam(Unit):
    """
    Switchable RAM, there are two memories and two sets of ports,
    Each set of ports is every time connected to opposite ram.
    By select you can choose between RAMs.

    This component is meant to be form of synchronization.
    Example first RAM is connected to first set of ports, writer performs actualizations on first RAM
    and reader reads data from second ram by second set of ports.

    Then select is set and access is flipped. Reader now has access to RAM 0 and writer to RAM 1.
    
    .. hwt-schematic::
    """

    def _config(self):
        RamSingleClock._config(self)

    def _declr(self):
        PORT_CNT = int(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()

    def _impl(self):
        propagateClk(self)
        PORT_CNT = int(self.PORT_CNT)

        fa = self.firstA
        sa = self.secondA

        If(self.select_sig,
           self.ram0.a(fa),
           self.ram1.a(sa)
        ).Else(
           self.ram0.a(sa),
           self.ram1.a(fa) 
        )
        if PORT_CNT == 2:
            fb = self.firstB
            sb = self.secondB
            If(self.select_sig,
               self.ram0.b(fb),
               self.ram1.b(sb),
            ).Else(
               self.ram0.b(sb),
               self.ram1.b(fb)
            )
        elif PORT_CNT > 2:
            raise NotImplementedError()